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

Android Studio多闹钟设置异常:仅最后一个闹钟生效求助

Android多闹钟设置只生效最后一个的问题排查与解决

嘿,我之前也踩过一模一样的坑!核心问题基本都出在PendingIntent的复用机制、请求码唯一性,再加上数组管理没做对,导致前面设置的闹钟被后面的直接覆盖了。下面给你拆解问题和解决办法:

问题根源

  1. 请求码重复:如果多个PendingIntent用了相同的requestCode,系统会直接复用之前的实例,后面的闹钟设置会直接覆盖掉前面的。
  2. PendingIntent标记使用错误:没加适配高版本的标记,或者标记逻辑不对,也会导致旧的PendingIntent被替换。
  3. 数组管理混乱:如果每次点击按钮都重新初始化数组,之前的AlarmManager和PendingIntent引用就丢失了,没法正确取消旧闹钟。

解决方案

1. 给每个闹钟分配唯一请求码

可以用一个递增的计数器,每次创建新PendingIntent时用不同的requestCode,彻底避免复用问题。

2. 先取消旧闹钟,再添加新闹钟

每次设置新闹钟前,先遍历数组把之前的闹钟全部取消,再清空数组重新添加新的,避免残留旧任务。

3. 适配Android高版本的PendingIntent标记

针对Android 12及以上,必须添加FLAG_IMMUTABLE或FLAG_MUTABLE(如果不需要修改Intent内容,优先用FLAG_IMMUTABLE)。

修正后的代码示例

先在Activity的成员变量里定义数组和计数器:

private ArrayList<AlarmManager> alarmManagers = new ArrayList<>();
private ArrayList<PendingIntent> pendingIntents = new ArrayList<>();
private int requestCodeCounter = 0; // 生成唯一请求码的计数器

然后修改点击事件的代码:

alarm_on.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // 第一步:取消所有已设置的旧闹钟
        for (int i = 0; i < alarmManagers.size(); i++) {
            AlarmManager am = alarmManagers.get(i);
            PendingIntent pi = pendingIntents.get(i);
            if (am != null && pi != null) {
                am.cancel(pi);
            }
        }
        // 清空数组,准备添加新闹钟
        alarmManagers.clear();
        pendingIntents.clear();

        // 第二步:设置第一个闹钟
        Calendar cal1 = Calendar.getInstance();
        cal1.set(Calendar.HOUR_OF_DAY, alarm_timepicker.getHour());
        cal1.set(Calendar.MINUTE, alarm_timepicker.getMinute());
        cal1.set(Calendar.SECOND, 0);
        // 避免设置过去的时间,自动加一天
        if (cal1.before(Calendar.getInstance())) {
            cal1.add(Calendar.DAY_OF_YEAR, 1);
        }

        Intent intent1 = new Intent(MainActivity.this, AlarmReceiver.class);
        PendingIntent pi1 = PendingIntent.getBroadcast(
                MainActivity.this,
                requestCodeCounter++, // 唯一请求码
                intent1,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
        AlarmManager am1 = (AlarmManager) getSystemService(ALARM_SERVICE);
        // 用setExactAndAllowWhileIdle确保低电量模式也能触发
        am1.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), pi1);
        alarmManagers.add(am1);
        pendingIntents.add(pi1);

        // 第三步:设置第二个闹钟(示例:比第一个晚30分钟)
        Calendar cal2 = Calendar.getInstance();
        cal2.setTimeInMillis(cal1.getTimeInMillis());
        cal2.add(Calendar.MINUTE, 30);

        Intent intent2 = new Intent(MainActivity.this, AlarmReceiver.class);
        PendingIntent pi2 = PendingIntent.getBroadcast(
                MainActivity.this,
                requestCodeCounter++, // 下一个唯一请求码
                intent2,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
        AlarmManager am2 = (AlarmManager) getSystemService(ALARM_SERVICE);
        am2.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), pi2);
        alarmManagers.add(am2);
        pendingIntents.add(pi2);
    }
});

额外提醒

  • 如果每个闹钟需要触发不同逻辑,可以给Intent添加不同的extra参数(比如intent.putExtra("ALARM_ID", 1)),方便在Receiver里区分处理。
  • 从Android 6.0开始,Doze模式会限制闹钟触发,setExactAndAllowWhileIdle比setExact更可靠,能确保低电量待机时闹钟正常触发。

内容的提问来源于stack exchange,提问作者Jay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:25:55