PeriodicWorkRequest has a nice Builder constructor where you can pass an interval for which the work can execute. You can check the details of the Builder and each parameter here
So, to set an initial delay to your periodic work you can do like this:
int hourOfTheDay = 10; // When to run the job
int repeatInterval = 1; // In days
long flexTime = calculateFlex(hourOfTheDay, repeatInterval);
Constraints myConstraints = new Constraints.Builder()
.setRequiresBatteryNotLow(true)
.build();
PeriodicWorkRequest workRequest =
new PeriodicWorkRequest.Builder(MyNiceWorker.class,
repeatInterval, TimeUnit.DAYS,
flexTime, TimeUnit.MILLISECONDS)
.setConstraints(myConstraints)
.build();
WorkManager.getInstance().enqueueUniquePeriodicWork(YOUR_NICE_WORK_TAG,
ExistingPeriodicWorkPolicy.REPLACE,
workRequest);
Here is where the magic happens:
private long calculateFlex(int hourOfTheDay, int periodInDays) {
// Initialize the calendar with today and the preferred time to run the job.
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, hourOfTheDay);
cal1.set(Calendar.MINUTE, 0);
cal1.set(Calendar.SECOND, 0);
// Initialize a calendar with now.
Calendar cal2 = Calendar.getInstance();
if (cal2.getTimeInMillis() < cal1.getTimeInMillis()) {
// Add the worker periodicity.
cal2.setTimeInMillis(cal2.getTimeInMillis() + TimeUnit.DAYS.toMillis(periodInDays));
}
long delta = (cal2.getTimeInMillis() - cal1.getTimeInMillis());
return ((delta > PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS) ? delta
: PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS);
}
Please be aware that this time is not exact. WorkManager may trigger your job at any time in that flex window depending on your constraints, system load, other scheduled jobs, etc.
If you want a precise timing, switch to AlarmManager.
Hope it helps!
setInitialDelay
works weird. When I set a startup period of 15 minutes and the initial delay of 1 minute, the worker starts after 16 minutes. I thought it would immediately (asOneTimeWorkRequest
), but after 1 minute (and not after 16 minutes). And the subsequent starts will be every 15 minutes. – Katharyn