Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android WorkManager - how to delay task?

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.

like image 201
rgoncalv Avatar asked Oct 29 '18 15:10

rgoncalv


1 Answers

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).

like image 188
pfmaggi Avatar answered Oct 27 '22 10:10

pfmaggi