mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-22 12:59:21 +00:00
Create a service
This commit is contained in:
parent
0af31bc3a0
commit
bf53babf53
@ -48,7 +48,6 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
|
||||||
applicationId "org.communiquons.comunic"
|
applicationId "org.communiquons.comunic"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||||
|
|
||||||
|
<!-- This is required for independent push notifications service to work
|
||||||
|
(when FCM service can not be used) -->
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
|
||||||
<!-- This is required on Android 11+ for image picker -->
|
<!-- This is required on Android 11+ for image picker -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
@ -26,9 +31,6 @@
|
|||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
<!-- This is required for independent push notifications service to work
|
|
||||||
(when FCM service can not be used) -->
|
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
|
||||||
|
|
||||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||||
@ -79,5 +81,18 @@
|
|||||||
android:name="com.yalantis.ucrop.UCropActivity"
|
android:name="com.yalantis.ucrop.UCropActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||||
|
|
||||||
|
<!-- Independent push notifications service -->
|
||||||
|
<service android:name=".independentnotifications.NotificationsService" />
|
||||||
|
|
||||||
|
<!-- Boot receiver to start independent push notifications service -->
|
||||||
|
<receiver android:name=".BootReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<!-- Cold boot -->
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@ import io.flutter.plugin.common.MethodCall;
|
|||||||
import io.flutter.plugin.common.MethodChannel;
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
|
||||||
public class NotificationsChannel implements MethodChannel.MethodCallHandler {
|
public class NotificationsChannel implements MethodChannel.MethodCallHandler {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
public NotificationsChannel(Activity context) {
|
public NotificationsChannel(Activity context) {
|
||||||
@ -21,14 +22,27 @@ public class NotificationsChannel implements MethodChannel.MethodCallHandler {
|
|||||||
@Override
|
@Override
|
||||||
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
|
||||||
try {
|
try {
|
||||||
if (call.method.equals("needPreConfiguration"))
|
switch (call.method) {
|
||||||
|
case "needPreConfiguration":
|
||||||
result.success(needPreConfiguration());
|
result.success(needPreConfiguration());
|
||||||
|
break;
|
||||||
|
|
||||||
else if (call.method.equals("preConfigure"))
|
case "preConfigure":
|
||||||
preConfigure(result);
|
preConfigure(result);
|
||||||
|
break;
|
||||||
|
|
||||||
else
|
case "configure":
|
||||||
|
configure((String) call.arguments, result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "disable":
|
||||||
|
disable(result);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
result.notImplemented();
|
result.notImplemented();
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
result.error("Failed to execute native code!", e.getMessage(), null);
|
result.error("Failed to execute native code!", e.getMessage(), null);
|
||||||
@ -60,4 +74,21 @@ public class NotificationsChannel implements MethodChannel.MethodCallHandler {
|
|||||||
result.success(null);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
4
android/app/src/main/res/values/strings.xml
Normal file
4
android/app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="independent_push_notification_notification_text">Push notifications service is running</string>
|
||||||
|
</resources>
|
@ -26,4 +26,14 @@ class IndependentPushNotificationsHelper {
|
|||||||
|
|
||||||
await platform.invokeMethod("preConfigure");
|
await platform.invokeMethod("preConfigure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configure independent push notification services with a pull URL
|
||||||
|
static Future<void> configure(String wsURL) async {
|
||||||
|
await platform.invokeMethod("configure", wsURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable independent push notifications service
|
||||||
|
static Future<void> disable() async {
|
||||||
|
await platform.invokeMethod("disable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:comunic/helpers/independent_push_notifications_helper.dart';
|
||||||
import 'package:comunic/helpers/preferences_helper.dart';
|
import 'package:comunic/helpers/preferences_helper.dart';
|
||||||
import 'package:comunic/helpers/server_config_helper.dart';
|
import 'package:comunic/helpers/server_config_helper.dart';
|
||||||
import 'package:comunic/models/api_request.dart';
|
import 'package:comunic/models/api_request.dart';
|
||||||
@ -39,7 +40,9 @@ class PushNotificationsHelper {
|
|||||||
if (status == null) status = PushNotificationsStatus.UNDEFINED;
|
if (status == null) status = PushNotificationsStatus.UNDEFINED;
|
||||||
|
|
||||||
if (status == PushNotificationsStatus.INDEPENDENT) {
|
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(
|
await (await PreferencesHelper.getInstance()).setString(
|
||||||
@ -51,7 +54,8 @@ class PushNotificationsHelper {
|
|||||||
await (await PreferencesHelper.getInstance())
|
await (await PreferencesHelper.getInstance())
|
||||||
.removeKey(PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS);
|
.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
|
/// Set new push notification status on the server
|
||||||
|
Loading…
Reference in New Issue
Block a user