Cambios de comportamiento en Android 5.0

Nivel de API: 21

Además de las nuevas funciones y capacidades, Android 5.0 incluye una variedad de cambios en el sistema y en el comportamiento de la API. En este documento, se destacan algunos de los cambios clave que debes comprender y tener en cuenta en tus apps.

Si ya publicaste una app para Android, ten en cuenta que esta podría verse afectada por estos cambios en Android 5.0.

Si deseas obtener una descripción general de las nuevas funciones de la plataforma, consulta los destacados de Android Lollipop.

Videos

Dev Byte: Novedades de Android 5.0

Dev Byte: Notificaciones

Tiempo de ejecución de Android (ART)

En Android 5.0, el tiempo de ejecución ART reemplaza a Dalvik como la configuración predeterminada de la plataforma. El entorno de ejecución de ART se introdujo en Android 4.4 de forma experimental.

Para obtener una descripción general de las nuevas funciones de ART, consulta Presentamos ART. Algunas de las principales funciones nuevas son las siguientes:

  • compilación por adelantado (AOT);
  • mejor recolección de elementos no usados (GC);
  • mayor compatibilidad de depuración.

La mayoría de las apps de Android deben funcionar en ART sin necesidad de realizar cambios. Sin embargo, algunas técnicas que funcionan en Dalvik no funcionan en ART. Para obtener información sobre los problemas más importantes, consulta Cómo verificar el comportamiento de la app en el entorno de ejecución de Android (ART). Presta especial atención en los siguientes casos:

  • Si en tu app se usa la interfaz nativa Java (JNI) para ejecutar el código C/C++.
  • Usas herramientas de desarrollo que generan código no estándar (como algunos ofuscadores).
  • Usas técnicas incompatibles con la compactación de la recolección de basura.

Notificaciones

Asegúrate de que en tus notificaciones se tengan en cuenta estos cambios de Android 5.0. Para obtener más información sobre el diseño de notificaciones para Android 5.0 y versiones posteriores, consulta la guía de diseño de notificaciones.

Estilo de material design

Las notificaciones se dibujan con texto oscuro sobre fondos blancos (o muy claros) para que coincidan con los nuevos widgets de Material Design. Asegúrate de que todas tus notificaciones se vean bien con el nuevo esquema de colores. Si tus notificaciones se ven incorrectas, sigue estos pasos para corregirlas:

  • Usa setColor() para establecer un color de contraste en un círculo detrás de la imagen del ícono.
  • Actualiza o quita los recursos que incluyen color. El sistema ignora todos los canales que no son alfa en los íconos de acción y en el ícono de notificación principal. Debes suponer que estos íconos serán solo alfa. El sistema dibuja íconos de notificación en blanco y de acción en gris oscuro.

Sonido y vibración

Si actualmente agregas sonidos y vibraciones a tus notificaciones con las clases Ringtone, MediaPlayer o Vibrator, quita este código para que el sistema pueda presentar las notificaciones correctamente en el modo prioridad. En su lugar, usa métodos Notification.Builder para agregar sonidos y vibraciones.

Si configuras el dispositivo en RINGER_MODE_SILENT, este entrará en el nuevo modo de prioridad. El dispositivo sale del modo prioritario si lo configuras en RINGER_MODE_NORMAL o RINGER_MODE_VIBRATE.

Anteriormente, Android usaba STREAM_MUSIC como la transmisión principal para controlar el volumen en dispositivos de tablet. En Android 5.0, la transmisión de volumen principal para teléfonos y tablets ahora está unificada y se controla con STREAM_RING o STREAM_NOTIFICATION.

Visibilidad de la pantalla bloqueada

De forma predeterminada, las notificaciones ahora aparecen en la pantalla de bloqueo del usuario en Android 5.0. Los usuarios pueden proteger la información sensible para que no se exponga, en cuyo caso el sistema oculta automáticamente el texto que muestra la notificación. Para personalizar esta notificación oculta, usa setPublicVersion().

Si la notificación no contiene información personal o si quieres permitir el control de reproducción de contenido multimedia en la notificación, llama al método setVisibility() y establece el nivel de visibilidad de la notificación en VISIBILITY_PUBLIC.

Reproducción de contenido multimedia

