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);
minato
  • 2,028
  • 1
  • 18
  • 30
  • 1
    **But, the task is not executed after the app is killed.** It shouldn't executed! – Ibrahim Ali Mar 26 '19 at 03:56
  • [this](https://stackoverflow.com/questions/50682061/android-is-workmanager-running-when-app-is-closed) link might help, give it a try. – iCantC Mar 26 '19 at 04:14
  • @Ibrahim Ali, how to execute a task even after the app is killed? – minato Mar 26 '19 at 04:15
  • You can start a never ending background service , checkout this [link](https://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android) . – iCantC Mar 26 '19 at 04:27

2 Answers2

21

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".

minato
  • 2,028
  • 1
  • 18
  • 30
  • 3
    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? – fdhsdrdark Mar 05 '22 at 08:08
3

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)
    }
}
Mohan Sai Manthri
  • 2,808
  • 1
  • 11
  • 26
  • 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. – Ali Akber Aug 23 '22 at 15:53