应用关闭后,WorkManager停止调度周期性的Worker。

3

也许这是关于WorkManager的又一个问题,但我真的找不到解决方案...

正如标题所示,我正在尝试每15分钟运行一次定期工作。 实际上,在worker中,我每分钟轮询一些数据。 在每次轮询后,几乎每1秒钟,我都会检查工作者是否被停止,如果是则返回,否则继续等待,直到达到1分钟并再次轮询数据。

根据文档,这应该可以工作,实际上也是如此,直到我从最近的应用程序屏幕中结束应用程序为止。

以下是代码:

package com.qsea.app.cordova;

import android.content.Context;

import android.os.SystemClock;

import android.util.Log;

import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class ServerListenerWorker extends Worker {

    public static final String TAG = "ServerListenerWorker";

    public ServerListenerWorker(
        Context appContext,
        WorkerParameters workerParams
    ) {
        super(appContext, workerParams);
    }

    @Override
    public Result doWork() {

        Log.d(TAG, "Doing work");

        final long startTime = SystemClock.elapsedRealtime();
        final int maxDelta = 840000; // 14 minutes

        while (true) {
            // I did this to stop this worker until 15 minutes
            // and then let the next worker run
            if (SystemClock.elapsedRealtime() - startTime >= maxDelta) {
                break;
            }

            // Here I'm polling data, if the polling results in a failure
            // I return Result.retry()

            // It avoid waiting if it remains only 1 minute until the max time
            if (SystemClock.elapsedRealtime() - startTime >= (maxDelta - 60000)) {
                break;
            }
            for (int i = 0; i < 60; i++) {
                SystemClock.sleep(950);
                // Here it checks if it is stopped
                if (isStopped()) {
                    Log.d(TAG, "Detected stop"); // this is actually never reached
                    break;
                }
            }
        }
        return Result.success();
    }
}

我按照以下步骤开始工作

Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(ServerListenerWorker.class, 15, TimeUnit.MINUTES)
    .addTag(serverListenerWorkerUID)
    .setConstraints(constraints)
    .build();
WorkManager.getInstance(cordova.getActivity()).enqueueUniquePeriodicWork(serverListenerWorkerUID, ExistingPeriodicWorkPolicy.KEEP, periodicWorkRequest);

我通过查看服务器日志来检查worker是否正常运行(如果我收到请求,它就可以正常工作),直到我关闭应用程序时,似乎它工作得很好。然后它停止运行实际的worker并且在重新打开应用程序之前永远不会再次运行worker,当应用程序打开时,工作似乎被排队并在应用程序打开后立即恢复。
我在初始化中做错了些什么吗? 我还在我的AndroidManifest.xml文件中加入了<service android:name=".ServerListenerWorker" android:permission="android.permission.BIND_JOB_SERVICE" />
这是预期的行为吗?
我读到中国ROM对后台服务有额外的限制,我有一个华为手机,似乎是最差的情况。那么这可能是设备的原因吗?如果是这样,Facebook、WhatsApp、Instagram和其他公司如何在这些设备上实现工作?

@GC,如果你的代码完美无缺(在一系列模拟器和实际标准设备如三星、索尼上运行正常),那么你可以尝试更改手机的自定义设置,特别是针对中国修改版ROM,如ColorOs、MUIUI、OxygenOS、Fun2Os等。这个列表永远不会结束。 - Rushikant Pawar
我正在进行一些测试,并成功地通过调整电池优化设置使其工作。我正在尝试找到一个以编程方式解决这个问题的解决方案(不是自动地,而是要求用户进行这些更改)。如果我找到任何可行的解决方案,我会编写一个解决方案。 - Giuliano Collacchioni
@GC,如果您能编写出适用于大多数手机制造商的代码,请不要忘记回答自己的问题,这将有助于社区。 - Rushikant Pawar
1
好的,我写了这段代码:Activity activity = cordova.getActivity(); activity.startActivityForResult(new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS), ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS_RESULT);,在onActivityResult中,我再次使用之前提到的技术调用startActivityResult,并且在用户标记应用程序以忽略电池优化后,启动worker。这应该附有一个说明,让用户理解该怎么做。但是,在华为P smart 2019上测试过,它可以工作!我很快就会清除代码并回答这个问题。 - Giuliano Collacchioni
我检查工作人员是否被停止。你怎么做到的? - IgorGanapolsky
显示剩余5条评论
1个回答

5

让我们将其分为两个不同的问题。

  1. 如果你的工作程序消耗电量较大,最好使用前台服务来通知用户你的应用在后台持续运行。你也可以使用 WorkManager,该工具支持长时间运行的 workers(底层使用前台服务)。文档中有更多信息

  2. 如果遇到特定OEM的问题,请在Android问题跟踪器上报告问题,因为这可能是CDD违规。Google可以联系OEM并要求其修复ROM。这需要时间,同时,您可以查看类似don't kill my app的网站,了解特定设备的限制,并使用autostarter之类的库来帮助用户导航到正确的设置。

顺便说一句,您不需要在AndroidManifest.xml文件中列出您的工作人员


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