Si implementas notificaciones que presentan el estado de reproducción de contenido multimedia o los controles de transporte, considera usar la nueva plantilla Notification.MediaStyle en lugar de un objeto RemoteViews.RemoteView personalizado. Independientemente del enfoque que elijas, asegúrate de establecer la visibilidad de la notificación en VISIBILITY_PUBLIC para que se pueda acceder a tus controles desde la pantalla de bloqueo. Ten en cuenta que, a partir de Android 5.0, el sistema ya no muestra objetos RemoteControlClient en la pantalla de bloqueo. Para obtener más información, consulta Si tu app usa RemoteControlClient.

Notificación emergente

Ahora las notificaciones pueden aparecer en una pequeña ventana flotante (también llamada notificación emergente) cuando el dispositivo está activo (es decir, está desbloqueado y la pantalla está encendida). Estas notificaciones se parecen al formato compacto de tu notificación, excepto que la notificación emergente también muestra botones de acción. Los usuarios pueden descartar o responder una notificación anticipada sin salir de la app actual.

Entre los ejemplos de condiciones que pueden activar notificaciones emergentes se incluyen los siguientes:

  • La actividad del usuario se encuentra en el modo de pantalla completa (la app usa fullScreenIntent).
  • La notificación tiene prioridad alta y usa tonos o vibración.

Si tu app implementa notificaciones en cualquiera de esas situaciones, asegúrate de que las notificaciones de atención se presenten correctamente.

Controles multimedia y RemoteControlClient

La clase RemoteControlClient dejó de estar disponible. Cambia a la nueva API de MediaSession lo antes posible.

Las pantallas de bloqueo en Android 5.0 no muestran controles de transporte para tu MediaSession o RemoteControlClient. En cambio, tu app puede proporcionar control de reproducción multimedia desde la pantalla de bloqueo a través de una notificación. Esto le brinda a tu app más control sobre la presentación de los botones multimedia y, al mismo tiempo, proporciona una experiencia coherente para los usuarios en dispositivos bloqueados y desbloqueados.

Android 5.0 presenta una nueva plantilla Notification.MediaStyle para este fin. Notification.MediaStyle convierte las acciones de notificación que agregaste con Notification.Builder.addAction() en botones compactos incorporados en las notificaciones de reproducción de contenido multimedia de tu app. Pasa el token de sesión al método setSession() para informarle al sistema que esta notificación controla una sesión multimedia en curso.

Asegúrate de establecer la visibilidad de la notificación en VISIBILITY_PUBLIC para marcarla como segura para mostrarla en cualquier pantalla de bloqueo (segura o no). Para obtener más información, consulta Notificaciones de la pantalla de bloqueo.

Para mostrar los controles de reproducción multimedia si tu app se ejecuta en la plataforma de TV o Wear de Android, implementa la clase MediaSession. También debes implementar MediaSession si tu app necesita recibir eventos de botones de contenido multimedia en dispositivos Android.

getRecentTasks()

Con la introducción de la nueva función de tareas de documentos y actividades simultáneas en Android 5.0 (consulta Documentos y actividades simultáneos en la pantalla Recientes a continuación), el método ActivityManager.getRecentTasks() dejó de estar disponible para mejorar la privacidad del usuario. Para la retrocompatibilidad, este método aún muestra un subconjunto pequeño de sus datos, incluidas las tareas de la aplicación que realiza la llamada y, posiblemente, algunas otras tareas no sensibles (como Home). Si tu app usa este método para recuperar sus propias tareas, usa getAppTasks() para recuperar esa información.

Compatibilidad con sistemas de 64 bits en el NDK de Android

Android 5.0 presenta compatibilidad con sistemas de 64 bits. La mejora de 64 bits aumenta el espacio de direcciones y mejora el rendimiento, a la vez que admite por completo las apps de 32 bits existentes. La compatibilidad con 64 bits también mejora el rendimiento de OpenSSL para la criptografía. Además, esta versión presenta nuevas APIs de NDK de medios nativos, así como compatibilidad nativa con OpenGL ES (GLES) 3.1.

Para usar la compatibilidad de 64 bits que se proporciona en Android 5.0, descarga e instala la revisión 10c del NDK desde la página del NDK de Android. Consulta las notas de la versión de la revisión 10c para obtener más información sobre los cambios importantes y las correcciones de errores del NDK.

