Cambios de comportamiento en Android 5.0

Nivel de API: 21

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

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

Para obtener un panorama de alto nivel de las nuevas funciones de la plataforma, consulta las funciones destacadas 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 Introducción a 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 tiempo 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).
  • Si usas técnicas incompatibles con la compactación de la recolección de elementos no utilizados.

Notificaciones

Asegúrate de que en tus notificaciones se tengan en cuenta estos cambios de Android 5.0. Si quieres obtener más información para diseñar tus 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 no se ven correctamente, corrígelas:

  • Usa setColor() para establecer un color de elementos destacados 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 sean alfa en los íconos de acción y el ícono de notificación principal. Debes suponer que estos íconos serán solo alfa. El sistema dibuja los íconos de notificaciones en blanco y los de acción en gris oscuro.

Sonido y vibración

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

Cuando se configura el dispositivo en RINGER_MODE_SILENT, este ingresa en el nuevo modo de prioridad. El dispositivo sale del modo de prioridad si lo estableces en RINGER_MODE_NORMAL o RINGER_MODE_VIBRATE.

Anteriormente, Android usaba STREAM_MUSIC como transmisión principal para controlar el volumen en las tablets. En Android 5.0, el flujo de volumen principal para teléfonos y tablets ahora está unificado y se controla mediante 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 elegir si quieren evitar que se exponga información sensible, en cuyo caso el sistema oculta automáticamente el texto que se muestra en 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 estás implementando notificaciones que presentan un estado de reproducción de contenido multimedia o controles de transporte, considera usar la nueva plantilla de Notification.MediaStyle en lugar de un objeto RemoteViews.RemoteView personalizado. Independientemente del enfoque que elijas, asegúrate de configurar 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 la app usa RemoteControlClient.

Notificación emergente

Las notificaciones ahora pueden aparecer en una ventana flotante pequeña (también llamada notificación de atención) cuando el dispositivo está activo (es decir, cuando está desbloqueado y la pantalla está encendida). Estas notificaciones son similares a la forma compacta de tu notificación, con la excepción de que la notificación emergente también muestra los botones de acción. Los usuarios pueden interactuar con una notificación emergente o descartarla sin salir de la app actual.

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

  • La actividad del usuario está 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 emergentes 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 de Android 5.0 no muestran los controles de transporte para tu MediaSession ni RemoteControlClient. En cambio, tu app puede ofrecer control de reproducción de contenido multimedia desde la pantalla de bloqueo mediante una notificación. Esto le brinda a tu app más control sobre la presentación de los botones multimedia y proporciona una experiencia coherente para los usuarios en dispositivos bloqueados y desbloqueados.

Para este fin, Android 5.0 presenta una plantilla Notification.MediaStyle nueva. 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 tu token de sesión al método setSession() para informar 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 a fin de marcarla como segura para mostrarse en cualquier pantalla de bloqueo (ya sea segura o de otra manera). Para obtener más información, consulta Notificaciones en pantalla de bloqueo.

Para mostrar los controles de reproducción de contenido multimedia si tu app se ejecuta en la plataforma Android TV o Wear, implementa la clase MediaSession. También debes implementar MediaSession si tu app necesita recibir eventos de botones de medios 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 de recientes a continuación), el método ActivityManager.getRecentTasks() dejó de estar disponible para mejorar la privacidad del usuario. Para ofrecer retrocompatibilidad, este método muestra un pequeño subconjunto de datos, incluidas las propias tareas de la aplicación que realiza la llamada y posiblemente algunas otras tareas no sensibles (como la página principal). Si tu app usa este método para recuperar sus propias tareas, usa getAppTasks() en su lugar 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, sin dejar de admitir por completo las apps de 32 bits existentes. La compatibilidad con arquitecturas de 64 bits también mejora el rendimiento de OpenSSL para la criptografía. Además, esta versión introduce nuevas API de NDK de medios nativos, así como compatibilidad nativa con OpenGL ES (GLES) 3.1.

Para aprovechar la compatibilidad con 64 bits que proporciona 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 Revision 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 arroja una excepción si se le otorga 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 está orientada al nivel de API 21 o uno superior, haz lo siguiente:
    • El sistema bloquea el contenido mixto y las cookies de terceros de forma predeterminada. Para permitir contenido mixto y cookies de terceros, usa los métodos setMixedContentMode() y setAcceptThirdPartyCookies(), respectivamente.
    • Ahora, el sistema elige de forma inteligente partes del documento HTML que dibujará. Este nuevo comportamiento predeterminado ayuda a reducir el uso de memoria y aumentar el rendimiento. Si quieres renderizar todo el documento de una vez, inhabilita esta optimización llamando a enableSlowWholeDocumentDraw().
  • Si tu app está orientada a niveles de API inferiores al 21: El sistema permite contenido mixto y cookies de terceros, y siempre procesa todo el documento de una 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 manera privada, sin usar los permisos predefinidos del sistema de la plataforma. Las apps definen permisos personalizados en 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 la creación de permisos personalizados no es necesaria y hasta puede suponer 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 se firme con la misma clave que otras apps que definen el permiso.

Apps que usan permisos personalizados duplicados

