精确闹钟用于用户有意发出的通知或需要在精确时间发生的行动。
SCHEDULE_EXACT_ALARM
是 Android 12 中引入的权限,用于应用安排精确闹钟,**对于大多数针对 Android 13 及更高版本的新安装的应用,不再预先授予此权限**(默认设置为拒绝)。如果用户通过备份和还原操作将应用数据传输到运行 Android 14 的设备,则权限仍将被拒绝。如果现有应用已拥有此权限,则在设备升级到 Android 14 时将预先授予此权限。
需要 SCHEDULE_EXACT_ALARM
权限才能通过以下 API 启动精确闹钟,否则将抛出 SecurityException
适用于 SCHEDULE_EXACT_ALARM
权限的现有最佳实践仍然适用,包括以下内容
- 在安排精确闹钟之前,使用
canScheduleExactAlarms()
检查权限。 - 设置您的应用以侦听并正确响应前台广播
AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
,系统在用户授予权限时会发送此广播。
受影响的应用
如果设备运行的是 Android 14 或更高版本,则此更改将影响具有以下特征的新安装的应用
- 以 Android 13(API 级别 33)或更高版本为目标。
- 在清单中声明
SCHEDULE_EXACT_ALARM
权限。 - 不属于 豁免 或 预先授予 方案。
- **不是**日历或闹钟应用。
日历和闹钟应用应声明 USE_EXACT_ALARM
日历或闹钟应用 需要在应用不再运行时发送日历提醒、唤醒闹钟或警报。这些应用可以请求 USE_EXACT_ALARM
常规权限。USE_EXACT_ALARM
权限将在安装时授予,持有此权限的应用将能够像具有 SCHEDULE_EXACT_ALARM
权限的应用一样安排精确闹钟。
可能不需要精确闹钟的用例
由于现在默认拒绝 SCHEDULE_EXACT_ALARM
权限,并且权限授予过程需要用户执行额外的步骤,因此强烈建议开发人员评估其用例,并确定精确闹钟对于其用例是否有意义。
以下列表显示了可能不需要精确闹钟的常见工作流程
- 在应用的生命周期内安排重复工作
- 如果任务需要考虑实时约束,例如明天下午 2:00 或 30 分钟后触发,则
set()
方法很有用。否则,建议改为使用postAtTime()
或postDelayed()
方法。 - 计划后台工作,例如更新您的应用和上传日志
WorkManager
提供了一种 安排时间敏感的定期工作 的方法。您可以提供重复间隔和 flexInterval(最少 15 分钟)来定义工作的粒度运行时间。- 需要在系统空闲状态下触发闹钟
- 使用非精确闹钟。具体来说,调用
setAndAllowWhileIdle()
。 - 用户指定的在特定时间后发生的事件
- 使用非精确闹钟。具体来说,调用
set()
。 - 用户指定的可以在时间窗口内发生的事件
- 使用非精确闹钟。具体来说,调用
setWindow()
。请注意,允许的最小窗口长度为 10 分钟。
继续使用精确闹钟的迁移步骤
至少,应用必须在安排精确闹钟之前检查其是否具有该权限。如果应用没有该权限,则必须通过调用意图向用户请求该权限。
这与 请求特殊权限 的标准工作流程相同。
- 应用应调用
AlarmManager.canScheduleExactAlarms()
以确认它具有相应的权限。 如果应用没有该权限,则调用一个意图,该意图包含
ACTION_REQUEST_SCHEDULE_EXACT_ALARM
以及应用的包名,以请求用户授予权限。在应用的
onResume()
方法中 检查用户的决定。侦听如果用户授予权限则发送的
AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED
广播。如果用户向您的应用授予了权限,则您的应用可以设置精确闹钟。如果用户拒绝了权限,则 优雅地降低应用体验,以便它在没有受该权限保护的信息的情况下为用户提供功能。
以下代码片段演示了如何检查 SCHEDULE_EXACT_ALARM
权限
val alarmManager: AlarmManager = context.getSystemService<AlarmManager>()!!
when {
// If permission is granted, proceed with scheduling exact alarms.
alarmManager.canScheduleExactAlarms() -> {
alarmManager.setExact(...)
}
else -> {
// Ask users to go to exact alarm page in system settings.
startActivity(Intent(ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
}
}
在 onResume()
中检查权限并处理用户决策的示例代码
override fun onResume() {
…
if (alarmManager.canScheduleExactAlarms()) {
// Set exact alarms.
alarmManager.setExact(...)
}
else {
// Permission not yet approved. Display user notice and revert to a fallback
// approach.
alarmManager.setWindow(...)
}
}
在权限被拒绝时优雅降级
一些用户会拒绝授予权限。在这种情况下,我们建议应用优雅地降低体验,并通过识别其 用例 继续努力提供尽可能好的备用用户体验。
豁免
以下类型的应用始终允许调用 setExact()
或 setExactAndAllowWhileIdle()
方法
- 使用平台证书签名的应用。
- 特权应用。
- 位于电源白名单上的应用(如果您的应用符合要求,您可以使用
ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
意图操作 请求此操作)。
预授权
SYSTEM_WELLBEING
的角色持有者将预先获得SCHEDULE_EXACT_ALARM
权限。
测试指南
要测试此更改,请从系统设置中的“特殊应用访问”页面(“设置”>“应用”>“特殊应用访问”>“闹钟和提醒”)禁用应用的“闹钟和提醒”权限,并观察应用的行为。