AndroidX Work Library отменяет операции, казалось бы, без причины - PullRequest
0 голосов
/ 16 октября 2019

Я работаю с AndroidX Work Dependency , чтобы попытаться выполнить некоторые операции фонового сервиса. В настоящее время я использую самую последнюю стабильную версию, 2.2.0 на момент публикации этого вопроса.

Фактическая операция, которую я выполняю в фоновом режиме, является довольно тяжелой операцией ЦП, поскольку она использует некоторый код сжатия в одноммоих библиотек ( здесь ) и может занять от 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)

Я буквально просто смотрю на свой телефон и вообще не взаимодействую с ним, когда это происходит случайно. Я не пытаюсь запускать другие приложения, и при этом я не пытаюсь загружать процессор для чего-то другого. Я никогда не вижу своих собственных стековых трасс и не вижу никаких непосредственных проблем или причин.

Следовательно, вопрос в том, что здесь происходит, что случайным образом останавливает службу Worker без какой-либо провокации? Почему происходит произвольная остановка операций?

Спасибо всем.

РЕДАКТИРОВАТЬ 1

  • Я тестировал удаление строки требований сетевых ограничений, думая, что это может быть причиной проблемы, и я видел, что это происходит даже после этого, поэтому я не верю, что это проблема.

  • Я тестирую на Google Pixel 3, API 28, Android 9, но на любом другом устройстве, которое я тестировал, независимо от уровня API (минимум поддерживается 21), возникла та же проблема.

Редактировать 2

  • Я попытался переписать класс для работы в асинхронном подходе, расширив класс ListenableWorker вместоWorker и это не решило проблему.

1 Ответ

1 голос
/ 22 октября 2019

вы, скорее всего, столкнулись с одной из 2 проблем.

Во-первых, если ваша фоновая служба работает более чем 10 минут can take anywhere from 3-30 minutes depending on the size and length of the video in question, вы можете столкнуться с жестким лимитом времени, которыйнавязывается кодом WorkManager.

В документах здесь говорится: The system instructed your app to stop your work for some reason. This can happen if you exceed the execution deadline of 10 minutes.

Это кажется наиболее вероятным, но другая проблема может быть связана с Androidздесь изложены ограничения фона здесь , в которых подробно описаны изменения, связанные с Apps that target Android 8.0 or higher. Как вы упомянули в редактировании, вы тестируете на Google Pixel 3, API 28, Android 9, и это может иметь прямое отношение.

Что касается решений, самое простое, хотя и разочаровывающее решение, было бы сообщить пользователю, что онинужно держать приложение на переднем плане. Это, по крайней мере, предотвратит этот 10-минутный разрыв.

Другой вариант - использовать новый Bubble API, который был представлен в API 29. Документация: здесь ираздел документации, который может вас заинтересовать, - там, где написано, When a bubble is expanded, the content activity goes through the normal process lifecycle, resulting in the application becoming a foreground process. Создание миниатюрного «расширенного» представления и его расширение пользователями при закрытии приложения может стать хорошей альтернативой обходу этого 10-минутного таймера.

...