WorkManager periodic task execution drifts beyond expected constraint windows
0 reputation · 21 Jul 2024, 09:41 UTC
0 reputation · 21 Jul 2024, 09:41 UTC
Schedule a low-traffic background sync using PeriodicWorkRequest with NetworkType.UNMETERED and RequiresCharging constraints so the task runs predictably during overnight charging windows.
The 15-minute minimum interval is respected, but the actual start time varies significantly across devices. On some OEM builds the work runs shortly after constraints are satisfied; on others it is delayed by hours or batched into a maintenance window that falls outside the desired overnight period. The documentation states WorkManager guarantees execution but not a precise timestamp, yet the degree of drift makes capacity planning difficult for a workload that must complete before a morning deadline.
setInitialDelay and a custom BackoffPolicy narrow the execution window without violating the 15-minute minimum?30275 reputation · 21 Jul 2024, 12:34 UTC
The observed timing drift is primarily caused by Android’s battery‑optimization mechanisms that group background work into maintenance windows. On API 23+ the Doze mode can defer work until the next maintenance window, and OEM‑specific power‑save layers (e.g., MIUI, OneUI, EMUI) add further delay. When the battery level falls below roughly 30 % the system may also postpone RequiresCharging work until the charge rises, extending the window.
setInitialDelay only shifts the first execution; it does not affect the jitter of the repeat interval.BackoffPolicy applies only to retry attempts after a failure and does not constrain the scheduler’s choice of when to run a successful periodic work.PeriodicWorkRequest, log System.currentTimeMillis() in Worker.doWork(), and collect data over several nights.adb shell dumpsys jobScheduler or adb shell cmd jobscheduler list to inspect the flex window that the system has granted for the job.PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
.setFlex(5, TimeUnit.MINUTES) // allows execution within [10,15] minute window
.setConstraints(new Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build())
.build();
Note: the flex must be ≥ 15 minutes when the repeat interval is the minimum 15 minutes; otherwise you must increase the repeat interval (e.g., to 30 minutes) and set a smaller flex to keep the window narrow.setInitialDelay can be used to align the first run with the start of your overnight charging period, but it will not reduce jitter for subsequent runs.BackoffPolicy does not help with periodic scheduling; it only controls retry timing after a failure.WorkManager does not provide a direct callback for “work deferred past a deadline,” but you can implement a detection pattern:
PeriodicWorkRequest, record the expected latest run time (e.g., System.currentTimeMillis() + interval + flex) in SharedPreferences or a Room table.Worker, after successful completion, update the stored timestamp to the actual run time.AlarmManager or another WorkRequest with a short interval) check the stored timestamp. If the elapsed time since the last successful run exceeds your acceptable threshold, surface a user‑visible warning (e.g., a notification or in‑app banner).WorkManager.getWorkInfoByIdLiveData() for the periodic work; if the state remains ENQUEUED or BLOCKED past the expected window, treat it as a deferral.To decide whether adjusting the flex interval is sufficient, please provide the measured average delay (in minutes) you are seeing across devices. If the delay is consistently within the flex window, tightening the flex will help; if it exceeds the flex window, you may need to consider alternative strategies such as using a foreground service with a timeout or alarm‑based fallback.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.