前言
Android 12 (API 31) 引入了前台服务启动限制: 以 Android 12 为目标平台的应用在后台运行时无法再启动前台服务(除了一些特殊情况), 否则会抛出异常: ForegroundServiceStartNotAllowedException
为应对新版本的变动, WorkManager 2.7.0
引入了加急工作的概念。可以调用 setExpedited()
来声明 Worker
应使用加急作业。这一新 API 在 targetSdkVersion = 31
的应用中运行时使用 加急作业
,而在早期 Android 版本中使用 前台服务
来提供向后兼容性。
注意:
加急作业
是属于 Android12 JobScheduler
中的新内容, 而 WorkManager的加急工作
, 在Android12 使用 加急作业
来完成, 在低版本手机上 使用 前台服务
来完成.
一、了解加急作业
Android 12 在 JobScheduler
中引入的加急作业 允许应用执行简短的重要任务; 其特性为:
- 它们适用于在几分钟内完成的简短任务。除非您的应用有足够的配额,否则系统可能会停止该作业。
- 它们不太受系统的某些电源管理限制(包括省电模式和低电耗模式)的影响。
- 只要系统的当前工作负载允许,系统就会立即运行这些作业。
加急作业可能会延迟
系统会尝试在调用指定的加急作业后,尽快执行该作业。不过,与其他类型的作业一样,系统可能会延迟启动新的加急作业,如在以下情况下:
- 系统负载过高,当有过多作业已在运行或者当系统内存不足时,就会发生这种情况。
- 已超出加急作业配额限制。加急作业使用基于应用待机存储分区的配额系统,并限制滚动时间窗口中的最大执行时间。用于加急作业的配额比用于其他类型的后台作业的配额限制更大。
二、加急工作
加急工作特征:
重要性:
加急工作适用于对用户很重要或由用户启动的任务。速度:
加急工作最适合那些立即启动并在几分钟内完成的简短任务。配额:
限制前台执行时间的系统级配额决定了加急作业是否可以启动。电源管理:
电源管理限制(如省电模式和低电耗模式)不太可能影响加急工作。延迟时间:
系统立即执行加急工作,前提是系统的当前工作负载允许执行此操作。这意味着这些工作对延迟时间较为敏感,不能安排到以后执行。
在用户想要发送消息或附加的图片时,可能会在聊天应用内使用加急工作。同样,处理付款/订阅流程的应用也可能需要使用加急工作。这是因为这些任务对用户很重要,会在后台快速执行,并需要立即开始执行。
配额:
系统必须先为加急作业分配应用执行时间,然后才能运行作业。执行时间并非无限制,而是受配额限制。 如果您的应用使用其执行时间并达到分配的配额,在配额刷新之前,您无法再执行加急工作。这样,Android 可以更有效地在应用之间平衡资源。
每个应用均有自己的前台执行时间配额。可用的执行时间取决于待机模式存储分区和进程的重要性。
注意: 当您的应用在前台运行时,配额不会限制加急工作的执行。仅在应用在后台运行时或当应用移至后台时,执行时间配额才适用。因此,您应在后台加快要继续的工作。当应用在前台运行时,您可以继续使用“setForeground()”。
执行加急工作:
val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>()
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
WorkManager.getInstance(this).enqueue(myWorkRequest)
配额政策:
当配额不足时, 加急工作该如何运行:
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST
- 会导致作业作为普通工作请求运行。OutOfQuotaPolicy.DROP_WORK_REQUEST
- 会在配额不足时导致请求取消。
延迟加急工作:
我们上面说到 加急作业
可能会延迟. 同样,新的 加急工作
也有可能在 系统负载过高 或配合不足
时延迟启动
向后兼容性和前台服务:
Android 8.0
引入了应用 后台执行限制
因此 WorkManager
在版本 2.3.0
添加了一些 API, 用于处理需立即执行的长时间运行任务
, 其中包括 setForegroundAsync()
、setForeground()
; 它会在 前台服务
中立即执行。
据官方描述:
- WorkManager 2.7 向后兼容,并在 12 之前的 Android 版本上运行。请注意,在这些情况下,它使用前台服务,而不是加速工作。
- 以 Android 12 或更高版本为目标平台时,前台服务仍可通过 setForegroundAsync() 使用。不过,我们强烈建议您使用 setExpedited()。
意思是: ?
假如: targetSdkVersion < 31
, 我 是否
只需调用 setForeground()
, 而不需要调用 setExpedited()
假如: targetSdkVersion >= 31
, 我 是否
只需调用 setExpedited()
, 而无需调用 setForeground()
总结
没有总结
上一篇: WorkManager笔记: 二、管理工作
下一篇: 记一次自定义View: 扇形圆环