You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现可在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:31:15