diff --git a/xwords4/android/app/src/main/AndroidManifest.xml b/xwords4/android/app/src/main/AndroidManifest.xml
index db24701c9..ef8e0f2d7 100644
--- a/xwords4/android/app/src/main/AndroidManifest.xml
+++ b/xwords4/android/app/src/main/AndroidManifest.xml
@@ -25,6 +25,7 @@
+
@@ -189,6 +190,7 @@
/>
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java
index f0277f0c7..4b984958a 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/BTService.java
@@ -191,6 +191,7 @@ public class BTService extends XWService {
private BTSenderThread m_sender;
private Notification m_notification; // make once use many
private Handler mHandler;
+ private BTServiceHelper mHelper;
private static int s_errCount = 0;
@@ -418,6 +419,8 @@ public class BTService extends XWService {
Log.d( TAG, "%s.onCreate()", this );
super.onCreate();
+ mHelper = new BTServiceHelper( this );
+
m_btMsgSink = new BTMsgSink();
mHandler = new Handler();
startForegroundIf();
@@ -522,7 +525,7 @@ public class BTService extends XWService {
boolean cameOn = intent.getBooleanExtra( RADIO_KEY, false );
MultiEvent evt = cameOn? MultiEvent.BT_ENABLED
: MultiEvent.BT_DISABLED;
- postEvent( evt );
+ mHelper.postEvent( evt );
if ( cameOn ) {
GameUtils.resendAllIf( this, CommsConnType.COMMS_CONN_BT );
} else {
@@ -581,6 +584,7 @@ public class BTService extends XWService {
private BluetoothServerSocket m_serverSocket;
private Context mContext;
private BTService mService;
+ private BTServiceHelper mHelper;
private volatile Thread mTimerThread;
private BTListenerThread( Context context, BTService service )
@@ -595,7 +599,8 @@ public class BTService extends XWService {
}
}
- static void startYourself( Context context, BTService service )
+ static void startYourself( Context context, BTService service,
+ BTServiceHelper helper )
{
Log.d( TAG, "startYourself(%s, %s)", context, service );
DbgUtils.assertOnUIThread();
@@ -604,7 +609,7 @@ public class BTService extends XWService {
s_listener[0] = new BTListenerThread( context, service );
s_listener[0].start();
} else if ( null != service ) {
- s_listener[0].setService( context, service );
+ s_listener[0].setService( context, service, helper );
}
}
}
@@ -612,7 +617,7 @@ public class BTService extends XWService {
static void startYourself( Context context )
{
DbgUtils.assertOnUIThread();
- startYourself( context, null );
+ startYourself( context, null, null );
}
static void stopYourself( BTListenerThread self )
@@ -634,11 +639,12 @@ public class BTService extends XWService {
}
}
- void setService( Context context, BTService service )
+ void setService( Context context, BTService service, BTServiceHelper helper )
{
if ( null == mService ) {
Log.d( TAG, "setService(): we didn't have one before. Do something!!!" );
mService = service;
+ mHelper = helper;
Assert.assertNotNull( context );
mContext = context; // Use Service instead of Receiver (possibly)
} else {
@@ -838,16 +844,16 @@ public class BTService extends XWService {
CommsAddrRec addr = new CommsAddrRec( host.getName(),
host.getAddress() );
- ReceiveResult rslt
- = mService.receiveMessage( mContext,
- gameID, mService.m_btMsgSink,
- buffer, addr );
+ XWServiceHelper.ReceiveResult rslt
+ = mHelper.receiveMessage( mContext,
+ gameID, mService.m_btMsgSink,
+ buffer, addr );
- result = rslt == ReceiveResult.GAME_GONE ?
+ result = rslt == XWServiceHelper.ReceiveResult.GAME_GONE ?
BTCmd.MESG_GAMEGONE : BTCmd.MESG_ACCPT;
break;
case MESG_GAMEGONE:
- mService.postEvent( MultiEvent.MESSAGE_NOGAME, gameID );
+ mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, gameID );
result = BTCmd.MESG_ACCPT;
break;
default:
@@ -977,7 +983,7 @@ public class BTService extends XWService {
addrs.add( dev );
}
if ( null != event ) {
- postEvent( event, dev.getName() );
+ mHelper.postEvent( event, dev.getName() );
}
}
} else {
@@ -1010,7 +1016,7 @@ public class BTService extends XWService {
} else {
gotReply = BTCmd.PONG == reply;
if ( gotReply && is.readBoolean() ) {
- postEvent( MultiEvent.MESSAGE_NOGAME, gameID );
+ mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, gameID );
}
}
@@ -1064,20 +1070,24 @@ public class BTService extends XWService {
}
if ( null == reply ) {
- postEvent( MultiEvent.APP_NOT_FOUND_BT, dev.getName() );
+ mHelper.postEvent( MultiEvent.APP_NOT_FOUND_BT,
+ dev.getName() );
} else {
switch ( reply ) {
case BAD_PROTO:
sendBadProto( socket );
break;
case INVITE_ACCPT:
- postEvent( MultiEvent.NEWGAME_SUCCESS, elem.m_gameID );
+ mHelper.postEvent( MultiEvent.NEWGAME_SUCCESS,
+ elem.m_gameID );
break;
case INVITE_DUPID:
- postEvent( MultiEvent.NEWGAME_DUP_REJECTED, dev.getName() );
+ mHelper.postEvent( MultiEvent.NEWGAME_DUP_REJECTED,
+ dev.getName() );
break;
default:
- postEvent( MultiEvent.NEWGAME_FAILURE, elem.m_gameID );
+ mHelper.postEvent( MultiEvent.NEWGAME_FAILURE,
+ elem.m_gameID );
break;
}
}
@@ -1160,10 +1170,10 @@ public class BTService extends XWService {
if ( null != evt ) {
String btName = nameForAddr( m_adapter, elem.m_btAddr );
- postEvent( evt, elem.m_gameID, 0, btName );
+ mHelper.postEvent( evt, elem.m_gameID, 0, btName );
if ( ! success ) {
int failCount = elem.incrFailCount();
- postEvent( MultiEvent.MESSAGE_RESEND, btName,
+ mHelper.postEvent( MultiEvent.MESSAGE_RESEND, btName,
RESEND_TIMEOUT, failCount );
}
}
@@ -1183,7 +1193,7 @@ public class BTService extends XWService {
iter.remove();
} else if ( elem.failCountExceeded() ) {
String btName = nameForAddr( m_adapter, elem.m_btAddr );
- postEvent( MultiEvent.MESSAGE_FAILOUT, btName );
+ mHelper.postEvent( MultiEvent.MESSAGE_FAILOUT, btName );
iter.remove();
}
}
@@ -1241,12 +1251,13 @@ public class BTService extends XWService {
btNames[ii] = nameForAddr( m_adapter, btAddrs[ii] );
++ii;
}
- postEvent( MultiEvent.SCAN_DONE, (Object)btAddrs, (Object)btNames );
+ mHelper.postEvent( MultiEvent.SCAN_DONE, (Object)btAddrs, (Object)btNames );
}
private void startListener()
{
- BTListenerThread.startYourself( this, this );
+ Assert.assertNotNull( mHelper );
+ BTListenerThread.startYourself( this, this, mHelper );
}
private void startSender()
@@ -1271,28 +1282,12 @@ public class BTService extends XWService {
m_sender = null;
}
- @Override
- void postNotification( String device, int gameID, long rowid )
- {
- String body = LocUtils.getString( this, R.string.new_bt_body_fmt,
- device );
-
- GameUtils.postInvitedNotification( this, gameID, body, rowid );
-
- postEvent( MultiEvent.BT_GAME_CREATED, rowid );
- }
-
- @Override
- MultiMsgSink getSink( long rowid )
- {
- return m_btMsgSink;
- }
-
private BTCmd makeOrNotify( NetLaunchInfo nli, String btName,
String btAddr )
{
BTCmd result;
- if ( handleInvitation( nli, btName, DictFetchOwner.OWNER_BT ) ) { // here
+ if ( mHelper.handleInvitation( nli, btName,
+ DictFetchOwner.OWNER_BT ) ) {
result = BTCmd.INVITE_ACCPT;
} else {
result = BTCmd.INVITE_DUP_INVITE; // dupe of rematch
@@ -1380,7 +1375,8 @@ public class BTService extends XWService {
private void sendBadProto( BluetoothSocket socket )
{
- postEvent( MultiEvent.BAD_PROTO_BT, socket.getRemoteDevice().getName() );
+ mHelper.postEvent( MultiEvent.BAD_PROTO_BT,
+ socket.getRemoteDevice().getName() );
}
private void updateStatusOut( boolean success )
@@ -1446,4 +1442,30 @@ public class BTService extends XWService {
return nSent;
}
}
+
+ private class BTServiceHelper extends XWServiceHelper {
+ private Service mService;
+
+ BTServiceHelper( Service service ) {
+ super( service );
+ mService = service;
+ }
+
+ @Override
+ MultiMsgSink getSink( long rowid )
+ {
+ return m_btMsgSink;
+ }
+
+ @Override
+ void postNotification( String device, int gameID, long rowid )
+ {
+ String body = LocUtils.getString( mService, R.string.new_bt_body_fmt,
+ device );
+
+ GameUtils.postInvitedNotification( mService, gameID, body, rowid );
+
+ postEvent( MultiEvent.BT_GAME_CREATED, rowid );
+ }
+ }
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java
index 18564462b..0bd011297 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/DelegateBase.java
@@ -143,14 +143,14 @@ public class DelegateBase implements DlgClickNotify,
protected void onResume()
{
m_isVisible = true;
- XWService.setListener( this );
+ XWServiceHelper.setListener( this );
runIfVisible();
}
protected void onPause()
{
m_isVisible = false;
- XWService.setListener( null );
+ XWServiceHelper.setListener( null );
}
protected DelegateBase curThis()
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
index 4934b75d5..14e8a0b78 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/RelayService.java
@@ -25,9 +25,9 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
+import android.support.v4.app.JobIntentService;
import android.text.TextUtils;
-
import org.eehouse.android.xw4.GameUtils.BackMoveResult;
import org.eehouse.android.xw4.MultiService.DictFetchOwner;
import org.eehouse.android.xw4.MultiService.MultiEvent;
@@ -62,7 +62,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
-public class RelayService extends XWService
+public class RelayService extends JobIntentService
implements NetStateCache.StateChangedIf {
private static final String TAG = RelayService.class.getSimpleName();
private static final int MAX_SEND = 1024;
@@ -121,6 +121,7 @@ public class RelayService extends XWService
private long m_lastGamePacketReceived;
private int m_nativeFailScore;
private boolean m_skipUPDSet;
+ private RelayServiceHelper mHelper;
private static DevIDType s_curType = DevIDType.ID_TYPE_NONE;
private static long s_regStartTime = 0;
@@ -221,20 +222,17 @@ public class RelayService extends XWService
public static void startService( Context context )
{
- Log.i( TAG, "startService()" );
Intent intent = getIntentTo( context, MsgCmds.UDP_CHANGED );
startService( context, intent );
}
+ // Must use the same lobID for all work enqueued for the same class
+ private final static int sJobID = RelayService.class.hashCode();
+
private static void startService( Context context, Intent intent )
{
- Log.d( TAG, "startService(%s)", intent );
-
- if ( inForeground() || Build.VERSION.SDK_INT < Build.VERSION_CODES.O ) {
- context.startService( intent );
- } else {
- Log.d( TAG, "startService(); not starting" );
- }
+ Log.d( TAG, "startService(%s) (calling enqueueWork())", intent );
+ enqueueWork( context, RelayService.class, sJobID, intent );
}
private static void stopService( Context context )
@@ -308,18 +306,11 @@ public class RelayService extends XWService
{
Log.d( TAG, "receiveInvitation: got nli from %d: %s", srcDevID,
nli.toString() );
- if ( !handleInvitation( nli, null, DictFetchOwner.OWNER_RELAY ) ) {
+ if ( !mHelper.handleInvitation( nli, null, DictFetchOwner.OWNER_RELAY ) ) {
Log.d( TAG, "handleInvitation() failed" );
}
}
- @Override
- void postNotification( String device, int gameID, long rowid )
- {
- String body = LocUtils.getString( this, R.string.new_relay_body );
- GameUtils.postInvitedNotification( this, gameID, body, rowid );
- }
-
// Exists to get incoming data onto the main thread
private static void postData( Context context, long rowid, byte[] msg )
{
@@ -364,16 +355,12 @@ public class RelayService extends XWService
return intent;
}
- @Override
- protected MultiMsgSink getSink( long rowid )
- {
- return new RelayMsgSink().setRowID( rowid );
- }
-
@Override
public void onCreate()
{
+ Log.d( TAG, "onCreate()" );
super.onCreate();
+ mHelper = new RelayServiceHelper( this );
m_lastGamePacketReceived =
XWPrefs.getPrefsLong( this, R.string.key_last_packet,
Utils.getCurSeconds() );
@@ -398,6 +385,8 @@ public class RelayService extends XWService
@Override
public int onStartCommand( Intent intent, int flags, int startId )
{
+ Log.d( TAG, "onStartCommand(%s)", intent );
+ super.onStartCommand( intent, flags, startId );
Integer result = handleCommand( intent );
if ( null == result ) {
@@ -409,6 +398,13 @@ public class RelayService extends XWService
return result;
}
+ @Override
+ public void onHandleWork( Intent intent )
+ {
+ Log.d( TAG, "onHandleWork(%s)", intent );
+ /*void*/ handleCommand( intent );
+ }
+
@Override
public void onDestroy()
{
@@ -436,7 +432,7 @@ public class RelayService extends XWService
cmd = null;
}
if ( null != cmd ) {
- // Log.d( TAG, "onStartCommand(): cmd=%s", cmd.toString() );
+ Log.d( TAG, "onStartCommand(): cmd=%s", cmd.toString() );
switch( cmd ) {
case PROCESS_GAME_MSGS:
String[] relayIDs = new String[1];
@@ -483,7 +479,7 @@ public class RelayService extends XWService
String relayID = intent.getStringExtra( RELAY_ID );
sendNoConnMessage( rowid, relayID, msg );
} else {
- receiveMessage( this, rowid, null, msg, s_addr );
+ mHelper.receiveMessage( this, rowid, null, msg, s_addr );
}
break;
case INVITE:
@@ -621,8 +617,6 @@ public class RelayService extends XWService
private void stopUDPThreadsIf()
{
- DbgUtils.assertOnUIThread();
-
UDPThreads threads = m_UDPThreadsRef.getAndSet( null );
if ( null != threads ) {
threads.stop();
@@ -648,7 +642,7 @@ public class RelayService extends XWService
Log.i( TAG, "relay unvailable for another %d seconds",
unavail );
String str = getVLIString( dis );
- postEvent( MultiEvent.RELAY_ALERT, str );
+ mHelper.postEvent( MultiEvent.RELAY_ALERT, str );
break;
case XWPDEV_ALERT:
str = getVLIString( dis );
@@ -999,7 +993,7 @@ public class RelayService extends XWService
long rowid = rowIDs[ii];
sink.setRowID( rowid );
for ( byte[] msg : forOne ) {
- receiveMessage( this, rowid, sink, msg, s_addr );
+ mHelper.receiveMessage( this, rowid, sink, msg, s_addr );
}
}
}
@@ -1728,6 +1722,28 @@ public class RelayService extends XWService
}
}
+ private class RelayServiceHelper extends XWServiceHelper {
+
+ private Service mService;
+ RelayServiceHelper( Service service ) {
+ super( service );
+ mService = service;
+ }
+
+ @Override
+ protected MultiMsgSink getSink( long rowid )
+ {
+ return new RelayMsgSink().setRowID( rowid );
+ }
+
+ @Override
+ void postNotification( String device, int gameID, long rowid )
+ {
+ String body = LocUtils.getString( mService, R.string.new_relay_body );
+ GameUtils.postInvitedNotification( mService, gameID, body, rowid );
+ }
+ }
+
// Exits only to exist, so instanceof can distinguish
private class EOQPacketData extends PacketData {}
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java
index eba26c22c..74500b81d 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/SMSService.java
@@ -86,6 +86,7 @@ public class SMSService extends XWService {
private BroadcastReceiver m_sentReceiver;
private BroadcastReceiver m_receiveReceiver;
private OnSharedPreferenceChangeListener m_prefsListener;
+ private SMSServiceHelper mHelper;
private int m_nReceived = 0;
private static int s_nSent = 0;
@@ -277,15 +278,10 @@ public class SMSService extends XWService {
return s_showToasts;
}
- @Override
- protected MultiMsgSink getSink( long rowid )
- {
- return new SMSMsgSink( this );
- }
-
@Override
public void onCreate()
{
+ mHelper = new SMSServiceHelper( this );
if ( Utils.deviceSupportsSMS( this ) ) {
registerReceivers();
} else {
@@ -469,10 +465,10 @@ public class SMSService extends XWService {
}
break;
case DEATH:
- postEvent( MultiEvent.MESSAGE_NOGAME, msg.gameID );
+ mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, msg.gameID );
break;
case ACK_INVITE:
- postEvent( MultiEvent.NEWGAME_SUCCESS, msg.gameID );
+ mHelper.postEvent( MultiEvent.NEWGAME_SUCCESS, msg.gameID );
break;
default:
Log.w( TAG, "unexpected cmd %s", msg.cmd );
@@ -489,26 +485,17 @@ public class SMSService extends XWService {
for ( SMSProtoMsg msg : msgs ) {
receive( msg, senderPhone );
}
- postEvent( MultiEvent.SMS_RECEIVE_OK );
+ mHelper.postEvent( MultiEvent.SMS_RECEIVE_OK );
} else {
Log.d( TAG, "receiveBuffer(): bogus or incomplete message from %s",
senderPhone );
}
}
- @Override
- protected void postNotification( String phone, int gameID, long rowid )
- {
- String owner = Utils.phoneToContact( this, phone, true );
- String body = LocUtils.getString( this, R.string.new_name_body_fmt,
- owner );
- GameUtils.postInvitedNotification( this, gameID, body, rowid );
- }
-
private void makeForInvite( String phone, NetLaunchInfo nli )
{
if ( nli != null ) {
- handleInvitation( nli, phone, DictFetchOwner.OWNER_SMS );
+ mHelper.handleInvitation( nli, phone, DictFetchOwner.OWNER_SMS );
ackInvite( phone, nli.gameID() );
}
}
@@ -554,7 +541,7 @@ public class SMSService extends XWService {
} catch ( NullPointerException npe ) {
Assert.fail(); // shouldn't be trying to do this!!!
} catch ( java.lang.SecurityException se ) {
- postEvent( MultiEvent.SMS_SEND_FAILED_NOPERMISSION );
+ mHelper.postEvent( MultiEvent.SMS_SEND_FAILED_NOPERMISSION );
} catch ( Exception ee ) {
Log.ex( TAG, ee );
}
@@ -575,11 +562,12 @@ public class SMSService extends XWService {
private boolean feedMessage( int gameID, byte[] msg, CommsAddrRec addr )
{
- ReceiveResult rslt = receiveMessage( this, gameID, null, msg, addr );
- if ( ReceiveResult.GAME_GONE == rslt ) {
+ XWServiceHelper.ReceiveResult rslt = mHelper
+ .receiveMessage( this, gameID, null, msg, addr );
+ if ( XWServiceHelper.ReceiveResult.GAME_GONE == rslt ) {
sendDiedPacket( addr.sms_phone, gameID );
}
- return rslt == ReceiveResult.OK;
+ return rslt == XWServiceHelper.ReceiveResult.OK;
}
private void registerReceivers()
@@ -590,15 +578,15 @@ public class SMSService extends XWService {
{
switch ( getResultCode() ) {
case Activity.RESULT_OK:
- postEvent( MultiEvent.SMS_SEND_OK );
+ mHelper.postEvent( MultiEvent.SMS_SEND_OK );
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
- postEvent( MultiEvent.SMS_SEND_FAILED_NORADIO );
+ mHelper.postEvent( MultiEvent.SMS_SEND_FAILED_NORADIO );
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
default:
Log.w( TAG, "FAILURE!!!" );
- postEvent( MultiEvent.SMS_SEND_FAILED );
+ mHelper.postEvent( MultiEvent.SMS_SEND_FAILED );
break;
}
}
@@ -655,4 +643,28 @@ public class SMSService extends XWService {
return sendPacket( addr.sms_phone, gameID, buf );
}
}
+
+ private class SMSServiceHelper extends XWServiceHelper {
+ private Service mService;
+
+ SMSServiceHelper( Service service ) {
+ super( service );
+ mService = service;
+ }
+
+ @Override
+ protected MultiMsgSink getSink( long rowid )
+ {
+ return new SMSMsgSink( SMSService.this );
+ }
+
+ @Override
+ protected void postNotification( String phone, int gameID, long rowid )
+ {
+ String owner = Utils.phoneToContact( mService, phone, true );
+ String body = LocUtils.getString( mService, R.string.new_name_body_fmt,
+ owner );
+ GameUtils.postInvitedNotification( mService, gameID, body, rowid );
+ }
+ }
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java
index 600c03770..432d191b9 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/WiDirService.java
@@ -124,6 +124,7 @@ public class WiDirService extends XWService {
private static Set s_peersSet;
private P2pMsgSink m_sink;
+ private WiDirServiceHelper mHelper;
public interface DevSetListener {
void setChanged( Map macToName );
@@ -133,6 +134,7 @@ public class WiDirService extends XWService {
public void onCreate()
{
m_sink = new P2pMsgSink();
+ mHelper = new WiDirServiceHelper(this);
}
@Override
@@ -751,8 +753,9 @@ public class WiDirService extends XWService {
CommsAddrRec addr = new CommsAddrRec( CommsConnType.COMMS_CONN_P2P )
.setP2PParams( macAddress );
- ReceiveResult rslt = receiveMessage( this, gameID, m_sink, data, addr );
- if ( ReceiveResult.GAME_GONE == rslt ) {
+ XWServiceHelper.ReceiveResult rslt = mHelper
+ .receiveMessage( this, gameID, m_sink, data, addr );
+ if ( XWServiceHelper.ReceiveResult.GAME_GONE == rslt ) {
sendNoGame( null, macAddress, gameID );
}
}
@@ -764,27 +767,15 @@ public class WiDirService extends XWService {
NetLaunchInfo nli = NetLaunchInfo.makeFrom( this, nliData );
String returnMac = intent.getStringExtra( KEY_SRC );
- if ( !handleInvitation( nli, returnMac, DictFetchOwner.OWNER_P2P ) ) {
+ if ( !mHelper.handleInvitation( nli, returnMac, DictFetchOwner.OWNER_P2P ) ) {
Log.d( TAG, "handleInvitation() failed" );
}
}
- @Override
- void postNotification( String device, int gameID, long rowid )
- {
- Log.e( TAG, "postNotification() doing nothing" );
- }
-
- @Override
- MultiMsgSink getSink( long rowid )
- {
- return m_sink;
- }
-
private void handleGameGone( Intent intent )
{
int gameID = intent.getIntExtra( KEY_GAMEID, 0 );
- postEvent( MultiEvent.MESSAGE_NOGAME, gameID );
+ mHelper.postEvent( MultiEvent.MESSAGE_NOGAME, gameID );
}
private void makeGame( NetLaunchInfo nli, String senderMac )
@@ -794,7 +785,7 @@ public class WiDirService extends XWService {
CommsAddrRec addr = nli.makeAddrRec( this );
long rowid = GameUtils.makeNewMultiGame( this, nli,
m_sink,
- getUtilCtxt() );
+ mHelper.getUtilCtxt() );
if ( DBUtils.ROWID_NOTFOUND != rowid ) {
if ( null != nli.gameName && 0 < nli.gameName.length() ) {
DBUtils.setName( this, rowid, nli.gameName );
@@ -1206,4 +1197,23 @@ public class WiDirService extends XWService {
private class P2pMsgSink extends MultiMsgSink {
public P2pMsgSink() { super( WiDirService.this ); }
}
+
+ private class WiDirServiceHelper extends XWServiceHelper {
+
+ WiDirServiceHelper( Service service ) {
+ super( service );
+ }
+
+ @Override
+ MultiMsgSink getSink( long rowid )
+ {
+ return m_sink;
+ }
+
+ @Override
+ void postNotification( String device, int gameID, long rowid )
+ {
+ Log.e( TAG, "postNotification() doing nothing" );
+ }
+ }
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java
index 4e431f2c0..c995ba897 100644
--- a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWService.java
@@ -1,6 +1,6 @@
/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */
/*
- * Copyright 2010 - 2012 by Eric House (xwords@eehouse.org). All
+ * Copyright 2010 - 2018 by Eric House (xwords@eehouse.org). All
* rights reserved.
*
* This program is free software; you can redistribute it and/or
@@ -21,166 +21,15 @@
package org.eehouse.android.xw4;
import android.app.Service;
-import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
-
-import org.eehouse.android.xw4.MultiService.DictFetchOwner;
-import org.eehouse.android.xw4.MultiService.MultiEvent;
-import org.eehouse.android.xw4.jni.CommsAddrRec;
-import org.eehouse.android.xw4.jni.JNIThread;
-import org.eehouse.android.xw4.jni.UtilCtxt;
-import org.eehouse.android.xw4.jni.UtilCtxtImpl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-abstract class XWService extends Service {
+class XWService extends Service {
private static final String TAG = XWService.class.getSimpleName();
- public static enum ReceiveResult { OK, GAME_GONE, UNCONSUMED };
-
- protected static MultiService s_srcMgr = null;
- private static Map s_seen = new HashMap<>();
-
- private UtilCtxt m_utilCtxt;
@Override
public IBinder onBind( Intent intent )
{
return null;
}
-
- public final static void setListener( MultiService.MultiEventListener li )
- {
- if ( null == s_srcMgr ) {
- // DbgUtils.logf( "XWService.setListener: registering %s", li.getClass().getName() );
- s_srcMgr = new MultiService();
- }
- s_srcMgr.setListener( li );
- }
-
- protected void postEvent( MultiEvent event, Object ... args )
- {
- if ( null != s_srcMgr ) {
- s_srcMgr.postEvent( event, args );
- } else {
- Log.d( TAG, "postEvent(): dropping %s event",
- event.toString() );
- }
- }
-
- // Check that we aren't already processing an invitation with this
- // inviteID.
- private static final long SEEN_INTERVAL_MS = 1000 * 5;
- private boolean checkNotDupe( NetLaunchInfo nli )
- {
- String inviteID = nli.inviteID();
- synchronized( s_seen ) {
- long now = System.currentTimeMillis();
- Long lastSeen = s_seen.get( inviteID );
- boolean seen = null != lastSeen && lastSeen + SEEN_INTERVAL_MS > now;
- if ( !seen ) {
- s_seen.put( inviteID, now );
- }
- Log.d( TAG, "checkNotDupe('%s') => %b", inviteID, !seen );
- return !seen;
- }
- }
-
- abstract void postNotification( String device, int gameID, long rowid );
-
- // Return true if able to start game only
- protected boolean handleInvitation( NetLaunchInfo nli, String device,
- DictFetchOwner dfo )
- {
- boolean success = false;
- long[] rowids = DBUtils.getRowIDsFor( this, nli.gameID() );
- if ( 0 == rowids.length
- || ( rowids.length < nli.nPlayersT // will break for two-per-device game
- && XWPrefs.getSecondInviteAllowed( this ) ) ) {
-
- if ( nli.isValid() && checkNotDupe( nli ) ) {
-
- if ( DictLangCache.haveDict( this, nli.lang, nli.dict ) ) {
- long rowid = GameUtils.makeNewMultiGame( this, nli,
- getSink( 0 ),
- getUtilCtxt() );
-
- if ( null != nli.gameName && 0 < nli.gameName.length() ) {
- DBUtils.setName( this, rowid, nli.gameName );
- }
-
- postNotification( device, nli.gameID(), rowid );
- success = true;
- } else {
- Intent intent = MultiService
- .makeMissingDictIntent( this, nli, dfo );
- MultiService.postMissingDictNotification( this, intent,
- nli.gameID() );
- }
- }
- }
- Log.d( TAG, "handleInvitation() => %b", success );
- return success;
- }
-
- protected UtilCtxt getUtilCtxt()
- {
- if ( null == m_utilCtxt ) {
- m_utilCtxt = new UtilCtxtImpl( this );
- }
- return m_utilCtxt;
- }
-
- // Meant to be overridden
- abstract MultiMsgSink getSink( long rowid );
-
- protected ReceiveResult receiveMessage( Context context, int gameID,
- MultiMsgSink sink, byte[] msg,
- CommsAddrRec addr )
- {
- ReceiveResult result;
- long[] rowids = DBUtils.getRowIDsFor( context, gameID );
- if ( null == rowids || 0 == rowids.length ) {
- result = ReceiveResult.GAME_GONE;
- } else {
- result = ReceiveResult.UNCONSUMED;
- for ( long rowid : rowids ) {
- if ( receiveMessage( context, rowid, sink, msg, addr ) ) {
- result = ReceiveResult.OK;
- }
- }
- }
- return result;
- }
-
- protected boolean receiveMessage( Context context, long rowid,
- MultiMsgSink sink, byte[] msg,
- CommsAddrRec addr )
- {
- boolean allConsumed = true;
- boolean[] isLocalP = new boolean[1];
- JNIThread jniThread = JNIThread.getRetained( rowid, false );
- boolean consumed = false;
- if ( null != jniThread ) {
- consumed = true;
- jniThread.receive( msg, addr ).release();
- } else {
- GameUtils.BackMoveResult bmr = new GameUtils.BackMoveResult();
- if ( null == sink ) {
- sink = getSink( rowid );
- }
- if ( GameUtils.feedMessage( context, rowid, msg, addr,
- sink, bmr, isLocalP ) ) {
- consumed = true;
- GameUtils.postMoveNotification( context, rowid, bmr,
- isLocalP[0] );
- }
- }
- if ( allConsumed && !consumed ) {
- allConsumed = false;
- }
- return allConsumed;
- }
}
diff --git a/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java
new file mode 100644
index 000000000..e23a85349
--- /dev/null
+++ b/xwords4/android/app/src/main/java/org/eehouse/android/xw4/XWServiceHelper.java
@@ -0,0 +1,182 @@
+/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */
+/*
+ * Copyright 2010 - 2018 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.app.Service;
+import android.content.Context;
+import android.content.Intent;
+
+import org.eehouse.android.xw4.MultiService.DictFetchOwner;
+import org.eehouse.android.xw4.MultiService.MultiEvent;
+import org.eehouse.android.xw4.jni.CommsAddrRec;
+import org.eehouse.android.xw4.jni.JNIThread;
+import org.eehouse.android.xw4.jni.UtilCtxt;
+import org.eehouse.android.xw4.jni.UtilCtxtImpl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+abstract class XWServiceHelper {
+ private static final String TAG = XWServiceHelper.class.getSimpleName();
+ private Service mService;
+ private static MultiService s_srcMgr = null;
+
+ public static enum ReceiveResult { OK, GAME_GONE, UNCONSUMED };
+
+ XWServiceHelper( Service service )
+ {
+ mService = service;
+ }
+
+ abstract MultiMsgSink getSink( long rowid );
+ abstract void postNotification( String device, int gameID, long rowid );
+
+ protected ReceiveResult receiveMessage( Context context, int gameID,
+ MultiMsgSink sink, byte[] msg,
+ CommsAddrRec addr )
+ {
+ ReceiveResult result;
+ long[] rowids = DBUtils.getRowIDsFor( context, gameID );
+ if ( null == rowids || 0 == rowids.length ) {
+ result = ReceiveResult.GAME_GONE;
+ } else {
+ result = ReceiveResult.UNCONSUMED;
+ for ( long rowid : rowids ) {
+ if ( receiveMessage( context, rowid, sink, msg, addr ) ) {
+ result = ReceiveResult.OK;
+ }
+ }
+ }
+ return result;
+ }
+
+ protected boolean receiveMessage( Context context, long rowid,
+ MultiMsgSink sink, byte[] msg,
+ CommsAddrRec addr )
+ {
+ boolean allConsumed = true;
+ boolean[] isLocalP = new boolean[1];
+ JNIThread jniThread = JNIThread.getRetained( rowid, false );
+ boolean consumed = false;
+ if ( null != jniThread ) {
+ consumed = true;
+ jniThread.receive( msg, addr ).release();
+ } else {
+ GameUtils.BackMoveResult bmr = new GameUtils.BackMoveResult();
+ if ( null == sink ) {
+ sink = getSink( rowid );
+ }
+ if ( GameUtils.feedMessage( context, rowid, msg, addr,
+ sink, bmr, isLocalP ) ) {
+ consumed = true;
+ GameUtils.postMoveNotification( context, rowid, bmr,
+ isLocalP[0] );
+ }
+ }
+ if ( allConsumed && !consumed ) {
+ allConsumed = false;
+ }
+ return allConsumed;
+ }
+
+ public final static void setListener( MultiService.MultiEventListener li )
+ {
+ if ( null == s_srcMgr ) {
+ // DbgUtils.logf( "XWService.setListener: registering %s",
+ // li.getClass().getName() );
+ s_srcMgr = new MultiService();
+ }
+ s_srcMgr.setListener( li );
+ }
+
+ protected void postEvent( MultiEvent event, Object ... args )
+ {
+ if ( null != s_srcMgr ) {
+ s_srcMgr.postEvent( event, args );
+ } else {
+ Log.d( TAG, "postEvent(): dropping %s event",
+ event.toString() );
+ }
+ }
+
+ protected boolean handleInvitation( NetLaunchInfo nli, String device,
+ DictFetchOwner dfo )
+ {
+ boolean success = false;
+ long[] rowids = DBUtils.getRowIDsFor( mService, nli.gameID() );
+ if ( 0 == rowids.length
+ || ( rowids.length < nli.nPlayersT // will break for two-per-device game
+ && XWPrefs.getSecondInviteAllowed( mService ) ) ) {
+
+ if ( nli.isValid() && checkNotDupe( nli ) ) {
+
+ if ( DictLangCache.haveDict( mService, nli.lang, nli.dict ) ) {
+ long rowid = GameUtils.makeNewMultiGame( mService, nli,
+ getSink( 0 ),
+ getUtilCtxt() );
+
+ if ( null != nli.gameName && 0 < nli.gameName.length() ) {
+ DBUtils.setName( mService, rowid, nli.gameName );
+ }
+
+ postNotification( device, nli.gameID(), rowid );
+ success = true;
+ } else {
+ Intent intent = MultiService
+ .makeMissingDictIntent( mService, nli, dfo );
+ MultiService.postMissingDictNotification( mService, intent,
+ nli.gameID() );
+ }
+ }
+ }
+ Log.d( TAG, "handleInvitation() => %b", success );
+ return success;
+ }
+
+ private UtilCtxt m_utilCtxt;
+ protected UtilCtxt getUtilCtxt()
+ {
+ if ( null == m_utilCtxt ) {
+ m_utilCtxt = new UtilCtxtImpl( mService );
+ }
+ return m_utilCtxt;
+ }
+
+ // Check that we aren't already processing an invitation with this
+ // inviteID.
+ private static final long SEEN_INTERVAL_MS = 1000 * 5;
+ private static Map s_seen = new HashMap<>();
+ private boolean checkNotDupe( NetLaunchInfo nli )
+ {
+ String inviteID = nli.inviteID();
+ synchronized( s_seen ) {
+ long now = System.currentTimeMillis();
+ Long lastSeen = s_seen.get( inviteID );
+ boolean seen = null != lastSeen && lastSeen + SEEN_INTERVAL_MS > now;
+ if ( !seen ) {
+ s_seen.put( inviteID, now );
+ }
+ Log.d( TAG, "checkNotDupe('%s') => %b", inviteID, !seen );
+ return !seen;
+ }
+ }
+}