joghm
joghm

Reputation: 717

Workmanager OneTimeWorkRequestBuilder not working with long duration in setInitialDelay

i am using Workmanager to perform an action every midnight , i am using it like that :

        val duration = midNight.time - now.time

    val workRequest =
        OneTimeWorkRequestBuilder<ActionWorker>()
            .setInitialDelay(duration, TimeUnit.MILLISECONDS)
            .build()

    WorkManager.getInstance(context)
        .enqueueUniqueWork(
            WORKER_ID,
            ExistingWorkPolicy.REPLACE,
            workRequest
        )

and inside the ActionWorker doWork i write to the sharedpreferences, the problem is when duration is relatively short time like 2 to 5 hours ,action is performed perfectly, otherwise if the duration is set to 12 hours for example, the action is not performed . i set duration to half an hour and i tried killing the process using adb shell am kill "package name" and the task is still performed well after half an hour, does anybody have an idea why it get lost when it is set to long duration ?

Upvotes: 1

Views: 1676

Answers (1)

Yavor Mitev
Yavor Mitev

Reputation: 1508

"not working for long durations" is not your problem. Try to debug the job scheduler. As WorkManager uses jobs underneath:

https://developer.android.com/topic/libraries/architecture/workmanager/how-to/debugging

Execute:

adb shell dumpsys jobscheduler

And check:

Unsatisfied constraints: TIMING_DELAY CONNECTIVITY [0x90000000]

If TIMING_DELAY is satisfied, and I am sure it will be - there might be other reasons why the Work is not executed. There are a lot of restrictions from Android like how many times a work can be executed per 24 hours or how much Network usage you are allowed. Check here:

https://developer.android.com/topic/performance/power/power-details

Are you also sure what you want to achieve? Why every night? Check:

https://developer.android.com/reference/androidx/work/Constraints.Builder

In general, the idea is for you to pick the conditions - idle/not idle device, Wi-Fi/no Wi-Fi, charging/not charging, low battery/not low battery, and then Android will decide when to execute. If there is something related to the server-side requirements I would get it. But otherwise, I don't.

And then you set the requirements, put a periodic job with a period of 24 hours and some flex period of 2-3 hours and you are done.

EDITED:

How to debug TIMING_DELAY problems:

check the following fields in the job info:

  • Minimum latency: +19m59s941ms
  • Enqueue time: -1m47s251ms
  • Run time:earliest=+18m12s690ms, latest=none, original latest=none

That is how you can see when the work was scheduled, what delay is set and when you should expect the TIMING_DELAY to be satisfied. If it is not what you expected - check again what you have set or check if you are now in the case of failing and retrying works. If it is retrying the minimum latency comes not from what you have set for a period/delay, but from the policy settings. More on this here:

https://developer.android.com/topic/libraries/architecture/workmanager/how-to/define-work#retries_backoff

Also, you should have in mind that the lifecycle of the Work is bigger than the one of the job. One Work can create and trash many jobs. You have a job for a single work. The work fails and needs to retry - a new job is scheduled. You can observe this more easily via:

Background Task Inspector https://developer.android.com/studio/inspect/task

Here you can see the number of retries, etc.

Upvotes: 2

Related Questions