183

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?

Adelino
  • 2,530
  • 4
  • 20
  • 32
  • 2
    Based on that `TODO` comment, it looks like this library needs to be updated. I do not see a public issue for this, though `182513352` might be a private one. Note that you have a year and change before you absolutely need `targetSdkVersion 31`, so you may wish to drop back to 30 until this library gets updated. – CommonsWare Jul 25 '21 at 11:39
  • 1
    The bug 182513352 was fixed on this commit https://android.googlesource.com/platform/frameworks/support/+/b676241c1174d10580a889743248a2cd1b315dd0 and based RELEASE NOTES from androidx.media:media the version 1.3.0-rc02 (https://developer.android.com/jetpack/androidx/releases/media) it was already released – Adelino Jul 26 '21 at 09:01
  • My project builds fine after setting implementation 'androidx.work:work-runtime:2.7.1', however, this error still happens when running some functions, specifically when fetching location data. – Md. Robi Ullah Nov 24 '22 at 18:11

21 Answers21

337

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.1'

This fixed my problem.

You can execute ./gradlew app:dependencies in the terminal in your project and discover what dependency is including work-runtime with and older version. Then you can try to upgrade that dependency in an effort of do the things right

andrey2ag
  • 3,670
  • 1
  • 12
  • 12
  • 4
    Winning answer! Fixed my issue too. Looks like it was fixed in v-alpha-02: https://developer.android.com/jetpack/androidx/releases/work#2.7.0-alpha02 – PieterAelse Sep 28 '21 at 15:31
  • 6
    You can execute `./gradlew app:dependencies` in the terminal in your project and discover what dependency is including `work-runtime` with and older version. Then you can try to upgrade that dependency in an effort of do the things right – Ricard Dec 23 '21 at 10:45
  • 1
    @master https://github.com/firebase/flutterfire/issues/7237#issuecomment-951616172 - Here is an explanation why to use this library to resolve this issue. – ThinkAndCode Aug 04 '22 at 10:28
138

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

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);
    }
Noaman Akram
  • 3,680
  • 4
  • 20
  • 37
  • 7
    WOW! What an awesome solution! Just one question. How were you planning to integrate that into the MediaSessionCompat initialization? You know, like the question asked. – me_ Feb 17 '22 at 21:35
  • @noaman, idk why IDE still gives warning on else condition for missing PendingIntent flags. Min SDK version is 19. – Anukool srivastav Sep 04 '22 at 04:38
  • While using flag - PendingIntent.FLAG_MUTABLE It is giving error as - Must be one or more of: PendingIntent.FLAG_ONE_SHOT, PendingIntent.FLAG_NO_CREATE, PendingIntent.FLAG_CANCEL_CURRENT, PendingIntent.FLAG_UPDATE_CURRENT, android.app.PendingIntent.FLAG_IMMUTABLE, android.app.PendingIntent.FLAG_MUTABLE, Intent.FILL_IN_ACTION, Intent.FILL_IN_DATA, Intent.FILL_IN_CATEGORIES, Intent.FILL_IN_COMPONENT, Intent.FILL_IN_PACKAGE, Intent.FILL_IN_SOURCE_BOUNDS, Intent.FILL_IN_SELECTOR, Intent.FILL_IN_CLIP_DATA – void pointer Oct 27 '22 at 13:39
  • Didn't get why use the `FLAG_ONE_SHOT` to previous versions. From the DOCS: Up until Build.VERSION_CODES.R, PendingIntents are assumed to be mutable by default, unless FLAG_IMMUTABLE is set. Starting with Build.VERSION_CODES.S, it will be required to explicitly specify the mutability of PendingIntents on creation – Gustavo Garcia Feb 24 '23 at 20:01
38

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.

