mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-27 07:58:49 +01:00
move dict-related methods from GameUtils.java to new DictUtils.java
This commit is contained in:
parent
d82193ff05
commit
ce8104f679
9 changed files with 466 additions and 408 deletions
|
@ -1170,7 +1170,7 @@ public class BoardActivity extends XWActivity
|
|||
{
|
||||
if ( 0 == m_jniGamePtr ) {
|
||||
String[] dictNames = GameUtils.dictNames( this, m_rowid );
|
||||
GameUtils.DictPairs pairs = GameUtils.openDicts( this, dictNames );
|
||||
DictUtils.DictPairs pairs = DictUtils.openDicts( this, dictNames );
|
||||
|
||||
if ( pairs.anyMissing( dictNames ) ) {
|
||||
showDictGoneFinish();
|
||||
|
|
|
@ -121,7 +121,7 @@ public class DictImportActivity extends XWActivity {
|
|||
private String saveDict( InputStream inputStream, String path )
|
||||
{
|
||||
String name = basename( path );
|
||||
if ( GameUtils.saveDict( this, inputStream, name, s_useSD ) ) {
|
||||
if ( DictUtils.saveDict( this, inputStream, name, s_useSD ) ) {
|
||||
return name;
|
||||
} else {
|
||||
return null;
|
||||
|
|
|
@ -95,7 +95,7 @@ public class DictLangCache {
|
|||
public static int getLangCount( Context context, int code )
|
||||
{
|
||||
int count = 0;
|
||||
String[] dicts = GameUtils.dictList( context );
|
||||
String[] dicts = DictUtils.dictList( context );
|
||||
for ( String dict : dicts ) {
|
||||
if ( code == getDictLangCode( context, dict ) ) {
|
||||
++count;
|
||||
|
@ -107,7 +107,7 @@ public class DictLangCache {
|
|||
private static DictInfo[] getInfosHaveLang( Context context, int code )
|
||||
{
|
||||
ArrayList<DictInfo> al = new ArrayList<DictInfo>();
|
||||
String[] dicts = GameUtils.dictList( context );
|
||||
String[] dicts = DictUtils.dictList( context );
|
||||
for ( String dict : dicts ) {
|
||||
DictInfo info = getInfo( context, dict );
|
||||
if ( code == info.langCode ) {
|
||||
|
@ -200,7 +200,7 @@ public class DictLangCache {
|
|||
public static void inval( final Context context, String name,
|
||||
boolean added )
|
||||
{
|
||||
name = GameUtils.removeDictExtn( name );
|
||||
name = DictUtils.removeDictExtn( name );
|
||||
s_nameToLang.remove( name );
|
||||
if ( added ) {
|
||||
getInfo( context, name );
|
||||
|
@ -226,7 +226,7 @@ public class DictLangCache {
|
|||
|
||||
public static String[] listLangs( Context context )
|
||||
{
|
||||
return listLangs( context, GameUtils.dictList( context ) );
|
||||
return listLangs( context, DictUtils.dictList( context ) );
|
||||
}
|
||||
|
||||
public static String[] listLangs( Context context, final String[] names )
|
||||
|
@ -315,8 +315,8 @@ public class DictLangCache {
|
|||
if ( s_nameToLang.containsKey( name ) ) {
|
||||
info = s_nameToLang.get( name );
|
||||
} else {
|
||||
byte[] dict = GameUtils.openDict( context, name );
|
||||
String path = GameUtils.getDictPath( context, name );
|
||||
byte[] dict = DictUtils.openDict( context, name );
|
||||
String path = DictUtils.getDictPath( context, name );
|
||||
info = new DictInfo();
|
||||
XwJNI.dict_getInfo( dict, path, JNIUtilsImpl.get(), info );
|
||||
info.name = name;
|
||||
|
|
|
@ -32,7 +32,7 @@ public class DictListPreference extends XWListPreference {
|
|||
{
|
||||
super( context, attrs );
|
||||
|
||||
String[] dicts = GameUtils.dictList( context );
|
||||
String[] dicts = DictUtils.dictList( context );
|
||||
String[] dictEntries = new String[dicts.length];
|
||||
for ( int ii = 0; ii < dicts.length; ++ii ) {
|
||||
dictEntries[ii] =
|
||||
|
|
|
@ -0,0 +1,426 @@
|
|||
/* -*- compile-command: "cd ../../../../../; ant install"; -*- */
|
||||
/*
|
||||
* Copyright 2009-2010 by Eric House (xwords@eehouse.org). All
|
||||
* rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
package org.eehouse.android.xw4;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import android.content.res.AssetManager;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import android.text.Html;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.jni.*;
|
||||
import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
|
||||
|
||||
public class DictUtils {
|
||||
|
||||
public enum DictLoc { BUILT_IN, INTERNAL, EXTERNAL, DOWNLOAD };
|
||||
public static final String INVITED = "invited";
|
||||
|
||||
public static class DictPairs {
|
||||
public byte[][] m_bytes;
|
||||
public String[] m_paths;
|
||||
public DictPairs( byte[][] bytes, String[] paths ) {
|
||||
m_bytes = bytes; m_paths = paths;
|
||||
}
|
||||
|
||||
public boolean anyMissing( final String[] names )
|
||||
{
|
||||
boolean missing = false;
|
||||
for ( int ii = 0; ii < m_paths.length; ++ii ) {
|
||||
if ( names[ii] != null ) {
|
||||
// It's ok for there to be no dict IFF there's no
|
||||
// name. That's a player using the default dict.
|
||||
if ( null == m_paths[ii] && null == m_bytes[ii] ) {
|
||||
missing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
} // DictPairs
|
||||
|
||||
|
||||
public static String[] dictList( Context context )
|
||||
{
|
||||
ArrayList<String> al = new ArrayList<String>();
|
||||
|
||||
for ( String file : getAssets( context ) ) {
|
||||
if ( isDict( file ) ) {
|
||||
al.add( removeDictExtn( file ) );
|
||||
}
|
||||
}
|
||||
|
||||
for ( String file : context.fileList() ) {
|
||||
if ( isDict( file ) ) {
|
||||
al.add( removeDictExtn( file ) );
|
||||
}
|
||||
}
|
||||
|
||||
File sdDir = getSDDir( context );
|
||||
if ( null != sdDir ) {
|
||||
for ( String file : sdDir.list() ) {
|
||||
if ( isDict( file ) ) {
|
||||
al.add( removeDictExtn( file ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return al.toArray( new String[al.size()] );
|
||||
}
|
||||
|
||||
public static DictLoc getDictLoc( Context context, String name )
|
||||
{
|
||||
DictLoc loc = null;
|
||||
name = addDictExtn( name );
|
||||
|
||||
for ( String file : getAssets( context ) ) {
|
||||
if ( file.equals( name ) ) {
|
||||
loc = DictLoc.BUILT_IN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( null == loc ) {
|
||||
try {
|
||||
FileInputStream fis = context.openFileInput( name );
|
||||
fis.close();
|
||||
loc = DictLoc.INTERNAL;
|
||||
} catch ( java.io.FileNotFoundException fnf ) {
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( null == loc ) {
|
||||
File file = getSDPathFor( context, name );
|
||||
if ( null != file && file.exists() ) {
|
||||
loc = DictLoc.EXTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
public static boolean dictExists( Context context, String name )
|
||||
{
|
||||
return null != getDictLoc( context, name );
|
||||
}
|
||||
|
||||
public static boolean dictIsBuiltin( Context context, String name )
|
||||
{
|
||||
return DictLoc.BUILT_IN == getDictLoc( context, name );
|
||||
}
|
||||
|
||||
public static boolean moveDict( Context context, String name,
|
||||
DictLoc from, DictLoc to )
|
||||
{
|
||||
name = addDictExtn( name );
|
||||
boolean success = copyDict( context, name, from, to );
|
||||
if ( success ) {
|
||||
deleteDict( context, name, from );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean copyDict( Context context, String name,
|
||||
DictLoc from, DictLoc to )
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
File file = getSDPathFor( context, name );
|
||||
if ( null != file ) {
|
||||
FileChannel channelIn = null;
|
||||
FileChannel channelOut = null;
|
||||
|
||||
try {
|
||||
FileInputStream fis;
|
||||
FileOutputStream fos;
|
||||
if ( DictLoc.INTERNAL == from ) {
|
||||
fis = context.openFileInput( name );
|
||||
fos = new FileOutputStream( file );
|
||||
} else {
|
||||
fis = new FileInputStream( file );
|
||||
fos = context.openFileOutput( name, Context.MODE_PRIVATE );
|
||||
}
|
||||
|
||||
channelIn = fis.getChannel();
|
||||
channelOut = fos.getChannel();
|
||||
|
||||
channelIn.transferTo( 0, channelIn.size(), channelOut );
|
||||
success = true;
|
||||
|
||||
} catch ( java.io.FileNotFoundException fnfe ) {
|
||||
Utils.logf( "%s", fnfe.toString() );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Utils.logf( "%s", ioe.toString() );
|
||||
} finally {
|
||||
try {
|
||||
// Order should match assignment order to above in
|
||||
// case one or both null
|
||||
channelIn.close();
|
||||
channelOut.close();
|
||||
} catch ( Exception e ) {
|
||||
Utils.logf( "%s", e.toString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
} // copyDict
|
||||
|
||||
private static void deleteDict( Context context, String name, DictLoc loc )
|
||||
{
|
||||
if ( DictLoc.EXTERNAL == loc ) {
|
||||
File onSD = getSDPathFor( context, name );
|
||||
if ( null != onSD ) {
|
||||
onSD.delete();
|
||||
} // otherwise what?
|
||||
} else {
|
||||
Assert.assertTrue( DictLoc.INTERNAL == loc );
|
||||
context.deleteFile( name );
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteDict( Context context, String name )
|
||||
{
|
||||
name = addDictExtn( name );
|
||||
deleteDict( context, name, getDictLoc( context, name ) );
|
||||
}
|
||||
|
||||
public static byte[] openDict( Context context, String name )
|
||||
{
|
||||
byte[] bytes = null;
|
||||
|
||||
name = addDictExtn( name );
|
||||
|
||||
try {
|
||||
AssetManager am = context.getAssets();
|
||||
InputStream dict = am.open( name,
|
||||
android.content.res.AssetManager.ACCESS_RANDOM );
|
||||
|
||||
int len = dict.available(); // this may not be the full length!
|
||||
bytes = new byte[len];
|
||||
int nRead = dict.read( bytes, 0, len );
|
||||
if ( nRead != len ) {
|
||||
Utils.logf( "**** warning ****; read only %d of %d bytes.",
|
||||
nRead, len );
|
||||
}
|
||||
// check that with len bytes we've read the whole file
|
||||
Assert.assertTrue( -1 == dict.read() );
|
||||
} catch ( java.io.IOException ee ){
|
||||
Utils.logf( "%s failed to open; likely not built-in", name );
|
||||
}
|
||||
|
||||
// not an asset? Try external and internal storage
|
||||
if ( null == bytes ) {
|
||||
try {
|
||||
File sdFile = getSDPathFor( context, name );
|
||||
FileInputStream fis;
|
||||
if ( null != sdFile && sdFile.exists() ) {
|
||||
Utils.logf( "loading %s from SD", name );
|
||||
fis = new FileInputStream( sdFile );
|
||||
} else {
|
||||
Utils.logf( "loading %s from private storage", name );
|
||||
fis = context.openFileInput( name );
|
||||
}
|
||||
int len = (int)fis.getChannel().size();
|
||||
bytes = new byte[len];
|
||||
fis.read( bytes, 0, len );
|
||||
fis.close();
|
||||
Utils.logf( "Successfully loaded %s", name );
|
||||
} catch ( java.io.FileNotFoundException fnf ) {
|
||||
Utils.logf( fnf.toString() );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Utils.logf( ioe.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static String getDictPath( Context context, String name )
|
||||
{
|
||||
name = addDictExtn( name );
|
||||
|
||||
File file = context.getFileStreamPath( name );
|
||||
if ( !file.exists() ) {
|
||||
file = getSDPathFor( context, name );
|
||||
if ( null != file && !file.exists() ) {
|
||||
file = null;
|
||||
}
|
||||
}
|
||||
String path = null == file? null : file.getPath();
|
||||
return path;
|
||||
}
|
||||
|
||||
public static DictPairs openDicts( Context context, String[] names )
|
||||
{
|
||||
byte[][] dictBytes = new byte[names.length][];
|
||||
String[] dictPaths = new String[names.length];
|
||||
|
||||
HashMap<String,byte[]> seen = new HashMap<String,byte[]>();
|
||||
for ( int ii = 0; ii < names.length; ++ii ) {
|
||||
byte[] bytes = null;
|
||||
String path = null;
|
||||
String name = names[ii];
|
||||
if ( null != name ) {
|
||||
path = getDictPath( context, name );
|
||||
if ( null == path ) {
|
||||
bytes = seen.get( name );
|
||||
if ( null == bytes ) {
|
||||
bytes = openDict( context, name );
|
||||
seen.put( name, bytes );
|
||||
}
|
||||
}
|
||||
}
|
||||
dictBytes[ii] = bytes;
|
||||
dictPaths[ii] = path;
|
||||
}
|
||||
return new DictPairs( dictBytes, dictPaths );
|
||||
}
|
||||
|
||||
public static boolean saveDict( Context context, InputStream in,
|
||||
String name, boolean useSD )
|
||||
{
|
||||
boolean success = false;
|
||||
File sdFile = null;
|
||||
if ( useSD ) {
|
||||
sdFile = getSDPathFor( context, name );
|
||||
}
|
||||
|
||||
if ( null != sdFile || !useSD ) {
|
||||
try {
|
||||
FileOutputStream fos;
|
||||
if ( null != sdFile ) {
|
||||
fos = new FileOutputStream( sdFile );
|
||||
} else {
|
||||
fos = context.openFileOutput( name, Context.MODE_PRIVATE );
|
||||
}
|
||||
byte[] buf = new byte[1024];
|
||||
int nRead;
|
||||
while( 0 <= (nRead = in.read( buf, 0, buf.length )) ) {
|
||||
fos.write( buf, 0, nRead );
|
||||
}
|
||||
fos.close();
|
||||
success = true;
|
||||
} catch ( java.io.FileNotFoundException fnf ) {
|
||||
Utils.logf( "saveDict: FileNotFoundException: %s",
|
||||
fnf.toString() );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Utils.logf( "saveDict: IOException: %s", ioe.toString() );
|
||||
deleteDict( context, name );
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean isGame( String file )
|
||||
{
|
||||
return file.endsWith( XWConstants.GAME_EXTN );
|
||||
}
|
||||
|
||||
private static boolean isDict( String file )
|
||||
{
|
||||
return file.endsWith( XWConstants.DICT_EXTN );
|
||||
}
|
||||
|
||||
public static String removeDictExtn( String str )
|
||||
{
|
||||
if ( str.endsWith( XWConstants.DICT_EXTN ) ) {
|
||||
int indx = str.lastIndexOf( XWConstants.DICT_EXTN );
|
||||
str = str.substring( 0, indx );
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static String addDictExtn( String str )
|
||||
{
|
||||
if ( ! str.endsWith( XWConstants.DICT_EXTN ) ) {
|
||||
str += XWConstants.DICT_EXTN;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static String[] getAssets( Context context )
|
||||
{
|
||||
try {
|
||||
AssetManager am = context.getAssets();
|
||||
return am.list("");
|
||||
} catch( java.io.IOException ioe ) {
|
||||
Utils.logf( ioe.toString() );
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean haveWriteableSD()
|
||||
{
|
||||
String state = Environment.getExternalStorageState();
|
||||
|
||||
return state.equals( Environment.MEDIA_MOUNTED );
|
||||
// want this later? Environment.MEDIA_MOUNTED_READ_ONLY
|
||||
}
|
||||
|
||||
private static File getSDDir( Context context )
|
||||
{
|
||||
File result = null;
|
||||
if ( haveWriteableSD() ) {
|
||||
File storage = Environment.getExternalStorageDirectory();
|
||||
if ( null != storage ) {
|
||||
String packdir = String.format( "Android/data/%s/files/",
|
||||
context.getPackageName() );
|
||||
result = new File( storage.getPath(), packdir );
|
||||
if ( !result.exists() ) {
|
||||
result.mkdirs();
|
||||
if ( !result.exists() ) {
|
||||
Utils.logf( "unable to create sd dir %s", packdir );
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static File getSDPathFor( Context context, String name )
|
||||
{
|
||||
File result = null;
|
||||
File dir = getSDDir( context );
|
||||
if ( dir != null ) {
|
||||
result = new File( dir, name );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -85,8 +85,8 @@ public class DictsActivity extends ExpandableListActivity
|
|||
private DictListAdapter m_adapter;
|
||||
|
||||
private long m_packedPosition;
|
||||
private GameUtils.DictLoc m_moveFromLoc;
|
||||
private GameUtils.DictLoc m_moveToLoc;
|
||||
private DictUtils.DictLoc m_moveFromLoc;
|
||||
private DictUtils.DictLoc m_moveToLoc;
|
||||
private SDCardWatcher m_cardWatcher;
|
||||
|
||||
private LayoutInflater m_factory;
|
||||
|
@ -133,7 +133,7 @@ public class DictsActivity extends ExpandableListActivity
|
|||
boolean canDelete = false;
|
||||
if ( null != dicts && childPosition < dicts.length ) {
|
||||
text = dicts[childPosition];
|
||||
canDelete = !GameUtils.dictIsBuiltin( DictsActivity.this,
|
||||
canDelete = !DictUtils.dictIsBuiltin( DictsActivity.this,
|
||||
text );
|
||||
} else {
|
||||
text = m_download;
|
||||
|
@ -144,8 +144,8 @@ public class DictsActivity extends ExpandableListActivity
|
|||
view.setDeleteCallback( DictsActivity.this );
|
||||
}
|
||||
|
||||
GameUtils.DictLoc loc =
|
||||
GameUtils.getDictLoc( DictsActivity.this, text );
|
||||
DictUtils.DictLoc loc =
|
||||
DictUtils.getDictLoc( DictsActivity.this, text );
|
||||
view.setComment( m_locNames[loc.ordinal()] );
|
||||
view.cache( loc );
|
||||
|
||||
|
@ -263,10 +263,10 @@ public class DictsActivity extends ExpandableListActivity
|
|||
lstnr = new DialogInterface.OnClickListener() {
|
||||
public void onClick( DialogInterface dlg, int item ) {
|
||||
XWListItem rowView = m_adapter.getSelChildView();
|
||||
if ( GameUtils.moveDict( DictsActivity.this,
|
||||
rowView.getText(),
|
||||
m_moveFromLoc,
|
||||
m_moveToLoc ) ) {
|
||||
if ( DictUtils.moveDict( DictsActivity.this,
|
||||
rowView.getText(),
|
||||
m_moveFromLoc,
|
||||
m_moveToLoc ) ) {
|
||||
rowView.
|
||||
setComment( m_locNames[m_moveToLoc.ordinal()]);
|
||||
rowView.cache( m_moveToLoc );
|
||||
|
@ -408,11 +408,11 @@ public class DictsActivity extends ExpandableListActivity
|
|||
|
||||
int tmp = savedInstanceState.getInt( MOVEFROMLOC, -1 );
|
||||
if ( -1 != tmp ) {
|
||||
m_moveFromLoc = GameUtils.DictLoc.values()[tmp];
|
||||
m_moveFromLoc = DictUtils.DictLoc.values()[tmp];
|
||||
}
|
||||
tmp = savedInstanceState.getInt( MOVETOLOC, -1 );
|
||||
if ( -1 != tmp ) {
|
||||
m_moveToLoc = GameUtils.DictLoc.values()[tmp];
|
||||
m_moveToLoc = DictUtils.DictLoc.values()[tmp];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,9 +452,9 @@ public class DictsActivity extends ExpandableListActivity
|
|||
inflater.inflate( R.menu.dicts_item_menu, menu );
|
||||
|
||||
XWListItem row = (XWListItem)info.targetView;
|
||||
GameUtils.DictLoc loc = (GameUtils.DictLoc)row.getCached();
|
||||
if ( loc == GameUtils.DictLoc.BUILT_IN
|
||||
|| ! GameUtils.haveWriteableSD() ) {
|
||||
DictUtils.DictLoc loc = (DictUtils.DictLoc)row.getCached();
|
||||
if ( loc == DictUtils.DictLoc.BUILT_IN
|
||||
|| ! DictUtils.haveWriteableSD() ) {
|
||||
menu.removeItem( R.id.dicts_item_move );
|
||||
}
|
||||
|
||||
|
@ -510,11 +510,11 @@ public class DictsActivity extends ExpandableListActivity
|
|||
// options for YY?
|
||||
private void askMoveDict( XWListItem item )
|
||||
{
|
||||
m_moveFromLoc = (GameUtils.DictLoc)item.getCached();
|
||||
if ( m_moveFromLoc == GameUtils.DictLoc.INTERNAL ) {
|
||||
m_moveToLoc = GameUtils.DictLoc.EXTERNAL;
|
||||
m_moveFromLoc = (DictUtils.DictLoc)item.getCached();
|
||||
if ( m_moveFromLoc == DictUtils.DictLoc.INTERNAL ) {
|
||||
m_moveToLoc = DictUtils.DictLoc.EXTERNAL;
|
||||
} else {
|
||||
m_moveToLoc = GameUtils.DictLoc.INTERNAL;
|
||||
m_moveToLoc = DictUtils.DictLoc.INTERNAL;
|
||||
}
|
||||
|
||||
showDialog( MOVE_DICT );
|
||||
|
@ -566,14 +566,14 @@ public class DictsActivity extends ExpandableListActivity
|
|||
|
||||
private void deleteDict( String dict )
|
||||
{
|
||||
GameUtils.deleteDict( this, dict );
|
||||
DictUtils.deleteDict( this, dict );
|
||||
DictLangCache.inval( this, dict, false );
|
||||
mkListAdapter();
|
||||
}
|
||||
|
||||
private void askStartDownload( int lang, String name )
|
||||
{
|
||||
if ( GameUtils.haveWriteableSD() ) {
|
||||
if ( DictUtils.haveWriteableSD() ) {
|
||||
m_lang = lang;
|
||||
m_name = name;
|
||||
showDialog( PICK_STORAGE );
|
||||
|
|
|
@ -47,7 +47,6 @@ import org.eehouse.android.xw4.jni.CurGameInfo.DeviceRole;
|
|||
|
||||
public class GameUtils {
|
||||
|
||||
public enum DictLoc { BUILT_IN, INTERNAL, EXTERNAL, DOWNLOAD };
|
||||
public static final String INVITED = "invited";
|
||||
|
||||
// Implements read-locks and write-locks per game. A read lock is
|
||||
|
@ -152,30 +151,6 @@ public class GameUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static class DictPairs {
|
||||
public byte[][] m_bytes;
|
||||
public String[] m_paths;
|
||||
public DictPairs( byte[][] bytes, String[] paths ) {
|
||||
m_bytes = bytes; m_paths = paths;
|
||||
}
|
||||
|
||||
public boolean anyMissing( final String[] names )
|
||||
{
|
||||
boolean missing = false;
|
||||
for ( int ii = 0; ii < m_paths.length; ++ii ) {
|
||||
if ( names[ii] != null ) {
|
||||
// It's ok for there to be no dict IFF there's no
|
||||
// name. That's a player using the default dict.
|
||||
if ( null == m_paths[ii] && null == m_bytes[ii] ) {
|
||||
missing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return missing;
|
||||
}
|
||||
} // DictPairs
|
||||
|
||||
private static Object s_syncObj = new Object();
|
||||
|
||||
public static byte[] savedGame( Context context, long rowid )
|
||||
|
@ -205,7 +180,7 @@ public class GameUtils {
|
|||
// as DeviceRole.SERVER_STANDALONE != gi.serverRole
|
||||
int gamePtr = loadMakeGame( context, gi, lockSrc );
|
||||
String[] dictNames = gi.dictNames();
|
||||
DictPairs pairs = openDicts( context, dictNames );
|
||||
DictUtils.DictPairs pairs = DictUtils.openDicts( context, dictNames );
|
||||
|
||||
if ( XwJNI.game_hasComms( gamePtr ) ) {
|
||||
addr = new CommsAddrRec( context );
|
||||
|
@ -333,7 +308,7 @@ public class GameUtils {
|
|||
byte[] stream = savedGame( context, lock );
|
||||
XwJNI.gi_from_stream( gi, stream );
|
||||
String[] dictNames = gi.dictNames();
|
||||
DictPairs pairs = openDicts( context, dictNames );
|
||||
DictUtils.DictPairs pairs = DictUtils.openDicts( context, dictNames );
|
||||
if ( pairs.anyMissing( dictNames ) ) {
|
||||
Utils.logf( "loadMakeGame() failing: dict unavailable" );
|
||||
} else {
|
||||
|
@ -490,7 +465,7 @@ public class GameUtils {
|
|||
{
|
||||
String[] dictNames = dictNames( context, rowid, missingLang );
|
||||
HashSet<String> missingSet;
|
||||
String[] installed = dictList( context );
|
||||
String[] installed = DictUtils.dictList( context );
|
||||
|
||||
missingSet = new HashSet<String>( Arrays.asList( dictNames ) );
|
||||
missingSet.remove( null );
|
||||
|
@ -532,288 +507,11 @@ public class GameUtils {
|
|||
// return name;
|
||||
}
|
||||
|
||||
public static String[] dictList( Context context )
|
||||
{
|
||||
ArrayList<String> al = new ArrayList<String>();
|
||||
|
||||
for ( String file : getAssets( context ) ) {
|
||||
if ( isDict( file ) ) {
|
||||
al.add( removeDictExtn( file ) );
|
||||
}
|
||||
}
|
||||
|
||||
for ( String file : context.fileList() ) {
|
||||
if ( isDict( file ) ) {
|
||||
al.add( removeDictExtn( file ) );
|
||||
}
|
||||
}
|
||||
|
||||
File sdDir = getSDDir( context );
|
||||
if ( null != sdDir ) {
|
||||
for ( String file : sdDir.list() ) {
|
||||
if ( isDict( file ) ) {
|
||||
al.add( removeDictExtn( file ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return al.toArray( new String[al.size()] );
|
||||
}
|
||||
|
||||
public static DictLoc getDictLoc( Context context, String name )
|
||||
{
|
||||
DictLoc loc = null;
|
||||
name = addDictExtn( name );
|
||||
|
||||
for ( String file : getAssets( context ) ) {
|
||||
if ( file.equals( name ) ) {
|
||||
loc = DictLoc.BUILT_IN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( null == loc ) {
|
||||
try {
|
||||
FileInputStream fis = context.openFileInput( name );
|
||||
fis.close();
|
||||
loc = DictLoc.INTERNAL;
|
||||
} catch ( java.io.FileNotFoundException fnf ) {
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( null == loc ) {
|
||||
File file = getSDPathFor( context, name );
|
||||
if ( null != file && file.exists() ) {
|
||||
loc = DictLoc.EXTERNAL;
|
||||
}
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
public static boolean dictExists( Context context, String name )
|
||||
{
|
||||
return null != getDictLoc( context, name );
|
||||
}
|
||||
|
||||
public static boolean dictIsBuiltin( Context context, String name )
|
||||
{
|
||||
return DictLoc.BUILT_IN == getDictLoc( context, name );
|
||||
}
|
||||
|
||||
public static boolean moveDict( Context context, String name,
|
||||
DictLoc from, DictLoc to )
|
||||
{
|
||||
name = addDictExtn( name );
|
||||
boolean success = copyDict( context, name, from, to );
|
||||
if ( success ) {
|
||||
deleteDict( context, name, from );
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean copyDict( Context context, String name,
|
||||
DictLoc from, DictLoc to )
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
File file = getSDPathFor( context, name );
|
||||
if ( null != file ) {
|
||||
FileChannel channelIn = null;
|
||||
FileChannel channelOut = null;
|
||||
|
||||
try {
|
||||
FileInputStream fis;
|
||||
FileOutputStream fos;
|
||||
if ( DictLoc.INTERNAL == from ) {
|
||||
fis = context.openFileInput( name );
|
||||
fos = new FileOutputStream( file );
|
||||
} else {
|
||||
fis = new FileInputStream( file );
|
||||
fos = context.openFileOutput( name, Context.MODE_PRIVATE );
|
||||
}
|
||||
|
||||
channelIn = fis.getChannel();
|
||||
channelOut = fos.getChannel();
|
||||
|
||||
channelIn.transferTo( 0, channelIn.size(), channelOut );
|
||||
success = true;
|
||||
|
||||
} catch ( java.io.FileNotFoundException fnfe ) {
|
||||
Utils.logf( "%s", fnfe.toString() );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Utils.logf( "%s", ioe.toString() );
|
||||
} finally {
|
||||
try {
|
||||
// Order should match assignment order to above in
|
||||
// case one or both null
|
||||
channelIn.close();
|
||||
channelOut.close();
|
||||
} catch ( Exception e ) {
|
||||
Utils.logf( "%s", e.toString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
} // copyDict
|
||||
|
||||
private static void deleteDict( Context context, String name, DictLoc loc )
|
||||
{
|
||||
if ( DictLoc.EXTERNAL == loc ) {
|
||||
File onSD = getSDPathFor( context, name );
|
||||
if ( null != onSD ) {
|
||||
onSD.delete();
|
||||
} // otherwise what?
|
||||
} else {
|
||||
Assert.assertTrue( DictLoc.INTERNAL == loc );
|
||||
context.deleteFile( name );
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteDict( Context context, String name )
|
||||
{
|
||||
name = addDictExtn( name );
|
||||
deleteDict( context, name, getDictLoc( context, name ) );
|
||||
}
|
||||
|
||||
public static byte[] openDict( Context context, String name )
|
||||
{
|
||||
byte[] bytes = null;
|
||||
|
||||
name = addDictExtn( name );
|
||||
|
||||
try {
|
||||
AssetManager am = context.getAssets();
|
||||
InputStream dict = am.open( name,
|
||||
android.content.res.AssetManager.ACCESS_RANDOM );
|
||||
|
||||
int len = dict.available(); // this may not be the full length!
|
||||
bytes = new byte[len];
|
||||
int nRead = dict.read( bytes, 0, len );
|
||||
if ( nRead != len ) {
|
||||
Utils.logf( "**** warning ****; read only %d of %d bytes.",
|
||||
nRead, len );
|
||||
}
|
||||
// check that with len bytes we've read the whole file
|
||||
Assert.assertTrue( -1 == dict.read() );
|
||||
} catch ( java.io.IOException ee ){
|
||||
Utils.logf( "%s failed to open; likely not built-in", name );
|
||||
}
|
||||
|
||||
// not an asset? Try external and internal storage
|
||||
if ( null == bytes ) {
|
||||
try {
|
||||
File sdFile = getSDPathFor( context, name );
|
||||
FileInputStream fis;
|
||||
if ( null != sdFile && sdFile.exists() ) {
|
||||
Utils.logf( "loading %s from SD", name );
|
||||
fis = new FileInputStream( sdFile );
|
||||
} else {
|
||||
Utils.logf( "loading %s from private storage", name );
|
||||
fis = context.openFileInput( name );
|
||||
}
|
||||
int len = (int)fis.getChannel().size();
|
||||
bytes = new byte[len];
|
||||
fis.read( bytes, 0, len );
|
||||
fis.close();
|
||||
Utils.logf( "Successfully loaded %s", name );
|
||||
} catch ( java.io.FileNotFoundException fnf ) {
|
||||
Utils.logf( fnf.toString() );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Utils.logf( ioe.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static String getDictPath( Context context, String name )
|
||||
{
|
||||
name = addDictExtn( name );
|
||||
|
||||
File file = context.getFileStreamPath( name );
|
||||
if ( !file.exists() ) {
|
||||
file = getSDPathFor( context, name );
|
||||
if ( null != file && !file.exists() ) {
|
||||
file = null;
|
||||
}
|
||||
}
|
||||
String path = null == file? null : file.getPath();
|
||||
return path;
|
||||
}
|
||||
|
||||
public static DictPairs openDicts( Context context, String[] names )
|
||||
{
|
||||
byte[][] dictBytes = new byte[names.length][];
|
||||
String[] dictPaths = new String[names.length];
|
||||
|
||||
HashMap<String,byte[]> seen = new HashMap<String,byte[]>();
|
||||
for ( int ii = 0; ii < names.length; ++ii ) {
|
||||
byte[] bytes = null;
|
||||
String path = null;
|
||||
String name = names[ii];
|
||||
if ( null != name ) {
|
||||
path = getDictPath( context, name );
|
||||
if ( null == path ) {
|
||||
bytes = seen.get( name );
|
||||
if ( null == bytes ) {
|
||||
bytes = openDict( context, name );
|
||||
seen.put( name, bytes );
|
||||
}
|
||||
}
|
||||
}
|
||||
dictBytes[ii] = bytes;
|
||||
dictPaths[ii] = path;
|
||||
}
|
||||
return new DictPairs( dictBytes, dictPaths );
|
||||
}
|
||||
|
||||
public static boolean saveDict( Context context, InputStream in,
|
||||
String name, boolean useSD )
|
||||
{
|
||||
boolean success = false;
|
||||
File sdFile = null;
|
||||
if ( useSD ) {
|
||||
sdFile = getSDPathFor( context, name );
|
||||
}
|
||||
|
||||
if ( null != sdFile || !useSD ) {
|
||||
try {
|
||||
FileOutputStream fos;
|
||||
if ( null != sdFile ) {
|
||||
fos = new FileOutputStream( sdFile );
|
||||
} else {
|
||||
fos = context.openFileOutput( name, Context.MODE_PRIVATE );
|
||||
}
|
||||
byte[] buf = new byte[1024];
|
||||
int nRead;
|
||||
while( 0 <= (nRead = in.read( buf, 0, buf.length )) ) {
|
||||
fos.write( buf, 0, nRead );
|
||||
}
|
||||
fos.close();
|
||||
success = true;
|
||||
} catch ( java.io.FileNotFoundException fnf ) {
|
||||
Utils.logf( "saveDict: FileNotFoundException: %s",
|
||||
fnf.toString() );
|
||||
} catch ( java.io.IOException ioe ) {
|
||||
Utils.logf( "saveDict: IOException: %s", ioe.toString() );
|
||||
deleteDict( context, name );
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static boolean isGame( String file )
|
||||
{
|
||||
return file.endsWith( XWConstants.GAME_EXTN );
|
||||
}
|
||||
|
||||
private static boolean isDict( String file )
|
||||
{
|
||||
return file.endsWith( XWConstants.DICT_EXTN );
|
||||
}
|
||||
|
||||
public static void launchGame( Activity activity, long rowid,
|
||||
boolean invited )
|
||||
{
|
||||
|
@ -925,7 +623,7 @@ public class GameUtils {
|
|||
gi.replaceDicts( newDict );
|
||||
|
||||
String[] dictNames = gi.dictNames();
|
||||
DictPairs pairs = openDicts( context, dictNames );
|
||||
DictUtils.DictPairs pairs = DictUtils.openDicts( context, dictNames );
|
||||
|
||||
int gamePtr = XwJNI.initJNI();
|
||||
XwJNI.game_makeFromStream( gamePtr, stream, JNIUtilsImpl.get(), gi,
|
||||
|
@ -950,7 +648,7 @@ public class GameUtils {
|
|||
// that don't reset the game, e.g. player name for standalone
|
||||
// games?
|
||||
String[] dictNames = gi.dictNames();
|
||||
DictPairs pairs = openDicts( context, dictNames );
|
||||
DictUtils.DictPairs pairs = DictUtils.openDicts( context, dictNames );
|
||||
String langName = gi.langName();
|
||||
int gamePtr = XwJNI.initJNI();
|
||||
boolean madeGame = false;
|
||||
|
@ -996,34 +694,6 @@ public class GameUtils {
|
|||
activity.startActivity( intent );
|
||||
}
|
||||
|
||||
public static String removeDictExtn( String str )
|
||||
{
|
||||
if ( str.endsWith( XWConstants.DICT_EXTN ) ) {
|
||||
int indx = str.lastIndexOf( XWConstants.DICT_EXTN );
|
||||
str = str.substring( 0, indx );
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static String addDictExtn( String str )
|
||||
{
|
||||
if ( ! str.endsWith( XWConstants.DICT_EXTN ) ) {
|
||||
str += XWConstants.DICT_EXTN;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
private static String[] getAssets( Context context )
|
||||
{
|
||||
try {
|
||||
AssetManager am = context.getAssets();
|
||||
return am.list("");
|
||||
} catch( java.io.IOException ioe ) {
|
||||
Utils.logf( ioe.toString() );
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
private static void tellRelayDied( Context context, GameLock lock,
|
||||
boolean informNow )
|
||||
{
|
||||
|
@ -1036,43 +706,5 @@ public class GameUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean haveWriteableSD()
|
||||
{
|
||||
String state = Environment.getExternalStorageState();
|
||||
|
||||
return state.equals( Environment.MEDIA_MOUNTED );
|
||||
// want this later? Environment.MEDIA_MOUNTED_READ_ONLY
|
||||
}
|
||||
|
||||
private static File getSDDir( Context context )
|
||||
{
|
||||
File result = null;
|
||||
if ( haveWriteableSD() ) {
|
||||
File storage = Environment.getExternalStorageDirectory();
|
||||
if ( null != storage ) {
|
||||
String packdir = String.format( "Android/data/%s/files/",
|
||||
context.getPackageName() );
|
||||
result = new File( storage.getPath(), packdir );
|
||||
if ( !result.exists() ) {
|
||||
result.mkdirs();
|
||||
if ( !result.exists() ) {
|
||||
Utils.logf( "unable to create sd dir %s", packdir );
|
||||
result = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static File getSDPathFor( Context context, String name )
|
||||
{
|
||||
File result = null;
|
||||
File dir = getSDDir( context );
|
||||
if ( dir != null ) {
|
||||
result = new File( dir, name );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import junit.framework.Assert;
|
|||
|
||||
import org.eehouse.android.xw4.Utils;
|
||||
import org.eehouse.android.xw4.R;
|
||||
import org.eehouse.android.xw4.GameUtils;
|
||||
import org.eehouse.android.xw4.DictUtils;
|
||||
|
||||
public class CommonPrefs {
|
||||
public static final int COLOR_TILE_BACK = 0;
|
||||
|
@ -211,8 +211,8 @@ public class CommonPrefs {
|
|||
public static String getDefaultHumanDict( Context context )
|
||||
{
|
||||
String value = getString( context, R.string.key_default_dict );
|
||||
if ( value.equals("") || !GameUtils.dictExists( context, value ) ) {
|
||||
value = GameUtils.dictList( context )[0];
|
||||
if ( value.equals("") || !DictUtils.dictExists( context, value ) ) {
|
||||
value = DictUtils.dictList( context )[0];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ public class CommonPrefs {
|
|||
public static String getDefaultRobotDict( Context context )
|
||||
{
|
||||
String value = getString( context, R.string.key_default_robodict );
|
||||
if ( value.equals("") || !GameUtils.dictExists( context, value ) ) {
|
||||
if ( value.equals("") || !DictUtils.dictExists( context, value ) ) {
|
||||
value = getDefaultHumanDict( context );
|
||||
}
|
||||
return value;
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.Arrays;
|
|||
import junit.framework.Assert;
|
||||
|
||||
import org.eehouse.android.xw4.Utils;
|
||||
import org.eehouse.android.xw4.GameUtils;
|
||||
import org.eehouse.android.xw4.DictUtils;
|
||||
import org.eehouse.android.xw4.R;
|
||||
import org.eehouse.android.xw4.DictLangCache;
|
||||
|
||||
|
@ -403,7 +403,7 @@ public class CurGameInfo {
|
|||
DictLangCache.getBestDefault( m_context, dictLang, false );
|
||||
|
||||
if ( null == dictName
|
||||
|| ! GameUtils.dictExists( m_context, dictName )
|
||||
|| ! DictUtils.dictExists( m_context, dictName )
|
||||
|| dictLang != DictLangCache.getDictLangCode( m_context,
|
||||
dictName ) ) {
|
||||
dictName = humanDict;
|
||||
|
|
Loading…
Add table
Reference in a new issue