使用enqueueUniquePeriodicWork的周期性工作不起作用

8

我正在尝试使用WorkManager创建一个重复周期为5天的定期Worker。

我在华为安卓7设备(API 24)上使用了1.0.0版本的WorkManager。

android.arch.work:work-runtime:1.0.0

这是代码:

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)
}

我的工作者:

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()
        }
    }

在MainActivity的onCreate()中调用了schedule()方法。

第一次安装应用程序时,Worker仅运行一次。同时在日志中看到以下错误:CancellationException task was canceled

我做错了什么? 谢谢。


你能否看一下,在模拟器上运行股票Android时是否遇到了问题?一些OEM正在对股票Android进行某些修改,这会防止WorkManager正确地工作:中国制造商(华为,OPPO,小米...)是否得到支持 - pfmaggi
你的代码完全没有问题,我在我的设备(One plus 5, Android 10)上尝试运行了相同的代码,它按预期工作。问题似乎出现在你的特定设备上。如果有更新可用,请尝试更新你的设备操作系统,或者尝试使用 -> android.work:work-runtime-ktx:2.4.0。 - Astha Garg
3个回答

0

第一步是使用最新的WorkManager版本,因为看起来你仍在使用一个非常旧的版本:

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

通过查看您的代码,很可能不会超过工作时间限制,大约为10分钟。从文档中,一些取消工作的原因包括:
  • 您明确要求取消它(例如通过调用WorkManager.cancelWorkById(UUID))。
  • 在唯一工作的情况下,您明确排队了一个新的WorkRequest,并将ExistingWorkPolicy设置为REPLACE。旧的WorkRequest立即被视为已取消。
  • 您的工作约束不再满足。
  • 系统出于某种原因指示您的应用停止工作。如果您超过10分钟的执行期限,则会安排重试工作。

话虽如此,其中包括华为在内的多个制造商实施了非常激进的应用程序终止,除非应用程序最近已打开,否则不会尊重甚至调度:

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

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

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


0

根据PerracoLabs的回答,

对于唯一的工作,您可以使用ExistingWorkPolicy.REPLACE显式地将新的WorkRequest加入队列中。旧的WorkRequest会立即被视为已取消。

请尽量仅安排一次工作。您可以使用SharedPreference检查工作是否已经被安排。如果没有,请安排工作并将SharedPreference设置为true。

编辑

根据官方文档,

下一次执行将在周期间隔期间发生;请注意,由于WorkManager受到操作系统电池优化(例如待机模式)的影响,因此执行可能会延迟。

请检查工作是否完全未执行或者是被延迟了。


不需要使用SharedPreference。WorkManager会在其自身端管理此项任务。在这种情况下,尽管他多次调用schedule(),但只有在应该执行doWork()时才会被调用(即5天后)。 - Astha Garg
没错。根据文档,WorkManager对于精确时间并不严格要求。除了开发人员提供的约束条件外,它还取决于设备的优化情况。我想知道@smoke89是否明智地检查了它。 - Basu

0

我不确定你遇到的CancellationException是什么,但你明确说你使用的设备是华为。作为一个华为用户,我之前也遇到过同样的问题,第一次可以完成工作,但在15分钟后(这是我的要求),如果应用程序在后台运行,工作就无法执行。原因是华为是一种特殊的设备。你在原生Android或AOSP Android上不会观察到这种行为,因为它们允许工作完成。然而,像华为小米这样的中国制造商将强制抑制工作,使工作未完成。

我有一部华为P20 Lite,我找到的解决方案是:

进入设置-->电池-->应用程序启动(或类似的选项)-->在列表中找到你的应用程序-->点击你的应用程序或点击右侧的开关-->选择“手动管理”并允许“后台运行”。

进行这个调整后,工作开始按照应该的方式执行。很抱歉,但这与你的代码无关,完全是制造商的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接