Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WorkManager.getInstance().cancelAllWorkByTag() not stopping the periodic job

for periodic task I am using work manager as:

PeriodicWorkRequest.Builder wifiWorkBuilder =
                            new PeriodicWorkRequest.Builder(FileUpload.class, 15,
                                    TimeUnit.MINUTES)
                                    .setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.METERED).build());
                    PeriodicWorkRequest wifiWork = wifiWorkBuilder.build();
                    WorkManager.getInstance().enqueueUniquePeriodicWork("wifiJob", ExistingPeriodicWorkPolicy.REPLACE, wifiWork);

I have one activity in that activity one check box is there if user unselect checkbox then I want to stop this job. So I am stopping job like:

WorkManager.getInstance().cancelAllWorkByTag("wifiJob");

But after stopping job also my task is executing. Previously I thought might be next job will be executed and after that it will stop but in last 1 hour it executed 4 times and still job is running in background. What is other way or correct way to stop job.

as per Docs:

Cancels all unfinished work with the given tag. Note that cancellation is a best-effort policy and work that is already executing may continue to run.

What is the meaning of this - cancellation is a best-effort policy and work that is already executing may continue to run. So what is the correct way to stop this

I am using version implementation "android.arch.work:work-runtime:1.0.0-alpha08" Thanks in advance

like image 686
PPD Avatar asked Sep 07 '18 08:09

PPD


3 Answers

While creating PeriodicWorkRequest i had added addTag() and to cancel task used same tag name, using this it cancel pending work. So my code is like:

PeriodicWorkRequest.Builder wifiWorkBuilder =
                            new PeriodicWorkRequest.Builder(FileUpload.class, 15,
                                    TimeUnit.MINUTES)
                                    .addTag("WIFIJOB1")
                                    .setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.METERED).build());
                    wifiWork = wifiWorkBuilder.build();
                    WorkManager.getInstance().enqueueUniquePeriodicWork("wifiJob", ExistingPeriodicWorkPolicy.REPLACE, wifiWork);

To stop job I am using:

WorkManager.getInstance().cancelAllWorkByTag("WIFIJOB1");
like image 192
PPD Avatar answered Sep 18 '22 20:09

PPD


I believe the problem you are having here is answered in this duplicate question.

In summary, if you have a pending worker which hasn't started yet, the worker will be cancelled and will not run. However if the worker is already running, cancelling work does not terminate the worker in a hard fashion - it simply sets the state flag of the worker to CANCELLED, as explained in the docs. It is up to you to handle the cancellation inside your doWork and terminate the worker.

One way to do this is to put a few checks in your doWork method to check if the worker has been cancelled, by calling isStopped(). If isStopped is true, return from the method with a Result instead of continuing with the rest of the work.

like image 45
James Allen Avatar answered Sep 20 '22 20:09

James Allen


I've been checking the official Android docs: https://developer.android.com/reference/androidx/work/WorkManager

There are two types of work supported by WorkManager: OneTimeWorkRequest and PeriodicWorkRequest.

You can enqueue requests using WorkManager as follows:

 WorkManager workManager = WorkManager.getInstance();
 workManager.enqueue(new OneTimeWorkRequest.Builder(FooWorker.class).build());

A WorkRequest has an associated id that can be used for lookups and observation as follows:

WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 workManager.enqueue(request);
 LiveData<WorkStatus> status = workManager.getStatusById(request.getId());
 status.observe(...);

You can also use the id for cancellation:

WorkRequest request = new OneTimeWorkRequest.Builder(FooWorker.class).build();
 workManager.enqueue(request);
 workManager.cancelWorkById(request.getId());

And here you can see a different ways to cancel a enqueued work:

enter image description here

Maybe you also can try to cancel a enqueued or blocked job using the State of the job:

WorkStatus workStatus = WorkManager.getInstance().getStatusById(wifiWork.getId()).getValue();
        if(workStatus.getState() == State.ENQUEUED || workStatus.getState() == State.BLOCKED){
            WorkManager.getInstance().cancelWorkById(wifiWork.getId());

        }

I hope it helps you.

like image 24
Juanjo Berenguer Avatar answered Sep 19 '22 20:09

Juanjo Berenguer