4. 后台任务类型与调度机制
Wear OS 的后台执行环境比手机端更苛刻:内存更小、电池更敏感、系统对后台唤醒的管控更积极,而且用户摘下手表后设备会进入深度休眠。因此,选择哪种后台任务机制,本质上是在“任务是否可延迟、是否必须准时、是否需要用户感知、能否被系统随时打断”这几个维度上做取舍。本节把四种机制放在同一张决策图上,先讲清各自的调度语义,再给出 Wear OS 上的具体限制和选型方法。
四种机制的调度语义差异
WorkManager 是 Jetpack 提供的统一调度入口,在手机端它会根据版本自动选择 JobScheduler 或 AlarmManager+广播作为底层实现。它的核心语义是“保证最终执行”,而不是“保证准时执行”。你可以声明约束条件(网络、充电、设备空闲)、设置退避策略、定义唯一工作链,系统会在满足约束时择机运行。在 Wear OS 上,WorkManager 依然是首选,因为它能正确参与系统的 Doze 与 App Standby 管控,不会因为强行唤醒而被限制。
JobScheduler 是 Android 框架层的原生调度服务,WorkManager 在 API 23+ 上正是基于它实现。直接使用 JobScheduler 的好处是可以更精细地控制 JobInfo 参数,例如设置 setPeriodic 的最小周期、setRequiredNetworkType、setExpedited 等。但在 Wear OS 上,周期性 Job 的最小间隔被系统强制拉长,且设备休眠时 Job 不会触发,直到下一次维护窗口。因此它适合“有明确约束、可等待”的批量任务,例如日志上传、本地数据库整理。
AlarmManager 提供的是“到点触发”的能力,语义上最接近定时器。它有三种主要类型:setExactAndAllowWhileIdle、setAndAllowWhileIdle、setWindow。在 Wear OS 上,精确闹钟受到严格限制:从 Android 12 起,SCHEDULE_EXACT_ALARM 权限默认不授予,应用需要引导用户到系统设置中手动开启;即使开启,系统也会对每分钟的精确闹钟数量做限制。因此 AlarmManager 只应用于“用户可感知的、时间敏感”的场景,例如闹钟、用药提醒、日程到点通知。
Foreground Service 是唯一能让任务在后台持续运行且不被轻易杀死的机制,代价是必须显示常驻通知。在 Wear OS 上,前台服务通知会出现在表盘下方的通知流中,用户可以直接看到并滑动关闭。它适合“用户明确知道正在进行”的长任务,例如运动记录、导航、音乐播放、持续心率监测。但要注意,Wear OS 对前台服务的类型有额外要求,从 Android 14 起必须声明 foregroundServiceType,且部分类型(如 health)需要对应的运行时权限。
WorkManager 在 Wear OS 上的实际用法
WorkManager 的典型用法是定义一个 Worker 或 CoroutineWorker,然后通过 WorkRequest 声明约束。下面是一个在 Wear OS 上上传本地运动摘要的示例,要求设备充电且连接 Wi-Fi,失败后指数退避重试:
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build()
val uploadRequest = OneTimeWorkRequestBuilder<UploadSummaryWorker>()
.setConstraints(constraints)
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS
)
.addTag("summary_upload")
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(
"daily_summary_upload",
ExistingWorkPolicy.KEEP,
uploadRequest
)
这里的关键点是 ExistingWorkPolicy.KEEP:如果已有同名任务在排队,新请求会被忽略,避免重复入队。在 Wear OS 上,setRequiresCharging(true) 非常实用,因为手表通常在夜间充电,此时系统更愿意放开后台执行。需要注意的是,WorkManager 的周期任务最小间隔是 15 分钟,但在 Wear OS 上实际触发间隔可能被拉长到数小时,因此不要用它来做“每分钟同步”这类需求。
AlarmManager 的精确闹钟限制与替代方案
如果你的任务是“早上 7:00 准时提醒吃药”,AlarmManager 是唯一能保证到点触发的手段。但从 Android 12 开始,setExactAndAllowWhileIdle 需要 SCHEDULE_EXACT_ALARM 权限,而 Wear OS 默认不授予该权限。应用需要先检查 alarmManager.canScheduleExactAlarms(),若返回 false,则通过 ACTION_REQUEST_SCHEDULE_EXACT_ALARM 引导用户到设置页开启。即便如此,系统仍会限制每分钟的精确闹钟数量,且设备深度休眠时触发时间可能有数秒到数十秒的偏差。
对于“可以晚几分钟但不能丢”的提醒,更推荐用 WorkManager 的 setExpedited 或 setInitialDelay 配合前台服务通知。例如,把“7:00 提醒”改为“7:00 前后 15 分钟内触发”,用 WorkManager 加一个 setInitialDelay 即可,既不需要精确闹钟权限,也不会被系统限制。
Foreground Service 的类型声明与通知约束
在 Wear OS 上使用前台服务,必须在 AndroidManifest.xml 中声明 foregroundServiceType,并在运行时调用 startForeground() 时传入对应的类型。以运动记录为例:
<service
android:name=".WorkoutTrackingService"
android:foregroundServiceType="health"
android:exported="false" />
从 Android 14 起,health 类型需要 BODY_SENSORS 或 ACTIVITY_RECOGNITION 权限。如果权限未授予就启动服务,系统会抛出 SecurityException。此外,前台服务的常驻通知在 Wear OS 上会显示在表盘下方,用户可以直接关闭,关闭后服务会被停止。因此,前台服务适合“用户主动发起且持续关注”的任务,不适合偷偷在后台跑的长任务。
选型速查与常见误区
把上面的判断逻辑压缩成一张速查表,方便在写代码前快速定位:
| 任务特征 | 推荐机制 | Wear OS 注意事项 |
|---|---|---|
| 可延迟、有约束、需重试 | WorkManager | 周期任务实际间隔可能数小时,充电约束可提高执行率 |
| 需精细控制 JobInfo 参数 | JobScheduler | 休眠时不触发,依赖维护窗口批量执行 |
| 用户可感知的准时提醒 | AlarmManager | 需精确闹钟权限,数量受限,深度休眠有偏差 |
| 持续运行且用户知情 | Foreground Service | 必须声明类型,通知可被用户关闭,权限需先授予 |
常见误区:用 AlarmManager 做“每 5 分钟同步一次数据”。在 Wear OS 上,这会导致精确闹钟权限被滥用、系统频繁唤醒、电量快速下降,最终可能被系统限制甚至被用户卸载。正确做法是改用 WorkManager 的周期任务,并把同步频率降到 1 小时以上,同时加上“充电时执行”的约束。
实践建议:在 Wear OS 上,优先问自己三个问题——任务能否晚点做?用户是否知道它在做?不做会不会丢数据?如果“能晚点、用户不知道、不会丢”,就用 WorkManager;如果“不能晚、用户知道、不能丢”,才考虑 AlarmManager 或 Foreground Service。大多数后台同步、日志上报、本地整理任务,都应该落在 WorkManager 这一侧。