Enlazar a un servicio (Service)

El método Context.bindService() ahora requiere un Intent explícito y genera una excepción si se le proporciona un intent implícito. Para garantizar que tu app sea segura, usa un intent explícito cuando inicies o vincules tu Service y no declares filtros de intents para el servicio.

WebView

Android 5.0 cambia el comportamiento predeterminado de tu app.

  • Si tu app se orienta al nivel de API 21 o versiones posteriores, haz lo siguiente:
    • El sistema bloquea el contenido mixto y las cookies de terceros de forma predeterminada. Para permitir contenido mezclado y cookies de terceros, usa los métodos setMixedContentMode() y setAcceptThirdPartyCookies(), respectivamente.
    • El sistema ahora elige de forma inteligente las partes del archivo HTML para dibujar. Este nuevo comportamiento predeterminado ayuda a reducir la huella de memoria y aumentar el rendimiento. Si quieres renderizar todo el documento de una sola vez, llama a enableSlowWholeDocumentDraw() para inhabilitar esta optimización.
  • Si tu app se orienta a niveles de API inferiores a 21: El sistema permite contenido mixto y cookies de terceros, y siempre renderiza todo el documento a la vez.

Requisito de singularidad para los permisos personalizados

Como se documenta en la descripción general de Permisos, las apps para Android pueden definir permisos personalizados como una forma de administrar el acceso a los componentes de forma propietaria, sin usar los permisos del sistema predefinidos de la plataforma. Las apps definen permisos personalizados en los elementos <permission> declarados en sus archivos de manifiesto.

Hay una pequeña cantidad de situaciones en las que definir permisos personalizados es un enfoque legítimo y seguro. Sin embargo, a veces, crear permisos personalizados es innecesario y puede incluso presentar un riesgo potencial para una app, según el nivel de protección asignado a los permisos.

Android 5.0 incluye un cambio de comportamiento para garantizar que solo una app pueda definir un permiso personalizado determinado, a menos que esté firmado con la misma clave que otras apps que definen el permiso.

Apps que usan permisos personalizados duplicados

Cualquier app puede definir cualquier permiso personalizado que desee, por lo que puede suceder que varias apps definan el mismo permiso personalizado. Por ejemplo, si dos apps ofrecen una función similar, podrían derivar el mismo nombre lógico para sus permisos personalizados. Las apps también pueden incorporar bibliotecas públicas comunes o ejemplos de código que incluyen las mismas definiciones de permisos personalizados.

En Android 4.4 y versiones anteriores, los usuarios podían instalar varias apps de este tipo en un dispositivo determinado, aunque el sistema asignaba el nivel de protección que especificaba la primera app instalada.

A partir de Android 5.0, el sistema aplica una nueva restricción de unicidad en los permisos personalizados para las apps que están firmadas con claves diferentes. Ahora, solo una app en un dispositivo puede definir un permiso personalizado determinado (según lo determine su nombre), a menos que la otra app que define el permiso esté firmada con la misma clave. Si el usuario intenta instalar una app con un permiso personalizado duplicado y no está firmada con la misma clave que la app residente que define el permiso, el sistema bloquea la instalación.

Consideraciones sobre tu app

En Android 5.0 y versiones posteriores, las apps pueden seguir definiendo sus propios permisos personalizados como antes y solicitar permisos personalizados de otras apps a través del mecanismo <uses-permission>. Sin embargo, con el nuevo requisito que se introdujo en Android 5.0, debes evaluar cuidadosamente los posibles impactos en tu app.

A continuación se muestran algunos aspectos que deben tenerse en cuenta:

  • ¿Tu app declara algún elemento <permission> en su manifiesto? Si es así, ¿son realmente necesarios para el funcionamiento adecuado de tu app o servicio? ¿O podrías usar un permiso predeterminado del sistema?
  • Si tienes elementos <permission> en tu app, ¿sabes de dónde provienen?
  • ¿Realmente deseas que otras apps soliciten tus permisos personalizados a través de <uses-permission>?
  • ¿Estás usando código de ejemplo o de plantilla en tu app que incluya elementos <permission>? ¿Son realmente necesarios esos elementos de permiso?
  • ¿Tus permisos personalizados usan nombres simples o basados en términos comunes que otras apps podrían compartir?

