From fd4e6276286911182ee59256711b18a0cfba73c0 Mon Sep 17 00:00:00 2001 From: Andy2 Date: Thu, 18 Aug 2011 07:54:00 -0700 Subject: [PATCH] when sd card is umounted, android sends a message to apps. I can't figure out how to get that so I ignore it and am killed then relaunched if I have a dict file open on the SD. On relauch, don't crash. Instead, check if any dicts used by the game is unreachable and put up an alert with only one choice: Close game. Thought about using the missing-dicts stuff from GamesList, but this is a special case that should be seen only when user umounts while a BoardActivity instance is frontmost. --- .../android/XWords4/res/values/strings.xml | 11 +- .../eehouse/android/xw4/BoardActivity.java | 172 ++++++++++-------- .../org/eehouse/android/xw4/GameUtils.java | 22 ++- 3 files changed, 125 insertions(+), 80 deletions(-) diff --git a/xwords4/android/XWords4/res/values/strings.xml b/xwords4/android/XWords4/res/values/strings.xml index 41ca0d2c1..ebd8ed481 100644 --- a/xwords4/android/XWords4/res/values/strings.xml +++ b/xwords4/android/XWords4/res/values/strings.xml @@ -389,13 +389,18 @@ Substitute dictionary (wordcount) Substitute + Close game + A dictionary this game is using has + disappeared. (Usually this means it\'s on an external card that + is no longer available.) Unable to open game \"%1$s\" because no %2$s dictionary found. (It may have been deleted, or stored on - an an SD card that\'s been unmounted.) + an external card that is no longer available.) Unable to open game \"%1$s\" because dictionary %2$s not found. (It may have been deleted, or stored - on an an SD card that\'s been unmounted.) You can download a - replacement or substitute another %3$s dictionary. + on an external card that is no longer available.) You can + download a replacement or substitute another %3$s + dictionary. Password for \"%s\": 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 a79c25951..94bfe9947 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/BoardActivity.java @@ -38,6 +38,7 @@ import android.app.Dialog; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.EditText; @@ -68,6 +69,7 @@ public class BoardActivity extends XWActivity private static final int QUERY_ENDGAME = DLG_OKONLY + 7; private static final int DLG_DELETED = DLG_OKONLY + 8; private static final int DLG_INVITE = DLG_OKONLY + 9; + private static final int DLG_NODICT = DLG_OKONLY + 10; private static final int CHAT_REQUEST = 1; private static final int SCREEN_ON_TIME = 10 * 60 * 1000; // 10 mins @@ -80,7 +82,7 @@ public class BoardActivity extends XWActivity private int m_jniGamePtr; private GameUtils.GameLock m_gameLock; private CurGameInfo m_gi; - CommsTransport m_xport; + private CommsTransport m_xport; private Handler m_handler = null; private TimerRunnable[] m_timers; private Runnable m_screenTimer; @@ -286,6 +288,21 @@ public class BoardActivity extends XWActivity .create(); } break; + case DLG_NODICT: + dialog = new AlertDialog.Builder( this ) + .setTitle( R.string.no_dict_title ) + .setMessage( R.string.no_dict_finish ) + .setPositiveButton( R.string.button_close_game, null ) + .create(); + OnDismissListener dlstnr; + dlstnr = new OnDismissListener() { + public void onDismiss( DialogInterface di ) { + // removeDialog( DLG_NODICT ); + finish(); + } + }; + dialog.setOnDismissListener( dlstnr ); + break; default: // just drop it; super.onCreateDialog likely failed break; @@ -1044,89 +1061,96 @@ public class BoardActivity extends XWActivity private void loadGame() { if ( 0 == m_jniGamePtr ) { - Assert.assertNull( m_gameLock ); - m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock(); - - byte[] stream = GameUtils.savedGame( this, m_gameLock ); - XwJNI.gi_from_stream( m_gi, stream ); - String[] dictNames = m_gi.dictNames(); GameUtils.DictPairs pairs = GameUtils.openDicts( this, dictNames ); - String langName = m_gi.langName(); - m_jniGamePtr = XwJNI.initJNI(); - if ( m_gi.serverRole != DeviceRole.SERVER_STANDALONE ) { - m_xport = new CommsTransport( m_jniGamePtr, this, this, - m_gi.serverRole ); - } + if ( pairs.anyMissing( dictNames ) ) { + showDialog( DLG_NODICT ); + } else { - CommonPrefs cp = CommonPrefs.get( this ); - if ( null == stream || - ! XwJNI.game_makeFromStream( m_jniGamePtr, stream, - m_gi, dictNames, pairs.m_bytes, - pairs.m_paths, langName, m_utils, - m_jniu, m_view, cp, m_xport ) ) { - XwJNI.game_makeNewGame( m_jniGamePtr, m_gi, m_utils, m_jniu, - m_view, cp, m_xport, dictNames, - pairs.m_bytes, pairs.m_paths, - langName ); - } + String langName = m_gi.langName(); - m_jniThread = new - JNIThread( m_jniGamePtr, m_gi, m_view, m_gameLock, this, - new Handler() { - public void handleMessage( Message msg ) { - switch( msg.what ) { - case JNIThread.DRAW: - m_view.invalidate(); - break; - case JNIThread.DIALOG: - m_dlgBytes = (String)msg.obj; - m_dlgTitle = msg.arg1; - showDialog( DLG_OKONLY ); - break; - case JNIThread.QUERY_ENDGAME: - showDialog( QUERY_ENDGAME ); - break; - case JNIThread.TOOLBAR_STATES: - if ( null != m_jniThread ) { - m_gsi = m_jniThread.getGameStateInfo(); - updateToolbar(); + Assert.assertNull( m_gameLock ); + m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock(); + + byte[] stream = GameUtils.savedGame( this, m_gameLock ); + XwJNI.gi_from_stream( m_gi, stream ); + + m_jniGamePtr = XwJNI.initJNI(); + + if ( m_gi.serverRole != DeviceRole.SERVER_STANDALONE ) { + m_xport = new CommsTransport( m_jniGamePtr, this, this, + m_gi.serverRole ); + } + + CommonPrefs cp = CommonPrefs.get( this ); + if ( null == stream || + ! XwJNI.game_makeFromStream( m_jniGamePtr, stream, + m_gi, dictNames, pairs.m_bytes, + pairs.m_paths, langName, m_utils, + m_jniu, m_view, cp, m_xport ) ) { + XwJNI.game_makeNewGame( m_jniGamePtr, m_gi, m_utils, m_jniu, + m_view, cp, m_xport, dictNames, + pairs.m_bytes, pairs.m_paths, + langName ); + } + + m_jniThread = new + JNIThread( m_jniGamePtr, m_gi, m_view, m_gameLock, this, + new Handler() { + public void handleMessage( Message msg ) { + switch( msg.what ) { + case JNIThread.DRAW: + m_view.invalidate(); + break; + case JNIThread.DIALOG: + m_dlgBytes = (String)msg.obj; + m_dlgTitle = msg.arg1; + showDialog( DLG_OKONLY ); + break; + case JNIThread.QUERY_ENDGAME: + showDialog( QUERY_ENDGAME ); + break; + case JNIThread.TOOLBAR_STATES: + if ( null != m_jniThread ) { + m_gsi = m_jniThread.getGameStateInfo(); + updateToolbar(); + } + break; } - break; } - } - } ); - // see http://stackoverflow.com/questions/680180/where-to-stop-\ - // destroy-threads-in-android-service-class - m_jniThread.setDaemon( true ); - m_jniThread.start(); + } ); + // see http://stackoverflow.com/questions/680180/where-to-stop-\ + // destroy-threads-in-android-service-class + m_jniThread.setDaemon( true ); + m_jniThread.start(); - m_view.startHandling( this, m_jniThread, m_jniGamePtr, m_gi ); - if ( null != m_xport ) { - m_xport.setReceiver( m_jniThread ); - } - m_jniThread.handle( JNICmd.CMD_START ); + m_view.startHandling( this, m_jniThread, m_jniGamePtr, m_gi ); + if ( null != m_xport ) { + m_xport.setReceiver( m_jniThread ); + } + m_jniThread.handle( JNICmd.CMD_START ); - if ( !CommonPrefs.getHideTitleBar( this ) ) { - setTitle( GameUtils.getName( this, m_rowid ) ); - } - m_toolbar = new Toolbar( this ); + if ( !CommonPrefs.getHideTitleBar( this ) ) { + setTitle( GameUtils.getName( this, m_rowid ) ); + } + m_toolbar = new Toolbar( this ); - populateToolbar(); + populateToolbar(); - int flags = DBUtils.getMsgFlags( this, m_rowid ); - if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) { - startChatActivity(); - } - if ( 0 != (GameSummary.MSG_FLAGS_GAMEOVER & flags) ) { - m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER ); - } - if ( 0 != flags ) { - DBUtils.setMsgFlags( m_rowid, GameSummary.MSG_FLAGS_NONE ); - } + int flags = DBUtils.getMsgFlags( this, m_rowid ); + if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) { + startChatActivity(); + } + if ( 0 != (GameSummary.MSG_FLAGS_GAMEOVER & flags) ) { + m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER ); + } + if ( 0 != flags ) { + DBUtils.setMsgFlags( m_rowid, GameSummary.MSG_FLAGS_NONE ); + } - trySendChats(); + trySendChats(); + } } } // loadGame @@ -1209,9 +1233,9 @@ public class BoardActivity extends XWActivity }); } // populateToolbar - private DialogInterface.OnDismissListener makeODLforBlocking( final int id ) + private OnDismissListener makeODLforBlocking( final int id ) { - return new DialogInterface.OnDismissListener() { + return new OnDismissListener() { public void onDismiss( DialogInterface di ) { releaseIfBlocking(); removeDialog( id ); 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 03b975378..3381468af 100644 --- a/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java +++ b/xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java @@ -158,7 +158,23 @@ public class GameUtils { 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(); @@ -180,7 +196,7 @@ public class GameUtils { * basis for a new one. */ public static GameLock resetGame( Context context, GameLock lockSrc, - GameLock lockDest ) + GameLock lockDest ) { int gamePtr = XwJNI.initJNI(); CurGameInfo gi = new CurGameInfo( context ); @@ -897,7 +913,7 @@ public class GameUtils { // Which isn't possible right now, so make sure the old and new // dict have the same langauge code. public static void replaceDicts( Context context, long rowid, - String oldDict, String newDict ) + String oldDict, String newDict ) { GameLock lock = new GameLock( rowid, true ).lock(); byte[] stream = savedGame( context, lock );