Guy
Guy

Reputation: 12512

Canceling Unnamed, Non-Unique Periodic WorkRequests in Android WorkManager

In a previous iteration of our application, we implemented a periodic task using WorkManager as follows:

WorkManager.getInstance(context).enqueue(
    new PeriodicWorkRequest.Builder(OurClassName.class, 8, TimeUnit.HOURS)
        .setConstraints(constraints)
        .setInputData(OurClassName.getParameterBundle())
        .build()
);

This code snippet schedules a job that executes every 8 hours.

However, we've encountered an issue where these tasks cannot be canceled since they were not assigned a unique 'name' or 'tag'.

Complicating matters, due to a bug, this scheduling code was executed every time the app launched, resulting in a significant accumulation of identical, scheduled jobs.

Despite attempting to use both WorkManager and JobScheduler's cancelAll methods as a broad-stroke solution, the jobs persist.

How can we effectively cancel these periodically scheduled tasks, especially considering they lack unique identifiers?

Upvotes: 0

Views: 108

Answers (2)

Guy
Guy

Reputation: 12512

As it turned out, the aforementioned code, which does not specify a tag creates a enqueued job with a tag which equals to the full class name. i.e. in our example: com.x.y.z.OurClassName

Thus:

WorkManager.getInstance(context).cancelAllWorkByTag("com.x.y.z.OurClassName");

Cancels old jobs, at least in testing on devices with Android 26+.

(The WorkManager uses different implementations per different underlying android versions)

Upvotes: 0

darshan
darshan

Reputation: 4579

We've encountered an issue where these tasks cannot be canceled since they were not assigned a unique 'name' or 'tag'.

The WorkRequest created by the .build() function can be used to fetch the id to manage its operation via WorkManager instance. Example:

val periodicWorker = new PeriodicWorkRequest.Builder(OurClassName.class, 8, TimeUnit.HOURS)
        .setConstraints(constraints)
        .setInputData(OurClassName.getParameterBundle())
        .build()

val workId = periodicWorker.id;

Complicating matters, due to a bug, this scheduling code was executed every time the app launched, resulting in a significant accumulation of identical, scheduled jobs.

This is expected due to the use of enqueue. Using enqueueUniquePeriodicWork would work as expected.

For cancellations, see: https://developer.android.com/develop/background-work/background-tasks/persistent/how-to/manage-work#cancelling


Assuming you need to cancel all the previous WorkRequests (say on a new app update), you can use - WorkManager.getInstance(context).cancelAllWork() or WorkManager.getInstance(context).cancelAllWorkById(workId) if you have the IDs & then register the new WorkRequests via enqueueUniquePeriodicWork.

Disclaimer from the docs:

Cancels all unfinished work. Use this method with extreme caution! By invoking it, you will potentially affect other modules or libraries in your codebase. It is strongly recommended that you use one of the other cancellation methods at your disposal.

Upvotes: 0

Related Questions