Arian A
Arian A

Reputation: 41

Fatal Exception: android.app.RemoteServiceException Context.startForegroundService() did not then call Service.startForeground()

We recently implemented foreground service and on Android 9 (Samsung devices only) some users experience some recurring crashes and we don't know what's causing this. Has anyone encountered the same issue? Is there a fix for this issue?

Fatal Exception: android.app.RemoteServiceException Context.startForegroundService() did not then call Service.startForeground()
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1874)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loop (Looper.java:214)
android.app.ActivityThread.main (ActivityThread.java:7073)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:964)

AndroidManigest.xml

<service
        android:name="com.sotg.base.util.GeoNotification"
        android:exported="true"
        android:foregroundServiceType="location" />

GeoNotificationManager.kt

    override fun startService() {
        val geoService = Intent(context, GeoNotification::class.java)
        geoService.action = GeoNotification.START_SERVICE_ACTION

        // for android Oreo and higher start as foreground
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(geoService)
        } else {
            context.startService(geoService)
        }
    }

    override fun stopService() {

        // Shouldn't initialize the service to stop it when the service is not running.
        if (!GeoNotification.isServiceRunning()) return;

        val geoService = Intent(context, GeoNotification::class.java)
        geoService.action = GeoNotification.STOP_TRACKING_ACTION
        runCatching { context.startService(geoService) }
                .onFailure(analytics::logException)
    }

GoeNotification.java

    private static boolean isServiceRunning;

    public static boolean isServiceRunning() {
        return isServiceRunning;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        isServiceRunning = false;
    }

    @Override
    public void onDestroy() {
        stopTracking();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (START_SERVICE_ACTION.equals(intent.getAction())) {
            startTracking();
        } else if (STOP_TRACKING_ACTION.equals(intent.getAction())) {
            stopTracking();
        } else {
            Log.w(TAG, "Unknown action for location service");
        }

        // Service restarts if it gets terminated
        // the original Intent is re-delivered to the onStartCommand
        // method when using START_REDELIVER_INTENT.
        return START_REDELIVER_INTENT;
    }

 private void startTracking() {

        if (isServiceRunning) return;

        // create notification and config as foreground only for android Oreo and higher
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForeground(Constants.NOTIFY_SURVEY_GCM, createForegroundNotification(this));
        }

        isServiceRunning = true;

       ...
    }

    private void stopTracking() {

        if (!isServiceRunning) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                stopForeground(true);
            }
            stopSelf();
            return;
        }

        // stop location updates on partner SDKs
       ....
        stopSelf();
        isServiceRunning = false;
    }

    public static Notification createForegroundNotification(Context context) {
            NotificationChannelUtil.INSTANCE.getPreparedManager(context);
            String channel = NotificationChannelUtil.INSTANCE.getSYSTEM_CHANNEL_ID();

            // The PendingIntent to launch activity.
            PendingIntent activityPendingIntent = PendingIntent.getActivity(context, 0,
                    new Intent(context, MainTabActivity.class), 0);

            NotificationCompat.Action settingsAction = NotificationUtil.createSettingAction(context);

            String title = context.getResources().getString(R.string.foreground_service_notification_title);
            String desc = context.getResources().getString(R.string.foreground_service_notification_description);
            String expandedText = context.getResources().getString(R.string.foreground_service_notification_description_expanded);

            NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channel)
                    .setContentIntent(activityPendingIntent)
                    .setSmallIcon(R.drawable.noti)
                    .setContentTitle(title)
                    .setContentText(desc)
                    .setStyle(new NotificationCompat.BigTextStyle()
                            .bigText(expandedText))
                    .addAction(settingsAction)
                    .setColorized(false)
                    .setOngoing(true);

            return builder.build();
        }

Upvotes: 4

Views: 4983

Answers (2)

Eyvind Almqvist
Eyvind Almqvist

Reputation: 332

This happens even if a notification is launched with startForeground(). This problem is caused by bugs in the software on some devices. So it can not be solved in the app code. The only realistic solution is to go to crashes and ANR on the play developer console and find the problem devices. Then go to device manager on the same developer console and exclude those devices. I have seen that Huawei HUAWEI Y5 causes a lot of these crashes.

Upvotes: 0

Fatih
Fatih

Reputation: 132

I had the same problem with Samsung and Huawei devices with Android Oreo or above. I would get the same errors.

If I remember correctly, since Android Oreo and above it is required to make use of startForeground() when using startService() or startForegroundService().

I solved it by adding the following code to the onCreate function of the service class. I created a notification and launched it with startForeground().

   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    NotificationChannel mNotificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_NONE);
    mNotificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    mNotificationManager.createNotificationChannel(mNotificationChannel);
    Notification note = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Reboot Sequence")
            .setContentText("Rescheduling Alarms")
            .setSmallIcon(R.drawable.ic_alarm_24dp)
            .build();
    startForeground(1, note);
}

I hope this will help you.

Upvotes: 2

Related Questions