Haris
  • 4,130
  • 3
  • 30
  • 47
  • I knew about that constructor but the issue is that I'm using more methods from media component that crash with this issue. For example the MediaButtonReceiver.buildMediaButtonPendingIntent returns a PendingIntent with the wrong flag and we are not able to change it. I think that at the moment the androidx.media library is not usable in Android 31 which I think it's very strange since most audio applications rely on this library – Adelino Jul 28 '21 at 10:07
  • 1
    Have you tried using version 1.3.0-rc2 where FLAG_IMMUTABLE was supported? – Haris Jul 28 '21 at 10:14
  • @Adelino I have tested with implementation "androidx.media:media:1.3.0-rc02" and it doesn't crash, So maybe the option is to use this version until the new release. – Haris Jul 28 '21 at 10:27
  • Now I'm feeling really stupid because that was the solution :| it's strange why they didn't include the changes from 1.3.0-rc02 in most recent versions – Adelino Jul 28 '21 at 10:35
  • It was supported in 1.3.0.rc02, but then changed in [1.3.0](https://android-review.googlesource.com/c/platform/frameworks/support/+/1675599/1/media/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java#127). Let's hope that this will be fixed with TODO(b/182513352) – Haris Jul 28 '21 at 10:43
  • 2
    The new version "androidx.media:media:1.4.1" it's working correctly in Android SDK 31 https://developer.android.com/jetpack/androidx/releases/media#version_141_3 – Adelino Aug 16 '21 at 12:03
34

For those using Java:

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

dependencies {
  // ...
  implementation 'androidx.work:work-runtime:2.7.1'
}
iDecode
  • 22,623
  • 19
  • 99
  • 186
13

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);
   }

or for C#/Xamarin.Android:

   PendingIntent pendingIntent = null;
   if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.S)
   {
      pendingIntent = PendingIntent.GetActivity(mContext, 0, intent, PendingIntentFlags.Mutable);
   }
   else
   {
                        pendingIntent = PendingIntent.GetActivity(mContext, 0, intent, PendingIntentFlags.OneShot);
   }
Luca Ziegler
  • 3,236
  • 1
  • 22
  • 39
  • Still getting the same error even after changing all the pending intents. #WeirdAndroidBehaviour – Kishan Solanki Aug 26 '22 at 11:03
  • While using flag - PendingIntent.FLAG_MUTABLE It is giving error as - Must be one or more of: PendingIntent.FLAG_ONE_SHOT, PendingIntent.FLAG_NO_CREATE, PendingIntent.FLAG_CANCEL_CURRENT, PendingIntent.FLAG_UPDATE_CURRENT, android.app.PendingIntent.FLAG_IMMUTABLE, android.app.PendingIntent.FLAG_MUTABLE, Intent.FILL_IN_ACTION, Intent.FILL_IN_DATA, Intent.FILL_IN_CATEGORIES, Intent.FILL_IN_COMPONENT, Intent.FILL_IN_PACKAGE, Intent.FILL_IN_SOURCE_BOUNDS, Intent.FILL_IN_SELECTOR, Intent.FILL_IN_CLIP_DATA – void pointer Oct 27 '22 at 13:39
  • but .FLAG_IMMUTABLEL is one of your list, how it gives this error! – صلي علي محمد - Atef Farouk Oct 28 '22 at 16:10
  • I used your solution in a global function and need only call the function when setting the flag, which I do in many parts of my app. – Ken Roy Dec 04 '22 at 15:14
12

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">
Mark Nashat
  • 668
  • 8
  • 9
  • In case anyone has the issue in a nfc reading context, you should change the flag to FLAG_MUTABLE in order to get the correct action for the new intent. Having the flag set to IMMUTABLE won't pass any action to your intent. – Captain Allergy Aug 02 '22 at 14:14
10

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.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • 1
    For more detail chack the note about version 20.4.0 in the official documentation https://developers.google.com/admob/android/rel-notes – walox Jan 04 '23 at 04:45
8

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);
Shomu
  • 2,734
  • 24
  • 32
8

This is working for me ->

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

Change in notification.java

PendingIntent.FLAG_IMMUTABLE

100% working

GUGAN RAJ
  • 101
  • 7
Kunal Kalwar
  • 685
  • 6
  • 20