Nuevas instalaciones y actualizaciones

Como se mencionó anteriormente, las instalaciones y actualizaciones nuevas de tu app en dispositivos que ejecutan Android 4.4 o versiones anteriores no se ven afectadas y no hay cambios en el comportamiento. En el caso de las instalaciones y actualizaciones nuevas en dispositivos que ejecutan Android 5.0 o versiones posteriores, el sistema impide la instalación de tu app si define un permiso personalizado que ya está definido por una app residente existente.

Instalaciones existentes con actualización de sistema a Android 5.0

Si tu app usa permisos personalizados y está ampliamente distribuida e instalada, es posible que se vea afectada cuando los usuarios actualicen sus dispositivos a Android 5.0. Después de que se instala la actualización del sistema, el sistema vuelve a validar las apps instaladas, incluida una verificación de sus permisos personalizados. Si tu app define un permiso personalizado que ya está definido por otra app que ya se validó, y tu app no está firmada con la misma clave que la otra, el sistema no vuelve a instalar tu app.

Recomendaciones

En dispositivos con Android 5.0 o versiones posteriores, te recomendamos que examines tu app de inmediato, realices los ajustes necesarios y publiques la versión actualizada lo antes posible para tus usuarios.

  • Si usas permisos personalizados en tu app, considera su origen y si realmente los necesitas. Quita todos los elementos <permission> de tu app, a menos que estés seguro de que son necesarios para que funcione correctamente.
  • Considera reemplazar tus permisos personalizados por los permisos predeterminados del sistema siempre que sea posible.
  • Si tu app requiere permisos personalizados, cámbiales el nombre para que sean únicos, por ejemplo, adjúntalos al nombre completo del paquete de tu app.
  • Si tienes un paquete de apps firmadas con diferentes claves y las apps acceden a un componente compartido a través de un permiso personalizado, asegúrate de que el permiso personalizado solo se defina una vez, en el componente compartido. Las apps que usan el componente compartido no deben definir el permiso personalizado por sí mismas, sino que deben solicitar acceso a través del mecanismo <uses-permission>.
  • Si tienes un paquete de apps firmadas con la misma clave, cada app puede definir los mismos permisos personalizados según sea necesario. El sistema permite que las apps se instalen de la manera habitual.

Cambios en la configuración predeterminada de TLS/SSL

Android 5.0 introduce cambios en la configuración predeterminada de TLS/SSL que usan las apps para HTTPS y otro tráfico TLS/SSL:

  • Los protocolos TLSv1.2 y TLSv1.1 ahora están habilitados.
  • Los conjuntos de cifrado AES-GCM (AEAD) ahora están habilitados.
  • Los conjuntos de cifrado MD5, 3DES, de exportación y ECDH de llave estática ahora están inhabilitados.
  • Se prefiere el uso de conjuntos de cifrado de confidencialidad directa (ECDHE y DHE).

Estos cambios pueden provocar interrupciones en la conectividad HTTPS o TLS/SSL en una pequeña cantidad de casos que se indican a continuación.

Ten en cuenta que el instalador de proveedores de seguridad de los Servicios de Google Play ya ofrece estos cambios en todas las versiones de la plataforma de Android hasta Android 2.3.

El servidor no admite ninguno de los conjuntos de cifrado habilitados

Por ejemplo, es posible que un servidor solo sea compatible con los conjuntos de cifrado 3DES o MD5. La corrección preferida es mejorar la configuración del servidor para habilitar protocolos y suites de algoritmos de cifrado más modernos y seguros. Idealmente, se deben habilitar TLSv1.2 y AES-GCM, y se deben habilitar y preferir los conjuntos de algoritmos de cifrado de confidencialidad avanzada (ECDHE, DHE).

Una alternativa es modificar la app para que use un SSLSocketFactory personalizado para comunicarse con el servidor. La fábrica debe diseñarse para crear instancias de SSLSocket que tengan habilitados algunos de los conjuntos de algoritmos de cifrado que requiere el servidor, además de los conjuntos de algoritmos de cifrado predeterminados.

