MediaSessionCompat 中 PendingIntent 标志的 Android 12 适配
问题概述
当应用程序以 Android 12(API 级别 31)或更高版本为目标平台时,使用 MediaSessionCompat
可能会遇到以下崩溃错误:
java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
这个错误是由于 Android 12 对 PendingIntent
的安全性要求变更引起的。从 Android 12 开始,所有 PendingIntent
必须明确指定可变性标志:FLAG_IMMUTABLE
或 FLAG_MUTABLE
。
根本原因
在 Android 12 之前,MediaSessionCompat
内部创建的 PendingIntent
可能没有明确指定这些标志。当应用以 Android 12 为目标平台时,系统会强制执行这一新的安全要求,导致应用崩溃。
解决方案
方法一:更新 MediaSessionCompat 的初始化方式
如果您直接使用 MediaSessionCompat
,可以手动创建并传递带有适当标志的 PendingIntent
:
override fun onCreate() {
super.onCreate()
val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
val pendingIntent = PendingIntent.getBroadcast(
applicationContext,
0,
mediaButtonIntent,
PendingIntent.FLAG_IMMUTABLE
)
mediaSession = MediaSessionCompat(this, TAG, null, pendingIntent).apply {
setCallback(mediaSessionCallback)
isActive = true
}
}
方法二:使用条件标志设置
对于需要兼容不同 Android 版本的应用,可以使用条件语句设置适当的标志:
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_IMMUTABLE
} else {
PendingIntent.FLAG_UPDATE_CURRENT // 或其他适用于旧版本的标志
}
val pendingIntent = PendingIntent.getBroadcast(
context,
requestCode,
intent,
flags
)
标志选择建议
- FLAG_IMMUTABLE:大多数情况下推荐使用,提供了更好的安全性
- FLAG_MUTABLE:仅在需要修改
PendingIntent
内容时使用(如内联回复或气泡通知)
方法三:更新相关依赖库
有时问题可能来自间接依赖的旧版本库。更新以下常用库可以解决问题:
// Kotlin
implementation 'androidx.work:work-runtime-ktx:2.7.1'
// Java
implementation 'androidx.work:work-runtime:2.7.1'
// 媒体库
implementation 'androidx.media:media:1.4.1'
// Google Play 服务广告库
implementation 'com.google.android.gms:play-services-ads:22.2.0'
// Firebase 消息
implementation 'com.google.firebase:firebase-messaging:23.0.0'
方法四:检查并更新所有相关依赖
使用以下命令检查项目中的依赖关系,找出可能使用旧版本 work-runtime 的库:
./gradlew app:dependencies
更新所有使用旧版本 Android WorkManager 的依赖项。
特殊情况处理
使用 Chuck 库的情况
如果您使用了网络调试库 Chuck,请更新到最新版本:
debugImplementation "com.github.chuckerteam.chucker:library:3.5.2"
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:3.5.2"
Ionic/Cordova 项目
对于混合应用开发,确保插件使用了正确的 Play 服务版本:
<plugin name="cordova-plugin-google-analytics" spec="1.8.6">
<variable name="PLAY_SERVICES_VERSION" value="18.0.1" />
<variable name="GMS_VERSION" value="18.0.1" />
</plugin>
版本要求说明
从以下版本开始,AndroidX 媒体库已修复此问题:
androidx.media:media:1.3.0-rc02
开始支持FLAG_IMMUTABLE
androidx.media:media:1.4.1
正式修复了此问题
结论
解决 Android 12 中 MediaSessionCompat
的 PendingIntent
问题主要有三种方法:
- 直接解决方案:手动创建带有适当标志的
PendingIntent
并传递给MediaSessionCompat
- 依赖更新:确保所有相关库(特别是 work-runtime)都已更新到兼容版本
- 条件处理:根据 Android 版本动态选择正确的
PendingIntent
标志
推荐优先考虑更新库的解决方案,因为这通常能解决更深层次的兼容性问题,并提供更好的长期维护性。
注意事项
- 确保测试应用在所有目标 Android 版本上的兼容性
- 如果使用
FLAG_MUTABLE
,请确保确实需要可变PendingIntent
的功能 - 检查所有使用
PendingIntent
的地方,确保都符合 Android 12 的要求