android - 加急工作请求需要 ListenableWorker 来提供 getForegroundInfoAsync() 的实现
问题描述
在这里做一些危险的问答。
我有一些工作有时需要按照2.7.0 版中的描述快速运行:WorkManager
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED).build()
val oneTimeWorkRequest = OneTimeWorkRequest.Builder(MyWorker::class.java)
.setInitialDelay(2, TimeUnit.SECONDS)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setConstraints(constraints).build()
WorkManager.getInstance(context).enqueueUniqueWork("my-identifier", ExistingWorkPolicy.REPLACE, oneTimeWorkRequest)
我相信代码在 Android 12/S 上运行得很好,但是当作业在 Android 11 上运行时,我收到以下错误:
E/WM-WorkerWrapper: Work [ id=<UUID>, tags={ [WorkerTag] } ] failed because it threw an exception/error
java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.IllegalStateException: Expedited WorkRequests require a ListenableWorker to provide an implementation for `getForegroundInfoAsync()`
at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:311)
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:923)
我需要做什么?
解决方案
的文档ListenableWorker.getForegroundInfoAsync()
说明了这一点:
在 Android S 之前,WorkManager 代表您管理和运行前台服务来执行 WorkRequest,显示 ForegroundInfo 中提供的通知。要随后更新此通知,应用程序可以使用 NotificationManager。
从 Android S 及更高版本开始,WorkManager 使用即时作业管理此 WorkRequest。
因此,在扩展类中,ListenableWorker
有必要覆盖getForegroundInfoAsync()
.
自己直接覆盖该方法的另一种方法是使用例如CoroutineWorker
:
class MyWorker(val context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) {
companion object {
private const val NOTIFICATION_CHANNEL_ID = "11"
private const val NOTIFICATION_CHANNEL_NAME = "Work Service"
}
override suspend fun doWork(): Result {
// TODO: Do work here
return Result.success()
}
override suspend fun getForegroundInfo(): ForegroundInfo {
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentIntent(PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), Constants.PENDING_INTENT_FLAG_IMMUTABLE))
.setSmallIcon(R.drawable.ic_refresh_24dp)
.setOngoing(true)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setContentTitle(context.getString(R.string.app_name))
.setLocalOnly(true)
.setVisibility(NotificationCompat.VISIBILITY_SECRET)
.setContentText("Updating widget")
.build()
return ForegroundInfo(1337, notification)
}
}
(待定意图标志的常量实际上只是val PENDING_INTENT_FLAG_MUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
为了使东西同时适用于 Android 12/S 及更早版本。)
推荐阅读
- java - 我在构建 Spring Boot 的 Web 项目时无法使用 freemarker
- mysql - 如何解析 json 对象 - mysql
- c - 为什么 orig_ax 没有正确的系统调用号
- java - 使用 compareToIgnoreCase (JShell) 对文件流进行排序时出现“找不到符号”
- google-apps-script - Google 脚本编辑器 - 找不到方法 formatDate(object,string,string)
- c - 如何在编译时初始化结构成员,具体取决于数组中先前定义的条目的值
- node.js - ECONNRESET error while fetching an URL in node.js
- mysql - 使用变量并重用它时 SELECT 语句无法正确显示数据
- sql - 如何在 oracle 中同时使用双重分组和求和语句
- android - 有没有办法检查 LOCAL_SHARED_LIBRARIES 是否成功集成到 android 应用程序中?