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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:05:26