如何避免长期工作人员进行重试操作的ForegroundServicestartnotallowedException?

问题描述 投票:0回答:1
Retry

在运行工人的长期操作之前,请调用
val workRequest = PeriodicWorkRequestBuilder<MyWorker>( repeatInterval = 1L, repeatIntervalTimeUnit = TimeUnit.HOURS, ) .setConstraints(NetworkType.CONNECTED) .addBackoffCriteria(30L) .build() WorkManager.getInstance(context) .enqueueUniquePeriodicWork( MyWorker.workerUniqueName, ExistingPeriodicWorkPolicy.KEEP, workRequest, )

I还遵循

android指南中描述的指南 - 对长期工作人员的支持。声明的前景服务类型为
setForegroundAsync()
。 wiven工人以4G+WiFi的启动,当禁用WiFi时,工人将停止(上述工作结果)。在这种情况下,每当系统尝试重新启动工人(重试策略)时,该应用在后台时,我在Android 14设备中都有以下例外:

doWork()
在其他情况下,我测试了在App在后台时停止和重新启动的工作的地方,我没有得到以上例外。
您是否知道为什么我有这个例外,在这种情况下,仅在这种情况下?你遇到了类似的问题吗?

我遇到了同样的问题,这就是我解决问题的方式。可能有更好的方法,但这对我有用。 问题根上的某些猜测

首先,您和我遇到的问题可能是一个Android错误。从您的堆栈trace中,线
dataSync

来自以下方法

Retry

在该方法中,它检查了工人任务是否。如果那是错误的,那么这个例外就不会发生。
或错误实际上是在调用中:

Moving WorkSpec (...) to the foreground startForegroundService() not allowed due to mAllowStartForeground false: service com.myapp/androidx.work.impl.foreground.SystemForegroundService android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service com.myapp/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.readParcelableInternal(Parcel.java:4870) at android.os.Parcel.readParcelable(Parcel.java:4852) at android.os.Parcel.createExceptionOrNull(Parcel.java:3052) at android.os.Parcel.createException(Parcel.java:3041) at android.os.Parcel.readException(Parcel.java:3024) at android.os.Parcel.readException(Parcel.java:2966) at android.app.IActivityManager$Stub$Proxy.startService(IActivityManager.java:5984) at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1931) at android.app.ContextImpl.startForegroundService(ContextImpl.java:1906) at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:830) at androidx.core.content.ContextCompat$Api26Impl.startForegroundService(ContextCompat.java:1189) at androidx.core.content.ContextCompat.startForegroundService(ContextCompat.java:752) at androidx.work.impl.Processor.startForeground(Processor.java:206) at androidx.work.impl.utils.WorkForegroundUpdater$1.run(WorkForegroundUpdater.java:100) at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) ... Moving WorkSpec (...) to the foreground Work [ id=..., tags={ ...MyWorker } ] failed because it threw an exception/error java.util.concurrent.ExecutionException: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=ACTION_NOTIFY cmp=com.myapp/androidx.work.impl.foreground.SystemForegroundService (has extras) }: app is in background uid UidRecord{... TRNB bg:+2m17s737ms idle change:procadj procs:0 seq(401644,401374)} caps=------ at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:515) at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:474) at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:316) at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) ... Worker result FAILURE for Work [ id=..., tags={ ...MyWorker } ] Unable to stop foreground service android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=ACTION_STOP_FOREGROUND cmp=com.myapp/androidx.work.impl.foreground.SystemForegroundService }: app is in background uid UidRecord{... TRNB bg:+2m17s772ms idle change:procadj procs:0 seq(401644,401374)} caps=------ at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1945) at android.app.ContextImpl.startService(ContextImpl.java:1900) at android.content.ContextWrapper.startService(ContextWrapper.java:825) at androidx.work.impl.Processor.stopForegroundService(Processor.java:403) at androidx.work.impl.Processor.cleanUpWorkerUnsafe(Processor.java:425) at androidx.work.impl.Processor.onExecuted(Processor.java:345) at androidx.work.impl.Processor.lambda$startWork$1$androidx-work-impl-Processor(Processor.java:179) at androidx.work.impl.Processor$$ExternalSyntheticLambda2.run(D8$$SyntheticClass:0) ...

任何人,足够的猜测。到对我有用的解决方法。

solution
android android-service android-workmanager foreground-service
1个回答
0
投票
我在文档中注意到了它说:

当该过程受到前景服务限制时,setforegroundsync的关键setForegroundAsenc将会因非法验证而失败。考虑使用Androidx。工作。 Workrequest。建筑商。 setExpedited(outofquotapolicy)和getforegroundInfoAsync()而不是

这个解决方案对我有用。我更新我的建筑商以供工作请求,并通过

Processor.cleanUpWorkerUnsafe(Processor.java:425)
呼叫:

    private WorkerWrapper cleanUpWorkerUnsafe(@NonNull String id) {
        WorkerWrapper wrapper = mForegroundWorkMap.remove(id);
        boolean wasForeground = wrapper != null;
        if (!wasForeground) {
            wrapper = mEnqueuedWorkMap.remove(id);
        }
        mWorkRuns.remove(id);
        if (wasForeground) {
            stopForegroundService();
        }
        return wrapper;
    }

然后,我不用使用

wasForeground
显示通知,而是使用

stopForegroundSerice()

手动添加了通知,然后用try/catch/try/catch/try/catch/the将所有内容添加堵塞。这是我的dowork()方法的缩短版本:

    private void stopForegroundService() {
        synchronized (mLock) {
            boolean hasForegroundWork = !mForegroundWorkMap.isEmpty();
            if (!hasForegroundWork) {
                Intent intent = createStopForegroundIntent(mAppContext);
                try {
                    // Wrapping this inside a try..catch, because there are bugs the platform
                    // that cause an IllegalStateException when an intent is dispatched to stop
                    // the foreground service that is running.
                    mAppContext.startService(intent);
                } catch (Throwable throwable) {
                    Logger.get().error(TAG, "Unable to stop foreground service", throwable);
                }
                // Release wake lock if there is no more pending work.
                if (mForegroundLock != null) {
                    mForegroundLock.release();
                    mForegroundLock = null;
                }
            }
        }
    }

	

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.