¡Te damos la bienvenida a la Vista previa para desarrolladores de Android 12! Envíanos comentarios con frecuencia y tan pronto como puedas, y ayúdanos a hacer de Android 12 la mejor versión hasta el momento.

Cambios en el comportamiento: apps orientadas a Android 12

Al igual que las versiones anteriores, Android 12 incluye cambios de comportamiento que podrían afectar tu app. Los siguientes cambios se aplican exclusivamente a las apps orientadas a Android 12 o versiones posteriores. Si tu app está orientada a Android 12, debes modificarla para que admita estos comportamientos correctamente, cuando corresponda.

En la siguiente tabla, se resumen los cambios clave que afectan tu app si esta se orienta a Android 12. Ten en cuenta que en esta tabla no se proporciona el conjunto completo de cambios.

Cambio clave Apps afectadas
Restricciones de lanzamiento del servicio en primer plano
Con algunas excepciones, se restringe a las apps para que no inicien actividades cuando se ejecutan en segundo plano. Si intentan hacerlo, se podría generar una excepción.
Apps que inician servicios en primer plano mientras se ejecutan en segundo plano
Los componentes de la app que contienen filtros de intents deben declarar el atributo exportado
Los componentes de la app que incluyen filtros de intents deben establecer explícitamente el atributo android:exported. Las apps que no establecen el atributo no se pueden instalar en Android 12.
Apps que declaran el atributo <intent-filter> en sus archivos de manifiesto
Lanzamientos no seguros de intents anidados
La prueba de modo estricto ahora detecta cuándo tu app usa intents anidados de forma no segura.
Apps que inician otra app y esperan una devolución de llamada mediante un intent interno

Asegúrate de revisar también la lista de cambios en el comportamiento que afectan a todas las apps que se ejecutan en Android 12.

Privacidad

Nuevos comportamientos de las cookies de SameSite en WebView

El componente WebView de Android se basa en Chromium, el proyecto de código abierto que potencia el navegador Chrome de Google. Durante el último año, Chromium introdujo cambios en el manejo de cookies de terceros con el objetivo de proporcionar mayor seguridad y privacidad, y ofrecer a los usuarios más transparencia y control. Estos cambios ya están disponibles para muchos usuarios de Chrome y, a partir de Android 12, los cambios ahora se aplicarán a WebView.

El atributo SameSite de una cookie controla si se puede enviar con cualquier solicitud o solo con solicitudes del mismo sitio. La versión base de WebView en Android 12 (versión 89.0.4385.0) incluye los siguientes cambios de protección de la privacidad que mejoran el manejo predeterminado de cookies de terceros y protegen contra el uso compartido entre sitios no deseados:

  • Las cookies que no tienen un atributo SameSite se consideran SameSite=Lax.
  • Las cookies con SameSite=None también deben especificar el atributo Secure, lo que significa que requieren un contexto seguro y deben enviarse mediante HTTPS.
  • Los vínculos entre las versiones HTTP y HTTPS de un sitio ahora se tratan como solicitudes entre sitios, por lo que las cookies no se envían, a menos que se marquen de forma adecuada como SameSite=None; Secure.

Para los desarrolladores, la práctica general es identificar las dependencias de cookies entre sitios en tus flujos de usuarios críticos y garantizar que el atributo SameSite esté establecido de forma explícita con los valores apropiados cuando sea necesario. Debes especificar de forma explícita las cookies que pueden funcionar en sitios web o en distintas navegaciones del mismo sitio que pasan de HTTP a HTTPS.

Si deseas obtener más información para desarrolladores web acerca de estos cambios, consulta los artículos Explicación de las cookies de SameSite y Schemeful SameSite.

Prueba los comportamientos de SameSite en tu app

Si tu app usa WebView, o si administras un sitio web o servicio que usa cookies, te recomendamos que pruebes tus flujos en WebView de Android 12. Si encuentras problemas, es posible que debas actualizar tus cookies para admitir los nuevos comportamientos de SameSite.

Observa los problemas en los accesos y el contenido integrado, en los flujos de registro, en las compras y en otros flujos de autenticación en los que el usuario comienza en una página insegura y pasa a una página segura.

Si quieres probar una app con WebView, debes completar uno de los siguientes pasos con el fin de habilitar los nuevos comportamientos de SameSite para la app que deseas probar:

  • Habilita manualmente los comportamientos de SameSite en el dispositivo de prueba. Para ello, activa la marca de IU webview-enable-modern-cookie-same-site en las herramientas para desarrolladores de WebView.

    Este enfoque te permite realizar pruebas en cualquier dispositivo que ejecute Android 5.0 (nivel de API 21) o una versión posterior, incluido Android 12, y WebView versión 89.0.4385.0 o posterior.

  • Compila tu app para que se oriente a Android 12 mediante targetSdkVersion.

    Si usas este enfoque, debes usar un dispositivo que ejecute Android 12 y WebView 89.0.4385.0 o versiones posteriores.

