mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-03 19:54:12 +00:00 
			
		
		
		
	Create a service
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,11 @@
 | 
			
		||||
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
 | 
			
		||||
    <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 -->
 | 
			
		||||
    <queries>
 | 
			
		||||
        <intent>
 | 
			
		||||
@@ -26,9 +31,6 @@
 | 
			
		||||
        </intent>
 | 
			
		||||
    </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
 | 
			
		||||
         calls FlutterMain.startInitialization(this); in its onCreate method.
 | 
			
		||||
@@ -79,5 +81,18 @@
 | 
			
		||||
            android:name="com.yalantis.ucrop.UCropActivity"
 | 
			
		||||
            android:screenOrientation="portrait"
 | 
			
		||||
            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>
 | 
			
		||||
</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;
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
		Reference in New Issue
	
	Block a user