From 7a7d8ee9ec3450c377c473e5a1b14b4db6932efa Mon Sep 17 00:00:00 2001 From: Jonas Thiem Date: Tue, 25 Jun 2019 14:06:19 +0200 Subject: [PATCH] Fix foreground notification being mandatory and more. Details: - Fixes that right now the service always slaps up a notification without this being configurable at runtime. It only is configurable right now if setting the foreground property via --service, which cannot be done when using the simpler service/main.py entrypoint - Fixes service_only service code template not rendering .foreground correctly since it added an outdated, useless function name override - Fixes notification channel name which is visible to end user hardcoding "python" in its name which is not ideal for end user naming (since the average user might not even know what python is) - Fixes override of doStartForeground() leading to quite some error-prone code duplication --- .../java/org/kivy/android/PythonService.java | 33 ++++++++---- .../common/build/templates/Service.tmpl.java | 52 ++++--------------- .../java/org/kivy/android/PythonActivity.java | 22 +++++++- .../java/org/kivy/android/PythonActivity.java | 22 +++++++- .../build/templates/Service.tmpl.java | 16 +++--- .../java/org/kivy/android/PythonActivity.java | 22 +++++++- 6 files changed, 101 insertions(+), 66 deletions(-) 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 7456c617b3..89ba8de4b5 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 @@ -35,8 +35,11 @@ public class PythonService extends Service implements Runnable { private String pythonHome; private String pythonPath; private String serviceEntrypoint; + private boolean serviceStartAsForeground; // Argument to pass to Python code, private String pythonServiceArgument; + + public static PythonService mService = null; private Intent startIntent = null; @@ -46,10 +49,6 @@ public void setAutoRestartService(boolean restart) { autoRestartService = restart; } - public boolean canDisplayNotification() { - return true; - } - public int startType() { return START_NOT_STICKY; } @@ -79,21 +78,35 @@ public int onStartCommand(Intent intent, int flags, int startId) { pythonName = extras.getString("pythonName"); pythonHome = extras.getString("pythonHome"); pythonPath = extras.getString("pythonPath"); + serviceStartAsForeground = ( + extras.getString("serviceStartAsForeground") == "true" + ); pythonServiceArgument = extras.getString("pythonServiceArgument"); - pythonThread = new Thread(this); pythonThread.start(); - if (canDisplayNotification()) { + if (serviceStartAsForeground) { doStartForeground(extras); } return startType(); } + protected String getServiceNotificationTitleFromParams(Bundle extras) { + return extras.getString("serviceTitle"); + } + + protected String getServiceNotificationDescription(Bundle extras) { + return extras.getString("serviceDescription"); + } + + protected int getServiceId() { + return 1; + } + protected void doStartForeground(Bundle extras) { - String serviceTitle = extras.getString("serviceTitle"); - String serviceDescription = extras.getString("serviceDescription"); + String serviceTitle = getServiceNotificationTitleFromParams(extras); + String serviceDescription = getServiceNotificationDescription(extras); Notification notification; Context context = getApplicationContext(); Intent contextIntent = new Intent(context, PythonActivity.class); @@ -116,7 +129,7 @@ protected void doStartForeground(Bundle extras) { // for android 8+ we need to create our own channel // https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1 String NOTIFICATION_CHANNEL_ID = "org.kivy.p4a"; //TODO: make this configurable - String channelName = "PythonSerice"; //TODO: make this configurable + String channelName = "Background Service"; //TODO: make this configurable NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE); @@ -132,7 +145,7 @@ protected void doStartForeground(Bundle extras) { builder.setSmallIcon(context.getApplicationInfo().icon); notification = builder.build(); } - startForeground(1, notification); + startForeground(getServiceId(), notification); } @Override diff --git a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java index 3ed10c2690..987742f899 100644 --- a/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java +++ b/pythonforandroid/bootstraps/common/build/templates/Service.tmpl.java @@ -1,15 +1,8 @@ package {{ args.package }}; -import android.os.Build; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; import android.content.Intent; import android.content.Context; -import android.app.Notification; -import android.app.PendingIntent; -import android.os.Bundle; import org.kivy.android.PythonService; -import org.kivy.android.PythonActivity; public class Service{{ name|capitalize }} extends PythonService { @@ -20,41 +13,9 @@ public int startType() { } {% endif %} - {% if not foreground %} - @Override - public boolean canDisplayNotification() { - return false; - } - {% endif %} - - @Override - protected void doStartForeground(Bundle extras) { - Notification notification; - Context context = getApplicationContext(); - 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, "{{ args.name }}", System.currentTimeMillis()); - try { - // prevent using NotificationCompat, this saves 100kb on apk - Method func = notification.getClass().getMethod( - "setLatestEventInfo", Context.class, CharSequence.class, - CharSequence.class, PendingIntent.class); - func.invoke(notification, context, "{{ args.name }}", "{{ name| capitalize }}", pIntent); - } catch (NoSuchMethodException | IllegalAccessException | - IllegalArgumentException | InvocationTargetException e) { - } - } else { - Notification.Builder builder = new Notification.Builder(context); - builder.setContentTitle("{{ args.name }}"); - builder.setContentText("{{ name| capitalize }}"); - builder.setContentIntent(pIntent); - builder.setSmallIcon(context.getApplicationInfo().icon); - notification = builder.build(); - } - startForeground({{ service_id }}, notification); + @override + protected int getServiceId() { + return {{ service_id }}; } static public void start(Context ctx, String pythonServiceArgument) { @@ -62,8 +23,15 @@ static public void start(Context ctx, String pythonServiceArgument) { String argument = ctx.getFilesDir().getAbsolutePath() + "/app"; intent.putExtra("androidPrivate", ctx.getFilesDir().getAbsolutePath()); intent.putExtra("androidArgument", argument); + intent.putExtra("serviceTitle", "{{ args.name }}"); + intent.putExtra("serviceDescription", "{{ name|capitalize }}"); intent.putExtra("serviceEntrypoint", "{{ entrypoint }}"); intent.putExtra("pythonName", "{{ name }}"); + {% if foreground %} + intent.putExtra("serviceStartAsForeground", "true"); + {% else %} + intent.putExtra("serviceStartAsForeground", "false"); + {% endif %} intent.putExtra("pythonHome", argument); intent.putExtra("pythonPath", argument + ":" + argument + "/lib"); intent.putExtra("pythonServiceArgument", pythonServiceArgument); diff --git a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java index 425923433f..dc76b50806 100644 --- a/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/sdl2/build/src/main/java/org/kivy/android/PythonActivity.java @@ -365,8 +365,23 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent) } } - public static void start_service(String serviceTitle, String serviceDescription, - String pythonServiceArgument) { + public static void start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument + ) { + // This is the legacy call with less parameters! + start_service( + serviceTitle, serviceDescription, pythonServiceArgument, true + ); + } + + public static void start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument, + boolean showForegroundNotification + ) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String filesDirectory = argument; @@ -378,6 +393,9 @@ public static void start_service(String serviceTitle, String serviceDescription, serviceIntent.putExtra("pythonName", "python"); serviceIntent.putExtra("pythonHome", app_root_dir); serviceIntent.putExtra("pythonPath", app_root_dir + ":" + app_root_dir + "/lib"); + serviceIntent.putExtra("serviceStartAsForeground", + (showForegroundNotification ? "true" : "false") + ); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); diff --git a/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java index 8e45967616..82abed480c 100644 --- a/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/service_only/build/src/main/java/org/kivy/android/PythonActivity.java @@ -380,8 +380,23 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent) } } - public static void start_service(String serviceTitle, String serviceDescription, - String pythonServiceArgument) { + public static void start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument + ) { + // This is the legacy call with less parameters! + start_service( + serviceTitle, serviceDescription, pythonServiceArgument, true + ); + } + + public static void start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument, + boolean showForegroundNotification + ) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String filesDirectory = argument; @@ -393,6 +408,9 @@ public static void start_service(String serviceTitle, String serviceDescription, serviceIntent.putExtra("pythonName", "python"); serviceIntent.putExtra("pythonHome", app_root_dir); serviceIntent.putExtra("pythonPath", app_root_dir + ":" + app_root_dir + "/lib"); + serviceIntent.putExtra("serviceStartAsForeground", + (showForegroundNotification ? "true" : "false") + ); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument); diff --git a/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java b/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java index ecbf3fe961..53da35ba29 100644 --- a/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java +++ b/pythonforandroid/bootstraps/service_only/build/templates/Service.tmpl.java @@ -22,15 +22,10 @@ public int startType() { } {% endif %} - {% if foreground %} - /** - * {@inheritDoc} - */ - @Override - public boolean getStartForeground() { - return true; + @override + protected int getServiceId() { + return {{ service_id }}; } - {% endif %} public static void start(Context ctx, String pythonServiceArgument) { String argument = ctx.getFilesDir().getAbsolutePath() + "/app"; @@ -41,6 +36,11 @@ public static void start(Context ctx, String pythonServiceArgument) { intent.putExtra("serviceTitle", "{{ name|capitalize }}"); intent.putExtra("serviceDescription", ""); intent.putExtra("pythonName", "{{ name }}"); + {% if foreground %} + intent.putExtra("serviceStartAsForeground", "true"); + {% else %} + intent.putExtra("serviceStartAsForeground", "false"); + {% endif %} intent.putExtra("pythonHome", argument); intent.putExtra("androidUnpack", argument); intent.putExtra("pythonPath", argument + ":" + argument + "/lib"); diff --git a/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java b/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java index effa54cf36..eac46a71ae 100644 --- a/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java +++ b/pythonforandroid/bootstraps/webview/build/src/main/java/org/kivy/android/PythonActivity.java @@ -437,8 +437,23 @@ protected void onActivityResult(int requestCode, int resultCode, Intent intent) } } - public static void start_service(String serviceTitle, String serviceDescription, - String pythonServiceArgument) { + public static void start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument + ) { + // This is the legacy call with less parameters! + start_service( + serviceTitle, serviceDescription, pythonServiceArgument, true + ); + } + + public static void start_service( + String serviceTitle, + String serviceDescription, + String pythonServiceArgument, + boolean showForegroundNotification + ) { Intent serviceIntent = new Intent(PythonActivity.mActivity, PythonService.class); String argument = PythonActivity.mActivity.getFilesDir().getAbsolutePath(); String filesDirectory = argument; @@ -450,6 +465,9 @@ public static void start_service(String serviceTitle, String serviceDescription, serviceIntent.putExtra("pythonName", "python"); serviceIntent.putExtra("pythonHome", app_root_dir); serviceIntent.putExtra("pythonPath", app_root_dir + ":" + app_root_dir + "/lib"); + serviceIntent.putExtra("serviceStartAsForeground", + (showForegroundNotification ? "true" : "false") + ); serviceIntent.putExtra("serviceTitle", serviceTitle); serviceIntent.putExtra("serviceDescription", serviceDescription); serviceIntent.putExtra("pythonServiceArgument", pythonServiceArgument);