Skip to content

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

Update to at least version 1.4.1 of the AndroidX Media library, which includes the necessary fix:

gradle
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:

kotlin
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:

gradle
// 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:

gradle
// 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:

kotlin
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:

xml
<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:

bash
./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.