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:
这个解决方案对我有用。我更新我的建筑商以供工作请求,并通过
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;
}
}
}
}