对我来说,我无法重现该异常;尽管假设满足所有工作限制;如果需要很长时间,系统可能会取消工作进程。
对于这种情况,文档提供了对长期工作的员工的支持 https://developer.android.com/guide/background/persistent/how-to/long-running它关联一个前台服务,向系统/用户指示后台有一个长时间运行的处理;因此系统可以保留进程,并且用户知道什么正在消耗他们的资源,这也可以让他们停止该工作人员。
尤其是当你提到它很长时:
我不确定为什么 10 分钟后我会自动收到此异常。
文档中说了一些我认为可能是原因的内容:
WorkManager 为长时间运行的工作人员提供内置支持。在这样的
在这种情况下,WorkManager 可以向操作系统提供一个信号,表明该进程
如果可能的话,在执行这项工作时应该保持活动状态。这些
工人可以运行超过10分钟。
要启用它,您需要调用startForeground() https://developer.android.com/reference/kotlin/androidx/work/CoroutineWorker#setforeground更新与前台服务相关的通知;通常随着工人的进步。
一个例子 https://developer.android.com/guide/background/persistent/how-to/long-running#long-running由文档提供,展示如何在工作人员中使用它;我在这里为你定制了它DownloadingWorker
:
class DownloadingWorker(context: Context, params: WorkerParameters) :
CoroutineWorker(context, params) {
private val notificationId: Int = 1
override suspend fun doWork(): Result {
return withContext(Dispatchers.IO) {
Log.i("MYTAG", "Started ${getCurrentDateTime()}")
return@withContext try {
for (i in 0..1000) {
delay(1000)
val progress = "Starting Download"
setForeground(createForegroundInfo(progress))
Log.i("MYTAG", "Downloading $i")
setForeground(createForegroundInfo("Downloading $i"))
}
Log.i("MYTAG", "Completed ${getCurrentDateTime()}")
setForeground(createForegroundInfo("Completed"))
Result.success()
} catch (e: Exception) {
Log.i("MYTAG", "Exception $e")
Result.failure()
}
}
}
// Creates an instance of ForegroundInfo which can be used to update the
// ongoing notification.
private fun createForegroundInfo(progress: String): ForegroundInfo {
val title = "notification title)"
val cancel = "cancel download"
val channelId = "notification id"
// This PendingIntent can be used to cancel the worker
val intent = WorkManager.getInstance(applicationContext)
.createCancelPendingIntent(getId())
// Create a Notification channel if necessary
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannel(channelId)
}
val notification = NotificationCompat.Builder(applicationContext, channelId)
.setContentTitle(title)
.setTicker(title)
.setContentText(progress)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setOngoing(true)
// Add the cancel action to the notification which can
// be used to cancel the worker
.addAction(android.R.drawable.ic_delete, cancel, intent)
.build()
return ForegroundInfo(notificationId, notification)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createChannel(channelId: String) {
// Create a Notification channel
val serviceChannel = NotificationChannel(
channelId,
"Download Channel",
NotificationManager.IMPORTANCE_DEFAULT
)
val notificationManager =
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as
NotificationManager
notificationManager.createNotificationChannel(serviceChannel)
}
private fun getCurrentDateTime(): String {
val time = SimpleDateFormat("dd/M/yyyy hh:mm:ss")
return time.format(Date())
}
}
确保将前台服务添加到清单中<application>
:
<application
....
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync" />
</application>
您还需要请求Manifest.permission.POST_NOTIFICATIONS
在 API 33+ 和清单中以编程方式:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />