java.lang.IllegalArgumentException: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent significa que una aplicación Android dirigida al nivel de API 31 o posterior creó un PendingIntent sin declarar su mutabilidad. Esto ocurre en tiempo de ejecución cuando se crea el PendingIntent. La primera medida más segura es examinar la traza de pila e identificar la llamada exacta al método de fábrica antes de cambiar ninguna marca; si la llamada pertenece al código de la aplicación y no se necesita completar ningún campo, conserva las marcas existentes y añade FLAG_IMMUTABLE.
Qué significa el error “Targeting S+” de PendingIntent
El requisito de mutabilidad de PendingIntent de Android se aplica cuando una aplicación dirigida a Android 12/nivel de API 31 o posterior llama a PendingIntent.getActivity(), getActivities(), getBroadcast(), getService() o getForegroundService() sin incluir una de las dos marcas explícitas de mutabilidad.
FLAG_IMMUTABLE y FLAG_MUTABLE son alternativas; no deben combinarse. Android recomienda usar objetos PendingIntent inmutables en la mayoría de los casos. La mutabilidad solo es apropiada cuando un receptor o una API de Android debe modificar campos sin completar del Intent encapsulado. La referencia de la API PendingIntent también distingue estas declaraciones de mutabilidad de marcas de comportamiento como FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT y FLAG_ONE_SHOT.
Esta excepción en tiempo de ejecución no es el requisito independiente de android:exported de Android 12, que afecta a las declaraciones de componentes en el manifiesto.
Localiza la llamada a PendingIntent que realmente genera la excepción
El mensaje de la excepción identifica la declaración que falta, pero no indica si la llamada pertenece al código de la aplicación, a código generado o a una biblioteca incluida.
- Comienza por
java.lang.IllegalArgumentExceptionen la traza de pila completa. - Localiza el primer marco relevante que no pertenezca al framework y que esté asociado con uno de los métodos de fábrica de PendingIntent.
- Relaciona ese marco con su paquete, módulo, componente generado o dependencia incluida.
- Registra el método de fábrica, el código de solicitud, el Intent encapsulado y la expresión completa de las marcas.
- Antes de elegir una corrección, clasifica la llamada según pertenezca a la aplicación, a código generado o a una dependencia.
No modifiques un PendingIntent no relacionado solo porque aparezca en el código de la aplicación. Si el marco relevante pertenece a una dependencia, cambiar una marca en otro punto del código de la aplicación puede dejar intacta la implementación que falla.
Corrige el código de la aplicación con FLAG_IMMUTABLE de forma predeterminada
Cuándo corresponde: Usa este procedimiento cuando la llamada al método de fábrica pertenezca al código de la aplicación y ningún emisor, receptor ni API de Android necesite modificar campos sin completar del Intent encapsulado.
Requisitos previos: Identifica la llamada exacta y conserva su código de solicitud, Intent, método de fábrica y marcas de comportamiento existentes. Al añadir FLAG_IMMUTABLE, no debes eliminar FLAG_UPDATE_CURRENT, FLAG_CANCEL_CURRENT, FLAG_ONE_SHOT ni ninguna otra marca necesaria que ya exista.
- Mantén sin cambios el código de solicitud y el Intent actuales.
- Combina
FLAG_IMMUTABLEcon las marcas existentes medianteoren Kotlin o|en Java. - Crea el PendingIntent con la expresión combinada.
- Reproduce la función que lo envía.
Ejemplo en Kotlin
Antes:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)
Después:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags or PendingIntent.FLAG_IMMUTABLE)
Ejemplo en Java
Antes:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags)
Después:
PendingIntent.getActivity(context, existingRequestCode, existingIntent, existingFlags | PendingIntent.FLAG_IMMUTABLE)
Resultado esperado: La llamada al método de fábrica ahora incluye la declaración de mutabilidad requerida. Aun así, debes probar la acción de notificación, el inicio de actividad, la alarma, el widget, la devolución de llamada o el inicio de servicio afectados para confirmar que su comportamiento se mantiene. El creador puede seguir actualizando un PendingIntent inmutable mediante FLAG_UPDATE_CURRENT.
Riesgo y reversión: Este cambio de código presenta un riesgo bajo y no tiene un riesgo documentado de pérdida de datos. Si las pruebas demuestran que el receptor o la API de la plataforma necesita completar campos, revierte únicamente la declaración de inmutabilidad añadida y evalúa el caso limitado de mutabilidad descrito a continuación.
Usa FLAG_MUTABLE solo cuando la función necesite completar campos
Cuándo corresponde: Usa FLAG_MUTABLE únicamente cuando una función documentada deba modificar el Intent encapsulado, como en respuestas directas, burbujas, devoluciones de llamada de ubicación, extras de recuento de alarmas repetitivas u otra operación necesaria para completar campos.
| Requisito | Declaración |
|---|---|
| El receptor o la plataforma no necesitan realizar ninguna modificación | FLAG_IMMUTABLE |
| Una función documentada debe proporcionar datos para completar campos | FLAG_MUTABLE |
Requisitos previos: Verifica el requisito de modificación de la función afectada. Conserva todas las marcas de comportamiento necesarias y, cuando sea posible, usa un Intent base explícito con su acción, paquete y componente definidos.
- Conserva el código de solicitud, el tipo de método de fábrica y las marcas de comportamiento necesarias.
- Añade
FLAG_MUTABLEen lugar deFLAG_IMMUTABLE. - Haz explícito el Intent base cuando sea posible.
- Vuelve a probar la operación exacta que necesita completar campos.
- Confirma que solo los campos documentados deban permanecer disponibles para completarse.
Ejemplo en Kotlin
PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags or PendingIntent.FLAG_MUTABLE)
Ejemplo en Java
PendingIntent.getActivity(context, existingRequestCode, explicitIntent, existingFlags | PendingIntent.FLAG_MUTABLE)
Resultado esperado: La llamada al método de fábrica declara la mutabilidad sin eliminar las marcas de comportamiento existentes, y la operación documentada del receptor o de la plataforma que completa campos continúa disponible.
Riesgo y reversión: Esta decisión de seguridad presenta un riesgo medio, aunque no tiene un riesgo documentado de pérdida de datos. Un PendingIntent mutable delega el control de los campos sin completar del Intent, por lo que aplicarlo de forma general puede aumentar la exposición. Sigue las recomendaciones de seguridad de Android para PendingIntent, da preferencia a un Intent base explícito y sustituye FLAG_MUTABLE por FLAG_IMMUTABLE si deja de existir la dependencia que necesita completar campos. El mismo principio de privilegio mínimo resulta pertinente al revisar el intercambio seguro de URI entre aplicaciones en Android.
Gestiona un PendingIntent creado por una dependencia
Si el primer marco relevante de la traza de pila pertenece a código generado o a un SDK incluido, cambiar un PendingIntent no relacionado que pertenezca a la aplicación no constituye una corrección confirmada. La corrección de dependencias depende de cada proyecto y debe verificarse en la documentación principal del artefacto responsable.
- Relaciona el paquete o módulo responsable que aparece en la traza de pila con el artefacto incluido exacto.
- Consulta la documentación principal de versiones de ese artefacto para buscar una versión mantenida que indique explícitamente que resuelve la compatibilidad de PendingIntent con Android 12.
- Si existe una versión documentada de ese tipo, actualiza únicamente mediante el proceso de gestión de dependencias establecido en el proyecto.
- Examina el grafo de dependencias resuelto para confirmar que se haya seleccionado el artefacto previsto y no una versión transitiva anterior.
- Vuelve a compilar la aplicación y reproduce la misma función.
- Confirma que la implementación corregida esté incluida en el paquete y que ya no aparezca la llamada original sin declaración de mutabilidad.
Resultado esperado: Si la versión verificada de la dependencia contiene la corrección y la aplicación recompilada resuelve esa versión, la llamada al método de fábrica perteneciente a la dependencia debería incluir una declaración explícita de mutabilidad. Este resultado no puede darse por hecho únicamente a partir de la versión solicitada.
Riesgo y reversión: Los cambios de dependencias pueden modificar comportamientos ajenos a la función que falla. Revisa la información de la versión de la dependencia y restaura el estado anterior de las dependencias del proyecto si la actualización introduce una regresión. No existe un nombre de dependencia ni una versión corregida universales para esta excepción.
Usa PendingIntentCompat cuando corresponda aplicar compatibilidad
Cuándo corresponde: Usa PendingIntentCompat de AndroidX cuando el código de la aplicación admita versiones de la plataforma para las que se prefiera el asistente de compatibilidad y el código que realiza la llamada aún pueda indicar si el PendingIntent debe ser mutable.
Requisitos previos: Confirma que la versión de AndroidX Core del proyecto incluya PendingIntentCompat, identifica el tipo del método de fábrica original y determina la mutabilidad según las necesidades reales de la función.
- Elige el asistente correspondiente a la operación original:
getActivity,getBroadcast,getServiceogetForegroundService. - Pasa al asistente las marcas de comportamiento existentes que no estén relacionadas con la mutabilidad.
- Establece
isMutableen false, salvo que exista un requisito de modificación verificado. - Mantén sin cambios el código de solicitud y el comportamiento del Intent encapsulado.
- Realiza pruebas con la configuración afectada dirigida a Android 12 o posterior.
Resultado esperado: El asistente de compatibilidad combina la decisión explícita de mutabilidad indicada por el código que realiza la llamada con las marcas existentes, según sea necesario en las versiones compatibles de la plataforma.
Riesgo y reversión: Esta vía de compatibilidad presenta un riesgo bajo y no tiene un riesgo documentado de pérdida de datos, aunque cambiar las API auxiliares puede afectar a la estructura de la llamada. Si el cambio de asistente provoca una regresión, vuelve al método de fábrica equivalente del framework y conserva una marca explícita de mutabilidad.
Verifica la corrección sin cambiar el comportamiento de PendingIntent
- Ejecuta la aplicación recompilada con un SDK de destino de nivel de API 31 o posterior y reproduce el desencadenante original.
- Confirma que la excepción exacta
Targeting S+ya no se produzca en la llamada al método de fábrica identificada. - Vuelve a probar el toque o la acción de notificación, la alarma, el widget, la devolución de llamada, el inicio de actividad o el inicio de servicio afectados.
- Si estaban presentes
FLAG_UPDATE_CURRENT,FLAG_CANCEL_CURRENToFLAG_ONE_SHOT, verifica que se mantenga su comportamiento original de actualización, cancelación o uso único. - En un PendingIntent mutable, verifica únicamente el comportamiento necesario para completar campos y confirma que el Intent base sea explícito cuando sea posible.
- En una corrección de dependencia, confirma que el artefacto resuelto e incluido en el paquete sea la versión verificada, en lugar de basarte únicamente en la declaración de dependencia solicitada.
Una compilación correcta no demuestra por sí sola que se haya corregido la ruta de ejecución. Mantén también separadas las restricciones de Android 14/API 34 para objetos PendingIntent implícitos mutables: producen una condición de error distinta y no se resuelven mediante este procedimiento para el nivel de API 31.