Para obtener información sobre la depuración remota de WebView en Android, consulta Cómo comenzar a usar los dispositivos Android de depuración remota.

Otros recursos

Para obtener más información sobre los nuevos comportamientos de SameSite y su implementación en Chrome y WebView, visita la página de actualizaciones de Chromium SameSite. Si encuentras un error en WebView o Chromium, puedes informarlo en la herramienta pública de seguimiento de errores de Chromium.

Restricciones de la copia de seguridad de ADB

Para ayudar a proteger los datos de apps privadas, Android 12 cambia el comportamiento predeterminado del comando adb backup. En el caso de las apps orientadas a Android 12, cuando un usuario ejecuta el comando adb backup, los datos de la app se excluyen de otros datos del sistema que se exportan del dispositivo.

Si tus flujos de trabajo de prueba o desarrollo usan los datos de la app con adb backup, ahora puedes habilitar la exportación de los datos si configuras android:debuggable como true en el archivo de manifiesto de tu app.

Seguridad

Exportación de componentes más segura

Ícono para enviar comentarios Nos encantaría saber qué opinas de este nuevo requisito para exportar componentes. Realiza una breve encuesta para contarnos lo que piensas. En particular, queremos conocer los casos de uso de tu app que se verán afectados por este cambio.

Si tu app está orientada a Android 12 y contiene actividades, servicios o receptores de emisión que usan filtros de intents, debes declarar explícitamente el atributo android:exported para estos componentes de la app.

Advertencia: Si una actividad, un servicio o un receptor de emisión utiliza filtros de intents y no tiene un valor declarado de forma explícita para android:exported, no se podrá instalar tu app en un dispositivo que ejecute Android 12.

Si intentas instalar una app de ese tipo cuando usas Android Studio, Logcat muestra el siguiente mensaje de error:

Installation did not succeed.
The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
List of apks:
[0] '.../build/outputs/apk/debug/app-debug.apk'
Installation failed due to: 'null'

Si tu app no declara un valor para android:exported cuando lo necesita, Logcat proporciona el siguiente mensaje de error:

Targeting S+ (version 10000 and above) requires that an explicit value for \
android:exported be defined when intent filters are present

El siguiente fragmento de código muestra un ejemplo de un servicio que contiene un filtro de intents y está configurado correctamente para Android 12:

<service android:name="com.example.app.backgroundService"
         android:exported="false">
    <intent-filter>
        <action android:name="com.example.app.START_BACKGROUND" />
    </intent-filter>
</service>

Los intents pendientes deben declarar la mutabilidad

Ícono para enviar comentarios Nos encantaría saber qué opinas de este nuevo requisito relacionado con los intents pendientes. Realiza una breve encuesta para contarnos lo que piensas. En particular, queremos conocer los casos de uso de tu app que se verán afectados por este cambio.

Si tu app está orientada a Android 12, debes especificar la mutabilidad de cada objeto PendingIntent que cree la app. Este requisito adicional mejora la seguridad de tu app.

Para declarar que un objeto PendingIntent determinado es mutable o inmutable, usa la marca PendingIntent.FLAG_MUTABLE o PendingIntent.FLAG_IMMUTABLE, respectivamente. Si tu app intenta crear un objeto PendingIntent sin establecer una de esas marcas, el sistema genera un elemento IllegalArgumentException y aparece el siguiente mensaje en Logcat:

PACKAGE_NAME: Targeting S+ (version 10000 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.

Crea intents pendientes inmutables cuando sea posible

En la mayoría de los casos, tu app debe crear objetos PendingIntent inmutables, como se muestra en el siguiente fragmento de código. Si un objeto PendingIntent es inmutable, una app no puede modificar el intent para ajustar el resultado de invocación del intent.

Kotlin

val pendingIntent = PendingIntent.getActivity(applicationContext,
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE)

Java

PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE);

Sin embargo, algunas apps necesitan crear objetos PendingIntent mutables:

Si tu app crea un objeto PendingIntent mutable, te recomendamos que uses un intent explícito y completes el elemento ComponentName. De esa manera, cada vez que otra app invoque el PendingIntent y pase el control a tu app, siempre se iniciará el mismo componente.

Prueba el cambio de mutación del intent pendiente

Para determinar si falta alguna declaración de mutación en tu app, busca la siguiente advertencia de lint en Android Studio:

Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag]

Durante la Vista previa para desarrolladores, puedes inhabilitar este comportamiento del sistema a fin de realizar pruebas. Para ello, desactiva la marca de compatibilidad de la app PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED.

Lanzamientos no seguros de intents anidados

