diff --git a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java index 4f20fb7808..f337782bed 100644 --- a/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java +++ b/pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonService.java @@ -18,6 +18,21 @@ import org.renpy.android.Hardware; +import android.content.pm.PackageManager; +import android.support.v4.app.ActivityCompat; +import android.Manifest; +import android.app.NotificationChannel; +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; +import android.support.v4.app.NotificationCompat; +import android.graphics.Color; +import android.app.Service; +import android.content.ComponentName; +import android.app.PendingIntent; + +import android.graphics.drawable.Icon; +import android.provider.Settings; public class PythonService extends Service implements Runnable { @@ -35,6 +50,7 @@ public class PythonService extends Service implements Runnable { private String pythonServiceArgument; public static PythonService mService = null; private Intent startIntent = null; + private String NOTIFICATION_CHANNEL_ID = "BackgroundService"; private boolean autoRestartService = false; @@ -67,8 +83,13 @@ public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; } - startIntent = intent; + startIntent = intent; Bundle extras = intent.getExtras(); + + if (canDisplayNotification()) { + doStartForeground(extras); + } + androidPrivate = extras.getString("androidPrivate"); androidArgument = extras.getString("androidArgument"); serviceEntrypoint = extras.getString("serviceEntrypoint"); @@ -80,10 +101,6 @@ public int onStartCommand(Intent intent, int flags, int startId) { pythonThread = new Thread(this); pythonThread.start(); - if (canDisplayNotification()) { - doStartForeground(extras); - } - return startType(); } @@ -96,6 +113,7 @@ protected void doStartForeground(Bundle extras) { Intent contextIntent = new Intent(context, PythonActivity.class); PendingIntent pIntent = PendingIntent.getActivity(context, 0, contextIntent, PendingIntent.FLAG_UPDATE_CURRENT); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { notification = new Notification( context.getApplicationInfo().icon, serviceTitle, System.currentTimeMillis()); @@ -108,6 +126,25 @@ protected void doStartForeground(Bundle extras) { } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String channelName = "Service"; + NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_MIN); + chan.setLightColor(Color.BLUE); + chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); + + NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + assert manager != null; + manager.createNotificationChannel(chan); + + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, "persistent"); + notification = notificationBuilder.setOngoing(true) + .setSmallIcon(context.getApplicationInfo().icon) + .setContentTitle(serviceTitle) + .setContentIntent(pIntent) + .setPriority(Notification.PRIORITY_MIN) + .setShowWhen(false) + .setOnlyAlertOnce(true) + .build(); } else { Notification.Builder builder = new Notification.Builder(context); builder.setContentTitle(serviceTitle); @@ -127,17 +164,14 @@ public void onDestroy() { Log.v("python service", "service restart requested"); startService(startIntent); } - Process.killProcess(Process.myPid()); } /** - * Stops the task gracefully when killed. - * Calling stopSelf() will trigger a onDestroy() call from the system. + * Stops the task gracefully, but don t kill the process. */ @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); - stopSelf(); } @Override diff --git a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java index 3ed10c2690..9b1c62986e 100644 --- a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java +++ b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java @@ -11,8 +11,23 @@ import org.kivy.android.PythonService; import org.kivy.android.PythonActivity; +import android.content.pm.PackageManager; +import android.support.v4.app.ActivityCompat; +import android.Manifest; +import android.app.NotificationChannel; +import android.app.Notification; +import android.app.NotificationManager; +import android.content.Context; +import android.support.v4.app.NotificationCompat; +import android.graphics.Color; +import android.app.Service; +import android.content.ComponentName; +import android.app.PendingIntent; public class Service{{ name|capitalize }} extends PythonService { + + private boolean autoRestartService = true; + {% if sticky %} @Override public int startType() { @@ -46,6 +61,25 @@ protected void doStartForeground(Bundle extras) { } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + String channelName = "{{ name| capitalize }}"; + NotificationChannel chan = new NotificationChannel("{{ args.name }}", channelName, NotificationManager.IMPORTANCE_MIN); + chan.setLightColor(Color.BLUE); + chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); + + NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + assert manager != null; + manager.createNotificationChannel(chan); + + NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, "{{ args.name }}"); + notification = notificationBuilder.setOngoing(true) + .setSmallIcon(context.getApplicationInfo().icon) + .setContentTitle(channelName) + .setContentIntent(pIntent) + .setPriority(Notification.PRIORITY_MIN) + .setShowWhen(false) + .setOnlyAlertOnce(true) + .build(); } else { Notification.Builder builder = new Notification.Builder(context); builder.setContentTitle("{{ args.name }}"); @@ -53,7 +87,7 @@ protected void doStartForeground(Bundle extras) { builder.setContentIntent(pIntent); builder.setSmallIcon(context.getApplicationInfo().icon); notification = builder.build(); - } + } startForeground({{ service_id }}, notification); } @@ -67,9 +101,20 @@ static public void start(Context ctx, String pythonServiceArgument) { intent.putExtra("pythonHome", argument); intent.putExtra("pythonPath", argument + ":" + argument + "/lib"); intent.putExtra("pythonServiceArgument", pythonServiceArgument); - ctx.startService(intent); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + ctx.startForegroundService(intent); + } else { + ctx.startService(intent); + } } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + static public void stop(Context ctx) { Intent intent = new Intent(ctx, Service{{ name|capitalize }}.class); ctx.stopService(intent);