如何实现可在Doze模式下触发的重复Alarm Manager?
问题解答
首先明确:Android系统并没有提供setRepeatingAndAllowWhileIdle这类API,要绕过Doze模式的限制实现精准重复闹钟,只能通过setExactAndAllowWhileIdle手动实现重复逻辑,具体方案如下:
核心思路
用setExactAndAllowWhileIdle设置单次精准闹钟,每次闹钟触发(广播接收器收到回调)后,再计算下一次触发的时间(次日7点),并再次调用setExactAndAllowWhileIdle设置下一次闹钟,以此实现循环重复的效果。
代码实现步骤
1. 修改初始闹钟设置代码
把原来的setRepeating替换为setExactAndAllowWhileIdle:
val mIntent = Intent(this, MyReceiver::class.java) val calendar: Calendar = Calendar.getInstance() calendar.timeInMillis = System.currentTimeMillis() calendar.set(Calendar.HOUR_OF_DAY, 7) calendar.set(Calendar.MINUTE, 0) if (calendar.timeInMillis < System.currentTimeMillis()) { calendar.add(Calendar.DAY_OF_MONTH, 1) } val mPendingIntent = PendingIntent.getBroadcast( this, 1, mIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE // 适配Android 12+ ) val mAlarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager // 使用setExactAndAllowWhileIdle替代setRepeating mAlarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, mPendingIntent )
2. 修改广播接收器,添加下一次闹钟逻辑
在MyReceiver的onReceive方法里,处理完业务逻辑后,计算下一次7点的时间并重新设置闹钟:
class MyReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { // 处理你的业务逻辑,比如发送通知、执行指定任务等 // 计算下一次7点的触发时间 val calendar: Calendar = Calendar.getInstance() calendar.timeInMillis = System.currentTimeMillis() calendar.set(Calendar.HOUR_OF_DAY, 7) calendar.set(Calendar.MINUTE, 0) // 当前已触发闹钟,直接设置次日7点 calendar.add(Calendar.DAY_OF_MONTH, 1) // 重新创建PendingIntent,requestCode需与之前一致 val nextIntent = Intent(context, MyReceiver::class.java) val nextPendingIntent = PendingIntent.getBroadcast( context, 1, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 设置下一次精准闹钟 val alarmManager = context?.getSystemService(Context.ALARM_SERVICE) as AlarmManager alarmManager.setExactAndAllowWhileIdle( AlarmManager.RTC_WAKEUP, calendar.timeInMillis, nextPendingIntent ) } }
额外注意事项
- 权限适配:Android 12及以上版本,需在
AndroidManifest.xml中添加POST_NOTIFICATIONS权限(若涉及发送通知),同时PendingIntent必须设置FLAG_IMMUTABLE或FLAG_MUTABLE(根据是否需要修改Intent内容选择)。 - 耗时任务处理:广播接收器的
onReceive方法执行时间有限制(通常10秒内),若业务逻辑耗时较长,建议启动前台服务处理,避免被系统杀死。 - 重启恢复:若需要设备重启后闹钟继续生效,需注册
BOOT_COMPLETED广播接收器,在设备重启完成后重新初始化闹钟设置。
内容的提问来源于stack exchange,提问作者Joshu
相关产品推荐
相关产品推荐

