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.

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();
        }