MediaSessionCompat:Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent

Viewed 60622

I'm trying to update my application to Android SDK 31 but I'm having an issue with MediaSessionCompat.

I have a MediaService that extends the MediaBrowserServiceCompat() and in method onCreate of that service I initialise the MediaSessionCompat.

override fun onCreate() {
  super.onCreate()
  mediaSession = MediaSessionCompat(this, TAG).apply {
    setCallback(mediaSessionCallback)
    isActive = true
  }
...

But I'm having the following error

java.lang.RuntimeException: Unable to create service com.radio.core.service.MediaService: java.lang.IllegalArgumentException: com.xxx.xxx: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
    Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:4498)
        at android.app.ActivityThread.access$1500(ActivityThread.java:250)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2064)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7829)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:982)
     Caused by: java.lang.IllegalArgumentException: com.xxx.xxx: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
    Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
        at android.app.PendingIntent.checkFlags(PendingIntent.java:375)
        at android.app.PendingIntent.getBroadcastAsUser(PendingIntent.java:645)
        at android.app.PendingIntent.getBroadcast(PendingIntent.java:632)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:567)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:537)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:501)
        at android.support.v4.media.session.MediaSessionCompat.<init>(MediaSessionCompat.java:475)
        at com.radio.core.service.MediaService.onCreate(MediaService.kt:63)
        at android.app.ActivityThread.handleCreateService(ActivityThread.java:4485)
            ... 9 more

I'm using the most recent version of media library ("androidx.media:media:1.4.0") that is able to handle the this requirement from the Andriod "S"". As it's possible to see in the MediaSessionCompact.java class.


// TODO(b/182513352): Use PendingIntent.FLAG_MUTABLE instead from S.
/**
 * @hide
 */
@RestrictTo(LIBRARY)
public static final int PENDING_INTENT_FLAG_MUTABLE = 
  Build.VERSION.CODENAME.equals("S") ? 0x02000000 : 0;

...

if (mbrComponent != null && mbrIntent == null) {
  // construct a PendingIntent for the media button
  Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
  // the associated intent will be handled by the component being registered
  mediaButtonIntent.setComponent(mbrComponent);
  mbrIntent = PendingIntent.getBroadcast(context,
    0/* requestCode, ignored */, mediaButtonIntent,
    PENDING_INTENT_FLAG_MUTABLE);
}

Source code demonstrating the problem - https://github.com/adelinolobao/issue-media-session-compat

Do you guys have any idea how can I fix the error?

12 Answers

If you are NOT USING PendingIntent anywhere. The issue might be resolved by adding or updating this dependency

    // required to avoid crash on Android 12 API 31
    implementation 'androidx.work:work-runtime-ktx:2.7.0'

This fixed my problem.

Solved This Error Just Used PendingIntent.FLAG_MUTABLE for Android Version 12 OR S

PendingIntent pendingIntent = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
        pendingIntent = PendingIntent.getActivity
               (this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE);
    }
    else
    {
         pendingIntent = PendingIntent.getActivity
                (this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT);
    }

If your app targets Android 12, you must specify the mutability of each PendingIntent object that your app creates.

In your case, android.support.v4.media.session.MediaSessionCompat was responsible for creating PendingItent during initialization of MediaSessionCompat.

Solution: Luckily, there is an additional @constructor for the MediaSessionCompat class, so we can pass pendingItent as a parameter. If we pass null for the component param, it will be initialized in the library.

override fun onCreate() {
        super.onCreate()

        val mediaButtonIntent = Intent(Intent.ACTION_MEDIA_BUTTON)
        val pendingItent = PendingIntent.getBroadcast(
            baseContext,
            0, mediaButtonIntent,
            PendingIntent.FLAG_IMMUTABLE
        )

        mediaSession = MediaSessionCompat(baseContext, TAG, null, pendingItent).also {
            it.isActive = true
        }

        sessionToken = mediaSession.sessionToken
        packageValidator = PackageValidator(this@MediaService, R.xml.allowed_media_browser_callers)
    }

Source code: https://github.com/dautovicharis/issue-media-session-compat

Update: Thanks go to:

