and*_*per 42 android android-workmanager android-12
以前我都是用一个前台的IntentService来处理纷至沓来的各种事件。然后当 Android 11 到来时(Android R,API 30)它就被弃用了,据说更喜欢使用使用setForegroundAsync 的Worker ,所以我就这么做了。
val builder = NotificationCompat.Builder(context,...)...
setForegroundAsync(ForegroundInfo(notificationId, builder.build()))
Run Code Online (Sandbox Code Playgroud)
随着 Android 12 的到来(Android S,API 31),仅在之后的一个版本,现在setForegroundAsync被标记为已弃用,并且我被告知要使用setExpedited来代替:
* @deprecated Use {@link WorkRequest.Builder#setExpedited(OutOfQuotaPolicy)} and
* {@link ListenableWorker#getForegroundInfoAsync()} instead.
Run Code Online (Sandbox Code Playgroud)
问题是,我不确定它到底是如何工作的。之前,我们有一个通知,当用户使用前台服务时应该向用户显示该通知(至少对于“旧”Android 版本)。现在看来getForegroundInfoAsync用于它,但我认为它不会用于 Android 12 :
在 Android S 之前,WorkManager 代表您管理和运行前台服务来执行 WorkRequest,显示 ForegroundInfo 中提供的通知。要随后更新此通知,应用程序可以使用NotificationManager。
从 Android S 及更高版本开始,WorkManager 使用即时作业来管理此 WorkRequest。
关于它的另一个线索是(这里):
从 WorkManager 2.7.0 开始,您的应用程序可以调用 setExpedited() 来声明 Worker 应使用加急作业。这个新 API 在 Android 12 上运行时使用加急作业,并且该 API 使用以前版本的 Android 上的前台服务来提供向后兼容性。
他们唯一的片段是调度本身:
OneTimeWorkRequestBuilder<T>().apply {
setInputData(inputData)
setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
}.build()
Run Code Online (Sandbox Code Playgroud)
即使OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST的文档也看起来很奇怪:
当应用没有任何加急作业配额时,加急工作请求将回退到常规工作请求。
我想要的只是立即、可靠地、不间断地(或至少尽可能降低机会)做某事,并使用操作系统提供的任何内容来完成它。
我不明白为什么setExpedited创建。
setExpedited运作?setExpedited前台服务一样可靠吗?它总是能够立即启动吗?setExpedited?为什么我应该更喜欢它而不是前台服务?Nek*_*cer 15
广告 1. 我无法准确解释这一点(没有查看代码),但从我们(开发人员)的角度来看,它就像一个作业请求队列,将您的应用程序作业配额考虑在内。所以基本上,如果您的应用程序在电池方面表现正常,您就可以依赖它(无论这意味着什么......)
广告 2. 每个应用程序都会获得一些不能超过的配额。此配额的详细信息是(并且可能始终是)OEM 内部实施细节。至于达到配额——这正是该OutOfQuotaPolicy标志的用途。您可以设置,如果您的应用程序达到其配额,作业可以像正常作业一样运行,也可以被删除
ad 3. 这是一个谜。在这里我们可以找到模糊的说法:
Android 12 中新增的加急作业允许应用执行简短而重要的任务,同时让系统更好地控制对资源的访问。这些作业具有介于前台服务和常规 JobScheduler 作业之间的一组特征
这(据我理解)意味着工作经理将仅适用于短期运行的工作。因此,这似乎不会是从后台启动长期运行作业的任何官方方式。这(我的观点)很疯狂,但是嘿 - 就是这样。
我们所知道的是它应该立即启动,但可能会推迟。来源
ad 4. 您无法从后台运行前台服务。因此,如果您需要在应用程序不在前台时运行“几分钟的任务” - 加急作业将是在 Android 12 中执行此操作的唯一方法。想要运行更长的任务吗?你需要让你的进入前台。它可能需要您运行作业只是为了显示启动活动的通知。比从活动中你可以运行前台服务!已经兴奋了吗?
广告 5. 在 Android 12 上,他们看不到任何东西。在早期版本中,加急作业将回退到前台服务。您需要重写public open suspend fun getForegroundInfo(): ForegroundInfo才能进行自定义通知。我不确定如果你不覆盖它会发生什么。
使用示例(日志上传worker):
@HiltWorker
class LogReporterWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
private val loggingRepository: LoggingRepository,
) : CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
loggingRepository.uploadLogs()
}
override suspend fun getForegroundInfo(): ForegroundInfo {
SystemNotificationsHandler.registerForegroundServiceChannel(applicationContext)
val notification = NotificationCompat.Builder(
applicationContext,
SystemNotificationsHandler.FOREGROUND_SERVICE_CHANNEL
)
.setContentTitle(Res.string(R.string.uploading_logs))
.setSmallIcon(R.drawable.ic_logo_small)
.setPriority(NotificationCompat.PRIORITY_LOW)
.build()
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ForegroundInfo(
NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
)
} else {
ForegroundInfo(
NOTIFICATION_ID,
notification
)
}
}
companion object {
private const val TAG = "LogReporterWorker"
private const val INTERVAL_HOURS = 1L
private const val NOTIFICATION_ID = 3562
fun schedule(context: Context) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
val worker = PeriodicWorkRequestBuilder<LogReporterWorker>(
INTERVAL_HOURS,
TimeUnit.HOURS
)
.setConstraints(constraints)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.addTag(TAG)
.build()
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.REPLACE, worker)
}
}
}
Run Code Online (Sandbox Code Playgroud)
key*_*fer 14
从概念上讲,前台服务和加急工作不是一回事。
OneTimeWorkRequest由于时间敏感,因此只能快速运行。任何 Worker 都可以请求在前台运行。这可能会成功,具体取决于应用程序的前台状态。
从 WorkManager 2.7 开始,AWorker可以尝试在前台运行其工作:setForeground[Async]()
class DownloadWorker(context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
override suspend fun getForegroundInfo(): ForegroundInfo {
TODO()
}
override suspend fun doWork(): Result {
return try {
setForeground(getForegroundInfo())
Result.success()
} catch(e: ForegroundServiceStartNotAllowedException) {
// TODO handle according to your use case or fail.
Result.fail()
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以在构建时使用 来请求WorkRequest尽快运行。setExpedited
val request = OneTimeWorkRequestBuilder<SendMessageWorker>()
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
WorkManager.getInstance(context)
.enqueue(request)
Run Code Online (Sandbox Code Playgroud)
在 12 之前的 Android 版本上,加急作业将作为前台服务运行,并显示通知。在 Android 12+ 上,可能不会显示通知。
| 归档时间: |
|
| 查看次数: |
10327 次 |
| 最近记录: |