Cualquier app puede definir el permiso personalizado que desee, de manera que puede suceder que varias apps definan el mismo permiso personalizado. Por ejemplo, si dos apps ofrecen una capacidad similar, pueden derivar el mismo nombre lógico para sus permisos personalizados. Las apps también pueden incorporar bibliotecas públicas o ejemplos de código comunes que incluyan 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 especificado por la app que se instalaba primero.

A partir de Android 5.0, el sistema aplica una nueva restricción de singularidad en los permisos personalizados para las apps firmadas con claves diferentes. Ahora, solo una app del dispositivo puede definir un permiso personalizado determinado (según 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 bloqueará la instalación.

Consideraciones sobre tu app

En Android 5.0 y versiones posteriores, las apps pueden continuar definiendo sus propios permisos personalizados al igual que antes y solicitando permisos personalizados de otras apps mediante el mecanismo <uses-permission>. Sin embargo, con el nuevo requisito presentado 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 correcto de tu app o servicio? ¿O podrías usar un permiso predeterminado del sistema en su lugar?
  • 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>?
  • ¿En tu app usas código estándar o de ejemplo que incluye elementos <permission>? ¿Son realmente necesarios esos elementos de permisos?
  • ¿Tus permisos personalizados usan nombres que son simples o se basan en términos comunes que otras apps podrían compartir?

Nuevas instalaciones y actualizaciones

Como se mencionó anteriormente, en el caso de las nuevas instalaciones y actualizaciones de tu app en dispositivos con Android 4.4 o versiones anteriores, no se verán afectadas y no se producirán cambios en el comportamiento. En el caso de las nuevas instalaciones y actualizaciones en dispositivos que ejecutan Android 5.0 o versiones posteriores, el sistema evita 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 reciban la actualización de sus dispositivos a Android 5.0. Una vez instalada la actualización del sistema, el sistema vuelve a validar las apps instaladas, incluida una verificación de los permisos personalizados. Si tu app define un permiso personalizado ya 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 la app.

de contenido

En los dispositivos que ejecutan Android 5.0 o versiones posteriores, te recomendamos examinar la app de inmediato, realizar los ajustes necesarios y publicar la versión actualizada para los usuarios lo antes posible.

  • Si usas permisos personalizados en tu app, considera su origen y si los necesitas realmente. Quita todos los elementos <permission> de tu app, a menos que estés seguro de que son necesarios para el correcto funcionamiento de la app.
  • Considera reemplazar tus permisos personalizados por permisos predeterminados del sistema siempre que sea posible.
  • Si tu app requiere permisos personalizados, cámbiale el nombre para que sean únicos, por ejemplo, agregándolos al nombre completo del paquete de la app.
  • Si tienes un conjunto de apps firmadas con diferentes claves y estas acceden a un componente compartido mediante un permiso personalizado, asegúrate de que este se defina una sola 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 conjunto de apps firmadas con la misma clave, cada una puede definir los mismos permisos personalizados según sea necesario; es decir, el sistema permite que las apps se instalen de la manera habitual.

Cambios en la configuración predeterminada de TLS/SSL

Android 5.0 presenta cambios en la configuración de TLS/SSL predeterminada que usan las apps para el tráfico 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 fallas 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 proveedor de seguridad ProviderInstaller de los Servicios de Google Play ya ofrece estos cambios en 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 solución preferida es mejorar la configuración del servidor para habilitar conjuntos de algoritmos de cifrado y protocolos más sólidos y modernos. Lo ideal sería que se habiliten TLSv1.2 y AES-GCM, así como que se habiliten los conjuntos de algoritmos de cifrado de confidencialidad directa (ECDHE, DHE) y se prefieran.

Una alternativa es modificar la app a fin de usar una SSLSocketFactory personalizada 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 requeridos por el servidor, además de los conjuntos de algoritmos 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 con éxito estos protocolos más recientes, o bien TLSv1 o protocolos anteriores, e ignore las extensiones TLS que no comprenda. En algunos casos, la inhabilitación de TLSv1.1 y TLSv1.2 en el servidor puede funcionar como medida provisoria hasta que se actualice el software del servidor.

Una alternativa es modificar la app a fin de usar una SSLSocketFactory personalizada para comunicarse con el servidor. La fábrica debe diseñarse para crear instancias de SSLSocket que tengan habilitados solo los protocolos que el servidor admite de forma correcta.

Compatibilidad con perfiles administrados

Los administradores de dispositivos pueden agregar un perfil administrado a un dispositivo. Este perfil es propiedad del administrador, lo que le da control sobre el perfil administrado y, al mismo tiempo, deja el perfil personal del usuario y su espacio de almacenamiento bajo el control del usuario. 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 del perfil administrado que normalmente esa aplicación controlaría 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 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.

A fin de evitarlo, 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 este proceso en Take Photos Solo: Take a Photo with the Camera App.

Cómo compartir archivos entre perfiles

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

A fin de estar seguro, cuando necesitas adjuntar un archivo a un intent que puede ir de un perfil al otro, debes crear y usar un URI de contenido para el archivo. Para obtener más información sobre cómo compartir archivos con URI 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 que se activa debe incluir un URI de contenido que especifique dónde se debe almacenar la foto. La app de 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; continúa admitiendo widgets en la pantalla principal.