Recast BTService as a JobIntentService

Got tired of the space the forground-service notification icons were
taking. So now BT sends and receives are done via static threads and
onHandleWork(). The send thread times itself out quickly. The receive
thread doesn't yet. We'll see how long the OS lets it run and what
needs to be done to deal with that.
This commit is contained in:
Eric House 2019-02-08 07:26:00 -08:00
parent 438e134870
commit 7ccb576214
10 changed files with 577 additions and 713 deletions

View file

@ -212,9 +212,6 @@
<intent-filter> <intent-filter>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" /> <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="org.eehouse.android.ACTION_STOP_BT" />
</intent-filter>
</receiver> </receiver>
<receiver android:name="SMSReceiver" > <receiver android:name="SMSReceiver" >

View file

@ -29,9 +29,6 @@ import android.content.Intent;
public class BTReceiver extends BroadcastReceiver { public class BTReceiver extends BroadcastReceiver {
private static final String TAG = BTReceiver.class.getSimpleName(); private static final String TAG = BTReceiver.class.getSimpleName();
// This string is also used in AndroidManifest (as a string literal)
static final String ACTION_STOP_BT = "org.eehouse.android.ACTION_STOP_BT";
@Override @Override
public void onReceive( Context context, Intent intent ) public void onReceive( Context context, Intent intent )
{ {
@ -41,9 +38,6 @@ public class BTReceiver extends BroadcastReceiver {
action, intent.toString() ); action, intent.toString() );
switch (action ) { switch (action ) {
case ACTION_STOP_BT:
BTService.stopBackground( context );
break;
case BluetoothDevice.ACTION_ACL_CONNECTED: case BluetoothDevice.ACTION_ACL_CONNECTED:
BTService.onACLConnected( context ); BTService.onACLConnected( context );
break; break;

View file

@ -85,7 +85,6 @@ public class GamesListDelegate extends ListDelegateBase
private static final String RELAYIDS_EXTRA = "relayids"; private static final String RELAYIDS_EXTRA = "relayids";
private static final String ROWID_EXTRA = "rowid"; private static final String ROWID_EXTRA = "rowid";
private static final String BACKGROUND_EXTRA = "bkgrnd";
private static final String GAMEID_EXTRA = "gameid"; private static final String GAMEID_EXTRA = "gameid";
private static final String REMATCH_ROWID_EXTRA = "rm_rowid"; private static final String REMATCH_ROWID_EXTRA = "rm_rowid";
private static final String REMATCH_DICT_EXTRA = "rm_dict"; private static final String REMATCH_DICT_EXTRA = "rm_dict";
@ -2289,14 +2288,6 @@ public class GamesListDelegate extends ListDelegateBase
} }
} }
private void tryBackgroundIntent( Intent intent )
{
if ( intent.getBooleanExtra( BACKGROUND_EXTRA, false ) ) {
makeOkOnlyBuilder( R.string.btservice_expl )
.show();
}
}
private void askDefaultName() private void askDefaultName()
{ {
String name = CommonPrefs.getDefaultPlayerName( m_activity, 0, true ); String name = CommonPrefs.getDefaultPlayerName( m_activity, 0, true );
@ -2511,7 +2502,6 @@ public class GamesListDelegate extends ListDelegateBase
startRematch( intent ); startRematch( intent );
tryAlert( intent ); tryAlert( intent );
tryNFCIntent( intent ); tryNFCIntent( intent );
tryBackgroundIntent( intent );
} }
private void doOpenGame( Object[] params ) private void doOpenGame( Object[] params )
@ -2704,12 +2694,6 @@ public class GamesListDelegate extends ListDelegateBase
; ;
} }
public static Intent makeBackgroundIntent( Context context )
{
return makeSelfIntent( context )
.putExtra( BACKGROUND_EXTRA, true );
}
public static Intent makeRowidIntent( Context context, long rowid ) public static Intent makeRowidIntent( Context context, long rowid )
{ {
Intent intent = makeSelfIntent( context ) Intent intent = makeSelfIntent( context )

View file

@ -26,7 +26,6 @@ import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.JobIntentService;
import android.text.TextUtils; import android.text.TextUtils;
import org.eehouse.android.xw4.FBMService; import org.eehouse.android.xw4.FBMService;
@ -64,7 +63,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
public class RelayService extends JobIntentService public class RelayService extends XWJIService
implements NetStateCache.StateChangedIf { implements NetStateCache.StateChangedIf {
private static final String TAG = RelayService.class.getSimpleName(); private static final String TAG = RelayService.class.getSimpleName();
private static final int MAX_SEND = 1024; private static final int MAX_SEND = 1024;
@ -82,10 +81,7 @@ public class RelayService extends JobIntentService
// One day, in seconds. Probably should be configurable. // One day, in seconds. Probably should be configurable.
private static final long MAX_KEEPALIVE_SECS = 24 * 60 * 60; private static final long MAX_KEEPALIVE_SECS = 24 * 60 * 60;
private static final String CMD_KEY = "CMD"; private static enum MsgCmds implements XWJICmds { INVALID,
private static final String TIMESTAMP = "TIMESTAMP";
private static enum MsgCmds { INVALID,
DO_WORK, DO_WORK,
PROCESS_GAME_MSGS, PROCESS_GAME_MSGS,
PROCESS_DEV_MSGS, PROCESS_DEV_MSGS,
@ -222,18 +218,7 @@ public class RelayService extends JobIntentService
private static void enqueueWork( Context context, Intent intent ) private static void enqueueWork( Context context, Intent intent )
{ {
enqueueWork( context, RelayService.class, sJobID, intent ); enqueueWork( context, RelayService.class, sJobID, intent );
Log.d( TAG, "called enqueueWork(cmd=%s)", cmdFrom( intent ) ); Log.d( TAG, "called enqueueWork(cmd=%s)", cmdFrom( intent, MsgCmds.values() ) );
}
private static MsgCmds cmdFrom( Intent intent )
{
MsgCmds cmd;
try {
cmd = MsgCmds.values()[intent.getIntExtra( CMD_KEY, -1 )];
} catch (Exception ex) { // OOB most likely
cmd = null;
}
return cmd;
} }
private static void stopService( Context context ) private static void stopService( Context context )
@ -353,10 +338,7 @@ public class RelayService extends JobIntentService
private static Intent getIntentTo( Context context, MsgCmds cmd ) private static Intent getIntentTo( Context context, MsgCmds cmd )
{ {
Intent intent = new Intent( context, RelayService.class ) return getIntentTo( context, RelayService.class, cmd );
.putExtra( CMD_KEY, cmd.ordinal() )
.putExtra( TIMESTAMP, System.currentTimeMillis() );
return intent;
} }
@Override @Override
@ -391,15 +373,15 @@ public class RelayService extends JobIntentService
} }
@Override @Override
public void onHandleWork( Intent intent ) void onHandleWorkImpl( Intent intent, XWJICmds jicmd, long timestamp )
{ {
DbgUtils.assertOnUIThread( false ); DbgUtils.assertOnUIThread( false );
Log.d( TAG, "%s.onHandleWork(cmd=%s)", this, cmdFrom( intent ) ); // Log.d( TAG, "%s.onHandleWork(cmd=%s)", this, cmdFrom( intent ) );
try { try {
connectSocketOnce(); // must not be on UI thread connectSocketOnce(); // must not be on UI thread
handleCommand( intent ); handleCommand( intent, jicmd, timestamp );
boolean goOn = serviceQueue(); boolean goOn = serviceQueue();
if ( !goOn ) { if ( !goOn ) {
@ -438,6 +420,9 @@ public class RelayService extends JobIntentService
Log.d( TAG, "%s.onDestroy() DONE", this ); Log.d( TAG, "%s.onDestroy() DONE", this );
} }
@Override
XWJICmds[] getCmds() { return MsgCmds.values(); }
// NetStateCache.StateChangedIf interface // NetStateCache.StateChangedIf interface
@Override @Override
public void onNetAvail( boolean nowAvailable ) public void onNetAvail( boolean nowAvailable )
@ -445,13 +430,9 @@ public class RelayService extends JobIntentService
startService( this ); // bad name: will *stop* threads too startService( this ); // bad name: will *stop* threads too
} }
private void handleCommand( Intent intent ) private void handleCommand( Intent intent, XWJICmds jicmd, long timestamp )
{ {
MsgCmds cmd = cmdFrom( intent ); MsgCmds cmd = (MsgCmds)jicmd;
if ( null != cmd ) {
long timestamp = intent.getLongExtra( TIMESTAMP, 0 );
Log.d( TAG, "handleCommand(): cmd=%s (age=%dms)", cmd.toString(),
System.currentTimeMillis() - timestamp );
switch( cmd ) { switch( cmd ) {
case DO_WORK: // exists only to launch service case DO_WORK: // exists only to launch service
break; break;
@ -534,7 +515,6 @@ public class RelayService extends JobIntentService
Assert.assertFalse( BuildConfig.DEBUG ); Assert.assertFalse( BuildConfig.DEBUG );
} }
} }
}
private synchronized void connectSocketOnce() throws InterruptedException private synchronized void connectSocketOnce() throws InterruptedException
{ {

View file

@ -99,16 +99,12 @@ public class XWApp extends Application implements LifecycleObserver {
Log.d( TAG, "onAny(%s)", event ); Log.d( TAG, "onAny(%s)", event );
switch( event ) { switch( event ) {
case ON_RESUME: case ON_RESUME:
BTService.onAppToForeground( this );
// Do here what checkForMoves does // Do here what checkForMoves does
if ( null != DBUtils.getRelayIDs( this, null ) ) { if ( null != DBUtils.getRelayIDs( this, null ) ) {
RelayService.timerFired( this ); RelayService.timerFired( this );
} }
GameUtils.resendAllIf( this, null ); GameUtils.resendAllIf( this, null );
break; break;
case ON_STOP:
BTService.onAppToBackground( this );
break;
} }
} }

View file

@ -0,0 +1,77 @@
/* -*- compile-command: "find-and-gradle.sh insXw4Deb"; -*- */
/*
* Copyright 2010 - 2015 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.support.v4.app.JobIntentService;
import android.content.Context;
import android.content.Intent;
abstract class XWJIService extends JobIntentService {
static final String CMD_KEY = "CMD";
private static final String TIMESTAMP = "TIMESTAMP";
public interface XWJICmds {
public int ordinal();
}
abstract void onHandleWorkImpl( Intent intent, XWJICmds cmd, long timestamp );
abstract XWJICmds[] getCmds();
@Override
public final void onHandleWork( Intent intent )
{
long timestamp = getTimestamp(intent);
XWJICmds cmd = cmdFrom( intent );
Log.d( getClass().getSimpleName(),
"onHandleWork(): cmd=%s; age=%dms; threadCount: %d)",
cmd, System.currentTimeMillis() - timestamp,
Thread.activeCount() );
onHandleWorkImpl( intent, cmd, timestamp );
}
static XWJICmds cmdFrom( Intent intent, XWJICmds[] values )
{
int ord = intent.getIntExtra( CMD_KEY, -1 );
return values[ord];
}
XWJICmds cmdFrom( Intent intent )
{
int ord = intent.getIntExtra( CMD_KEY, -1 );
return getCmds()[ord];
}
long getTimestamp( Intent intent )
{
long result = intent.getLongExtra( TIMESTAMP, 0 );
return result;
}
static Intent getIntentTo( Context context, Class clazz, XWJICmds cmd )
{
Intent intent = new Intent( context, clazz )
.putExtra( CMD_KEY, cmd.ordinal() )
.putExtra( TIMESTAMP, System.currentTimeMillis() );
return intent;
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 B

View file

@ -2056,10 +2056,6 @@
<string name="title_enable_p2p">Enable WiFi Direct</string> <string name="title_enable_p2p">Enable WiFi Direct</string>
<string name="summary_enable_p2p">Experimental, uses lots of battery</string> <string name="summary_enable_p2p">Experimental, uses lots of battery</string>
<string name="bkng_notify_text">Accepting Bluetooth messages…</string>
<string name="bkng_stop_text">Stop</string>
<string name="bkng_settings_text">Settings</string>
<!-- --> <!-- -->
<string name="confirm_sms_title">Confirm your SMS plan</string> <string name="confirm_sms_title">Confirm your SMS plan</string>
<!-- --> <!-- -->
@ -2678,12 +2674,6 @@
player name \"%1$s\". Would you like to personalize with your own player name \"%1$s\". Would you like to personalize with your own
name before you create this game?</string> name before you create this game?</string>
<string name="btservice_expl">This notification is present whenever
CrossWords is running in the background to accept Bluetooth
messages. It usually runs for about 15 minutes after CrossWords
starts or a Bluetooth message is received.
</string>
<string name="no_invites">This game has sent no invitations</string> <string name="no_invites">This game has sent no invitations</string>
<string name="disable_dualpane">Disable side-by-side</string> <string name="disable_dualpane">Disable side-by-side</string>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 471 B