MediaSessionCompat FLAG_IMMUTABLE/FLAG_MUTABLE: solución completa en Kotlin

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: El reproductor "roto" en Android 12 y superior

\n

Imagine: usted publica con orgullo una actualización de su aplicación reproductora o cliente de podcasts. Pasan unos días y en la sección de reseñas aparecen comentarios furiosos: "¡Después de la actualización la música dejó de reproducirse!", "¡Los botones en la pantalla bloqueada no funcionan!", "¡La aplicación se cierra al intentar reproducir una pista!". ¿Le suena familiar? Lo más probable es que se haya topado con ese error que atormenta a miles de desarrolladores en todo el mundo:

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

Este problema es una de las preguntas más populares en Stack Overflow (decenas de miles de visitas) y está directamente relacionado con los cambios en Android 12 (API level 31). La buena noticia: la corrección es simple y le tomará no más de 10 minutos. En este artículo analizaremos las causas del error, la solución correcta en Kotlin y las mejores prácticas para que su aplicación vuelva a funcionar como un reloj.

\n\n

¿Por qué ocurre el error? Entendiendo PendingIntent

\n

Para entender la esencia del problema, debemos recordar cómo funciona MediaSessionCompat. Este es un componente que permite a su aplicación interactuar con los controles multimedia del sistema: botones del auricular, pantalla de bloqueo, panel de notificaciones. Para ello, crea un PendingIntent, una especie de "llamada diferida" para los servicios del sistema. El sistema usa este Intent para decirle a su aplicación: "El usuario presionó Play/Pause/Next".

\n

A partir de Android 12 (API 31), Google endureció los requisitos de seguridad de PendingIntent. Antes, los desarrolladores podían no especificar la bandera FLAG_IMMUTABLE o FLAG_MUTABLE, y el sistema usaba por defecto la variante mutable. Ahora, usted está obligado a indicar explícitamente si el sistema puede modificar el contenido de su Intent después de su creación. Si no lo hace, la aplicación fallará. Android 12+ simplemente no permitirá crear dicho PendingIntent.

\n\n

FLAG_IMMUTABLE vs FLAG_MUTABLE: ¿cuál elegir?

\n
    \n
  • FLAG_IMMUTABLE (recomendado): El Intent no se puede modificar después de su creación. Es más seguro, ya que un atacante no podrá sustituir los datos. Use esta bandera en el 90% de los casos, incluyendo MediaSessionCompat.
  • \n
  • FLAG_MUTABLE: El Intent se puede modificar. Solo es necesario en casos especiales, por ejemplo, si usa NotificationCompat con acciones que requieren datos dinámicos, o al trabajar con AlarmManager.
  • \n
\n

Para MediaSessionCompat y las notificaciones multimedia, use siempre FLAG_IMMUTABLE. Esto mejora la seguridad y estabilidad de su aplicación.

\n\n

Corrección paso a paso en Kotlin

\n

Veamos cómo se ve el código típico que causa el error y cómo corregirlo. La mayoría de las veces, el problema surge en el método onCreate() de su servicio o navegador multimedia.

\n\n

Código incorrecto (causará un fallo en Android 12+)

\n
// Forma antigua — sin especificar la bandera\nval pendingIntent = PendingIntent.getActivity(\n    this,\n    0,\n    Intent(this, MainActivity::class.java),\n    0 // <-- ¡Error! No tiene FLAG_IMMUTABLE ni FLAG_MUTABLE\n)
\n\n

Código correcto en Kotlin (corrección)

\n

Simplemente agregue PendingIntent.FLAG_IMMUTABLE en el último parámetro:

\n
val pendingIntent = PendingIntent.getActivity(\n    this,\n    0,\n    Intent(this, MainActivity::class.java),\n    PendingIntent.FLAG_IMMUTABLE // <-- ¡Solución!\n)
\n

Si su aplicación es compatible con versiones anteriores de Android (inferiores a API 31), use una verificación condicional para evitar fallos en dispositivos antiguos:

\n
val flags = if (Build.VERS                

Blogs

Book Recommendations