Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if WorkRequest has been previously enquequed by WorkManager Android

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.

like image 793
Bhavita Lalwani Avatar asked Jul 18 '18 11:07

Bhavita Lalwani


People also ask

How do I know if a manager is running or not?

You can check this by running getStatus() method on the WorkInfo instance. Calling the state immediately after enqueuing the WorkRequest will give the state as ENQUEUED and hence don't get any output data.

How do I cancel WorkManager on Android?

Stop a running Worker You explicitly asked for it to be cancelled (by calling WorkManager. cancelWorkById(UUID) , for example). In the case of unique work, you explicitly enqueued a new WorkRequest with an ExistingWorkPolicy of REPLACE . The old WorkRequest is immediately considered cancelled.

Which existing policy is available in WorkManager?

WorkManager PoliciesKEEP — keeps the existing unfinished WorkRequest. Enqueues it if one does not already exist. REPLACE — always replace the WorkRequest. Cancels and deletes the old one, if it exists.

Does WorkManager run when app is closed?

WorkManager is intended for tasks that require a guarantee that the system will run them even if the app exits, like uploading app data to a server. It is not intended for in-process background work that can safely be terminated if the app process goes away; for situations like that, we recommend using ThreadPools.


2 Answers

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

like image 149
Alex Avatar answered Sep 23 '22 05:09

Alex


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.

like image 33
pRaNaY Avatar answered Sep 21 '22 05:09

pRaNaY