【问题标题】:AndroidX Work Library is canceling operations, seemingly without reasonAndroidX Work Library 正在取消操作,看似无缘无故
【发布时间】:2019-10-16 18:03:46
【问题描述】:

我正在使用AndroidX Work Dependency 尝试运行一些后台服务操作。在发布此问题时,我目前正在运行最新的稳定版本 2.2.0

我在后台运行的实际操作是一个相当繁重的 CPU 操作,因为它在我的一个库 (here) 中使用了一些压缩代码,并且可能需要 3-30 分钟,具体取决于大小和相关视频的长度。

这是我构建和运行工作请求的代码:

    public static void startService(){
        //Create the Work Request
        String uniqueTag = "Tag_" + new Date().getTime() + "_ChainVids";
        OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(CompleteVideoBackgroundService.class);
        Constraints.Builder constraints = new Constraints.Builder();
        constraints.setRequiredNetworkType(NetworkType.CONNECTED);
        builder.setConstraints(constraints.build());
        builder.setInitialDelay(1, TimeUnit.MILLISECONDS);
        builder.addTag(uniqueTag);
        Data inputData = new Data.Builder().putString("some_key", mySerializedJSONString).build();
        builder.setInputData(inputData);
        OneTimeWorkRequest compressRequest = builder.build();

        //Set the Work Request to run
        WorkManager.getInstance(MyApplication.getContext())
                .beginWith(compressRequest)
                .enqueue();
    }

然后它会触发这个运行所有后台服务操作的类:

public class MyServiceSampleForStackoverflow  extends Worker {

    private Context context;
    private WorkerParameters params;

    public MyServiceSampleForStackoverflow(@NonNull Context context, @NonNull WorkerParameters params){
        super(context, params);
        this.context = context;
        this.params = params;
    }

    /**
     * Trimming this code down considerably, but the gist is still here
     */
    @NonNull
    @Override
    public Result doWork() {
        try {
            //Using using a hard-coded 50% for this SO sample
            float percentToBringDownTo = 0.5F;
            Uri videoUriToCompress = MyCustomCode.getVideoUriToCompress();
            VideoConversionProgressListener listener = (progressPercentage, estimatedNumberOfMillisecondsLeft) -> {
                float percentComplete = (100 * progressPercentage);
                //Using this value to update the Notification Bar as well as printing in the logcat. Erroneous code removed
            };
            String newFilePath = MyCustomCode.generateNewFilePath();
            //The line below this is the one that takes a while as it is running a long operation
            String compressedFilePath = SiliCompressor.with(MyApplication.getContext()).compressVideo(
                    listener, videoUriToCompress.getPath(), newFilePath, percentToBringDownTo);
            //Do stuff here with the compressedFilePath as it is now done
            return Result.success();
        } catch (Exception e){
            e.printStackTrace();
            return Result.failure();
        }
    }
}

偶尔,在没有任何押韵或理由的情况下,工人在没有我告诉它的情况下随机停止。发生这种情况时,我会看到此错误:


Work [ id=254ae962-114e-4088-86ec-93a3484f948d, tags={ Tag_1571246190190_ChainVids, myapp.packagename.services.MyServiceSampleForStackoverflow } ] was cancelled
    java.util.concurrent.CancellationException: Task was cancelled.
        at androidx.work.impl.utils.futures.AbstractFuture.cancellationExceptionWithCause(AbstractFuture.java:1184)
        at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:514)
        at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
        at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:284)
        at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

当这种随机发生时,我实际上只是盯着我的手机看,根本不与它互动。我不想运行其他应用程序,也不想占用 CPU 做其他事情。我从来没有看到我自己的任何堆栈跟踪,也没有直接的问题或原因是可见的。

因此,问题是,这里发生了什么随机停止 Worker 服务而没有任何挑衅? 为什么会随机停止操作?

谢谢大家。

编辑 1

  • 我确实测试了删除可能导致问题的网络约束要求行,并且我确实看到它甚至在那之后发生,所以我不认为这是问题所在。

  • 我正在 Google Pixel 3、API 28、Android 9 上进行测试,但我测试过的任何其他设备(无论 API 级别如何(支持的最低级别为 21))都显示出同样的问题。

编辑 2

  • 我尝试通过让类扩展 ListenableWorker 而不是 Worker 来重写类以使用异步方法,但这并没有解决问题。

【问题讨论】:

  • 你在什么操作系统版本和设备/模拟器上测试。
  • 我更新了底部的问题,感谢莫里森的提问!
  • 我也有同样的问题

标签: java android android-service androidx


【解决方案1】:

您很可能面临 2 个问题之一。

首先,假设您的后台服务运行时间超过 10 分钟can take anywhere from 3-30 minutes depending on the size and length of the video in question,您可能会遇到 WorkManager 代码施加的硬时间限制。

docs here 他们说:The system instructed your app to stop your work for some reason. This can happen if you exceed the execution deadline of 10 minutes.

这似乎是最有可能的,但另一个问题可能与here 概述的 Android 背景限制有关,其中详细说明了与Apps that target Android 8.0 or higher 相关的更改。正如您在编辑中提到的,您正在测试 Google Pixel 3, API 28, Android 9,这可能是直接相关的。

就解决方案而言,最简单但令人沮丧的解决方案是告诉用户他们需要将应用程序保持在前台。这至少可以避免 10 分钟的间隔。

另一种选择是使用 API 29 中引入的新 Bubble API。文档是 here,您可能感兴趣的文档部分是它所说的 When a bubble is expanded, the content activity goes through the normal process lifecycle, resulting in the application becoming a foreground process .制作一个小型化的“扩展”视图并在应用程序关闭时由用户扩展它是绕过 10 分钟计时器的一个很好的替代解决方案。

【讨论】:

  • 是的......经过测试,第二个 10 分钟是取消发生的时间。耗时不到 10 分钟的压缩作业会起作用,但一旦根据视频的大小超过 10 分钟,就会导致取消。
【解决方案2】:

我们现在可以运行超过 10 分钟,至少根据工作管理器版本Support for long-running workers

WorkManager 2.3.0-alpha02 增加了对长时间运行的一流支持 工人。在这种情况下,WorkManager 可以向操作系统提供信号 在这项工作进行期间,如果可能,该过程应该保持活跃 执行。这些 Worker 可以运行超过 10 分钟。例子 此新功能的用例包括批量上传或下载(即 不能被分块),在本地处理 ML 模型,或者任务 对应用程序的用户很重要。

在共享的链接中给出了一个示例。请检查一下。

【讨论】:

  • 好发现!由于这是在野外的生产应用程序上,我会等到它稳定后再部署,但我肯定会立即测试 alpha 版本。感谢您的研究。
  • 稳定版已经出。我们有适用于 androidx 的 2.3.0 版。
猜你喜欢
  • 1970-01-01
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-11
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多