Estoy tratando de actualizar mi aplicación a Android SDK 31 pero tengo un problema con MediaSessionCompat.
Tengo un MediaService que extiende MediaBrowserServiceCompat() y en el método onCreate de ese servicio, inicializo MediaSessionCompat.
override fun onCreate() { super.onCreate() mediaSession = MediaSessionCompat(this, TAG).apply { setCallback(mediaSessionCallback) isActive = true } ...pero tengo el siguiente 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, eg 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, eg 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 moreEstoy usando la versión más reciente de la biblioteca de medios ("androidx.media:media:1.4.0") que puede manejar este requisito de Andriod "S". Como es posible ver en MediaSessionCompact.java clase.
// 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); }Código fuente que demuestra el problema: https://github.com/adelinolobao/issue-media-session-compat
¿Tienen alguna idea de cómo puedo solucionar el error?
Si su aplicación tiene como objetivo Android 12, debe especificar la mutabilidad de cada objeto PendingIntent que crea su aplicación.
En su caso, android.support.v4.media.session.MediaSessionCompat fue responsable de crear PendingItent durante la inicialización de MediaSessionCompat .
Solución: afortunadamente, hay un @constructor adicional para la clase MediaSessionCompat , por lo que podemos pendingItent como parámetro. Si pasamos nulo para el parámetro del component , se inicializará en la biblioteca.
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) }Código fuente: https://github.com/dautovicharis/issue-media-session-compat
Actualización : gracias a:
En la versión 1.3.0 hubo nuevos cambios en MediaSessionCompat donde podemos ver claramente que falta algo relacionado con Android 12 según el comentario TODO(b/182513352).
Hasta que se publique el nuevo androidx.media:media: el uso de la solución alternativa que proporcioné debería funcionar bien.
Actualización : Esperamos que TODO(b/182513352) se solucione en las próximas versiones. Hasta entonces, podemos usar la implementation "androidx.media:media:1.3.0-rc02 " donde se admite FLAG_IMMUTABLE .
Esto debería solucionarse ahora si actualiza a la versión al menos 1.4.1
https://developer.android.com/jetpack/androidx/releases/media#media-1.4.1
Versión 1.4.1 4 de agosto de 2021
Se lanza androidx.media:media:1.4.1. La versión 1.4.1 contiene estas confirmaciones.
Corrección de errores
- Corrija el indicador de mutabilidad para crear PendingIntent para evitar bloqueos al apuntar a Android S.
- Solucione ClassVerificationFailure para NotificationCompat.MediaStyle.
Si NO está UTILIZANDO PendingIntent ningún lado. El problema podría resolverse agregando o actualizando esta dependencia
// required to avoid crash on Android 12 API 31 implementation 'androidx.work:work-runtime-ktx:2.7.0'Esto solucionó mi problema.
Resolvió este error , solo usó PendingIntent.FLAG_MUTABLE para la versión de Android 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); } Agrega la siguiente línea a tu build.gradle(app) bajo dependencies .
dependencies { // ... implementation 'androidx.work:work-runtime:2.7.1' }