Skip to content Skip to sidebar Skip to footer

How To Restart Service After The App Is Killed From Recent Tasks

I have created a service to fetch current location of the device in periodic intervals. I want the service to run in the background even if the app is cleared from recently opened

Solution 1:

Override onTaskRemoved() in your service and use alarm manager to start the service again. Below is code from our app that does the same and works fine:

@OverridepublicvoidonTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);

    Log.d(TAG, "TASK REMOVED");

    PendingIntentservice= PendingIntent.getService(
            getApplicationContext(),
            1001,
            newIntent(getApplicationContext(), MyService.class),
            PendingIntent.FLAG_ONE_SHOT);

    AlarmManageralarmManager= (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
}  

As you may want to send location periodically even in the case if the service gets killed on low memory (or for any reason), I suggest you to handle the uncaughtException to restart it after N seconds. This is how we have done in our app that works perfectly:

private Thread.UncaughtExceptionHandler defaultUEH;
private Thread.UncaughtExceptionHandleruncaughtExceptionHandler=newThread.UncaughtExceptionHandler() {

    @OverridepublicvoiduncaughtException(Thread thread, Throwable ex) {
        Log.d(TAG, "Uncaught exception start!");
        ex.printStackTrace();

        //Same as done in onTaskRemoved()PendingIntentservice= PendingIntent.getService(
                getApplicationContext(),
                1001,
                newIntent(getApplicationContext(), MyService.class),
                PendingIntent.FLAG_ONE_SHOT);

        AlarmManageralarmManager= (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
        System.exit(2);
        }
    };

Note: I THINK and I remember I verified it on Kitkat that START_STICKY does not work on Kitkat and higher API levels. Please verify this for yourself.

MORE: As you do loc sending periodically, you may have to consider the deep sleep mode. To get things work in deep sleep, use WakefulBroadcastReceiver combined with AlarmManager. Take a look at my other post How to use http in deep sleep mode.

UPDATE: This solution does not work (in fact need not to work) if user "FORCE STOP" the application from Settings. This is good in fact as restarting the service is not a good way if user himself wants to stop application. So, it is fine.

Solution 2:

Solution 3:

If you ONLY want to restart service after it kill from Recent Task, simple use

@OverridepublicintonStartCommand(Intent intent, int flags, int startId) {
    return START_STICKY;
}

If you use START_STICKY, when you kill app from recent task, your service will be killed (onTaskRemoved fired, onDestroyNOT fired) THEN it will auto start again (onCreate fired, onStartComand fired)

Solution 4:

I use android 9 and the solution works partially for me. I had a case with foreground service (working 24/7), which I wanted to restart after the application was crashed. When the event uncaughtExceptionHandler was caught, the application got frozen besides public void onTaskRemoved(Intent rootIntent) { event doesn't work anymore in latest Android versions (I suppose O+). My application has only one activity with fragments if you need solution for more activities just use this link. To solve that problem I've added a function which checks if the activity is working (to kill it) and some instructions to kill the process:

classMyApplication : Application() {

    privatevar currentActivity: Activity? = nulloverridefunonCreate() {
        super.onCreate()
        StorageManager.init()

        this.registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            overridefunonActivityPaused(activity: Activity) {

            }

            overridefunonActivityStarted(activity: Activity) {
                currentActivity = activity
            }

            overridefunonActivityDestroyed(activity: Activity) {
            }

            overridefunonActivitySaveInstanceState(activity: Activity, outState: Bundle) {
            }

            overridefunonActivityStopped(activity: Activity) {
                currentActivity = null
            }

            overridefunonActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            }

            overridefunonActivityResumed(activity: Activity) {
            }
        })

        Thread.setDefaultUncaughtExceptionHandler { _, e ->
            // Close current activity
            currentActivity?.finish()

            val service : PendingIntent? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // Start service in Oreo and latest
                PendingIntent.getForegroundService(
                    applicationContext,
                    8888,
                    Intent(applicationContext, SensorService::class.java),
                    PendingIntent.FLAG_ONE_SHOT)
            } else {
                // Start service in Nougat and older
                PendingIntent.getService(
                    applicationContext,
                    8888,
                    Intent(applicationContext, MyService::class.java),
                    PendingIntent.FLAG_ONE_SHOT)
            }

            // The great solution introduced by @cgrval alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service)

            // Kill the current application process to avoid freezing activity
            android.os.Process.killProcess(android.os.Process.myPid())
            exitProcess(10)
        }
    }
}

Add to manifest:

    <application
        android:name="com.example.MyApplication"
        ...

Post a Comment for "How To Restart Service After The App Is Killed From Recent Tasks"