Con el objetivo de mejorar la seguridad de la plataforma, Android 12 proporciona una función de depuración que te advierte si tu app realiza un lanzamiento no seguro de un intent anidado. Un intent anidado es un intent que se pasa como un valor adicional en otro intent. Si tu app realiza las dos acciones siguientes, se producirá un incumplimiento de StrictMode.

  1. La app descomprime un intent anidado desde los valores adicionales de un intent entregado.
  2. La app inicia inmediatamente un componente de la app con ese intent anidado, como cuando se pasa el intent a startActivity(), startService() o bindService().

Configura tu app para que detecte lanzamientos no seguros de intents anidados

Para verificar los inicios no seguros de intents anidados en la app, llama a detectUnsafeIntentLaunch() cuando configures tu VmPolicy, como se muestra en el siguiente fragmento de código. Si la app detecta un incumplimiento de StrictMode, te recomendamos detener la ejecución de la app a fin de proteger la información potencialmente sensible.

Kotlin

fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        // Other StrictMode checks that you've previously added.
        // ...
        .detectUnsafeIntentLaunch()
        .penaltyLog()
        // Consider also adding penaltyDeath()
        .build())
}

Java

protected void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
        // Other StrictMode checks that you've previously added.
        // ...
        .detectUnsafeIntentLaunch()
        .penaltyLog()
        // Consider also adding penaltyDeath()
        .build());
}

Usa los intents de manera más responsable

Tu app podría iniciar intents anidados para navegar entre componentes dentro de ella o para realizar una acción en nombre de otra app. A fin de minimizar las posibilidades de encontrar un incumplimiento de StrictMode en cualquier situación, haz lo siguiente:

  • Lanzamiento interno del intent anidado: Asegúrate de que estos componentes no se exporten.
  • Lanzamiento entre apps del intent anidado: Usa un elemento PendingIntent en lugar de un intent anidado. De esta manera, cuando PendingIntent no está separado del elemento Intent que lo contiene, el componente de una app puede iniciar el PendingIntent con la identidad del proceso de llamada. Esta configuración permite que una app de proveedor envíe una devolución de llamada a cualquier componente, incluido un componente no exportado, de la app emisora.

    Si deseas obtener más información para identificar esta situación y realizar cambios en tu app, lee la entrada de blog sobre intents anidados de Android en Medium.

Rendimiento

Restricciones para el inicio del servicio en primer plano

Las apps orientadas a Android 12 ya no pueden iniciar servicios en primer plano mientras se ejecutan en segundo plano, excepto en algunos casos especiales. Si una app intenta iniciar un servicio en primer plano mientras se ejecuta en segundo plano, se produce una excepción (salvo en algunos casos especiales). Considera usar WorkManager para programar y comenzar a trabajar mientras tu app se ejecuta en segundo plano.

Si quieres obtener más información sobre cómo esto afecta a tu app y cómo puedes actualizarla según estos cambios, lee la guía sobre las restricciones del inicio del servicio en primer plano. También puedes revisar el archivo WorkManagerSample en GitHub.

No es posible crear trampolines de notificaciones desde servicios o receptores de emisión

Ícono para enviar comentarios Nos encantaría saber qué opinas de estos cambios en el comportamiento del trampolín de notificaciones. Realiza una breve encuesta para contarnos lo que piensas. En particular, queremos conocer los casos de uso de tu app que se verán afectados por este cambio.

Cuando los usuarios interactúan con las notificaciones, algunas apps responden a los toques en ellas mediante el inicio de un componente de la app que, eventualmente, inicia la actividad que el usuario ve y con la que interactúa. A este componente de app se lo conoce como trampolín de notificaciones.

Para mejorar el rendimiento y la UX de las apps, las apps orientadas a Android 12 no pueden iniciar actividades de servicios o receptores de emisión que se usan como trampolines de notificaciones. En otras palabras, después de que el usuario presiona una notificación o un botón de acción dentro de la notificación, tu app no puede llamar a startActivity() dentro de un servicio o receptor de emisión.

Cuando tu app intenta iniciar una actividad desde un servicio o receptor de emisión que funciona como trampolín de notificaciones, el sistema impide que se inicie la actividad y aparece el siguiente mensaje en Logcat:

Indirect notification activity start (trampoline) from PACKAGE_NAME, \
this should be avoided for performance reasons.

Actualiza tu app

Si tu app inicia una actividad desde un servicio o receptor de emisión que funciona como trampolín de notificaciones, completa los siguientes pasos de migración:

  1. Crea un objeto PendingIntent que esté asociado con una de las siguientes actividades:

    • La actividad que los usuarios ven después de presionar la notificación (opción preferida)
    • Una actividad de trampolín o una actividad que inicia la actividad que ven los usuarios después de presionar la notificación
  2. Usa el objeto PendingIntent que creaste en el paso anterior como parte de la compilación de tu notificación

