From bf53babf535d47ebb8f2d13a2d795635013729d6 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Wed, 14 Apr 2021 18:03:27 +0200 Subject: [PATCH] Create a service --- android/app/build.gradle | 1 - android/app/src/main/AndroidManifest.xml | 21 +++- .../communiquons/comunic/BootReceiver.java | 24 ++++ .../NotificationsChannel.java | 43 ++++++- .../NotificationsService.java | 107 ++++++++++++++++++ android/app/src/main/res/values/strings.xml | 4 + ...independent_push_notifications_helper.dart | 10 ++ lib/helpers/push_notifications_helper.dart | 8 +- 8 files changed, 206 insertions(+), 12 deletions(-) create mode 100644 android/app/src/main/java/org/communiquons/comunic/BootReceiver.java create mode 100644 android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsService.java create mode 100644 android/app/src/main/res/values/strings.xml diff --git a/android/app/build.gradle b/android/app/build.gradle index 1cf17cd..7a72e44 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -48,7 +48,6 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "org.communiquons.comunic" minSdkVersion 21 targetSdkVersion 30 diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f51463c..c451572 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -15,6 +15,11 @@ + + + + @@ -26,9 +31,6 @@ - - + + + + + + + + + diff --git a/android/app/src/main/java/org/communiquons/comunic/BootReceiver.java b/android/app/src/main/java/org/communiquons/comunic/BootReceiver.java new file mode 100644 index 0000000..63e9b00 --- /dev/null +++ b/android/app/src/main/java/org/communiquons/comunic/BootReceiver.java @@ -0,0 +1,24 @@ +package org.communiquons.comunic; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import org.communiquons.comunic.independentnotifications.NotificationsService; + +public class BootReceiver extends BroadcastReceiver { + private static final String TAG = BootReceiver.class.getSimpleName(); + + @Override + public void onReceive(Context context, Intent intent) { + if (intent == null || !intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { + Log.e(TAG, "Invalid call to intent!"); + return; + } + + Log.v(TAG, "Boot received, starting independent push notifications service if required..."); + + NotificationsService.startService(context); + } +} diff --git a/android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsChannel.java b/android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsChannel.java index afc0e99..a4c31a7 100644 --- a/android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsChannel.java +++ b/android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsChannel.java @@ -12,6 +12,7 @@ import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; public class NotificationsChannel implements MethodChannel.MethodCallHandler { + private final Context context; public NotificationsChannel(Activity context) { @@ -21,14 +22,27 @@ public class NotificationsChannel implements MethodChannel.MethodCallHandler { @Override public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) { try { - if (call.method.equals("needPreConfiguration")) - result.success(needPreConfiguration()); + switch (call.method) { + case "needPreConfiguration": + result.success(needPreConfiguration()); + break; - else if (call.method.equals("preConfigure")) - preConfigure(result); + case "preConfigure": + preConfigure(result); + break; - else - result.notImplemented(); + case "configure": + configure((String) call.arguments, result); + break; + + case "disable": + disable(result); + break; + + default: + result.notImplemented(); + break; + } } catch (Exception e) { e.printStackTrace(); result.error("Failed to execute native code!", e.getMessage(), null); @@ -60,4 +74,21 @@ public class NotificationsChannel implements MethodChannel.MethodCallHandler { result.success(null); } + /** + * Configure Independent Push Notifications service + * + * @param wsURL The URL this service will have to connect to + */ + private void configure(@NonNull String wsURL, @NonNull MethodChannel.Result result) { + NotificationsService.configure(wsURL, context); + result.success(null); + } + + /** + * Disable push notifications service + */ + private void disable(@NonNull MethodChannel.Result result) { + NotificationsService.disable(context); + result.success(null); + } } diff --git a/android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsService.java b/android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsService.java new file mode 100644 index 0000000..d870037 --- /dev/null +++ b/android/app/src/main/java/org/communiquons/comunic/independentnotifications/NotificationsService.java @@ -0,0 +1,107 @@ +package org.communiquons.comunic.independentnotifications; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Build; +import android.os.IBinder; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; +import androidx.core.content.ContextCompat; + +import org.communiquons.comunic.MainActivity; +import org.communiquons.comunic.R; + +public class NotificationsService extends Service { + public static final String CHANNEL_ID = "IndependentPushServiceChannel"; + private static final String INDEPENDENT_PUSH_NOTIFICATIONS_SERVICE = "independent-push-notifications-service"; + private static final String WS_URL_PREF_KEY = "ws_url"; + + public static void configure(@NonNull String wsURL, @NonNull Context context) { + SharedPreferences prefs = context.getSharedPreferences(INDEPENDENT_PUSH_NOTIFICATIONS_SERVICE, MODE_PRIVATE); + + if (prefs.getString(WS_URL_PREF_KEY, "").equals(wsURL)) + return; + + stopService(context); + prefs.edit().putString(WS_URL_PREF_KEY, wsURL).apply(); + startService(context); + } + + public static void disable(@NonNull Context context) { + SharedPreferences prefs = context.getSharedPreferences(INDEPENDENT_PUSH_NOTIFICATIONS_SERVICE, MODE_PRIVATE); + prefs.edit().remove(WS_URL_PREF_KEY).apply(); + + stopService(context); + } + + public static void stopService(@NonNull Context context) { + Intent serviceIntent = new Intent(context, NotificationsService.class); + context.stopService(serviceIntent); + } + + public static void startService(@NonNull Context context) { + SharedPreferences prefs = context.getSharedPreferences(INDEPENDENT_PUSH_NOTIFICATIONS_SERVICE, MODE_PRIVATE); + + if (!prefs.contains(WS_URL_PREF_KEY)) { + System.err.println("Independent push notifications service not configured ! Skipping!"); + return; + } + + Intent intent = new Intent(context, NotificationsService.class); + ContextCompat.startForegroundService(context, intent); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + createNotificationChannel(); + + Intent notificationIntent = new Intent(this, MainActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(this, + 0, notificationIntent, 0); + Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) + .setContentTitle("Comunic") + .setContentText(getText(R.string.independent_push_notification_notification_text)) + .setSmallIcon(R.drawable.splash_icon) + .setContentIntent(pendingIntent) + .build(); + startForeground(1, notification); + + initService(); + + return START_STICKY; + } + + private void createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel serviceChannel = new NotificationChannel( + CHANNEL_ID, + "Foreground Service Channel", + NotificationManager.IMPORTANCE_DEFAULT + ); + NotificationManager manager = getSystemService(NotificationManager.class); + manager.createNotificationChannel(serviceChannel); + } + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + private void initService() { + String url = getSharedPreferences(INDEPENDENT_PUSH_NOTIFICATIONS_SERVICE, MODE_PRIVATE) + .getString(WS_URL_PREF_KEY, null); + + System.out.println("START HEAVY WORK HERE !!!!"); + System.out.println("Connect to " + url); + } +} diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..7a44c66 --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Push notifications service is running + \ No newline at end of file diff --git a/lib/helpers/independent_push_notifications_helper.dart b/lib/helpers/independent_push_notifications_helper.dart index f118b4c..2119dce 100644 --- a/lib/helpers/independent_push_notifications_helper.dart +++ b/lib/helpers/independent_push_notifications_helper.dart @@ -26,4 +26,14 @@ class IndependentPushNotificationsHelper { await platform.invokeMethod("preConfigure"); } + + /// Configure independent push notification services with a pull URL + static Future configure(String wsURL) async { + await platform.invokeMethod("configure", wsURL); + } + + /// Disable independent push notifications service + static Future disable() async { + await platform.invokeMethod("disable"); + } } diff --git a/lib/helpers/push_notifications_helper.dart b/lib/helpers/push_notifications_helper.dart index f8037da..b513aa8 100644 --- a/lib/helpers/push_notifications_helper.dart +++ b/lib/helpers/push_notifications_helper.dart @@ -1,3 +1,4 @@ +import 'package:comunic/helpers/independent_push_notifications_helper.dart'; import 'package:comunic/helpers/preferences_helper.dart'; import 'package:comunic/helpers/server_config_helper.dart'; import 'package:comunic/models/api_request.dart'; @@ -39,7 +40,9 @@ class PushNotificationsHelper { if (status == null) status = PushNotificationsStatus.UNDEFINED; if (status == PushNotificationsStatus.INDEPENDENT) { - // TODO : Invoke plugin to apply new WebSocket URL + // Invoke plugin to apply new WebSocket URL + await IndependentPushNotificationsHelper.configure( + response["independent_push_url"]); } await (await PreferencesHelper.getInstance()).setString( @@ -51,7 +54,8 @@ class PushNotificationsHelper { await (await PreferencesHelper.getInstance()) .removeKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS); - // TODO : stop local refresh notification refresh + // Stop local refresh notification refresh + IndependentPushNotificationsHelper.disable(); } /// Set new push notification status on the server