Android WorkManager - how to delay task?
Asked Answered
E

3

12

I am building a functionality that will allow merchants to set the schedule of their business. Such functionality would automatically change the variable open to true and false accordingly to the times the merchant set in each day of the week. Therefore, there would be a total of 14 possible different times.

I am trying to build a recurrent background task that would accomplish such a thing using WorkManager, the new Android Architecture Components library.

val scheduleStartWork = PeriodicWorkRequest.Builder(ScheduleWorker::class.java, 7, TimeUnit.DAYS)
                .setInputData(Data.Builder().putBoolean("isStart", true).build())
                .setScheduleRequestedAt(diff_time, TimeUnit.MILLISECONDS)
                .addTag(weekdays[index])
                .build()

It's giving me the following APILibraryException error though:

Builder.setScheduleRequestedAt can only be called from within the same library group

My questions:

1) Is it setScheduleRequestedAt the right method to call if I want to delay the scheduling by diff_time?

2) If so, how can I solve this problem?

PS: diff_time is the difference, in milliseconds, to each of the corresponding hours of each day set by the user. Example: Monday-Friday = 08:00, Sat-Sun= 10:00.

Epigene answered 29/10, 2018 at 15:4 Comment(4)
I can't find this method in the Javadoc developer.android.com/reference/androidx/work/…Hancock
Yeah :/ I didn't find either but this method exists when writing code. Is there any other method though that can delay the scheduling?Epigene
There probably isn't a way to schedule a repeated task with an initial delay. There's no such functionality in JobScheduler and WorkManager is a layer above it.Hancock
But there's such a functionality in AlarmManager and WorkManager is a layer above it as well, right?Epigene
S
19

UPDATE

Since WorkManager v2.1-alpha02 it is now possible add an initial delay to a PeriodicWorkRequest. Now your call became simply:

val scheduleStartWork = PeriodicWorkRequest.Builder(ScheduleWorker::class.java, 7, TimeUnit.DAYS)
                .setInputData(Data.Builder().putBoolean("isStart", true).build())
                .setInitialDelay(diff_time, TimeUnit.MILLISECONDS)
                .addTag(weekdays[index])
                .build()

Note because the setInitialDelay has been introduced in the parent class, WorkRequest, this introduced a binary change moving from v2.0 to v2.1 for the OneTimeWorkRequest#setInitialDelay() method. This means that to use the new library you need to recompile the project when upgrading from v2.0.

Follows original answer

It's not possible to delay the first run of a periodic task with WorkManager.

Your best option is to use a OneTimeWorker with the delay that you want and from there you can enqueue your periodic worker with the period you want.

There's a feature request on WorkManager's issue tracker with an explanation for this workaround that you can use as a reference.

Note: because of how the minimum interval works, you cannot build a periodic work request that is executed at a recurring time, e.g. every day at 4:00 AM. You can specify a 24 hours repeat interval, but this can get the worker executed at 4:05AM the first day, 6:00AM the second, 6:10 AM the third day and so on. If you need to execute a worker at the same time every day, your best option is to use a OneTimeWorkRequest with an initial delay:

OneTimeWorkRequest save = new OneTimeWorkRequest
            .Builder(SaveImageToFileWorker.class)
            .setConstraints(constraints)
            .setInitialDelay(24, TimeUnit.HOURS)
            .addTag(TAG_OUTPUT)
            .build();

When the worker has been completed, you can reschedule it with a Delay so that it is going to be fired at the correct time (the exact time that the worker is going to be executed depends on the constraints that you’re using when creating the work request).

Saccharose answered 30/10, 2018 at 11:18 Comment(1)
can you please look my issueGrados
H
2

You need to update the work manager library version to 2.1.0-alpha03. In the version WorkManager provides the functionality to add initial delay in task.

Then you need to use the method setInitialDelay(). Following is the implementation to use the same in a way to achieve specific time trigger work:

long initialDelayInSeconds = (futureSpecificTime - System.currentTimeInMills()) / 1000;

PeriodicWorkRequest workRequest =
                new PeriodicWorkRequest.Builder(WorkerClass.class, interval, TimeUnit.SECONDS)
                        .setConstraints(workRequestConstraints)
                        .setInputData(inputData)
                        .addTag(TAG_TASK)
                        .setInitialDelay(initialDelayInSeconds, TimeUnit.SECONDS)
                        .build();
Harm answered 6/6, 2019 at 6:7 Comment(1)
can you please look my issueGrados
D
1

In the new version of Work manager (Version 2.1.0-alpha02 released on May 16, 2019) PeriodicWorkRequests now support initial delays. You can use the setInitialDelay method on PeriodicWorkRequest.Builder to set an initial delay.

PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
        WorkerReminderPeriodic.class,
        24,
        TimeUnit.HOURS,
        PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
        TimeUnit.MILLISECONDS)
    .setInitialDelay(1, TimeUnit.HOURS)
    .addTag("send_reminder_periodic")
    .build();


WorkManager.getInstance()
        .enqueueUniquePeriodicWork("send_reminder_periodic", ExistingPeriodicWorkPolicy.REPLACE, workRequest);
Dementia answered 22/5, 2019 at 6:14 Comment(1)
can you please look my issueGrados

© 2022 - 2024 — McMap. All rights reserved.