MediaSessionCompat FLAG_IMMUTABLE Fix for Android 12
Problem Statement
When targeting Android 12 (API level 31) or higher, you may encounter the following runtime exception when using 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
This error occurs because Android 12 introduced new security requirements for PendingIntent
objects. The system now requires explicit declaration of whether a PendingIntent
should be mutable or immutable.
Root Cause
The MediaSessionCompat
class internally creates a PendingIntent
for media button handling. In older versions of the AndroidX Media library, this internal implementation didn't specify the required mutability flag when targeting Android 12.
Solutions
Solution 1: Update AndroidX Media Library (Recommended)
Update to at least version 1.4.1 of the AndroidX Media library, which includes the necessary fix:
implementation 'androidx.media:media:1.4.1'
This version specifically addresses:
- Mutability flag for creating PendingIntent to prevent crash when targeting Android S
- Class verification failures for NotificationCompat.MediaStyle
Solution 2: Manual PendingIntent Creation
If you cannot update the library immediately, manually create a PendingIntent
and pass it to the MediaSessionCompat
constructor:
override fun onCreate() {
super.onCreate()
val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
val pendingIntent = PendingIntent.getBroadcast(
baseContext,
0,
mediaButtonIntent,
PendingIntent.FLAG_IMMUTABLE
)
mediaSession = MediaSessionCompat(baseContext, "TAG", null, pendingIntent).apply {
setCallback(mediaSessionCallback)
isActive = true
}
sessionToken = mediaSession.sessionToken
}
Solution 3: Update Dependencies with Work Manager
If you're not directly using PendingIntent
but still encounter this error, it might be caused by outdated transitive dependencies. Update the Work Manager library:
// Kotlin
implementation 'androidx.work:work-runtime-ktx:2.8.0'
// Java
implementation 'androidx.work:work-runtime:2.8.0'
Solution 4: Update Other Problematic Dependencies
Some common libraries that may cause this issue when outdated:
// Firebase Messaging
implementation 'com.google.firebase:firebase-messaging:23.0.0'
// Google Play Services Ads
implementation 'com.google.android.gms:play-services-ads:22.0.0'
// Chuck library (network interceptor)
debugImplementation "com.github.chuckerteam.chucker:library:3.5.2"
releaseImplementation "com.github.chuckerteam.chucker:library-no-op:3.5.2"
Version Check Pattern for PendingIntent
When creating PendingIntent
objects directly, use version checking:
val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.FLAG_IMMUTABLE
} else {
PendingIntent.FLAG_UPDATE_CURRENT
}
val pendingIntent = PendingIntent.getActivity(
context,
requestCode,
intent,
flag
)
WARNING
Use FLAG_MUTABLE
only if your app needs to modify the intent contents (e.g., for inline replies or bubbles). Google strongly recommends using FLAG_IMMUTABLE
for most use cases.
Android Manifest Requirements for Android 12
Ensure your AndroidManifest.xml includes the proper exported attributes:
<activity
android:name=".MainActivity"
android:exported="true">
<!-- ... -->
</activity>
<service
android:name=".MediaService"
android:exported="true">
<!-- ... -->
</service>
Verification
After applying the fix, verify your dependencies are up to date:
./gradlew app:dependencies
This command will show your dependency tree and help identify any outdated libraries that might still be causing issues.
Conclusion
The Android 12 PendingIntent
mutability requirement is a security enhancement that prevents unintended modification of intents. The most straightforward solution is to update your AndroidX Media library to version 1.4.1 or later. If that's not immediately possible, manually creating the PendingIntent
with the appropriate flag provides a reliable workaround.
Always ensure all your dependencies are updated to their latest compatible versions to avoid similar issues with other components that might create PendingIntent
objects internally.