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

Android 12中PendingIntent.FLAG_UPDATE_CURRENT报错及相关疑问

Android 12+ AlarmManager 报错解决方案与疑问解答

问题背景

使用AlarmManager实现每日特定时间闹钟时,Android 12以下设备正常运行,但Android 12及以上设备触发报错,Firebase Crashlytics报错信息如下:

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable

原实现代码

Calendar calendar = Calendar.getInstance();

calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 15);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

Calendar cur = Calendar.getInstance();

if (cur.after(calendar)) {
    calendar.add(Calendar.DATE, 1);
}

Intent myIntent = new Intent(mCon, DailyReminder.class);
int ALARM1_ID = 10000;

PendingIntent pendingIntent= PendingIntent.getBroadcast(mCon, ALARM1_ID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager alarmManager = (AlarmManager) mCon.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);

找到的解决方案

PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    pendingIntent= PendingIntent.getBroadcast(mCon, ALARM1_ID, myIntent, PendingIntent.FLAG_IMMUTABLE);
} else {
    pendingIntent = PendingIntent.getBroadcast(mCon, ALARM1_ID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}

疑问解答

1. PendingIntent.FLAG_UPDATE_CURRENT 与 PendingIntent.FLAG_IMMUTABLE 的区别是什么?

  • FLAG_UPDATE_CURRENT:核心作用是更新已存在的PendingIntent内的Intent内容。如果系统中已经存在匹配的PendingIntent(相同上下文、requestCode、Intent过滤规则),调用getBroadcast时会把原PendingIntent里的Intent替换成新传入的,同时保留PendingIntent引用,确保后续触发时用的是最新的Intent数据。这是Android 12之前常用的标记,用来保证Intent携带的信息是最新的。
  • FLAG_IMMUTABLE:Android 12(API 31)新增的安全标记,标记PendingIntent为不可变状态。一旦创建完成,该PendingIntent内的Intent内容无法被修改,第三方应用也不能篡改它。系统强烈推荐优先用这个标记,能降低恶意应用篡改Intent的安全风险。

注意:这两个标记可以组合使用(如PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE),既可以更新Intent内容,又能保证PendingIntent的不可变性,这也是Android 12+的更优写法。

2. 每次用户启动应用时调用该闹钟设置方法是否可行?会创建新闹钟还是更新已有闹钟?

完全可行,且不会创建新闹钟,而是更新已有的闹钟:

  • 因为你用了固定的ALARM1_ID(10000),且Intent的目标组件是DailyReminder.class,系统会根据上下文、requestCode和Intent的匹配规则判断是否存在已有的PendingIntent。如果存在,会复用该PendingIntent(若用了FLAG_UPDATE_CURRENT或组合标记,会同步更新Intent内容)。
  • 调用alarmManager.setRepeating时,系统会检测是否存在同ID的重复闹钟,若存在则直接更新闹钟的触发时间和重复规则,不会生成新的闹钟实例。
  • 这种做法的好处是:确保每次应用启动时,闹钟都是激活状态(避免系统重启、应用被清理导致闹钟失效);如果后续允许用户修改闹钟时间,启动时调用也能同步更新到最新设置的时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:31:08