When receiving an invite for a dict we don't have, post a notification

to DictsActivity that offers to download, and on download completion
arranges for notification of SMSService so the game can be created.
This commit is contained in:
Eric House 2012-10-17 21:20:08 -07:00
parent 3e83af3b97
commit e5feded0b1
4 changed files with 209 additions and 59 deletions

View file

@ -2128,4 +2128,14 @@
<string name="inform_dict_phonies">\u0020(Remember that phonies
will be discarded based on the host\'s wordlist.)</string>
<string name="missing_dict_title">Game invitation pending</string>
<string name="missing_dict_detail">Required wordlist missing</string>
<string name="invite_dict_missing_title">Missing wordlist</string>
<string name="invite_dict_missing_bodyf">%1$s has invited you to
play Crosswords using the wordlist %2$s (for play in %3$s), but it
is not installed. Would you like to download the wordlist or
decline the invitation?</string>
<string name="button_decline">Decline</string>
</resources>

View file

@ -78,6 +78,7 @@ public class DictsActivity extends ExpandableListActivity
private static final int PICK_STORAGE = DlgDelegate.DIALOG_LAST + 1;
private static final int MOVE_DICT = DlgDelegate.DIALOG_LAST + 2;
private static final int SET_DEFAULT = DlgDelegate.DIALOG_LAST + 3;
private static final int DICT_OR_DECLINE = DlgDelegate.DIALOG_LAST + 4;
private int m_lang = 0;
private String[] m_langs;
private String m_name = null;
@ -92,6 +93,7 @@ public class DictsActivity extends ExpandableListActivity
private DictUtils.DictLoc m_moveFromLoc;
private int m_moveFromItem;
private int m_moveToItm;
private boolean m_launchedForMissing = false;
private LayoutInflater m_factory;
@ -248,7 +250,7 @@ public class DictsActivity extends ExpandableListActivity
@Override
protected Dialog onCreateDialog( int id )
{
OnClickListener lstnr;
OnClickListener lstnr, lstnr2;
Dialog dialog;
String format;
String message;
@ -349,6 +351,27 @@ public class DictsActivity extends ExpandableListActivity
.setNegativeButton( R.string.button_default_both, lstnr )
.create();
break;
case DICT_OR_DECLINE:
lstnr = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) {
Intent intent = getIntent();
int lang = intent.getIntExtra( MultiService.LANG, -1 );
String name = intent.getStringExtra( MultiService.DICT );
m_launchedForMissing = true;
askStartDownload( lang, name );
}
};
lstnr2 = new OnClickListener() {
public void onClick( DialogInterface dlg, int item ) {
finish();
}
};
dialog = MultiService.missingDictDialog( this, getIntent(),
lstnr, lstnr2 );
break;
default:
dialog = m_delegate.onCreateDialog( id );
doRemove = false;
@ -413,14 +436,18 @@ public class DictsActivity extends ExpandableListActivity
Intent intent = getIntent();
if ( null != intent ) {
boolean downloadNow = intent.getBooleanExtra( DICT_DOLAUNCH, false );
if ( downloadNow ) {
int lang = intent.getIntExtra( DICT_LANG_EXTRA, 0 );
String name = intent.getStringExtra( DICT_NAME_EXTRA );
askStartDownload( lang, name );
}
if ( MultiService.isMissingDictIntent( intent ) ) {
showDialog( DICT_OR_DECLINE );
} else {
boolean downloadNow = intent.getBooleanExtra( DICT_DOLAUNCH, false );
if ( downloadNow ) {
int lang = intent.getIntExtra( DICT_LANG_EXTRA, 0 );
String name = intent.getStringExtra( DICT_NAME_EXTRA );
askStartDownload( lang, name );
}
downloadNewDict( intent );
downloadNewDict( intent );
}
}
}
@ -543,6 +570,18 @@ public class DictsActivity extends ExpandableListActivity
return handled;
}
@Override
public void onWindowFocusChanged( boolean hasFocus )
{
super.onWindowFocusChanged( hasFocus );
if ( hasFocus && m_launchedForMissing ) {
Intent intent = getIntent();
if ( MultiService.returnOnDownload( this, intent ) ) {
finish();
}
}
}
private void downloadNewDict( Intent intent )
{
String url = intent.getStringExtra( UpdateCheckReceiver.NEW_DICT_URL );
@ -673,19 +712,21 @@ public class DictsActivity extends ExpandableListActivity
private void startDownload( String url, boolean toSD )
{
DictImportActivity.setUseSD( toSD );
try {
startActivity( mkDownloadIntent( this, url ) );
} catch ( android.content.ActivityNotFoundException anfe ) {
Toast.makeText( this, R.string.no_download_warning,
Toast.LENGTH_SHORT).show();
}
Intent intent = mkDownloadIntent( this, url );
startDownload( intent );
}
private void startDownload( int lang, String name, boolean toSD )
{
DictImportActivity.setUseSD( toSD );
Intent intent = mkDownloadIntent( this, lang, name );
startDownload( intent );
}
private void startDownload( Intent downloadIntent )
{
try {
startActivity( mkDownloadIntent( this, lang, name ) );
startActivity( downloadIntent );
} catch ( android.content.ActivityNotFoundException anfe ) {
Toast.makeText( this, R.string.no_download_warning,
Toast.LENGTH_SHORT).show();

View file

@ -20,8 +20,25 @@
package org.eehouse.android.xw4;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
public class MultiService {
public static final String LANG = "LANG";
public static final String DICT = "DICT";
public static final String GAMEID = "GAMEID";
public static final String GAMENAME = "GAMENAME";
public static final String NPLAYERST = "NPLAYERST";
public static final String NPLAYERSH = "NPLAYERSH";
public static final String INVITER = "INVITER";
public static final String OWNER = "OWNER";
public static final int OWNER_SMS = 1;
private BTEventListener m_li;
public enum MultiEvent { BAD_PROTO
@ -67,4 +84,54 @@ public class MultiService {
}
}
public static boolean isMissingDictIntent( Intent intent )
{
return intent.hasExtra( LANG )
&& intent.hasExtra( DICT )
&& intent.hasExtra( GAMEID )
&& intent.hasExtra( GAMENAME )
&& intent.hasExtra( NPLAYERST )
&& intent.hasExtra( NPLAYERSH );
}
public static Dialog missingDictDialog( Context context, Intent intent,
OnClickListener onDownload,
OnClickListener onDecline )
{
int lang = intent.getIntExtra( LANG, -1 );
String langStr = DictLangCache.getLangName( context, lang );
String dict = intent.getStringExtra( DICT );
String inviter = intent.getStringExtra( INVITER );
String msg = context.getString( R.string.invite_dict_missing_bodyf,
inviter, dict, langStr );
return new AlertDialog.Builder( context )
.setTitle( R.string.invite_dict_missing_title )
.setMessage( msg)
.setPositiveButton( R.string.button_download, onDownload )
.setNegativeButton( R.string.button_decline, onDecline )
.create();
}
// resend the intent, but only if the dict it names is here. (If
// it's not, we may need to try again later, e.g. because our cue
// was a focus gain.)
static boolean returnOnDownload( Context context, Intent intent )
{
boolean downloaded = isMissingDictIntent( intent );
if ( downloaded ) {
int lang = intent.getIntExtra( LANG, -1 );
String dict = intent.getStringExtra( DICT );
downloaded = DictLangCache.haveDict( context, lang, dict );
if ( downloaded ) {
int owner = intent.getIntExtra( OWNER, -1 );
if ( owner == OWNER_SMS ) {
SMSService.onGameDictDownload( context, intent );
} else {
DbgUtils.logf( "unexpected OWNER: %d", owner );
}
}
}
return downloaded;
}
}

View file

@ -67,17 +67,12 @@ public class SMSService extends Service {
private static final int REMOVE = 4;
private static final int MESG_GAMEGONE = 5;
private static final int CHECK_MSGDB = 6;
private static final int ADDED_MISSING = 7;
private static final String CMD_STR = "CMD";
private static final String BUFFER = "BUFFER";
private static final String BINBUFFER = "BINBUFFER";
private static final String PHONE = "PHONE";
private static final String GAMEID = "GAMEID";
private static final String GAMENAME = "GAMENAME";
private static final String LANG = "LANG";
private static final String DICT = "DICT";
private static final String NPLAYERST = "NPLAYERST";
private static final String NPLAYERSH = "NPLAYERSH";
private static Boolean s_showToasts = null;
private static MultiService s_srcMgr = null;
@ -120,13 +115,8 @@ public class SMSService extends Service {
int nPlayersT, int nPlayersH )
{
Intent intent = getIntentTo( context, INVITE );
intent.putExtra( PHONE, phone );
intent.putExtra( GAMEID, gameID );
intent.putExtra( GAMENAME, gameName );
intent.putExtra( LANG, lang );
intent.putExtra( DICT, dict );
intent.putExtra( NPLAYERST, nPlayersT );
intent.putExtra( NPLAYERSH, nPlayersH );
fillInviteIntent( intent, phone, gameID, gameName, lang, dict,
nPlayersT, nPlayersH );
context.startService( intent );
}
@ -137,7 +127,7 @@ public class SMSService extends Service {
if ( XWPrefs.getSMSEnabled( context ) ) {
Intent intent = getIntentTo( context, SEND );
intent.putExtra( PHONE, phone );
intent.putExtra( GAMEID, gameID );
intent.putExtra( MultiService.GAMEID, gameID );
intent.putExtra( BINBUFFER, binmsg );
context.startService( intent );
nSent = binmsg.length;
@ -151,7 +141,14 @@ public class SMSService extends Service {
{
Intent intent = getIntentTo( context, REMOVE );
intent.putExtra( PHONE, phone );
intent.putExtra( GAMEID, gameID );
intent.putExtra( MultiService.GAMEID, gameID );
context.startService( intent );
}
public static void onGameDictDownload( Context context, Intent intentOld )
{
Intent intent = getIntentTo( context, ADDED_MISSING );
intent.fillIn( intentOld, 0 );
context.startService( intent );
}
@ -257,24 +254,30 @@ public class SMSService extends Service {
receiveBuffer( buffer, phone );
break;
case INVITE:
case ADDED_MISSING:
phone = intent.getStringExtra( PHONE );
int gameID = intent.getIntExtra( GAMEID, -1 );
String gameName = intent.getStringExtra( GAMENAME );
int lang = intent.getIntExtra( LANG, -1 );
String dict = intent.getStringExtra( DICT );
int nPlayersT = intent.getIntExtra( NPLAYERST, -1 );
int nPlayersH = intent.getIntExtra( NPLAYERSH, -1 );
inviteRemote( phone, gameID, gameName, lang, dict,
nPlayersT, nPlayersH );
int gameID = intent.getIntExtra( MultiService.GAMEID, -1 );
String gameName = intent.getStringExtra( MultiService.GAMENAME );
int lang = intent.getIntExtra( MultiService.LANG, -1 );
String dict = intent.getStringExtra( MultiService.DICT );
int nPlayersT = intent.getIntExtra( MultiService.NPLAYERST, -1 );
int nPlayersH = intent.getIntExtra( MultiService.NPLAYERSH, -1 );
if ( INVITE == cmd ) {
inviteRemote( phone, gameID, gameName, lang, dict,
nPlayersT, nPlayersH );
} else if ( ADDED_MISSING == cmd ) {
makeForInvite( phone, gameID, gameName, lang, dict,
nPlayersT, nPlayersH );
}
break;
case SEND:
phone = intent.getStringExtra( PHONE );
byte[] bytes = intent.getByteArrayExtra( BINBUFFER );
gameID = intent.getIntExtra( GAMEID, -1 );
gameID = intent.getIntExtra( MultiService.GAMEID, -1 );
sendPacket( phone, gameID, bytes );
break;
case REMOVE:
gameID = intent.getIntExtra( GAMEID, -1 );
gameID = intent.getIntExtra( MultiService.GAMEID, -1 );
phone = intent.getStringExtra( PHONE );
sendDiedPacket( phone, gameID );
break;
@ -406,7 +409,6 @@ public class SMSService extends Service {
private void receive( SMS_CMD cmd, byte[] data, String phone )
{
CommsAddrRec addr = new CommsAddrRec( phone );
DataInputStream dis =
new DataInputStream( new ByteArrayInputStream(data) );
try {
@ -420,31 +422,27 @@ public class SMSService extends Service {
int nPlayersH = dis.readByte();
if ( DictLangCache.haveDict( this, lang, dict ) ) {
long rowid =
GameUtils.makeNewSMSGame( this, gameID, addr, lang,
dict, nPlayersT, nPlayersH );
if ( null != gameName && 0 < gameName.length() ) {
DBUtils.setName( this, rowid, gameName );
}
String owner = Utils.phoneToContact( this, phone, true );
String body = Utils.format( this, R.string.new_name_bodyf,
owner );
postNotification( gameID, R.string.new_sms_title, body );
ackInvite( phone, gameID );
makeForInvite( phone, gameID, gameName, lang, dict,
nPlayersT, nPlayersH );
} else {
// PENDING: post notification so user can choose
// to download or delete.
DbgUtils.showf( this, "Dropping invite for missing dict %s",
dict );
Intent intent = new Intent( this, DictsActivity.class );
fillInviteIntent( intent, phone, gameID, gameName, lang, dict,
nPlayersT, nPlayersH );
intent.putExtra( MultiService.OWNER,
MultiService.OWNER_SMS );
intent.putExtra( MultiService.INVITER,
Utils.phoneToContact( this, phone, true ) );
Utils.postNotification( this, intent,
R.string.missing_dict_title,
R.string.missing_dict_detail,
gameID );
}
break;
case DATA:
gameID = dis.readInt();
byte[] rest = new byte[dis.available()];
dis.read( rest );
feedMessage( gameID, rest, addr );
feedMessage( gameID, rest, new CommsAddrRec( phone ) );
break;
case DEATH:
gameID = dis.readInt();
@ -532,6 +530,26 @@ public class SMSService extends Service {
}
}
private void makeForInvite( String phone, int gameID, String gameName,
int lang, String dict, int nPlayersT,
int nPlayersH )
{
long rowid =
GameUtils.makeNewSMSGame( this, gameID,
new CommsAddrRec( phone ),
lang, dict, nPlayersT, nPlayersH );
if ( null != gameName && 0 < gameName.length() ) {
DBUtils.setName( this, rowid, gameName );
}
String owner = Utils.phoneToContact( this, phone, true );
String body = Utils.format( this, R.string.new_name_bodyf,
owner );
postNotification( gameID, R.string.new_sms_title, body );
ackInvite( phone, gameID );
}
private PendingIntent makeStatusIntent( String msg )
{
Intent intent = new Intent( msg );
@ -567,6 +585,20 @@ public class SMSService extends Service {
return success;
}
private static void fillInviteIntent( Intent intent, String phone,
int gameID, String gameName,
int lang, String dict,
int nPlayersT, int nPlayersH )
{
intent.putExtra( PHONE, phone );
intent.putExtra( MultiService.GAMEID, gameID );
intent.putExtra( MultiService.GAMENAME, gameName );
intent.putExtra( MultiService.LANG, lang );
intent.putExtra( MultiService.DICT, dict );
intent.putExtra( MultiService.NPLAYERST, nPlayersT );
intent.putExtra( MultiService.NPLAYERSH, nPlayersH );
}
private void feedMessage( int gameID, byte[] msg, CommsAddrRec addr )
{
long[] rowids = DBUtils.getRowIDsFor( this, gameID );