Nivel de API: 21
Además de nuevas funciones y capacidades, Android 5.0 incorpora varios cambios en el sistema y cambios en los comportamientos de la API. En este documento, se destacan algunos de los cambios clave que debes comprender y tener en cuenta en tus apps.
Si publicaste anteriormente una app para Android, ten en cuenta que tu app podría verse afectada por estos cambios en Android 5.0.
Para obtener una visión 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
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 Android Runtime (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 para desarrolladores que generan código no estándar (como algunos ofuscadores).
- Usas técnicas que no son compatibles 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. Para obtener más información sobre cómo 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 tienen errores, corrígelas de la siguiente manera:
- 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 en 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 con 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 entra 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 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 optar por proteger la información sensible para que no quede expuesta, 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 implementas notificaciones que presentan un estado de reproducción de contenido multimedia o controles de transporte, considera usar la nueva plantilla Notification.MediaStyle
en lugar de un objeto RemoteViews.RemoteView
personalizado. Sin importar el 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 tu app usa RemoteControlClient.
Notificación emergente
Las notificaciones ahora pueden aparecer en una ventana flotante pequeña (también denominada notificación de atención) cuando el dispositivo está activo (es decir, está desbloqueado y la pantalla está encendida). Estas notificaciones tienen una apariencia similar a la forma compacta de tu notificación, con la excepción de que la notificación de atención también muestra los botones de acción. Los usuarios pueden actuar en función de una notificación de atención 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 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.
En las pantallas de bloqueo de Android 5.0, no se muestran los controles de transporte de 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. De esta manera, tu app tiene más control sobre la presentación de los botones multimedia y, al mismo tiempo, brinda una experiencia coherente para los usuarios en dispositivos bloqueados y desbloqueados.
Para este fin, Android 5.0 presenta una nueva plantilla Notification.MediaStyle
.
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 configurar la visibilidad de la notificación en VISIBILITY_PUBLIC
para marcarla como segura para la visualización en cualquier pantalla de bloqueo (ya sea segura o de otra manera). Para obtener más información, consulta Notificaciones en la 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 multimedia en dispositivos Android.
getRecentTasks()
Con la introducción de la nueva función de tareas y documentos simultáneos en Android 5.0 (consulta Documentos y actividades simultáneos en la pantalla de recientes más abajo), 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 sus 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, a la vez que sigue siendo compatible por completo con 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 introduce nuevas API nativas de NDK de contenido multimedia, así como compatibilidad nativa con OpenGL ES (GLES) 3.1.
Para usar la compatibilidad con 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 y las correcciones de errores importantes en el NDK.
Enlazar a un servicio (Service)
El método Context.bindService()
ahora requiere un Intent
explícito y arroja una excepción si tiene 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 tiene como objetivo el nivel de API 21 o uno posterior, 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()
ysetAcceptThirdPartyCookies()
, respectivamente. - Ahora el sistema elige de manera inteligente partes del documento HTML para dibujar. Este nuevo comportamiento predeterminado ayuda a reducir el uso de memoria y aumentar el rendimiento. Si deseas renderizar todo el documento de una vez, llama a
enableSlowWholeDocumentDraw()
para inhabilitar esta optimización.
- 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
- Si tu app se orienta 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 los elementos
<permission>
declarados en sus archivos de manifiesto.
Hay una pequeña cantidad de situaciones en las que la definición de permisos personalizados es un enfoque legítimo y seguro. Sin embargo, crear permisos personalizados suele ser innecesario y hasta puede suponer un riesgo potencial para una app, según el nivel de protección asignado a los permisos.
En Android 5.0, se 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, por lo que es posible que varias apps definan el mismo permiso personalizado. Por ejemplo, si dos apps ofrecen una capacidad similar, podrían 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 exclusividad en los permisos personalizados para 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 bloqueará la instalación.
Consideraciones sobre tu app
En Android 5.0 y versiones posteriores, las apps pueden continuar definiendo sus propios permisos personalizados como antes y solicitando permisos personalizados de otras apps mediante el mecanismo <uses-permission>
. Sin embargo, con el nuevo requisito que se introdujo en Android 5.0, debes evaluar cuidadosamente el posible impacto 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 mediante
<uses-permission>
? - ¿Estás usando código estándar o de ejemplo en tu app que incluye elementos
<permission>
? ¿Son realmente necesarios esos elementos de permiso? - ¿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 que ejecutan Android 4.4 o versiones anteriores, no se ven afectadas las actualizaciones y no se produce ningún cambio en el comportamiento. En el caso de las instalaciones y actualizaciones nuevas en dispositivos que ejecutan Android 5.0 o versiones posteriores, el sistema evita la instalación de tu app si define un permiso personalizado ya 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, existe la posibilidad de que se vea afectada cuando los usuarios reciban la actualización de 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, lo que incluye una verificación de sus 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 tu app.
Recomendaciones
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 lo antes posible para los 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 el funcionamiento correcto de la app. - Considera reemplazar tus permisos personalizados con permisos predeterminados del sistema siempre que sea posible.
- Si tu app requiere permisos personalizados, cámbiales 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 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 presenta cambios en la configuración 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 producir fallas en la conectividad HTTPS o TLS/SSL en una pequeña cantidad de los casos que se indican a continuación.
Ten en cuenta que ProviderInstaller 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 solución preferida es mejorar la configuración del servidor para habilitar conjuntos y protocolos de cifrado más sólidos y modernos. Lo ideal es que se habiliten TLSv1.2 y AES-GCM, además de que se habiliten los conjuntos de cifrado de confidencialidad directa (ECDHE, DHE), que sean los preferidos.
Una alternativa es modificar la app para que use una SSLSocketFactory personalizada y se comunique 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 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 se daña 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 nuevos, o bien TLSv1 o protocolos anteriores, e ignore las extensiones de TLS que no comprenda. En algunos casos, inhabilitar TLSv1.1 y TLSv1.2 en el servidor puede funcionar como medida temporal hasta que se actualice el software del servidor.
Una alternativa es modificar la app para que use una SSLSocketFactory personalizada y se comunique con el servidor. La fábrica debe diseñarse para crear instancias de SSLSocket que tengan habilitados solo los protocolos que el servidor admite correctamente.
Compatibilidad con perfiles administrados
Los administradores del dispositivo pueden agregar un perfil administrado a un dispositivo. Este perfil es propiedad del administrador, lo que le da el 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 desde el perfil administrado que normalmente controlaría esa aplicación 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 en el 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 generará una ActivityNotFoundException
.
A fin de evitarlo, comprueba que haya al menos un controlador para cualquier intent antes de activarlo. Para verificar si hay un controlador válido, llama a Intent.resolveActivity()
. Para ver un ejemplo de esto, consulta Cómo tomar fotos simplemente: tomar una foto con la app de la 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, significa que un URI de archivo que es válido en un perfil no lo es en el otro. Por lo general, esto no es un problema para una app, que solo accede a los archivos que crea. Sin embargo, si una app conecta un archivo a un intent, no es seguro adjuntar un URI de archivo, ya que en algunas circunstancias el intent podría controlarse en el otro perfil. Por ejemplo, el administrador de un dispositivo podría especificar que la app de cámara en el perfil personal deba controlar los eventos de captura de imágenes. 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.
Para estar seguro, cuando necesites adjuntar un archivo a un intent que podría pasar 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 puede 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 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 pantalla de bloqueo; sigue admitiendo widgets en la pantalla principal.