diff --git a/xwords4/android/XWords4/jni/anddict.c b/xwords4/android/XWords4/jni/anddict.c index 1c86f7018..70cfd6649 100644 --- a/xwords4/android/XWords4/jni/anddict.c +++ b/xwords4/android/XWords4/jni/anddict.c @@ -346,7 +346,10 @@ parseDict( AndDictionaryCtxt* ctxt, XP_U8 const* ptr, XP_U32 dictLength, #endif ) { JNIEnv* env = ctxt->env; - jstring jsum = and_util_figureMD5Sum( ctxt->jniutil, ptr, end - ptr ); + jstring jsum = and_util_getMD5SumFor( ctxt->jniutil, ctxt->super.name ); + if ( NULL == jsum ) { + jsum = and_util_figureMD5Sum( ctxt->jniutil, ptr, end - ptr ); + } XP_UCHAR* md5Sum = getStringCopy( MPPARM(ctxt->super.mpool) env, jsum ); (*env)->DeleteLocalRef( env, jsum ); if ( NULL == ctxt->super.md5Sum ) { diff --git a/xwords4/android/XWords4/jni/jniutlswrapper.c b/xwords4/android/XWords4/jni/jniutlswrapper.c index e5d5b5d91..70bfc5e45 100644 --- a/xwords4/android/XWords4/jni/jniutlswrapper.c +++ b/xwords4/android/XWords4/jni/jniutlswrapper.c @@ -92,6 +92,19 @@ and_util_splitFaces( JNIUtilCtxt* jniutil, const XP_U8* bytes, jsize len, return strarray; } +jstring +and_util_getMD5SumFor( JNIUtilCtxt* jniutil, const XP_UCHAR* name ) +{ + JNIEnv* env = *jniutil->envp; + jmethodID mid = getMethodID( env, jniutil->jjniutil, "getMD5SumFor", + "(Ljava/lang/String;)Ljava/lang/String;" ); + jstring jname = (*env)->NewStringUTF( env, name ); + jstring result = + (*env)->CallObjectMethod( env, jniutil->jjniutil, mid, jname ); + (*env)->DeleteLocalRef( env, jname ); + return result; +} + jstring and_util_figureMD5Sum( JNIUtilCtxt* jniutil, const XP_U8* bytes, jsize len ) { diff --git a/xwords4/android/XWords4/jni/jniutlswrapper.h b/xwords4/android/XWords4/jni/jniutlswrapper.h index 0cc6c53dc..389c1462d 100644 --- a/xwords4/android/XWords4/jni/jniutlswrapper.h +++ b/xwords4/android/XWords4/jni/jniutlswrapper.h @@ -35,6 +35,7 @@ jobject and_util_makeJBitmap( JNIUtilCtxt* jniu, int nCols, int nRows, const jboolean* colors ); jobject and_util_splitFaces( JNIUtilCtxt* jniu, const XP_U8* bytes, int len, XP_Bool isUTF8 ); +jstring and_util_getMD5SumFor( JNIUtilCtxt* jniutil, const XP_UCHAR* name ); jstring and_util_figureMD5Sum( JNIUtilCtxt* jniutil, const XP_U8* bytes, jsize len ); diff --git a/xwords4/android/XWords4/jni/xwjni.c b/xwords4/android/XWords4/jni/xwjni.c index d7d7998d3..0433e41b1 100644 --- a/xwords4/android/XWords4/jni/xwjni.c +++ b/xwords4/android/XWords4/jni/xwjni.c @@ -285,7 +285,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_comms_1getUUID JNIEXPORT jboolean JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getInfo -( JNIEnv* env, jclass C, jbyteArray jDictBytes, jstring jpath, +( JNIEnv* env, jclass C, jbyteArray jDictBytes, jstring jname, jstring jpath, jobject jniu, jboolean check, jobject jinfo ) { jboolean result = false; @@ -293,7 +293,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1getInfo MemPoolCtx* mpool = mpool_make(); #endif JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(mpool) &env, jniu ); - DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, jniutil, NULL, + DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, jniutil, jname, jDictBytes, jpath, NULL, check ); if ( NULL != dict ) { if ( NULL != jinfo ) { @@ -1382,7 +1382,8 @@ typedef struct _DictIterData { JNIEXPORT jint JNICALL Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1init -(JNIEnv* env, jclass C, jbyteArray jDictBytes, jstring jpath, jobject jniu ) +( JNIEnv* env, jclass C, jbyteArray jDictBytes, jstring jname, + jstring jpath, jobject jniu ) { jint closure = 0; #ifdef MEM_DEBUG @@ -1391,7 +1392,7 @@ Java_org_eehouse_android_xw4_jni_XwJNI_dict_1iter_1init DictIterData* data = XP_CALLOC( mpool, sizeof(*data) ); data->env = env; JNIUtilCtxt* jniutil = makeJNIUtil( MPPARM(mpool) &data->env, jniu ); - DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, jniutil, NULL, + DictionaryCtxt* dict = makeDict( MPPARM(mpool) env, jniutil, jname, jDictBytes, jpath, NULL, false ); if ( !!dict ) { data->vtMgr = make_vtablemgr( MPPARM_NOCOMMA(mpool) ); diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java index e9d14ce29..d5ce62292 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -448,7 +448,7 @@ public class BoardActivity extends XWActivity } m_utils = new BoardUtilCtxt(); - m_jniu = JNIUtilsImpl.get(); + m_jniu = JNIUtilsImpl.get( this ); setContentView( R.layout.board ); m_timers = new TimerRunnable[4]; // needs to be in sync with // XWTimerReason diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DBUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DBUtils.java index d732e94dc..52a024977 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DBUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DBUtils.java @@ -1031,6 +1031,31 @@ public class DBUtils { } } + public static String dictsGetMD5Sum( Context context, String name ) + { + DictInfo info = dictsGetInfo( context, name ); + String result = null == info? null : info.md5Sum; + return result; + } + + public static void dictsSetMD5Sum( Context context, String name, String sum ) + { + initDB( context ); + synchronized( s_dbHelper ) { + SQLiteDatabase db = s_dbHelper.getWritableDatabase(); + String selection = String.format( NAME_FMT, DBHelper.DICTNAME, name ); + ContentValues values = new ContentValues(); + values.put( DBHelper.MD5SUM, sum ); + int result = db.update( DBHelper.TABLE_NAME_DICTINFO, + values, selection, null ); + if ( 0 == result ) { + values.put( DBHelper.DICTNAME, name ); + db.insert( DBHelper.TABLE_NAME_DICTINFO, null, values ); + } + db.close(); + } + } + public static DictInfo dictsGetInfo( Context context, String name ) { DictInfo result = null; @@ -1147,6 +1172,8 @@ public class DBUtils { { if ( null == s_dbHelper ) { s_dbHelper = new DBHelper( context ); + // force any upgrade + s_dbHelper.getWritableDatabase().close(); } } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictBrowseActivity.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictBrowseActivity.java index 47b08a19e..116283703 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictBrowseActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictBrowseActivity.java @@ -164,9 +164,9 @@ public class DictBrowseActivity extends XWListActivity String[] names = { name }; DictUtils.DictPairs pairs = DictUtils.openDicts( this, names ); - m_dictClosure = XwJNI.dict_iter_init( pairs.m_bytes[0], - pairs.m_paths[0], - JNIUtilsImpl.get() ); + m_dictClosure = XwJNI.dict_iter_init( pairs.m_bytes[0], + name, pairs.m_paths[0], + JNIUtilsImpl.get(this) ); m_browseState = DBUtils.dictsGetOffset( this, name ); boolean newState = null == m_browseState; diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java index c6ecddf96..6bdca3580 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictLangCache.java @@ -367,8 +367,9 @@ public class DictLangCache { DictUtils.DictPairs pairs = DictUtils.openDicts( context, names ); info = new DictInfo(); - if ( XwJNI.dict_getInfo( pairs.m_bytes[0], pairs.m_paths[0], - JNIUtilsImpl.get(), + if ( XwJNI.dict_getInfo( pairs.m_bytes[0], dal.name, + pairs.m_paths[0], + JNIUtilsImpl.get( context ), DictUtils.DictLoc.DOWNLOAD == dal.loc, info ) ) { diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictUtils.java index d37f13083..02a519bdc 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/DictUtils.java @@ -114,14 +114,14 @@ public class DictUtils { // changes? } - private static void tryDir( File dir, boolean strict, DictLoc loc, - ArrayList al ) + private static void tryDir( Context context, File dir, boolean strict, + DictLoc loc, ArrayList al ) { if ( null != dir ) { String[] list = dir.list(); if ( null != list ) { for ( String file : list ) { - if ( isDict( file, strict? dir : null ) ) { + if ( isDict( context, file, strict? dir : null ) ) { al.add( new DictAndLoc( removeDictExtn( file ), loc ) ); } } @@ -135,21 +135,21 @@ public class DictUtils { ArrayList al = new ArrayList(); for ( String file : getAssets( context ) ) { - if ( isDict( file, null ) ) { + if ( isDict( context, file, null ) ) { al.add( new DictAndLoc( removeDictExtn( file ), DictLoc.BUILT_IN ) ); } } for ( String file : context.fileList() ) { - if ( isDict( file, null ) ) { + if ( isDict( context, file, null ) ) { al.add( new DictAndLoc( removeDictExtn( file ), DictLoc.INTERNAL ) ); } } - tryDir( getSDDir( context ), false, DictLoc.EXTERNAL, al ); - tryDir( getDownloadDir(), true, DictLoc.DOWNLOAD, al ); + tryDir( context, getSDDir( context ), false, DictLoc.EXTERNAL, al ); + tryDir( context, getDownloadDir(), true, DictLoc.DOWNLOAD, al ); s_dictListCache = al.toArray( new DictUtils.DictAndLoc[al.size()] ); @@ -480,13 +480,13 @@ public class DictUtils { return file.endsWith( XWConstants.GAME_EXTN ); } - private static boolean isDict( String file, File dir ) + private static boolean isDict( Context context, String file, File dir ) { boolean ok = file.endsWith( XWConstants.DICT_EXTN ); if ( ok && null != dir ) { String fullPath = new File( dir, file ).getPath(); - ok = XwJNI.dict_getInfo( null, fullPath, JNIUtilsImpl.get(), - true, null ); + ok = XwJNI.dict_getInfo( null, removeDictExtn( file ), fullPath, + JNIUtilsImpl.get(context), true, null ); } return ok; } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java index 4c3f99231..25ac8f8bb 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java @@ -220,7 +220,7 @@ public class GameUtils { XwJNI.game_dispose( gamePtr ); gamePtr = XwJNI.initJNI(); - XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get(), + XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get( context ), CommonPrefs.get( context ), dictNames, pairs.m_bytes, pairs.m_paths, gi.langName() ); @@ -360,11 +360,11 @@ public class GameUtils { XwJNI.game_makeFromStream( gamePtr, stream, gi, dictNames, pairs.m_bytes, pairs.m_paths, langName, - util, JNIUtilsImpl.get(), + util, JNIUtilsImpl.get( context ), CommonPrefs.get(context), tp); if ( !madeGame ) { - XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get(), + XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get(context), CommonPrefs.get(context), dictNames, pairs.m_bytes, pairs.m_paths, langName ); @@ -773,7 +773,7 @@ public class GameUtils { int gamePtr = XwJNI.initJNI(); XwJNI.game_makeFromStream( gamePtr, stream, gi, dictNames, pairs.m_bytes, pairs.m_paths, - gi.langName(), JNIUtilsImpl.get(), + gi.langName(), JNIUtilsImpl.get(context), CommonPrefs.get( context ) ); // second time required as game_makeFromStream can overwrite gi.replaceDicts( newDict ); @@ -816,11 +816,12 @@ public class GameUtils { new CurGameInfo(context), dictNames, pairs.m_bytes, pairs.m_paths, langName, - JNIUtilsImpl.get(), cp ); + JNIUtilsImpl.get(context), + cp ); } if ( forceNew || !madeGame ) { - XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get(), + XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get(context), cp, dictNames, pairs.m_bytes, pairs.m_paths, langName ); } diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtils.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtils.java index ce9dff290..d1fff71a6 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtils.java @@ -26,5 +26,6 @@ public interface JNIUtils { // Stuff I can't do in C.... String[] splitFaces( byte[] chars, boolean isUTF8 ); + String getMD5SumFor( String dictName ); String figureMD5Sum( byte[] bytes ); } \ No newline at end of file diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtilsImpl.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtilsImpl.java index fc450e1ab..27b832446 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtilsImpl.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/JNIUtilsImpl.java @@ -20,6 +20,7 @@ package org.eehouse.android.xw4.jni; +import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import java.io.ByteArrayInputStream; @@ -31,15 +32,17 @@ import org.eehouse.android.xw4.*; public class JNIUtilsImpl implements JNIUtils { - private static JNIUtils s_impl = null; + private static JNIUtilsImpl s_impl = null; + private Context m_context; private JNIUtilsImpl(){} - public static JNIUtils get() + public static JNIUtils get( Context context ) { if ( null == s_impl ) { s_impl = new JNIUtilsImpl(); } + s_impl.m_context = context; return s_impl; } @@ -88,6 +91,11 @@ public class JNIUtilsImpl implements JNIUtils { return result; } + public String getMD5SumFor( String dictName ) + { + return DBUtils.dictsGetMD5Sum( m_context, dictName ); + } + public String figureMD5Sum( byte[] bytes ) { byte[] digest = null; diff --git a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java index 52795f0b1..e13d9df23 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/jni/XwJNI.java @@ -239,15 +239,15 @@ public class XwJNI { // Dicts public static native boolean dict_tilesAreSame( int dictPtr1, int dictPtr2 ); public static native String[] dict_getChars( int dictPtr ); - public static native boolean dict_getInfo( byte[] dict, String path, - JNIUtils jniu, boolean check, - DictInfo info ); + public static native boolean dict_getInfo( byte[] dict, String name, + String path, JNIUtils jniu, + boolean check, DictInfo info ); public static native int dict_getTileValue( int dictPtr, int tile ); // Dict iterator public final static int MAX_COLS_DICT = 15; // from dictiter.h - public static native int dict_iter_init( byte[] dict, String path, - JNIUtils jniu ); + public static native int dict_iter_init( byte[] dict, String name, + String path, JNIUtils jniu ); public static native void dict_iter_setMinMax( int closure, int min, int max ); public static native void dict_iter_destroy( int closure );