mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-01-31 19:57:06 +01:00
use foregroundService on devices that can handle it
And show the notification regardless. Tested only on pre-Oreo device so far.
This commit is contained in:
parent
6177914213
commit
2ba5982ddf
7 changed files with 99 additions and 48 deletions
|
@ -179,15 +179,16 @@
|
||||||
<activity android:name=".loc.LocItemEditActivity"
|
<activity android:name=".loc.LocItemEditActivity"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<service android:name="RelayService"
|
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
|
||||||
android:exported="false"
|
|
||||||
/>
|
|
||||||
<service android:name="BTService"
|
<service android:name="BTService"
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
/>
|
/>
|
||||||
<service android:name="SMSService"/>
|
<service android:name="SMSService"
|
||||||
|
android:exported="false"
|
||||||
|
/>
|
||||||
|
<service android:name="RelayService"
|
||||||
|
android:exported="false"
|
||||||
|
/>
|
||||||
|
|
||||||
<receiver android:name=".MountEventReceiver">
|
<receiver android:name=".MountEventReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
package org.eehouse.android.xw4;
|
package org.eehouse.android.xw4;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothClass.Device.Major;
|
import android.bluetooth.BluetoothClass.Device.Major;
|
||||||
|
@ -29,7 +31,8 @@ import android.bluetooth.BluetoothServerSocket;
|
||||||
import android.bluetooth.BluetoothSocket;
|
import android.bluetooth.BluetoothSocket;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.v4.app.JobIntentService;
|
import android.os.Build;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
@ -66,6 +69,8 @@ public class BTService extends XWService {
|
||||||
private static final int BT_PROTO = BT_PROTO_JSONS; // change in a release or two
|
private static final int BT_PROTO = BT_PROTO_JSONS; // change in a release or two
|
||||||
|
|
||||||
private enum BTAction { _NONE,
|
private enum BTAction { _NONE,
|
||||||
|
START_FOREGROUND,
|
||||||
|
START_BACKGROUND,
|
||||||
SCAN,
|
SCAN,
|
||||||
INVITE,
|
INVITE,
|
||||||
SEND,
|
SEND,
|
||||||
|
@ -93,6 +98,8 @@ public class BTService extends XWService {
|
||||||
private static final String BT_NAME_KEY = "BT_NAME";
|
private static final String BT_NAME_KEY = "BT_NAME";
|
||||||
private static final String BT_ADDRESS_KEY = "BT_ADDRESS";
|
private static final String BT_ADDRESS_KEY = "BT_ADDRESS";
|
||||||
|
|
||||||
|
private static Boolean sInForeground;
|
||||||
|
|
||||||
private enum BTCmd {
|
private enum BTCmd {
|
||||||
BAD_PROTO,
|
BAD_PROTO,
|
||||||
PING,
|
PING,
|
||||||
|
@ -225,12 +232,33 @@ public class BTService extends XWService {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void onAppStateChange( Context context, boolean inForeground )
|
||||||
|
{
|
||||||
|
if ( sInForeground == null || sInForeground != inForeground ) {
|
||||||
|
sInForeground = inForeground;
|
||||||
|
|
||||||
|
Intent intent =
|
||||||
|
getIntentTo( context,
|
||||||
|
inForeground ? BTAction.START_FOREGROUND
|
||||||
|
: BTAction.START_BACKGROUND );
|
||||||
|
startService( context, intent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onAppToForeground( Context context )
|
||||||
|
{
|
||||||
|
onAppStateChange( context, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onAppToBackground( Context context )
|
||||||
|
{
|
||||||
|
onAppStateChange( context, false );
|
||||||
|
}
|
||||||
|
|
||||||
public static void startService( Context context )
|
public static void startService( Context context )
|
||||||
{
|
{
|
||||||
if ( XWApp.BTSUPPORTED ) {
|
if ( XWApp.BTSUPPORTED ) {
|
||||||
startService( context, new Intent( context, BTService.class ) );
|
startService( context, new Intent( context, BTService.class ) );
|
||||||
// didn't help
|
|
||||||
// startService( context, new Intent( /*context, BTService.class*/ ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,17 +350,26 @@ public class BTService extends XWService {
|
||||||
{
|
{
|
||||||
Log.d( TAG, "startService(%s)", intent );
|
Log.d( TAG, "startService(%s)", intent );
|
||||||
|
|
||||||
if ( false ) {
|
if ( ! sInForeground && canRunForegroundService() ) {
|
||||||
// requires asking for Manifest.permission.FOREGROUND_SERVICE
|
|
||||||
context.startForegroundService( intent );
|
context.startForegroundService( intent );
|
||||||
} else {
|
} else if ( sInForeground || Build.VERSION.SDK_INT < Build.VERSION_CODES.O ) {
|
||||||
JobIntentService.enqueueWork( context, BTService.class, 1111, intent );
|
context.startService( intent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We can run a foreground service IIF the OS version is recent enough AND
|
||||||
|
// user hasn't said not to do it.
|
||||||
|
private static boolean canRunForegroundService()
|
||||||
|
{
|
||||||
|
// added in API level 26
|
||||||
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
|
||||||
|
// && Prefs.runForegroundServiceEnabled( context, true )
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
private static Intent getIntentTo( Context context, BTAction cmd )
|
private static Intent getIntentTo( Context context, BTAction cmd )
|
||||||
{
|
{
|
||||||
Intent intent = new Intent( /*context, BTService.class*/ );
|
Intent intent = new Intent( context, BTService.class );
|
||||||
intent.putExtra( CMD_KEY, cmd.ordinal() );
|
intent.putExtra( CMD_KEY, cmd.ordinal() );
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
@ -358,7 +395,13 @@ public class BTService extends XWService {
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand( Intent intent, int flags, int startId )
|
public int onStartCommand( Intent intent, int flags, int startId )
|
||||||
{
|
{
|
||||||
return handleCommand( intent );
|
int result = handleCommand( intent );
|
||||||
|
|
||||||
|
if ( Service.START_STICKY == result && !sInForeground ) {
|
||||||
|
startForeground();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int handleCommand( Intent intent )
|
private int handleCommand( Intent intent )
|
||||||
|
@ -375,6 +418,12 @@ public class BTService extends XWService {
|
||||||
BTAction cmd = BTAction.values()[ordinal];
|
BTAction cmd = BTAction.values()[ordinal];
|
||||||
Log.i( TAG, "onStartCommand; cmd=%s", cmd.toString() );
|
Log.i( TAG, "onStartCommand; cmd=%s", cmd.toString() );
|
||||||
switch( cmd ) {
|
switch( cmd ) {
|
||||||
|
case START_FOREGROUND:
|
||||||
|
stopForeground( true ); // Kill the notification
|
||||||
|
// FALLTHRU
|
||||||
|
case START_BACKGROUND:
|
||||||
|
break;
|
||||||
|
|
||||||
case CLEAR:
|
case CLEAR:
|
||||||
String[] btAddrs = intent.getStringArrayExtra( CLEAR_KEY );
|
String[] btAddrs = intent.getStringArrayExtra( CLEAR_KEY );
|
||||||
clearDevs( btAddrs );
|
clearDevs( btAddrs );
|
||||||
|
@ -450,11 +499,21 @@ public class BTService extends XWService {
|
||||||
return result;
|
return result;
|
||||||
} // handleCommand()
|
} // handleCommand()
|
||||||
|
|
||||||
@Override
|
private void startForeground()
|
||||||
protected void onHandleWork( Intent intent )
|
|
||||||
{
|
{
|
||||||
Log.e( TAG, "onHandleWork(%s)", intent );
|
Intent notifIntent = GamesListDelegate.makeBackgroundIntent( this );
|
||||||
/*(void)*/handleCommand( intent );
|
PendingIntent pendIntent = PendingIntent
|
||||||
|
.getActivity(this, Utils.nextRandomInt(), notifIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||||
|
Notification notification =
|
||||||
|
new NotificationCompat.Builder(this, Utils.CHANNEL_ID)
|
||||||
|
.setSmallIcon( R.drawable.notify )
|
||||||
|
.setContentTitle( BTService.class.getSimpleName() )
|
||||||
|
.setContentText("listening for bluetooth messages...")
|
||||||
|
.setContentIntent(pendIntent)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Log.d( TAG, "calling startForeground()" );
|
||||||
|
startForeground( 1337, notification );
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BTListenerThread extends Thread {
|
private class BTListenerThread extends Thread {
|
||||||
|
|
|
@ -2665,6 +2665,12 @@ public class GamesListDelegate extends ListDelegateBase
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Intent makeBackgroundIntent( Context context )
|
||||||
|
{
|
||||||
|
Intent intent = makeSelfIntent( context );
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
public static Intent makeRowidIntent( Context context, long rowid )
|
public static Intent makeRowidIntent( Context context, long rowid )
|
||||||
{
|
{
|
||||||
Intent intent = makeSelfIntent( context );
|
Intent intent = makeSelfIntent( context );
|
||||||
|
|
|
@ -25,7 +25,6 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.v4.app.JobIntentService;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
@ -201,10 +200,9 @@ public class RelayService extends XWService
|
||||||
Log.d( TAG, "startService(%s)", intent );
|
Log.d( TAG, "startService(%s)", intent );
|
||||||
|
|
||||||
if ( false ) {
|
if ( false ) {
|
||||||
// requires asking for Manifest.permission.FOREGROUND_SERVICE
|
|
||||||
context.startForegroundService( intent );
|
context.startForegroundService( intent );
|
||||||
} else {
|
} else {
|
||||||
JobIntentService.enqueueWork( context, RelayService.class, 1112, intent );
|
context.startService( intent );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,13 +389,6 @@ public class RelayService extends XWService
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onHandleWork( Intent intent )
|
|
||||||
{
|
|
||||||
Log.e( TAG, "onHandleWork(%s)", intent );
|
|
||||||
handleCommand( intent );
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetStateCache.StateChangedIf interface
|
// NetStateCache.StateChangedIf interface
|
||||||
public void onNetAvail( boolean nowAvailable )
|
public void onNetAvail( boolean nowAvailable )
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class Utils {
|
||||||
private static final String TAG = Utils.class.getSimpleName();
|
private static final String TAG = Utils.class.getSimpleName();
|
||||||
public static final int TURN_COLOR = 0x7F00FF00;
|
public static final int TURN_COLOR = 0x7F00FF00;
|
||||||
|
|
||||||
private static final String CHANNEL_ID = BuildConfig.APPLICATION_ID + "_channel_id";
|
static final String CHANNEL_ID = BuildConfig.APPLICATION_ID + "_channel_id";
|
||||||
|
|
||||||
private static final String DB_PATH = "XW_GAMES";
|
private static final String DB_PATH = "XW_GAMES";
|
||||||
private static final String HIDDEN_PREFS = "xwprefs_hidden";
|
private static final String HIDDEN_PREFS = "xwprefs_hidden";
|
||||||
|
|
|
@ -94,16 +94,23 @@ public class XWApp extends Application implements LifecycleObserver {
|
||||||
}
|
}
|
||||||
UpdateCheckReceiver.restartTimer( this );
|
UpdateCheckReceiver.restartTimer( this );
|
||||||
|
|
||||||
BTService.startService( this );
|
|
||||||
RelayService.startService( this );
|
RelayService.startService( this );
|
||||||
GCMIntentService.init( this );
|
GCMIntentService.init( this );
|
||||||
WiDirWrapper.init( this );
|
WiDirWrapper.init( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnLifecycleEvent(ON_ANY)
|
@OnLifecycleEvent(ON_ANY)
|
||||||
public void onAny(LifecycleOwner source, Lifecycle.Event event)
|
public void onAny( LifecycleOwner source, Lifecycle.Event event )
|
||||||
{
|
{
|
||||||
Log.d( TAG, "onAny(%s, %s)", source, event );
|
Log.d( TAG, "onAny(%s)", event );
|
||||||
|
switch( event ) {
|
||||||
|
case ON_RESUME:
|
||||||
|
BTService.onAppToForeground( this );
|
||||||
|
break;
|
||||||
|
case ON_STOP:
|
||||||
|
BTService.onAppToBackground( this );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is called on emulator only, but good for ensuring no memory leaks
|
// This is called on emulator only, but good for ensuring no memory leaks
|
||||||
|
|
|
@ -23,9 +23,7 @@ package org.eehouse.android.xw4;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.v4.app.JobIntentService;
|
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
@ -39,7 +37,7 @@ import org.eehouse.android.xw4.jni.UtilCtxtImpl;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
abstract class XWService extends JobIntentService {
|
abstract class XWService extends Service {
|
||||||
private static final String TAG = XWService.class.getSimpleName();
|
private static final String TAG = XWService.class.getSimpleName();
|
||||||
public static enum ReceiveResult { OK, GAME_GONE, UNCONSUMED };
|
public static enum ReceiveResult { OK, GAME_GONE, UNCONSUMED };
|
||||||
|
|
||||||
|
@ -48,21 +46,10 @@ abstract class XWService extends JobIntentService {
|
||||||
|
|
||||||
private UtilCtxt m_utilCtxt;
|
private UtilCtxt m_utilCtxt;
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public IBinder onBind( Intent intent )
|
|
||||||
// {
|
|
||||||
// IBinder result = null;
|
|
||||||
// if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ) {
|
|
||||||
// result = super.onBind( intent );
|
|
||||||
// }
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleWork(Intent intent)
|
public IBinder onBind( Intent intent )
|
||||||
{
|
{
|
||||||
Log.e( TAG, "%s.onHandleWork(%s); dropping!!!", getClass().getSimpleName(),
|
return null;
|
||||||
intent );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static void setListener( MultiService.MultiEventListener li )
|
public final static void setListener( MultiService.MultiEventListener li )
|
||||||
|
|
Loading…
Add table
Reference in a new issue