A Worker says what to do in doWork(); a WorkRequest says when: once (OneTimeWorkRequest) or repeatedly (PeriodicWorkRequest). WorkManager 234 stores the request and returns at once:
fun schedulePeriodic(context: Context) {
val request = PeriodicWorkRequestBuilder<CatalogSyncWorker>(6, TimeUnit.HOURS)
.setConstraints(online)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS)
.addTag("catalog")
.build()
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork("catalog-sync", ExistingPeriodicWorkPolicy.KEEP, request)
}The minimum period is 15 minutes (MIN_PERIODIC_INTERVAL_MILLIS), and a run lands anywhere inside its period. Since BookNestApp.onCreate() calls this on every launch, the work is unique: KEEP leaves an existing schedule alone, UPDATE swaps in the new request keeping its timing, CANCEL_AND_REENQUEUE starts over, while a plain enqueue() would stack a copy per launch. The system scheduler then shows:
adb -s emulator-5556 shell dumpsys jobscheduler JOB androidx.work.systemjobscheduler:u0a216/0: e65e824 @androidx.work.systemjobscheduler@...
JobInfo:
Service: com.example.booknest/androidx.work.impl.background.systemjob.SystemJobService
Requires: charging=false batteryNotLow=true deviceIdle=false
...
Backoff: policy=1 initial=+30s0ms
Required constraints: BATTERY_NOT_LOW CONNECTIVITY FLEXIBILITY [0x10200002]It is job 0 in namespace androidx.work.systemjobscheduler. There is no period: WorkManager schedules each run as a one-off job and computes the next itself; the first run started at once.