Merge branch 'android_branch' into send_in_background

Conflicts:
	xwords4/android/XWords4/src/org/eehouse/android/xw4/GameUtils.java
This commit is contained in:
Andy2 2011-08-20 12:44:17 -07:00
commit eb00984563
13 changed files with 390 additions and 214 deletions

View file

@ -389,11 +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="no_dictf">Unable to open game because no %s <string name="button_close_game">Close game</string>
dictionary found.</string> <string name="no_dict_finish">A dictionary this game is using has
<string name="no_dict_substf">Unable to open game because disappeared. (Usually this means it\'s on an external card that
dictionary %1$s not found. You can download a replacement or is no longer available.)</string>
substitute another %2$s dictionary.</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 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 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> <string name="msg_ask_password">Password for \"%s\":</string>

View file

@ -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;
@ -80,7 +81,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;
@ -1044,89 +1045,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, showDictGoneFinish();
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 +1217,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 );

View file

@ -55,7 +55,8 @@ import org.eehouse.android.xw4.jni.JNIUtilsImpl;
import org.eehouse.android.xw4.jni.CommonPrefs; import org.eehouse.android.xw4.jni.CommonPrefs;
public class DictsActivity extends ExpandableListActivity public class DictsActivity extends ExpandableListActivity
implements View.OnClickListener, XWListItem.DeleteCallback { implements View.OnClickListener, XWListItem.DeleteCallback,
SDCardWatcher.SDCardNotifiee {
private static final String DICT_DOLAUNCH = "do_launch"; private static final String DICT_DOLAUNCH = "do_launch";
private static final String DICT_LANG_EXTRA = "use_lang"; private static final String DICT_LANG_EXTRA = "use_lang";
@ -75,9 +76,10 @@ public class DictsActivity extends ExpandableListActivity
private XWListItem m_rowView; private XWListItem m_rowView;
GameUtils.DictLoc m_moveFromLoc; GameUtils.DictLoc m_moveFromLoc;
GameUtils.DictLoc m_moveToLoc; GameUtils.DictLoc m_moveToLoc;
String m_moveName; private SDCardWatcher m_cardWatcher;
private String m_moveName;
LayoutInflater m_factory; private LayoutInflater m_factory;
private class DictListAdapter implements ExpandableListAdapter { private class DictListAdapter implements ExpandableListAdapter {
private Context m_context; private Context m_context;
@ -331,10 +333,17 @@ public class DictsActivity extends ExpandableListActivity
protected void onResume() protected void onResume()
{ {
super.onResume(); super.onResume();
m_cardWatcher = new SDCardWatcher( this, this );
mkListAdapter(); mkListAdapter();
expandGroups(); expandGroups();
} }
protected void onPause() {
m_cardWatcher.close();
m_cardWatcher = null;
super.onPause();
}
public void onClick( View v ) public void onClick( View v )
{ {
askStartDownload( 0, null ); askStartDownload( 0, null );
@ -429,7 +438,7 @@ public class DictsActivity extends ExpandableListActivity
showDialog( MOVE_DICT ); showDialog( MOVE_DICT );
} }
// DeleteCallback interface // XWListItem.DeleteCallback interface
public void deleteCalled( int myPosition, final String dict ) public void deleteCalled( int myPosition, final String dict )
{ {
int code = DictLangCache.getDictLangCode( this, dict ); int code = DictLangCache.getDictLangCode( this, dict );
@ -457,6 +466,13 @@ public class DictsActivity extends ExpandableListActivity
m_delegate.showConfirmThen( msg, action ); m_delegate.showConfirmThen( msg, action );
} }
// SDCardWatcher.SDCardNotifiee interface
public void cardMounted()
{
mkListAdapter();
expandGroups();
}
private void deleteDict( String dict ) private void deleteDict( String dict )
{ {
GameUtils.deleteDict( this, dict ); GameUtils.deleteDict( this, dict );

View file

@ -40,7 +40,8 @@ public class DlgDelegate {
public static final int DIALOG_NOTAGAIN = 3; public static final int DIALOG_NOTAGAIN = 3;
public static final int CONFIRM_THEN = 4; public static final int CONFIRM_THEN = 4;
public static final int TEXT_OR_HTML_THEN = 5; public static final int TEXT_OR_HTML_THEN = 5;
public static final int DIALOG_LAST = TEXT_OR_HTML_THEN; public static final int DLG_DICTGONE = 6;
public static final int DIALOG_LAST = DLG_DICTGONE;
private int m_msgID; private int m_msgID;
private String m_msg; private String m_msg;
@ -78,6 +79,9 @@ public class DlgDelegate {
case TEXT_OR_HTML_THEN: case TEXT_OR_HTML_THEN:
dialog = createHtmlThenDialog(); dialog = createHtmlThenDialog();
break; break;
case DLG_DICTGONE:
dialog = createDictGoneDialog();
break;
} }
return dialog; return dialog;
} }
@ -141,6 +145,11 @@ public class DlgDelegate {
m_activity.showDialog( DIALOG_OKONLY ); m_activity.showDialog( DIALOG_OKONLY );
} }
public void showDictGoneFinish()
{
m_activity.showDialog( DLG_DICTGONE );
}
public void showAboutDialog() public void showAboutDialog()
{ {
m_activity.showDialog( DIALOG_ABOUT ); m_activity.showDialog( DIALOG_ABOUT );
@ -283,4 +292,23 @@ public class DlgDelegate {
.create(); .create();
} }
private Dialog createDictGoneDialog()
{
Utils.logf( "DlgDelegate.createDictGoneDialog() called" );
Dialog dialog;
dialog = new AlertDialog.Builder( m_activity )
.setTitle( R.string.no_dict_title )
.setMessage( R.string.no_dict_finish )
.setPositiveButton( R.string.button_close_game, null )
.create();
dialog.setOnDismissListener( new DialogInterface.OnDismissListener() {
public void onDismiss( DialogInterface di ) {
m_activity.finish();
}
} );
return dialog;
}
} }

View file

@ -396,88 +396,91 @@ public class GameConfig extends XWActivity
{ {
super.onResume(); super.onResume();
int gamePtr = XwJNI.initJNI();
m_giOrig = new CurGameInfo( this ); m_giOrig = new CurGameInfo( this );
// Lock in case we're going to config. We *could* re-get the // Lock in case we're going to config. We *could* re-get the
// lock once the user decides to make changes. PENDING. // lock once the user decides to make changes. PENDING.
m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock(); m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock();
GameUtils.loadMakeGame( this, gamePtr, m_giOrig, m_gameLock ); int gamePtr = GameUtils.loadMakeGame( this, m_giOrig, m_gameLock );
m_gameStarted = XwJNI.model_getNMoves( gamePtr ) > 0 if ( 0 == gamePtr ) {
|| XwJNI.comms_isConnected( gamePtr ); showDictGoneFinish();
if ( m_gameStarted ) {
if ( null == m_gameLockedCheck ) {
m_gameLockedCheck =
(CheckBox)findViewById( R.id.game_locked_check );
m_gameLockedCheck.setVisibility( View.VISIBLE );
m_gameLockedCheck.setChecked( true );
m_gameLockedCheck.setOnClickListener( this );
}
handleLockedChange();
}
m_gi = new CurGameInfo( this, m_giOrig );
m_carOrig = new CommsAddrRec( this );
if ( XwJNI.game_hasComms( gamePtr ) ) {
XwJNI.comms_getAddr( gamePtr, m_carOrig );
} else { } else {
String relayName = CommonPrefs.getDefaultRelayHost( this ); m_gameStarted = XwJNI.model_getNMoves( gamePtr ) > 0
int relayPort = CommonPrefs.getDefaultRelayPort( this ); || XwJNI.comms_isConnected( gamePtr );
XwJNI.comms_getInitialAddr( m_carOrig, relayName, relayPort );
}
XwJNI.game_dispose( gamePtr );
m_car = new CommsAddrRec( m_carOrig ); if ( m_gameStarted ) {
if ( null == m_gameLockedCheck ) {
m_notNetworkedGame = DeviceRole.SERVER_STANDALONE == m_gi.serverRole; m_gameLockedCheck =
setTitle(); (CheckBox)findViewById( R.id.game_locked_check );
m_gameLockedCheck.setVisibility( View.VISIBLE );
if ( !m_notNetworkedGame ) { m_gameLockedCheck.setChecked( true );
m_joinPublicCheck = m_gameLockedCheck.setOnClickListener( this );
(CheckBox)findViewById(R.id.join_public_room_check);
m_joinPublicCheck.setOnClickListener( this );
m_joinPublicCheck.setChecked( m_car.ip_relay_seeksPublicRoom );
Utils.setChecked( this, R.id.advertise_new_room_check,
m_car.ip_relay_advertiseRoom );
m_publicRoomsSet =
(LinearLayout)findViewById(R.id.public_rooms_set );
m_privateRoomsSet =
(LinearLayout)findViewById(R.id.private_rooms_set );
Utils.setText( this, R.id.room_edit, m_car.ip_relay_invite );
m_roomChoose = (Spinner)findViewById( R.id.room_spinner );
m_refreshRoomsButton =
(ImageButton)findViewById( R.id.refresh_button );
m_refreshRoomsButton.setOnClickListener( this );
adjustConnectStuff();
}
loadPlayers();
configLangSpinner();
m_phoniesSpinner.setSelection( m_gi.phoniesAction.ordinal() );
setSmartnessSpinner();
Utils.setChecked( this, R.id.hints_allowed, !m_gi.hintsNotAllowed );
Utils.setInt( this, R.id.timer_minutes_edit,
m_gi.gameSeconds/60/m_gi.nPlayers );
CheckBox check = (CheckBox)findViewById( R.id.use_timer );
CompoundButton.OnCheckedChangeListener lstnr =
new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged( CompoundButton buttonView,
boolean checked ) {
View view = findViewById( R.id.timer_set );
view.setVisibility( checked ? View.VISIBLE : View.GONE );
} }
}; handleLockedChange();
check.setOnCheckedChangeListener( lstnr ); }
Utils.setChecked( this, R.id.use_timer, m_gi.timerEnabled );
m_gi = new CurGameInfo( this, m_giOrig );
m_carOrig = new CommsAddrRec( this );
if ( XwJNI.game_hasComms( gamePtr ) ) {
XwJNI.comms_getAddr( gamePtr, m_carOrig );
} else {
String relayName = CommonPrefs.getDefaultRelayHost( this );
int relayPort = CommonPrefs.getDefaultRelayPort( this );
XwJNI.comms_getInitialAddr( m_carOrig, relayName, relayPort );
}
XwJNI.game_dispose( gamePtr );
m_car = new CommsAddrRec( m_carOrig );
m_notNetworkedGame = DeviceRole.SERVER_STANDALONE == m_gi.serverRole;
setTitle();
if ( !m_notNetworkedGame ) {
m_joinPublicCheck =
(CheckBox)findViewById(R.id.join_public_room_check);
m_joinPublicCheck.setOnClickListener( this );
m_joinPublicCheck.setChecked( m_car.ip_relay_seeksPublicRoom );
Utils.setChecked( this, R.id.advertise_new_room_check,
m_car.ip_relay_advertiseRoom );
m_publicRoomsSet =
(LinearLayout)findViewById(R.id.public_rooms_set );
m_privateRoomsSet =
(LinearLayout)findViewById(R.id.private_rooms_set );
Utils.setText( this, R.id.room_edit, m_car.ip_relay_invite );
m_roomChoose = (Spinner)findViewById( R.id.room_spinner );
m_refreshRoomsButton =
(ImageButton)findViewById( R.id.refresh_button );
m_refreshRoomsButton.setOnClickListener( this );
adjustConnectStuff();
}
loadPlayers();
configLangSpinner();
m_phoniesSpinner.setSelection( m_gi.phoniesAction.ordinal() );
setSmartnessSpinner();
Utils.setChecked( this, R.id.hints_allowed, !m_gi.hintsNotAllowed );
Utils.setInt( this, R.id.timer_minutes_edit,
m_gi.gameSeconds/60/m_gi.nPlayers );
CheckBox check = (CheckBox)findViewById( R.id.use_timer );
CompoundButton.OnCheckedChangeListener lstnr =
new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged( CompoundButton buttonView,
boolean checked ) {
View view = findViewById( R.id.timer_set );
view.setVisibility( checked ? View.VISIBLE : View.GONE );
}
};
check.setOnCheckedChangeListener( lstnr );
Utils.setChecked( this, R.id.use_timer, m_gi.timerEnabled );
}
} // onResume } // onResume
@Override @Override

View file

@ -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,15 +196,14 @@ 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();
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
CommsAddrRec addr = null; CommsAddrRec addr = null;
// loadMakeGame, if makinga new game, will add comms as long // loadMakeGame, if makinga new game, will add comms as long
// as DeviceRole.SERVER_STANDALONE != gi.serverRole // as DeviceRole.SERVER_STANDALONE != gi.serverRole
loadMakeGame( context, gamePtr, gi, lockSrc ); int gamePtr = loadMakeGame( context, gi, lockSrc );
String[] dictNames = gi.dictNames(); String[] dictNames = gi.dictNames();
DictPairs pairs = openDicts( context, dictNames ); DictPairs pairs = openDicts( context, dictNames );
@ -266,9 +281,8 @@ public class GameUtils {
public static GameSummary summarize( Context context, GameLock lock ) public static GameSummary summarize( Context context, GameLock lock )
{ {
int gamePtr = XwJNI.initJNI();
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
loadMakeGame( context, gamePtr, gi, lock ); int gamePtr = loadMakeGame( context, gi, lock );
return summarizeAndClose( context, lock, gamePtr, gi ); return summarizeAndClose( context, lock, gamePtr, gi );
} }
@ -305,33 +319,41 @@ public class GameUtils {
return result; return result;
} }
public static void loadMakeGame( Context context, int gamePtr, public static int loadMakeGame( Context context, CurGameInfo gi,
CurGameInfo gi, GameLock lock ) GameLock lock )
{ {
loadMakeGame( context, gamePtr, gi, null, null, lock ); return loadMakeGame( context, gi, null, null, lock );
} }
public static void loadMakeGame( Context context, int gamePtr, public static int loadMakeGame( Context context, CurGameInfo gi,
CurGameInfo gi, UtilCtxt util, UtilCtxt util, TransportProcs tp,
TransportProcs tp, GameLock lock ) GameLock lock )
{ {
int gamePtr = 0;
byte[] stream = savedGame( context, lock ); byte[] stream = savedGame( context, lock );
XwJNI.gi_from_stream( gi, stream ); XwJNI.gi_from_stream( gi, stream );
String[] dictNames = gi.dictNames(); String[] dictNames = gi.dictNames();
DictPairs pairs = openDicts( context, dictNames ); DictPairs pairs = openDicts( context, dictNames );
String langName = gi.langName(); if ( pairs.anyMissing( dictNames ) ) {
Utils.logf( "loadMakeGame() failing: dict unavailable" );
} else {
gamePtr = XwJNI.initJNI();
boolean madeGame = XwJNI.game_makeFromStream( gamePtr, stream, gi, String langName = gi.langName();
dictNames, pairs.m_bytes, boolean madeGame = XwJNI.game_makeFromStream( gamePtr, stream, gi,
pairs.m_paths, langName, dictNames, pairs.m_bytes,
util, JNIUtilsImpl.get(), pairs.m_paths, langName,
CommonPrefs.get(context), util, JNIUtilsImpl.get(),
tp ); CommonPrefs.get(context),
if ( !madeGame ) { tp);
XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get(), if ( !madeGame ) {
CommonPrefs.get(context), dictNames, XwJNI.game_makeNewGame( gamePtr, gi, JNIUtilsImpl.get(),
pairs.m_bytes, pairs.m_paths, langName ); CommonPrefs.get(context), dictNames,
pairs.m_bytes, pairs.m_paths, langName );
}
} }
return gamePtr;
} }
public static long saveGame( Context context, int gamePtr, public static long saveGame( Context context, int gamePtr,
@ -718,7 +740,7 @@ public class GameUtils {
File file = context.getFileStreamPath( name ); File file = context.getFileStreamPath( name );
if ( !file.exists() ) { if ( !file.exists() ) {
file = getSDPathFor( context, name ); file = getSDPathFor( context, name );
if ( !file.exists() ) { if ( null != file && !file.exists() ) {
file = null; file = null;
} }
} }
@ -856,13 +878,12 @@ public class GameUtils {
boolean draw = false; boolean draw = false;
long rowid = DBUtils.getRowIDFor( context, relayID ); long rowid = DBUtils.getRowIDFor( context, relayID );
if ( -1 != rowid ) { if ( -1 != rowid ) {
int gamePtr = XwJNI.initJNI();
CurGameInfo gi = new CurGameInfo( context ); CurGameInfo gi = new CurGameInfo( context );
FeedUtilsImpl feedImpl = new FeedUtilsImpl( context, rowid ); FeedUtilsImpl feedImpl = new FeedUtilsImpl( context, rowid );
GameLock lock = new GameLock( rowid, true ); GameLock lock = new GameLock( rowid, true );
if ( lock.tryLock() ) { if ( lock.tryLock() ) {
loadMakeGame( context, gamePtr, gi, feedImpl, sink, lock ); int gamePtr = loadMakeGame( context, gi, feedImpl, sink, lock );
XwJNI.comms_resendAll( gamePtr ); XwJNI.comms_resendAll( gamePtr );
if ( null != msgs ) { if ( null != msgs ) {
@ -902,7 +923,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 );

View file

@ -97,14 +97,16 @@ public class GamesList extends XWListActivity
} }
}; };
String message; String message;
String langName = DictLangCache.getLangName( this, String langName =
m_missingDictLang ); DictLangCache.getLangName( this, m_missingDictLang );
String gameName = GameUtils.getName( this, m_rowid );
if ( WARN_NODICT == id ) { if ( WARN_NODICT == id ) {
message = String.format( getString(R.string.no_dictf), message = String.format( getString( R.string.no_dictf ),
langName ); gameName, langName );
} else { } else {
message = String.format( getString(R.string.no_dict_substf), message = String.format( getString(R.string.no_dict_substf),
m_missingDictNames[0], langName ); gameName, m_missingDictNames[0],
langName );
} }
ab = new AlertDialog.Builder( this ) ab = new AlertDialog.Builder( this )
@ -127,24 +129,26 @@ public class GamesList extends XWListActivity
case SHOW_SUBST: case SHOW_SUBST:
m_sameLangDicts = m_sameLangDicts =
DictLangCache.getHaveLangCounts( this, m_missingDictLang ); DictLangCache.getHaveLangCounts( this, m_missingDictLang );
ab = new AlertDialog.Builder( this ) lstnr = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dlg,
int which ) {
int pos = ((AlertDialog)dlg).getListView().
getCheckedItemPosition();
String dict = m_sameLangDicts[pos];
dict = DictLangCache.stripCount( dict );
GameUtils.replaceDicts( GamesList.this,
m_missingDictRowId,
m_missingDictNames[0],
dict );
}
};
dialog = new AlertDialog.Builder( this )
.setTitle( R.string.subst_dict_title ) .setTitle( R.string.subst_dict_title )
.setPositiveButton( R.string.button_substdict, lstnr )
.setNegativeButton( R.string.button_cancel, null ) .setNegativeButton( R.string.button_cancel, null )
.setItems( m_sameLangDicts, .setSingleChoiceItems( m_sameLangDicts, 0, null )
new DialogInterface.OnClickListener() { .create();
public void onClick( DialogInterface dlg,
int which ) {
String dict = m_sameLangDicts[which];
dict = DictLangCache.stripCount( dict );
GameUtils.
replaceDicts( GamesList.this,
m_missingDictRowId,
m_missingDictNames[0],
dict );
}
})
; ;
dialog = ab.create();
// Force destruction so onCreateDialog() will get // Force destruction so onCreateDialog() will get
// called next time and we can insert a different // called next time and we can insert a different
// list. There seems to be no way to change the list // list. There seems to be no way to change the list

View file

@ -67,10 +67,9 @@ public class RelayGameActivity extends XWActivity
{ {
super.onStart(); super.onStart();
int gamePtr = XwJNI.initJNI();
m_gi = new CurGameInfo( this ); m_gi = new CurGameInfo( this );
m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock(); m_gameLock = new GameUtils.GameLock( m_rowid, true ).lock();
GameUtils.loadMakeGame( this, gamePtr, m_gi, m_gameLock ); int gamePtr = GameUtils.loadMakeGame( this, m_gi, m_gameLock );
m_car = new CommsAddrRec( this ); m_car = new CommsAddrRec( this );
if ( XwJNI.game_hasComms( gamePtr ) ) { if ( XwJNI.game_hasComms( gamePtr ) ) {
XwJNI.comms_getAddr( gamePtr, m_car ); XwJNI.comms_getAddr( gamePtr, m_car );

View file

@ -0,0 +1,68 @@
/* -*- 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.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
public class SDCardWatcher {
public interface SDCardNotifiee {
void cardMounted();
}
private UmountReceiver m_rcvr;
private Context m_context;
private SDCardNotifiee m_notifiee;
private class UmountReceiver extends BroadcastReceiver {
@Override
public void onReceive( Context context, Intent intent )
{
if ( intent.getAction().
equals( Intent.ACTION_MEDIA_MOUNTED ) ) {
m_notifiee.cardMounted();
}
}
}
public SDCardWatcher( Context context, SDCardNotifiee notifiee )
{
m_context = context;
m_rcvr = new UmountReceiver();
m_notifiee = notifiee;
IntentFilter filter =
new IntentFilter( Intent.ACTION_MEDIA_MOUNTED );
// filter.addAction( Intent.ACTION_MEDIA_UNMOUNTED );
// filter.addAction( Intent.ACTION_MEDIA_EJECT );
filter.addDataScheme( "file" );
/*Intent intent = */context.getApplicationContext().
registerReceiver( m_rcvr, filter );
}
public void close()
{
m_context.getApplicationContext().unregisterReceiver( m_rcvr );
}
}

View file

@ -36,6 +36,7 @@ public class XWActivity extends Activity {
private DlgDelegate m_delegate; private DlgDelegate m_delegate;
@Override
protected void onCreate( Bundle savedInstanceState ) protected void onCreate( Bundle savedInstanceState )
{ {
Utils.logf( "%s.onCreate(this=%H)", getClass().getName(), this ); Utils.logf( "%s.onCreate(this=%H)", getClass().getName(), this );
@ -84,10 +85,10 @@ public class XWActivity extends Activity {
@Override @Override
protected Dialog onCreateDialog( int id ) protected Dialog onCreateDialog( int id )
{ {
Utils.logf( "%s.onCreateDialog() called", getClass().getName() ); Dialog dialog = super.onCreateDialog( id );
Dialog dialog = m_delegate.onCreateDialog( id ); if ( null == dialog ) {
if ( null != dialog ) { Utils.logf( "%s.onCreateDialog() called", getClass().getName() );
setRemoveOnDismiss( dialog, id ); dialog = m_delegate.onCreateDialog( id );
} }
return dialog; return dialog;
} }
@ -100,6 +101,7 @@ public class XWActivity extends Activity {
@Override @Override
protected void onPrepareDialog( int id, Dialog dialog ) protected void onPrepareDialog( int id, Dialog dialog )
{ {
super.onPrepareDialog( id, dialog ); // docs say should call through
m_delegate.onPrepareDialog( id, dialog ); m_delegate.onPrepareDialog( id, dialog );
} }
@ -121,6 +123,11 @@ public class XWActivity extends Activity {
m_delegate.showOKOnlyDialog( msgID ); m_delegate.showOKOnlyDialog( msgID );
} }
protected void showDictGoneFinish()
{
m_delegate.showDictGoneFinish();
}
protected void showConfirmThen( int msgID, protected void showConfirmThen( int msgID,
DialogInterface.OnClickListener action ) DialogInterface.OnClickListener action )
{ {

View file

@ -106,6 +106,7 @@ public class XWListActivity extends ListActivity {
@Override @Override
protected void onPrepareDialog( int id, Dialog dialog ) protected void onPrepareDialog( int id, Dialog dialog )
{ {
super.onPrepareDialog( id, dialog );
m_delegate.onPrepareDialog( id, dialog ); m_delegate.onPrepareDialog( id, dialog );
} }

View file

@ -61,6 +61,7 @@ void
stack_setBitsPerTile( StackCtxt* stack, XP_U16 bitsPerTile ) stack_setBitsPerTile( StackCtxt* stack, XP_U16 bitsPerTile )
{ {
XP_ASSERT( !!stack ); XP_ASSERT( !!stack );
XP_ASSERT( bitsPerTile == 5 || bitsPerTile == 6 );
stack->bitsPerTile = bitsPerTile; stack->bitsPerTile = bitsPerTile;
} }

View file

@ -225,11 +225,17 @@ close_device() {
unset ROOMS[$ID] unset ROOMS[$ID]
} }
OBITS=""
kill_from_log() { kill_from_log() {
LOG=$1 LOG=$1
RELAYID=$(./scripts/relayID.sh --long $LOG) RELAYID=$(./scripts/relayID.sh --long $LOG)
if [ -n "$RELAYID" ]; then if [ -n "$RELAYID" ]; then
../relay/rq -a $HOST -d $RELAYID 2>/dev/null || true OBITS="$OBITS -d $RELAYID"
if [ 0 -eq $(($RANDOM%2)) ]; then
../relay/rq -a $HOST $OBITS 2>/dev/null || true
OBITS=""
fi
return 0 # success return 0 # success
fi fi
echo "unable to send kill command for $LOG" echo "unable to send kill command for $LOG"
@ -281,10 +287,15 @@ check_game() {
close_device $ID $DONEDIR "game over" close_device $ID $DONEDIR "game over"
done done
date date
# XWRELAY_ERROR_DELETED may be old
elif grep -q 'relay_error_curses(XWRELAY_ERROR_DELETED)' $LOG; then elif grep -q 'relay_error_curses(XWRELAY_ERROR_DELETED)' $LOG; then
echo "deleting $LOG $(connName $LOG) b/c another resigned" echo "deleting $LOG $(connName $LOG) b/c another resigned"
kill_from_log $LOG || true kill_from_log $LOG || true
close_device $KEY $DEADDIR "other resigned" close_device $KEY $DEADDIR "other resigned"
elif grep -q 'relay_error_curses(XWRELAY_ERROR_DEADGAME)' $LOG; then
echo "deleting $LOG $(connName $LOG) b/c another resigned"
kill_from_log $LOG || true
close_device $KEY $DEADDIR "other resigned"
else else
maybe_resign $KEY maybe_resign $KEY
fi fi
@ -334,6 +345,8 @@ run_cmds() {
fi fi
done done
[ -n "$OBITS" ] && ../relay/rq -a $HOST $OBITS 2>/dev/null || true
# kill any remaining games # kill any remaining games
if [ $COUNT -gt 0 ]; then if [ $COUNT -gt 0 ]; then
mkdir -p ${LOGDIR}/not_done mkdir -p ${LOGDIR}/not_done