mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-28 09:58:30 +01:00
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.
This commit is contained in:
parent
7a1346e530
commit
fd4e627628
3 changed files with 125 additions and 80 deletions
|
@ -389,13 +389,18 @@
|
|||
<string name="subst_dict_title">Substitute dictionary (wordcount)</string>
|
||||
<string name="button_substdict">Substitute</string>
|
||||
|
||||
<string name="button_close_game">Close game</string>
|
||||
<string name="no_dict_finish">A dictionary this game is using has
|
||||
disappeared. (Usually this means it\'s on an external card that
|
||||
is no longer available.)</string>
|
||||
<string name="no_dictf">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.)</string>
|
||||
an external card that is no longer available.)</string>
|
||||
<string name="no_dict_substf">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.</string>
|
||||
on an external card that is no longer available.) You can
|
||||
download a replacement or substitute another %3$s
|
||||
dictionary.</string>
|
||||
|
||||
<string name="msg_ask_password">Password for \"%s\":</string>
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in a new issue