Work Manager not working when app is killed by the user. Why?
Asked Answered
B

2

21

I want to execute a task, even after the application is killed using work manager. But, the task is not executed after the app is killed.

    workManager = WorkManager.getInstance();
    Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
    OneTimeWorkRequest saveData = new OneTimeWorkRequest.Builder(SaveDataWorker.class).setConstraints(constraints).setInitialDelay(10,TimeUnit.SECONDS).build();
    workManager.enqueue(saveData);
Bloodred answered 26/3, 2019 at 3:35 Comment(4)
But, the task is not executed after the app is killed. It shouldn't executed!Soekarno
this link might help, give it a try.Flaxen
@Ibrahim Ali, how to execute a task even after the app is killed?Bloodred
You can start a never ending background service , checkout this link .Flaxen
B
24

As I found out, the work manager depends on the device manufacturer. In my case, it is an miui device, which does not allow work manager to work in case the app is killed or rebooted. The work manager worked when I provided the application with "autostart permission".

Bloodred answered 27/3, 2019 at 6:4 Comment(1)
Just a question: Is there a way to know if the work manager is allowed to work in case the app is killed or not before hand? That is before the enqueue?Spelling
D
4

Work manager completely depends upon the manufacturer, Some manufacturers or you can also say devices with stock ROM were allowing work manager to work as it should be, but there are some devices manufacturers ("Chinese ROM's") were very aggressive while clearing the background apps, they're even killing the work manager, however, Google is trying to make work manager work normally on all devices by talking with OEM's.

As of now If you really want to run anything in the background, you can turn on autostart option in xiaomi & some other devices or else you can also show a notification in notification tray which makes an app to run in the foreground. you can check whether the app is still running in the background or not, if not you can restart it.

if (!isServiceRunning(this, MyService::class.java)) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(Intent(this, MyService::class.java))
        } else {
            startService(Intent(this, MyService::class.java))
        }

    }


 private fun isServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
    val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    val services = activityManager.getRunningServices(Integer.MAX_VALUE)

    if (services != null) {
        for (i in services.indices) {
            if (serviceClass.name == services[i].service.className && services[i].pid != 0) {
                return true
            }
        }
    }
    return false
}


 val am = getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val pi = PendingIntent.getBroadcast(
        applicationContext,
        34,
        Intent(this, MyBroadcastReceiver::class.java),
        PendingIntent.FLAG_UPDATE_CURRENT
    )
    am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, pi)

And Finally in Broadcast receiver.

 override fun onReceive(context: Context?, intent: Intent?) {
    Handler(Looper.getMainLooper()).post {
        if (!isServiceRunning(context!!, MyService::class.java)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(Intent(context, MyService::class.java))
            } else {
                context.startService(Intent(context, MyService::class.java))
            }
        }
        val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val pi = PendingIntent.getBroadcast(
            context, 34, Intent(context, MyBroadcastReceiver::class.java),
            PendingIntent.FLAG_UPDATE_CURRENT
        )
        am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5000, pi)
    }
}
Devisal answered 21/5, 2019 at 4:41 Comment(1)
Where does this bit of code go? ``` val am = getSystemService(Context.ALARM_SERVICE) as AlarmManager val pi = PendingIntent.getBroadcast( applicationContext, 34, Intent(this, MyBroadcastReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT ) am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, pi) ``` As far as I understood, this part is responsible for sending the broadcast when the app is terminated. But I'm not sure where to put this.Softcover

© 2022 - 2024 — McMap. All rights reserved.