How to change periodic work request period without it running immediately using WorkManager?

There is no way to do exactly what you want with periodic work in a clean way.

However, there's absolutely no need to use periodic work itself. The same structure can be easily accomplished by scheduling the next WorkRequest at the end of your doWork method, right before returning Result.SUCCESS:

fun doWork(): Result {
  reallyDoWork()
  // Now schedule the next "periodic" work
  val request = OneTimeWorkRequestBuilder<FooWorker>().build()
  WorkManager.getInstance().enqueueUniqueWork(
    "FOO",
    ExistingWorkPolicy.REPLACE,
    request
  )
  return Result.SUCCESS
}

With this setup, your onCreate() of Application can safely use ExistingWorkPolicy.KEEP to avoid rescheduling work if you already have a WorkRequest queued up and when that queued up work fires, the next WorkRequest will be queued up with the appropriate new period.


Looks like there is a way to replace a periodic work now with enqueueUniquePeriodicWork.

  val request = PeriodicWorkRequest.Builder(FooWorker::class.java, 1, TimeUnit.DAYS).build()
  WorkManager.getInstance(appContext)
  .enqueueUniquePeriodicWork(WORK_TAG, ExistingPeriodicWorkPolicy.REPLACE, request)

Make sure you are passing ExistingPeriodicWorkPolicy instead of ExistingWorkPolicy


If you want to use ExistingPeriodicWorkPolicy.KEEP and to update PeriodicWorkRequest only when you want to change repeat interval, there is no solution from WorkManager, but you can save interval in sharedPreferences and check if interval was changed. And based on that to use ExistingPeriodicWorkPolicy.KEEP or ExistingPeriodicWorkPolicy.REPLACE

public static void enqueue(Context context) {
        Log.d(TAG, "enqueue()");
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        int repeatInterval = sharedPreferences.getInt("REPEAT_INTERVAL_HOURS", 0);

        PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest
            .Builder(FooWorker.class, REPEAT_INTERVAL_HOURS, TimeUnit.HOURS)
            .build();

        ExistingPeriodicWorkPolicy policy = repeatInterval == REPEAT_INTERVAL_HOURS ? ExistingPeriodicWorkPolicy.KEEP : ExistingPeriodicWorkPolicy.REPLACE;

        sharedPreferences.edit().putInt("REPEAT_INTERVAL_HOURS", REPEAT_INTERVAL_HOURS).apply();

        WorkManager.getInstance(context).enqueueUniquePeriodicWork("fileRemove", policy, periodicWorkRequest);
    }