Search code examples
androidkotlinserviceandroid-workmanager

Kotlin Start worker when onTaskRemoved


I have a service which gets called when the app is getting removed/closed. The service will start a OneTimeWorkRequest. Somehow the Workmanager will never start when onTaskRemoved is called.

Is there a way to make sure that when the app is killed the Workmanager gets to work?

This is my code: AndroidManifest.xml

<service android:name=".OnClearFromRecentService"
    android:enabled="true"
    android:exported="true"
    android:stopWithTask="false" />

OnClearFromRecentService.kt

class OnClearFromRecentService : Service() {

    override fun onBind(p0: Intent?): IBinder? {
        TODO("Not yet implemented")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d("log", "Service Started")
        return START_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("log", "Service Destroyed")
    }

    override fun onTaskRemoved(rootIntent: Intent?) {
        Log.d("log", "END")

        val request = OneTimeWorkRequestBuilder<BackgroundTask>()
            .addTag("oneTime")
            .build()
        WorkManager.getInstance(this).enqueue(request)
        
        stopSelf()
    }

}

Solution

  • I had the same problem as you that the worker is not executed and started experimenting. I found the following workaround, which simply has Thread.sleep() after the code. I suspect that the WorkManager needs additional time to schedule the request before the service is killed. From my understanding, after a work request is scheduled, it is guaranteed to execute independent of the app`s state

    I tested it multiple times and it always worked. One downside is that it usually takes ~30 seconds until the worker is executed. It seems that it takes some time because it is executed in a new process.

        @Override
        public void onTaskRemoved(Intent rootIntent) {
            Constraints constraint = new Constraints.Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build();
    
            WorkRequest workRequest = new OneTimeWorkRequest
                    .Builder(ServiceKilledJob.class)
                    .setConstraints(constraint)
                    .build();
    
            workManager.enqueue(workRequest);
    
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    

    P.S.: Code is in Java not Kotlin, but I think the workaround should work either way.

    Additional note: In this answer the author states that onTaskRemoved is not always called if android:stopWithTask is set to false. Therefore I suggest setting it true.