Activa o desactiva el comportamiento

Cuando pruebas tu app durante la Vista previa para desarrolladores, puedes habilitar o inhabilitar esta restricción con la marca de compatibilidad de apps de NOTIFICATION_TRAMPOLINE_BLOCK.

Restricciones en interfaces no SDK

Android 12 incluye listas actualizadas de este tipo de interfaces que están basadas en la colaboración con desarrolladores de Android y las pruebas internas más recientes. Siempre que sea posible, nos aseguramos de que las alternativas públicas estén disponibles antes de restringir las interfaces que no pertenecen al SDK.

Si tu app no está orientada a Android 12, es posible que algunos de estos cambios no te afecten de inmediato. Sin embargo, aunque actualmente puedes usar algunas interfaces que no pertenecen al SDK (según el nivel de API al que esté orientada la app), utilizar cualquier método o campo que no pertenezca al SDK siempre implica un gran riesgo de error para tu app.

En caso de no saber con certeza si tu app usa este tipo de interfaces, puedes probarla para verificarlo. Si tu app depende de interfaces que no pertenezcan al SDK, deberías planificar una migración hacia otras alternativas que sí lo hagan. Sin embargo, sabemos que algunas apps tienen casos prácticos válidos para usarlas. Si no encuentras una alternativa al uso de una interfaz que no pertenece al SDK para una función de tu app, deberías solicitar una nueva API pública.

Para obtener más información sobre los cambios implementados en esta versión de Android, consulta Actualizaciones a las restricciones de interfaces que no pertenecen al SDK en Android 12. Para obtener más información sobre interfaces que no pertenecen al SDK en general, consulta Restricciones en interfaces que no pertenecen al SDK.

Cambios en las notificaciones personalizadas

Android 12 cambia la apariencia de las notificaciones totalmente personalizadas. Antes, las notificaciones personalizadas podían usar toda el área de notificaciones y proporcionar sus propios diseños y estilos. De esta manera, se producían antipatrones que podían confundir a los usuarios y causar errores de compatibilidad en diferentes dispositivos.

En el caso de las apps orientadas a Android 12, las notificaciones con vistas de contenido personalizado ya no utilizan el área de notificaciones completa. En su lugar, el sistema aplica una plantilla estándar. Esta plantilla garantiza que las notificaciones personalizadas tengan la misma decoración que otras notificaciones en todos los estados, como el ícono y las opciones de expansión de la notificación (en el estado contraído), el ícono o el nombre de la app y la opción de contracción (en el estado de expansión). Este comportamiento es casi idéntico al comportamiento de Notification.DecoratedCustomViewStyle.

De esta manera, Android 12 permite que todas las notificaciones sean visualmente coherentes y fáciles de analizar, con una expansión de notificaciones familiar y fácil de encontrar para los usuarios.

En la siguiente ilustración, se muestra una notificación personalizada en la plantilla estándar:

Los siguientes ejemplos muestran cómo se procesarían las notificaciones personalizadas en un estado contraído y expandido:

El cambio en Android 12 afecta a las apps que definen subclases de Notification.Style personalizadas o que usan los métodos setCustomContentView(RemoteViews), setCustomBigContentView(RemoteViews) y setCustomHeadsUpContentView(RemoteViews) de Notification.Builder.

Si tu app usa notificaciones totalmente personalizadas, te recomendamos probar con la plantilla nueva lo antes posible y realizar los ajustes necesarios:

  1. Habilita el cambio de notificaciones personalizadas:

    1. Cambia el elemento targetSdkVersion de tu app a S para habilitar el nuevo comportamiento.
    2. Vuelve a compilar.
    3. Instala la app en un dispositivo o emulador que ejecute Android 12.
  2. Prueba todas las notificaciones que usan vistas personalizadas a fin de asegurarte de que se vean como esperabas en el panel.

  3. Ten en cuenta las mediciones de vistas personalizadas. En general, la altura otorgada a las notificaciones personalizadas es menor que antes. En el estado contraído, la altura máxima del contenido personalizado disminuyó de 106 dp a 48 dp. Además, hay menos espacio horizontal.

  4. Para asegurarte de que el estado de "Atención" se vea como esperas, no olvides aumentar la importancia del canal de notificaciones a "HIGH" (ventana emergente).

Conectividad

Cuando los dispositivos orientados a Android 12 y versiones posteriores se ejecuten en dispositivos con compatibilidad de hardware, el uso de conexiones entre pares no desconectará la conexión Wi-Fi existente durante la creación de la conexión al dispositivo par. Para verificar la compatibilidad de esta función, usa WifiManager.isMultiStaConcurrencySupported().