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?
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.
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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With