In version 1.3.0 there were new changes in MediaSessionCompat where we can clearly see that something is missing related to Android 12 based on TODO(b/182513352) comment.

Until new androidx.media:media: is released, using the workaround I have provided should work just fine.

Update: We hope that TODO(b/182513352) will be fixed in upcoming releases. Until then, we can use implementation "androidx.media:media:1.3.0-rc02" where FLAG_IMMUTABLE is supported.

For those using Java:

Add the following line to your build.gradle(app) under dependencies.

dependencies {
  // ...
  implementation 'androidx.work:work-runtime:2.7.1'
}

If you are not using pending intent in your app then try this one. implementation 'androidx.work:work-runtime-ktx:2.7.0'

else If you are using pending intent, then change this

pendingIntent = PendingIntent.getActivity(
                        this,
                        0, intentToLaunchThisActivityFromNotification,
                        PendingIntent.FLAG_UPDATE_CURRENT);

to

`

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {

 

               pendingIntent = PendingIntent.getActivity(
                        this,
                        0, intentToLaunchThisActivityFromNotification,
                        PendingIntent.FLAG_IMMUTABLE);
            }
            else
            {
                 pendingIntent = PendingIntent.getActivity(
                        this,
                        0, intentToLaunchThisActivityFromNotification,
                        PendingIntent.FLAG_UPDATE_CURRENT);
            }`

If using java or react-native then paste this inside app/build.gradle

dependencies {
  // ...
  implementation 'androidx.work:work-runtime:2.7.1'
}

If using Kotlin then use this

dependencies {
  // ...
  implementation 'androidx.work:work-runtime-ktx:2.7.0'
}

Error when using PendingIntent

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {

 

               pendingIntent = PendingIntent.getActivity(
                        this,
                        0, intentToLaunchThisActivityFromNotification,
                        PendingIntent.FLAG_IMMUTABLE);
            }
            else
            {
                 pendingIntent = PendingIntent.getActivity(
                        this,
                        0, intentToLaunchThisActivityFromNotification,
                        PendingIntent.FLAG_UPDATE_CURRENT);
            }

and if anybody still facing the crash issue for android 12 then make sure you add following in AndroidMenifest.xml

<activity 
   ...
   android:exported="true" // in most cases it is true but based on requirements it can be false also   
>   


   // If using react-native push notifications then make sure to add into it also

 <receiver   
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver" android:exported="true">
 
   //  Similarly
 
 <service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService" android:exported="true">

For me, I had to upgrade

    liteImplementation "com.google.android.gms:play-services-ads:20.4.0"

to

    liteImplementation "com.google.android.gms:play-services-ads:20.6.0"

Apparently play-services-ads:20.4.0 has a dependency on a version of work-runtime which doesn't support sdk 31.

  1. Add the following line to the build.gradle(app)
implementation 'androidx.work:work-runtime:2.7.1'
  1. Add the following permission to the Manifest.xml
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
  1. Modify the pending intent as the following

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, PendingIntent.getBroadcast(getApplicationContext(), 0, alertIntent, PendingIntent.FLAG_MUTABLE)); } else { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, PendingIntent.getBroadcast(getApplicationContext(), 0, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT)); }

Upgrade app targets with Android Version 12 or S, Just Used PendingIntent.FLAG_MUTABLE and PendingIntent.FLAG_IMMUTABLE

int intentFlagType = PendingIntent.FLAG_ONE_SHOT;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
    intentFlagType = PendingIntent.FLAG_IMMUTABLE;  // or only use FLAG_MUTABLE >> if it needs to be used with inline replies or bubbles.
}
PendingIntent pendingIntent = PendingIntent.getActivity(context, notificationID, intent, intentFlagType);

This should be fixed now if you update to version at least 1.4.1

https://developer.android.com/jetpack/androidx/releases/media#media-1.4.1

Version 1.4.1 August 4, 2021

androidx.media:media:1.4.1 is released. Version 1.4.1 contains these commits.

Bug Fixes

  • Fix mutability flag for creating PendingIntent to prevent crash when targeting Android S.
  • Fix ClassVerificationFailure for NotificationCompat.MediaStyle.

I updated your libraries after changing SdkVersion to 31, then error is gone

This is working for me ->

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
Related