Android应用API 31+无法运行,PendingIntent报错求助
解决API 31+ PendingIntent必须指定可变/不可变标志的问题
这个错误是因为Android 12(API 31)开始强制要求所有PendingIntent创建时必须声明FLAG_IMMUTABLE或FLAG_MUTABLE,哪怕是用FLAG_NO_CREATE这种仅用于查询的标志也不例外。你的代码里两处PendingIntent调用都没加这个标志,导致API31+环境报错。
修复步骤
你的场景是给AlarmManager使用PendingIntent,不需要修改Intent内容,所以优先使用官方推荐的FLAG_IMMUTABLE。
方法1:手动做版本兼容判断
直接修改代码中两处PendingIntent的调用,组合对应的标志位:
public static void initSyncReceiver(Context context) { Intent intent = new Intent(context, SyncReciver.class); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); // 修复报错的查询代码:根据API版本组合标志 int flags = PendingIntent.FLAG_NO_CREATE; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { flags |= PendingIntent.FLAG_IMMUTABLE; } boolean alarmUp = (PendingIntent.getBroadcast(context, 23231, intent, flags) != null); if (!Common.SharedPreferenceHelper.getSharedPreference(context, context.getString(R.string.survey_sync_settings_key), true)) { if (alarmUp) { Log.e(TAG, "sync booking alarm is up but not needed, canceling.."); // 同样修复取消Alarm时的标志位 int cancelFlags = PendingIntent.FLAG_CANCEL_CURRENT; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { cancelFlags |= PendingIntent.FLAG_IMMUTABLE; } PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 23231, intent, cancelFlags); pendingIntent.cancel(); alarmManager.cancel(pendingIntent); } else { Log.e(TAG, "sync booking alarm neither up nor needed..."); } return; } setAlarm(intent, context, 23231, 5); Log.e(TAG, "sync booking alarm needed so setting..."); }
方法2:用AndroidX的PendingIntentCompat简化(推荐)
既然你已经迁移到AndroidX,直接用PendingIntentCompat类可以自动处理版本差异,不用手动写版本判断:
import androidx.core.app.PendingIntentCompat; public static void initSyncReceiver(Context context) { Intent intent = new Intent(context, SyncReciver.class); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); // 替换成PendingIntentCompat.getBroadcast,自动适配版本标志 boolean alarmUp = (PendingIntentCompat.getBroadcast(context, 23231, intent, PendingIntent.FLAG_NO_CREATE, true) != null); if (!Common.SharedPreferenceHelper.getSharedPreference(context, context.getString(R.string.survey_sync_settings_key), true)) { if (alarmUp) { Log.e(TAG, "sync booking alarm is up but not needed, canceling.."); PendingIntent pendingIntent = PendingIntentCompat.getBroadcast(context, 23231, intent, PendingIntent.FLAG_CANCEL_CURRENT, true); pendingIntent.cancel(); alarmManager.cancel(pendingIntent); } else { Log.e(TAG, "sync booking alarm neither up nor needed..."); } return; } setAlarm(intent, context, 23231, 5); Log.e(TAG, "sync booking alarm needed so setting..."); }
这里最后一个参数true代表使用FLAG_IMMUTABLE,如果确实需要可变的PendingIntent(比如配合气泡、内联回复功能),就传false。
注意点
- 务必检查项目中所有创建PendingIntent的地方(比如通知、Alarm、广播等),只要是API31+环境,都需要添加这两个标志之一。
- 优先使用
FLAG_IMMUTABLE,只有当你需要修改PendingIntent内部的Intent时才用FLAG_MUTABLE,这样更符合Android的安全规范。
内容的提问来源于stack exchange,提问作者Moeez
相关产品推荐
相关产品推荐

