使用WorkManager时如何避免android.app.ForegroundServiceStartNotAllowedException?

Che*_*eng 5 android

一直以来,我们都在使用WorkManager前台服务来帮助我们执行长时间运行的任务

https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running(我根据指南中给出的Java示例实现我的代码)

现在,我们正在将我们的应用程序移植到 API 31。

在某些情况下我们会收到以下运行时错误

致命异常:android.app.ForegroundServiceStartNotAllowedException:由于 mAllowStartForeground false,不允许 Service.startForeground():service com.xxx.yyy/androidx.work.impl.foreground.SystemForegroundService

完整的崩溃日志是

Fatal Exception: android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service com.xxx.yyy/androidx.work.impl.foreground.SystemForegroundService
   at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54)
   at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50)
   at android.os.Parcel.readParcelable(Parcel.java:3349)
   at android.os.Parcel.createExceptionOrNull(Parcel.java:2436)
   at android.os.Parcel.createException(Parcel.java:2425)
   at android.os.Parcel.readException(Parcel.java:2408)
   at android.os.Parcel.readException(Parcel.java:2350)
   at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:7194)
   at android.app.Service.startForeground(Service.java:786)
   at androidx.work.impl.foreground.SystemForegroundService$1.run(SystemForegroundService.java:124)
   at android.os.Handler.handleCallback(Handler.java:938)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loopOnce(Looper.java:233)
   at android.os.Looper.loop(Looper.java:344)
   at android.app.ActivityThread.main(ActivityThread.java:8191)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)
Run Code Online (Sandbox Code Playgroud)

我们使用WorkManager前台服务的代码片段如下。

public class XXXApplication extends MultiDexApplication implements DefaultLifecycleObserver {
    @Override
    public void onPause(LifecycleOwner owner) {
        startCloudWorker();
    }
}

public static void startCloudWorker() {
    OneTimeWorkRequest oneTimeWorkRequest =
            new OneTimeWorkRequest.Builder(CloudWorker.class)
                    .setInitialDelay(..., TimeUnit.MILLISECONDS)
                    ...
                    .build();

    WorkManager workManager = getWorkManager();
    workManager.enqueue(oneTimeWorkRequest);
}

public class CloudWorker extends Worker {
    public CloudWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        final ForegroundInfo foregroundInfo = createForegroundInfo(...)

        setForegroundAsync(foregroundInfo);
        
        // Some busy job here...

        return Result.success();
    }
}
Run Code Online (Sandbox Code Playgroud)

大多数时候,上面的代码就可以工作。

但是,有时,根据崩溃报告,它会失败并出现异常android.app.ForegroundServiceStartNotAllowedException

我想在此期间,我们的应用程序已进入后台模式,并遇到新的限制(当应用程序处于后台模式时无法启动前台服务)

我想知道有没有办法至少避免这种异常。例如,如果检测到应用程序处于后台模式,那么我们不会启动前台服务吗?


如果我在模拟器下测试,我会收到以下通知

在此输入图像描述