PeriodicWork with enqueueUniquePeriodicWork doesn't work
Asked Answered
A

3

8

I'm trying to use WorkManger by creating a periodic Worker that repeats once every 5 days.

I am using version 1.0.0 of workmanagers on a Huawei Android 7 device (API 24)

android.arch.work:work-runtime:1.0.0

This is the code:

fun schedule() {
    val constraints: Constraints = Constraints.Builder().apply {
        setRequiredNetworkType(NetworkType.CONNECTED)
    }.build()

    val request = PeriodicWorkRequest
            .Builder(MyWorker::class.java, 5, TimeUnit.DAYS)
            .setConstraints(constraints)
            .build()

    WorkManager.getInstance()
            .enqueueUniquePeriodicWork(MyWorker.TAG, ExistingPeriodicWorkPolicy.KEEP, request)
}

MyWorker:

class MyWorker(appContext: Context, workerParams: WorkerParameters)
    : Worker(appContext, workerParams) {

    override fun doWork(): Result {
        return try {
            Thread.sleep(5000)
            Timber.i("success")
            Result.success()
        } catch (e: Exception) {
            Timber.e(e, "error")
            Result.failure()
        }
    }

The method schedule() is called in the onCreate() of the MainActivity.

When I install the app for the first time, the Worker runs only once. Also in the logs I see this error: CancellationException task was canceled

What am I doing wrong? Thanks.

Abscise answered 4/4, 2019 at 9:49 Comment(2)
Could you see if you see the problem running the application on the emulator with stock Android? Some OEMs are doing some modification of the stock Android that prevents WorkManager to behave correctly: are the Chinese manufacturers (Huawei, Oppo, Xiaomi...) supportedCodicodices
Your code is perfectly fine, I tried running same on my device(One plus 5, Android 10), it's working as expected. The issue seems to on your particular device. Try updating your device OS if any update is available or try with -> android.work:work-runtime-ktx:2.4.0Odontograph
S
0

The first step is to use the latest WorkManager version, as it seem you still use a very old one:

https://developer.android.com/jetpack/androidx/releases/work

By seeing your code it is unlikely you are exceeding the Work time limit, which is around 10 minutes. From the documentation, some of the reasons for a Work to be cancelled are:

  • You explicitly asked for it to be cancelled (by calling WorkManager.cancelWorkById(UUID), for example).
  • In the case of unique work, you explicitly enqueued a new WorkRequest with an ExistingWorkPolicy of REPLACE. The old WorkRequest is immediately considered cancelled.
  • Your work's constraints are no longer met.
  • The system instructed your app to stop your work for some reason. This can happen if you exceed the execution deadline of 10 minutes. The work is scheduled for retry at a later time.

That said, several manufacturers between them Huawei, implement very aggressive app killing, which don't respect even scheduling unless the app has been recently opened:

https://issuetracker.google.com/issues/122098785

https://issuetracker.google.com/issues/122098785#comment41

https://issuetracker.google.com/issues/122098785#comment74

Shackleford answered 8/10, 2020 at 17:52 Comment(0)
F
0

From PerracoLabs's answer,

In the case of unique work, you explicitly enqueued a new WorkRequest with an ExistingWorkPolicy of REPLACE. The old WorkRequest is immediately considered cancelled.

Please try to schedule your work only once. You can use SharedPreference to check if the work has been scheduled on not. If not, schedule the work and set the SharedPreference to true.

EDIT

According to official doc,

The next execution will happen during the period interval; note that execution may be delayed because WorkManager is subject to OS battery optimizations, such as doze mode.

Please check if the work is not at all getting executed or is delayed.

Foretopmast answered 11/10, 2020 at 8:32 Comment(2)
No, SharedPreference is not needed. WorkManager manages this at its own end. In his case although he's calling schedule() multiple times but doWork() is called only when it should (after 5days).Odontograph
Right. Also, WorkManager is not strict about the exact timing according to documentation. Besides the constraints provided by the dev, it also depends on the optimization of the device too. I wonder if @Abscise checked it wisely.Foretopmast
K
0

I'm not sure about the CancellationException you are getting but you've specifically said that the device you have is a Huawei device. As a Huawei user myself, I've encountered the same issue before, the work gets done the first time, and after 15 minutes (that was my requirement), if the app is in background, the work was not executed. The reason for that is, Huawei is a special device. You won't observe this behavior on stock Android or AOSP Android, because they allow the works to be done. However, Chinese manufacturers such as Huawei or Xiaomi will enforce the work to be suppressed, leaving the work undone.

I have a Huawei P20 Lite, and the solution I've got for this is,

Go to Settings --> Battery --> App startup (or something like that) --> in the list, find your app --> click your app or click the switch on the right --> select "Manage manually" and allow "Run in background".

After this tweak, the works started to be executed as they should. I'm sorry but this has nothing to do with your code, this is entirely the manufacturer's fault.

Karleen answered 13/10, 2020 at 11:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.