Check if WorkRequest has been previously enquequed by WorkManager Android
Asked Answered
R

4

18

I am using PeriodicWorkRequest to perform a task for me every 15 minutes. I would like to check, if this periodic work request has been previously scheduled. If not, schedule it.

     if (!PreviouslyScheduled) {
        PeriodicWorkRequest dataupdate = new PeriodicWorkRequest.Builder( DataUpdateWorker.class , 15 , TimeUnit.MINUTES).build();
        WorkManager.getInstance().enqueue(dataupdate);
      }

Previously when I was performing task using JobScheduler, I used to use

public static boolean isJobServiceScheduled(Context context, int JOB_ID ) {
    JobScheduler scheduler = (JobScheduler) context.getSystemService( Context.JOB_SCHEDULER_SERVICE ) ;

    boolean hasBeenScheduled = false ;

    for ( JobInfo jobInfo : scheduler.getAllPendingJobs() ) {
        if ( jobInfo.getId() == JOB_ID ) {
            hasBeenScheduled = true ;
            break ;
        }
    }

    return hasBeenScheduled ;
}

Need help constructing a similar module for work request to help find scheduled/active workrequests.

Rixdollar answered 18/7, 2018 at 11:41 Comment(0)
I
32

Set some Tag to your PeriodicWorkRequest task:

    PeriodicWorkRequest work =
            new PeriodicWorkRequest.Builder(DataUpdateWorker.class, 15, TimeUnit.MINUTES)
                    .addTag(TAG)
                    .build();

Then check for tasks with the TAG before enqueue() work:

    WorkManager wm = WorkManager.getInstance();
    ListenableFuture<List<WorkStatus>> future = wm.getStatusesByTag(TAG);
    List<WorkStatus> list = future.get();
    // start only if no such tasks present
    if((list == null) || (list.size() == 0)){
        // shedule the task
        wm.enqueue(work);
    } else {
        // this periodic task has been previously scheduled
    }

But if you dont really need to know that it was previously scheduled or not, you could use:

    static final String TASK_ID = "data_update"; // some unique string id for the task
    PeriodicWorkRequest work =
            new PeriodicWorkRequest.Builder(DataUpdateWorker.class,
                    15, TimeUnit.MINUTES)
                    .build();

    WorkManager.getInstance().enqueueUniquePeriodicWork(TASK_ID,
                ExistingPeriodicWorkPolicy.KEEP, work);

ExistingPeriodicWorkPolicy.KEEP means that the task will be scheduled only once and then work periodically even after device reboot. In case you need to re-schedule the task (for example in case you need to change some parameters of the task), you will need to use ExistingPeriodicWorkPolicy.REPLACE here

Incise answered 30/10, 2018 at 7:49 Comment(0)
N
1

You need to add a unique tag to every WorkRequest. Check Tagged work.

You can group your tasks logically by assigning a tag string to any WorkRequest object. For that you need to call WorkRequest.Builder.addTag()

Check below Android doc example:

OneTimeWorkRequest cacheCleanupTask =
    new OneTimeWorkRequest.Builder(MyCacheCleanupWorker.class)
.setConstraints(myConstraints)
.addTag("cleanup")
.build();

Same you can use for PeriodicWorkRequest

Then, You will get a list of all the WorkStatus for all tasks with that tag using WorkManager.getStatusesByTag().

Which gives you a LiveData list of WorkStatus for work tagged with a tag.

Then you can check status using WorkStatus as below:

       WorkStatus workStatus = listOfWorkStatuses.get(0);

        boolean finished = workStatus.getState().isFinished();
        if (!finished) {
            // Work InProgress
        } else {
            // Work Finished
        }

You can check below google example for more details. Here they added how to add a tag to WorkRequest and get status of work by tag :

https://github.com/googlecodelabs/android-workmanager

Edits Check below code and comment to how we can get WorkStatus by tag. And schedule our Work if WorkStatus results empty.

 // Check work status by TAG
    WorkManager.getInstance().getStatusesByTag("[TAG_STRING]").observe(this, listOfWorkStatuses -> {

        // Note that we will get single WorkStatus if any tag (here [TAG_STRING]) related Work exists

        // If there are no matching work statuses
        // then we make sure that periodic work request has been previously not scheduled
        if (listOfWorkStatuses == null || listOfWorkStatuses.isEmpty()) {
           // we can schedule our WorkRequest here
            PeriodicWorkRequest dataupdate = new PeriodicWorkRequest.Builder( DataUpdateWorker.class , 15 , TimeUnit.MINUTES)
                    .addTag("[TAG_STRING]")
                    .build();
            WorkManager.getInstance().enqueue(dataupdate);
            return;
        }

        WorkStatus workStatus = listOfWorkStatuses.get(0);
        boolean finished = workStatus.getState().isFinished();
        if (!finished) {
            // Work InProgress
        } else {
            // Work Finished
        }
    });

I have not tested code. Please provide your feedback for the same.

Hope this helps you.

Neva answered 19/7, 2018 at 6:13 Comment(1)
Thank you for answering. But AFAIK you will receive isFinished true if state is in Succeeded , Failed or cancelled state. So, this may give erroneous results say when the workrequest was cancelled and no more scheduled it would give true and say when task is not added it will give false. We need some approach, where we can find out if the task is scheduled/enqueued.Rixdollar
I
0

I was also searching for the same condition.I couldn't find one.So in order to solve this problem i found a mechanism.First cancel all scheduled works and reschedule the work again. So that we can ensure that only one instance of your work will be maintained. Also please be ensure that you have to maintain your worker code logic like that.

For canceling a work. For more

UUID compressionWorkId = compressionWork.getId();
WorkManager.getInstance().cancelWorkById(compressionWorkId);
Indium answered 19/7, 2018 at 6:12 Comment(5)
Instead of cancelling work, you can add tag to request and check status by tag. My answer may helps you.Neva
Okay. But the developer needs make his current work to a pending event if the previous work is not finished right? I don't think there is no other mechanism to attach extra work to currently occurring work. I also had a situation to handle this kind of logic and I have solved it by canceling and rescheduling it. @NevaIndium
Thank you for answer and approach. But I dont think, I want to cancel my task everytime and reschedule it, this would somehow break periodic property. I just want to know if some task has been scheduled or not.Rixdollar
Okay @BhavitaLalwaniIndium
@AtHulAntony Please check my updated answer. May helps you.Neva
D
0

keep same taskID with ExistingPeriodicWorkPolicy.KEEP will not create new task each time .

 WorkManager.getInstance().enqueueUniquePeriodicWork(TASK_ID,
                ExistingPeriodicWorkPolicy.KEEP, work);
Doenitz answered 22/7, 2020 at 6:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.