La app hace predicciones incorrectas respecto de los conjuntos de cifrado empleados para conectarse al servidor

Por ejemplo, algunas apps contienen un X509TrustManager personalizado que falla porque espera que el parámetro authType sea RSA, pero encuentra ECDHE_RSA o DHE_RSA.

El servidor no admite TLSv1.1, TLSv1.2 ni extensiones TLS nuevas

Por ejemplo, el protocolo de enlace TLS/SSL con un servidor se rechaza o se detiene por error. La solución preferida es actualizar el servidor para que cumpla con el protocolo TLS/SSL. Esto hará que el servidor negocie correctamente estos protocolos más nuevos o negocie TLSv1 o protocolos anteriores, y omita las extensiones de TLS que no comprenda. En algunos casos, inhabilitar TLSv1.1 y TLSv1.2 en el servidor puede funcionar como medida provisional hasta que se actualice el software del servidor.

Una alternativa es modificar la app para que use un SSLSocketFactory personalizado para comunicarse con el servidor. La fábrica debe diseñarse para crear instancias de SSLSocket con solo los protocolos habilitados que el servidor admite correctamente.

Compatibilidad con perfiles administrados

Los administradores de dispositivos pueden agregar un perfil administrado a un dispositivo. El administrador es el propietario de este perfil, lo que le permite controlar el perfil administrado y, al mismo tiempo, dejar el perfil personal del usuario y su espacio de almacenamiento bajo su control. Este cambio puede afectar el comportamiento de tu app existente de las siguientes maneras:

Administración de intents

Los administradores de dispositivos pueden restringir el acceso a las aplicaciones del sistema desde el perfil administrado. En este caso, si una app activa un intent desde el perfil administrado que esa aplicación controlaría normalmente y no hay un controlador adecuado para el intent en el perfil administrado, el intent genera una excepción. Por ejemplo, el administrador del dispositivo puede restringir el acceso de las apps del perfil administrado a la aplicación de la cámara del sistema. Si tu app se ejecuta en el perfil administrado y llama a startActivityForResult() para MediaStore.ACTION_IMAGE_CAPTURE, y no hay ninguna app en el perfil administrado que pueda controlar el intent, se genera una ActivityNotFoundException.

Para evitar esto, verifica que haya al menos un controlador para cualquier intent antes de activarlo. Para verificar si hay un controlador válido, llama a Intent.resolveActivity(). Puedes ver un ejemplo de esto en Cómo tomar fotos de forma sencilla: Cómo tomar una foto con la app de Cámara.

Cómo compartir archivos entre perfiles

Cada perfil cuenta con su propio almacenamiento de archivos. Dado que un URI de archivo hace referencia a una ubicación específica en el almacenamiento de archivos, esto significa que un URI de archivo que es válido en un perfil no es válido en el otro. Por lo general, esto no es un problema para una app, que suele acceder solo a los archivos que crea. Sin embargo, si una app adjunta un archivo a un intent, no es seguro adjuntar un URI de archivo, ya que, en algunas circunstancias, el intent se puede controlar en el otro perfil. Por ejemplo, un administrador de dispositivos puede especificar que la app de la cámara del perfil personal debe controlar los eventos de captura de imágenes. Si una app del perfil administrado activa el intent, la cámara debe poder escribir la imagen en una ubicación donde las apps del perfil administrado puedan leerla.

Para mayor seguridad, cuando necesites adjuntar un archivo a un intent que pueda cruzarse de un perfil a otro, debes crear y usar un URI de contenido para el archivo. Para obtener más información sobre cómo compartir archivos con URIs de contenido, consulta Cómo compartir archivos. Por ejemplo, el administrador del dispositivo podría permitir que la cámara controle ACTION_IMAGE_CAPTURE en el perfil personal. El EXTRA_OUTPUT del intent de activación debe contener un URI de contenido que especifique dónde se debe almacenar la foto. La app de la cámara puede escribir la imagen en la ubicación especificada por ese URI, y la app que activó el intent podría leer ese archivo, incluso si la app está en el otro perfil.

Eliminación de la compatibilidad con widgets de pantalla bloqueada

Android 5.0 quita la compatibilidad con los widgets de la pantalla de bloqueo, pero sigue admitiendo widgets en la pantalla principal.