4

I have built a simple PeriodicWorkRequest following Android's WorkManager docs here. I basically need a worker that runs every 15 minutes. However my worker is only running once and never again.

Here is how I start the work request:

PeriodicWorkRequest myWorkRequest =
            new PeriodicWorkRequest.Builder(
                    MyWorker.class,
                    PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
                    TimeUnit.MILLISECONDS
            ).build();

WorkManager.getInstance(this).enqueue(myWorkRequest);

My worker class is nothing but only a system log inside, just to test it. Here is the related part of the worker:

@Override
public Result doWork() {
    Log.d("Worker runs");
    return Result.success();
}

I am expecting this worker to run every 15 minutes. However, it only runs once at the launching of the app, and never again.

I have searched a lot and noticed a few things about it, but still no luck:

  • Time interval is important and has to be minimum 15 minutes as also answered here. However, my interval is already the constant PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS so it should work with it. I've even tried with 16 minutes but does not work either.

  • Another suggestion was using unique ID in case they are cancelling each other as described here. I've added a tag and started the worker as follows:

    WorkManager.getInstance(this).enqueueUniquePeriodicWork(
         UNIQUE_ID, ExistingPeriodicWorkPolicy.REPLACE, myWorkRequest);
    

    However this does not change and it still runs only once.

  • I read that WorkManager has some bugs and might not work well on some phones. But I tried with different devices and emulator, and it does not work in any of them.

My WorkManager version "androidx.work:work-runtime:2.5.0" and currently I'm testing on an Android 11 emulator. Any help would be appreciated, thanks!

Faruk Yazici
  • 2,344
  • 18
  • 38
  • 2
    You will not get **exact** jobs with WorkManager, it works depending on it's internal "device health" which is poorly documented. For exact tasks, they still suggest using the AlarmManager. – Shark Jul 26 '21 at 16:15
  • but for *deferable* work, WorkManager does a great job; you just have no control over when it will go off. Test on real devices as well. However, I don't know what you expect to see with `System.out.println` because that's going to the standard `stdout`, which isn't logcat. – Shark Jul 26 '21 at 16:17
  • Did you wait 15 after first start? my thouths is that: It can be runned any time in the interval. First 15min was on start of that 15mins interal. Next may be after 30min. [read here](https://medium.com/androiddevelopers/workmanager-periodicity-ff35185ff006) – Pentiux Jul 26 '21 at 16:22
  • @Pentiux I waited for more than an hour, where emulator and Android Studio was all open. And it is still only run once. – Faruk Yazici Jul 27 '21 at 06:58
  • @Shark don't mind the System.out, I use Log.d() actually. I am seeing the logs in logcat and it's only once. So isn't WorkManager suitable for running a task periodically, like once in every hour, every day, every half hour etc?? – Faruk Yazici Jul 27 '21 at 07:01
  • honestly, why not try with 1min and see if it works and that you're not missing the time it's running somehow? the time interval can be less just to test, that's my point. – Wale Jul 27 '21 at 07:12
  • Also, I think you should try Log.e() this way you can switch your log tab to error only and have a better view – Wale Jul 27 '21 at 07:14
  • @FarukYazici you're asking me two questions there. 1) "Isn't WorkManager suitable for running a task periodically?" 2) "Isn't WorkManager suitable for running a task periodically at exact times". The answers are "Yes, yes it is." and "No, it is not because you have no control over when a task is ran by the WorkManager". – Shark Jul 27 '21 at 09:37
  • 1
    WorkManager will *respect* the interval, but depending on mysterious "device health" - tasks that need to be ran 15 minutes again from now may be executed up to 8h from now. It is not **exact**. It will execute the task when period time is elapsed and all constraints are met, but will not sacrifice this "device health" to make it happen. – Shark Jul 27 '21 at 09:38
  • So to answer - if you want tasks to run exactly every 15 minutes, WorkManager is not the best thing; some tasks will run 15 minutes apart, but sometimes they will execute 20+ minutes later. – Shark Jul 27 '21 at 09:39
  • This is the reason they say "deferrable non-exact background tasks" in all of their documents. The only thing that **does** guarantee that WM executes the task immediatelly is showing the notification while it's doing it's job. In that case, the tasks **should** run exactly 15 minutes apart, no exceptions. – Shark Jul 27 '21 at 09:41
  • @Wale the time cannot be less for testing purposes. Testing the WorkManager isn't actually very trivial, as you can only test the Workers, but not the WorkManager itself. And guess what, they made it like that "by design". – Shark Jul 27 '21 at 09:45
  • Wao, that's weird, so if I have to debug that the scheduling is working well, you're saying I will have to write individual test for each time frame? I don't think you're right! – Wale Jul 27 '21 at 12:18
  • My goal is just to see it work for let say O scheduled it for 10mins intervals, then I can assume it will work well for another time interval, or else its interrupted by the system itself – Wale Jul 27 '21 at 12:20
  • Thanks everyone for the answers. I've chosen AlarmManager to continue with. Even AlarmManager is not exact in timing for repeating tasks, but works better than WorkManager for this case as I see. – Faruk Yazici Jul 28 '21 at 08:42
  • @Shark thanks for AlarmManager suggestion. If you wish, you could make an answer for me to accept as solution. – Faruk Yazici Jul 28 '21 at 08:43
  • @Wale no, you misunderstood me... scheduling isn't a problem, execution of the task is. But then again, for tests you use a `WorkManagerTestUtils` to create the worker (running on a SynchronousExecutor or not) and call `worker.doWork() / startWork()` yourself. When the WorkManager actually calls those methods in the real world is outside of your control and testing capability. As far as tests go, you can test whether WorkRequests are scheduled, and how the Workers perform. You can't test anything related to WorkManager itself. That's why they give you these official hacks in the first place. – Shark Jul 28 '21 at 10:50
  • @FarukYazici feel free to post the answer and accept it. – Shark Jul 28 '21 at 10:50
  • @Wale lets also not forget that enqueueing (scheduling) of tasks is different for production code and test code as well... To put it simply, testing the workmanager is very ungrateful work. To have your production code actually testable (with e.g. integration tests) you will have to introduce a `WorkManagerDelegate` that does things **slightly** differently depending whether it's running tests or not. Otherwise your production code will be untestable. – Shark Jul 28 '21 at 10:59

0 Answers0