mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-30 10:26:58 +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="subst_dict_title">Substitute dictionary (wordcount)</string>
|
||||||
<string name="button_substdict">Substitute</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
|
<string name="no_dictf">Unable to open game \"%1$s\" because no
|
||||||
%2$s dictionary found. (It may have been deleted, or stored on
|
%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
|
<string name="no_dict_substf">Unable to open game \"%1$s\" because
|
||||||
dictionary %2$s not found. (It may have been deleted, or stored
|
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
|
on an external card that is no longer available.) You can
|
||||||
replacement or substitute another %3$s dictionary.</string>
|
download a replacement or substitute another %3$s
|
||||||
|
dictionary.</string>
|
||||||
|
|
||||||
<string name="msg_ask_password">Password for \"%s\":</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.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.DialogInterface.OnDismissListener;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.EditText;
|
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 QUERY_ENDGAME = DLG_OKONLY + 7;
|
||||||
private static final int DLG_DELETED = DLG_OKONLY + 8;
|
private static final int DLG_DELETED = DLG_OKONLY + 8;
|
||||||
private static final int DLG_INVITE = DLG_OKONLY + 9;
|
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 CHAT_REQUEST = 1;
|
||||||
private static final int SCREEN_ON_TIME = 10 * 60 * 1000; // 10 mins
|
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 int m_jniGamePtr;
|
||||||
private GameUtils.GameLock m_gameLock;
|
private GameUtils.GameLock m_gameLock;
|
||||||
private CurGameInfo m_gi;
|
private CurGameInfo m_gi;
|
||||||
CommsTransport m_xport;
|
private CommsTransport m_xport;
|
||||||
private Handler m_handler = null;
|
private Handler m_handler = null;
|
||||||
private TimerRunnable[] m_timers;
|
private TimerRunnable[] m_timers;
|
||||||
private Runnable m_screenTimer;
|
private Runnable m_screenTimer;
|
||||||
|
@ -286,6 +288,21 @@ public class BoardActivity extends XWActivity
|
||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
// just drop it; super.onCreateDialog likely failed
|
// just drop it; super.onCreateDialog likely failed
|
||||||
break;
|
break;
|
||||||
|
@ -1044,89 +1061,96 @@ public class BoardActivity extends XWActivity
|
||||||
private void loadGame()
|
private void loadGame()
|
||||||
{
|
{
|
||||||
if ( 0 == m_jniGamePtr ) {
|
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();
|
String[] dictNames = m_gi.dictNames();
|
||||||
GameUtils.DictPairs pairs = GameUtils.openDicts( this, dictNames );
|
GameUtils.DictPairs pairs = GameUtils.openDicts( this, dictNames );
|
||||||
String langName = m_gi.langName();
|
|
||||||
m_jniGamePtr = XwJNI.initJNI();
|
|
||||||
|
|
||||||
if ( m_gi.serverRole != DeviceRole.SERVER_STANDALONE ) {
|
if ( pairs.anyMissing( dictNames ) ) {
|
||||||
m_xport = new CommsTransport( m_jniGamePtr, this, this,
|
showDialog( DLG_NODICT );
|
||||||
m_gi.serverRole );
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
CommonPrefs cp = CommonPrefs.get( this );
|
String langName = m_gi.langName();
|
||||||
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
|
Assert.assertNull( m_gameLock );
|
||||||
JNIThread( m_jniGamePtr, m_gi, m_view, m_gameLock, this,
|
m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock();
|
||||||
new Handler() {
|
|
||||||
public void handleMessage( Message msg ) {
|
byte[] stream = GameUtils.savedGame( this, m_gameLock );
|
||||||
switch( msg.what ) {
|
XwJNI.gi_from_stream( m_gi, stream );
|
||||||
case JNIThread.DRAW:
|
|
||||||
m_view.invalidate();
|
m_jniGamePtr = XwJNI.initJNI();
|
||||||
break;
|
|
||||||
case JNIThread.DIALOG:
|
if ( m_gi.serverRole != DeviceRole.SERVER_STANDALONE ) {
|
||||||
m_dlgBytes = (String)msg.obj;
|
m_xport = new CommsTransport( m_jniGamePtr, this, this,
|
||||||
m_dlgTitle = msg.arg1;
|
m_gi.serverRole );
|
||||||
showDialog( DLG_OKONLY );
|
}
|
||||||
break;
|
|
||||||
case JNIThread.QUERY_ENDGAME:
|
CommonPrefs cp = CommonPrefs.get( this );
|
||||||
showDialog( QUERY_ENDGAME );
|
if ( null == stream ||
|
||||||
break;
|
! XwJNI.game_makeFromStream( m_jniGamePtr, stream,
|
||||||
case JNIThread.TOOLBAR_STATES:
|
m_gi, dictNames, pairs.m_bytes,
|
||||||
if ( null != m_jniThread ) {
|
pairs.m_paths, langName, m_utils,
|
||||||
m_gsi = m_jniThread.getGameStateInfo();
|
m_jniu, m_view, cp, m_xport ) ) {
|
||||||
updateToolbar();
|
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-\
|
||||||
// see http://stackoverflow.com/questions/680180/where-to-stop-\
|
// destroy-threads-in-android-service-class
|
||||||
// destroy-threads-in-android-service-class
|
m_jniThread.setDaemon( true );
|
||||||
m_jniThread.setDaemon( true );
|
m_jniThread.start();
|
||||||
m_jniThread.start();
|
|
||||||
|
|
||||||
m_view.startHandling( this, m_jniThread, m_jniGamePtr, m_gi );
|
m_view.startHandling( this, m_jniThread, m_jniGamePtr, m_gi );
|
||||||
if ( null != m_xport ) {
|
if ( null != m_xport ) {
|
||||||
m_xport.setReceiver( m_jniThread );
|
m_xport.setReceiver( m_jniThread );
|
||||||
}
|
}
|
||||||
m_jniThread.handle( JNICmd.CMD_START );
|
m_jniThread.handle( JNICmd.CMD_START );
|
||||||
|
|
||||||
if ( !CommonPrefs.getHideTitleBar( this ) ) {
|
if ( !CommonPrefs.getHideTitleBar( this ) ) {
|
||||||
setTitle( GameUtils.getName( this, m_rowid ) );
|
setTitle( GameUtils.getName( this, m_rowid ) );
|
||||||
}
|
}
|
||||||
m_toolbar = new Toolbar( this );
|
m_toolbar = new Toolbar( this );
|
||||||
|
|
||||||
populateToolbar();
|
populateToolbar();
|
||||||
|
|
||||||
int flags = DBUtils.getMsgFlags( this, m_rowid );
|
int flags = DBUtils.getMsgFlags( this, m_rowid );
|
||||||
if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) {
|
if ( 0 != (GameSummary.MSG_FLAGS_CHAT & flags) ) {
|
||||||
startChatActivity();
|
startChatActivity();
|
||||||
}
|
}
|
||||||
if ( 0 != (GameSummary.MSG_FLAGS_GAMEOVER & flags) ) {
|
if ( 0 != (GameSummary.MSG_FLAGS_GAMEOVER & flags) ) {
|
||||||
m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER );
|
m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER );
|
||||||
}
|
}
|
||||||
if ( 0 != flags ) {
|
if ( 0 != flags ) {
|
||||||
DBUtils.setMsgFlags( m_rowid, GameSummary.MSG_FLAGS_NONE );
|
DBUtils.setMsgFlags( m_rowid, GameSummary.MSG_FLAGS_NONE );
|
||||||
}
|
}
|
||||||
|
|
||||||
trySendChats();
|
trySendChats();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // loadGame
|
} // loadGame
|
||||||
|
|
||||||
|
@ -1209,9 +1233,9 @@ public class BoardActivity extends XWActivity
|
||||||
});
|
});
|
||||||
} // populateToolbar
|
} // 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 ) {
|
public void onDismiss( DialogInterface di ) {
|
||||||
releaseIfBlocking();
|
releaseIfBlocking();
|
||||||
removeDialog( id );
|
removeDialog( id );
|
||||||
|
|
|
@ -158,7 +158,23 @@ public class GameUtils {
|
||||||
public DictPairs( byte[][] bytes, String[] paths ) {
|
public DictPairs( byte[][] bytes, String[] paths ) {
|
||||||
m_bytes = bytes; m_paths = 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();
|
private static Object s_syncObj = new Object();
|
||||||
|
|
||||||
|
@ -180,7 +196,7 @@ public class GameUtils {
|
||||||
* basis for a new one.
|
* basis for a new one.
|
||||||
*/
|
*/
|
||||||
public static GameLock resetGame( Context context, GameLock lockSrc,
|
public static GameLock resetGame( Context context, GameLock lockSrc,
|
||||||
GameLock lockDest )
|
GameLock lockDest )
|
||||||
{
|
{
|
||||||
int gamePtr = XwJNI.initJNI();
|
int gamePtr = XwJNI.initJNI();
|
||||||
CurGameInfo gi = new CurGameInfo( context );
|
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
|
// Which isn't possible right now, so make sure the old and new
|
||||||
// dict have the same langauge code.
|
// dict have the same langauge code.
|
||||||
public static void replaceDicts( Context context, long rowid,
|
public static void replaceDicts( Context context, long rowid,
|
||||||
String oldDict, String newDict )
|
String oldDict, String newDict )
|
||||||
{
|
{
|
||||||
GameLock lock = new GameLock( rowid, true ).lock();
|
GameLock lock = new GameLock( rowid, true ).lock();
|
||||||
byte[] stream = savedGame( context, lock );
|
byte[] stream = savedGame( context, lock );
|
||||||
|
|
Loading…
Reference in a new issue