5

In my case, the reason is about old version Chuck library..

I have changed it from

implementation 'com.readystatesoftware.chuck:library:1.1.0'

to new implementation like

dependencies {
  debugImplementation "com.github.chuckerteam.chucker:library:3.5.2"
  releaseImplementation "com.github.chuckerteam.chucker:library-no-op:3.5.2"
}

val client = OkHttpClient.Builder()
                .addInterceptor(ChuckerInterceptor(context))
                .build()


android {
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }

  // For Kotlin projects add also this line
  kotlinOptions.jvmTarget = "1.8"
}

then crash was gone.

See the documentation : https://github.com/ChuckerTeam/chucker

oguzhan
  • 2,073
  • 1
  • 26
  • 23
4

To Solve this issue just implement given dependency in build.gradle.

implementation 'androidx.work:work-runtime-ktx:2.7.1'

it will solve your issue.

Rakesh Jha
  • 279
  • 2
  • 7
3
  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)); }

Leenah
  • 850
  • 3
  • 15
  • 36
1

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.
Stevie Kideckel
  • 1,928
  • 2
  • 17
  • 21
1

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

Prashanth
  • 993
  • 8
  • 18
1

I am using Flag mutable for shedule call class

alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, AlarmReceiver.class), PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
Procrastinator
  • 2,526
  • 30
  • 27
  • 36
Roxy Hasan
  • 11
  • 3
1

In my case, I copied the implementation for hilt of other project that contains the hilt-worker while the current project is not implemented worker library yet and the error occurs.

implementation 'androidx.hilt:hilt-work:1.0.0'

I solved by just remove it, or implement the worker library if you need to use worker as the best answers above. Hope it can help

Quốc Hùng
  • 106
  • 1
  • 7
1

I tried all answers here none of them worked for me. Here's my solution

PendingIntent pendingItent = PendingIntent.getBroadcast(
            getApplicationContext(),
            0, new Intent(this, MainActivity.class),
            PendingIntent.FLAG_IMMUTABLE
    );

    MediaSessionCompat mediaSessionCompat = new MediaSessionCompat(this, "simple player session", null, pendingItent);
Michael
  • 411
  • 2
  • 6
  • 15
0

Sometimes you just need to update the Gradle build tool in Android studio. Simply upgrading to the latest version ironed out the issues that led to this for me.

To update to the latest version of Gradle, simple click the little Gradle update dialog that shows up at the bottom right corner of Android Studio.

kc ochibili
  • 3,103
  • 2
  • 25
  • 25
0

Two changes are to be made

  1. Update your work library dependency as shown below

def work_version = "2.7.0"

// (Java only)
implementation "androidx.work:work-runtime:$work_version"    

// Kotlin + coroutines
implementation "androidx.work:work-runtime-ktx:$work_version"
  1. Add FLAG_IMMUTABLE while creating pending intent

    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAG_IMMUTABLE);
    
Shubham Goel
  • 1,962
  • 17
  • 25
0

Updating the version of the com.google.android.gms:play-services-analytics dependency to 18.0.1 in the build.gradle file solved an issue I was experiencing. In Ionic, you can also change the version in the config.xm

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

or removing and adding the plugin again adding the parameters with the proper versions for PLAY_SERVICES_VERSION and GMS_VERSION.

Also becareful, make sure if you do this change that you change all play services to the same version (18.+ in my case), for example I use cordova-plugin-googleplus, so you should change also the PLAY_SERVICES_VERSION for this plugin and all that inject a play-services dependency in the build.gradle file after the build.

Cristian Zumelzu
  • 842
  • 10
  • 15
0

In my case it was due to play-services-ads. if you are using, please check. Open build.gradle and update dependencies.

I changed this line

implementation 'com.google.android.gms:play-services-ads:19.5.0'

to

implementation 'com.google.android.gms:play-services-ads:22.2.0'

and Bingo, Solved and everything works fine now.

Confiance
  • 706
  • 5
  • 7