lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Funciones y API de Android 8.0

Android 8.0 presenta varias funciones y capacidades nuevas para usuarios y desarrolladores. En este documento, se destacan las novedades para desarrolladores.

Asegúrate de revisar los cambios de comportamiento en Android 8.0 para obtener información sobre las áreas en las cuales los cambios en la plataforma pueden afectar tus apps.

Experiencia del usuario

Notificaciones

En Android 8.0, rediseñamos las notificaciones para proporcionar una manera más sencilla y uniforme de administrar su comportamiento y sus configuraciones. Entre esos cambios se incluye lo siguiente:

    Un menú de notificaciones de presión prolongada en Android 8.0.

    Figura 1: Los usuarios pueden presionar de forma prolongada los íconos de inicio de la app para ver notificaciones en Android 8.0.

  • Canales de notificación: Android 8.0 presenta canales de notificación que te permiten crear un canal que el usuario puede personalizar para cada tipo de notificación que desees mostrar. En la interfaz de usuario se hace referencia a los canales de notificación como categorías de notificación. Para obtener información sobre cómo implementar canales de notificación, consulta la guía de Canales de notificación.
  • Insignias de notificación: en Android 8.0 se incorpora compatibilidad con la exhibición de insignias de notificación en los íconos de inicio de la app. Las insignias de notificación reflejan la presencia de notificaciones asociadas con una app, que el usuario aún no ha descartado ni utilizado. Las insignias de notificación también se conocen como “puntos de notificación”. Para obtener información sobre cómo ajustar insignias de notificación, consulta la guía Insignias de notificación.
  • Posposición: Los usuarios pueden posponer las notificaciones para que reaparezcan posteriormente. Las notificaciones vuelven a reaparecer con el mismo nivel de importancia con el que aparecieron por primera vez. Las apps pueden quitar o actualizar una notificación pospuesta, pero la actualización de una notificación pospuesta no hace que vuelva a aparecer.
  • Tiempos de espera de notificaciones: Ahora puedes fijar un tiempo de espera cuando creas una notificación usando setTimeoutAfter(). Puedes usar este método para especificar un plazo después del cual se debe cancelar una notificación. Si es necesario, puedes cancelar una notificación antes de que transcurra el tiempo de espera especificado.
  • Configuración de notificaciones: puedes llamar a setSettingsText() para establecer la aparición de texto cuando creas un vínculo a la configuración de notificaciones de tu app desde una notificación que use el intent Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES. El sistema puede proporcionar los siguientes valores adicionales con el intent para filtrar la configuración que tu app debe mostrar a los usuarios: EXTRA_CHANNEL_ID, NOTIFICATION_TAG y NOTIFICATION_ID.
  • Descarte de notificaciones: Ahora el sistema distingue si un usuario descarta una notificación o si una app la quita. Para verificar la manera en que se descartan las notificaciones, debes implementar el método nuevo onNotificationRemoved() de la clase NotificationListenerService.
  • Colores de fondo: Ahora puedes configurar y habilitar un color de fondo para una notificación. Solo debes usar esta función en notificaciones para tareas en curso que son críticas para que un usuario las vea rápidamente. Por ejemplo, puedes configurar un color de fondo para las notificaciones relacionadas con indicaciones de manejo o una llamada de teléfono en curso. También puedes configurar el color de fondo deseado usando Notification.Builder.setColor(). Hacerlo te permite usar Notification.Builder.setColorized() para habilitar el uso de un color de fondo en una notificación.
  • Estilo de mensajería: Las notificaciones que usan la clase MessagingStyle ahora muestran más contenido en su forma contraída. Debes usar la clase MessagingStyle para notificaciones relacionadas con la mensajería. También puedes usar el nuevo método addHistoricMessage() para proporcionar contexto a una conversación agregando mensajes históricos a las notificaciones relacionadas con la mensajería.

Marco Autofill

La creación de cuentas, el acceso y las transacciones con tarjetas de crédito llevan tiempo y están sujetas a errores. Los usuarios pueden frustrarse fácilmente ante aplicaciones que requieren estos tipos de tareas repetitivas.

Android 8.0 hace que resulte más fácil completar formularios, como los de acceso o tarjetas de crédito, gracias a la introducción del marco Autofill. Las aplicaciones existentes y las nuevas funcionan con el marco Autofill una vez que el usuario incluye el autocompletado.

Puedes tomar algunas medidas para optimizar la manera en la que tu aplicación funciona con el marco. Para obtener más información, consulta Información general del marco de trabajo Autofill.

Modo de imagen en imagen

Android 8.0 permite el lanzamiento de actividades en el modo de imagen en imagen (PIP). PIP es una clase especial de modo de ventanas múltiples que se usa principalmente para la reproducción de videos. El modo PIP ya se encuentra disponible para Android TV; Android 8.0 hace que esta función esté disponible en otros dispositivos de Android.

Cuando una actividad funciona en el modo PIP, se encuentra en un estado de pausa, pero debe continuar mostrando el contenido. Por esta razón, debes asegurarte de que tu aplicación no pause la reproducción en su controlador onPause(). Como alternativa, debes pausar el video en onStop() y reanudar la reproducción en onStart(). Para obtener más información, consulta Ciclo de vida en el modo de ventanas múltiples.

Para especificar que tu actividad puede usar el modo PIP, fija android:supportsPictureInPicture en true en el manifiesto. (A partir de Android 8.0, no es necesario que fijes android:resizeableActivity en true si admites el modo PIP, ya sea en Android TV o en otros dispositivos Android. Solo debes configurar android:resizeableActivity si tu actividad admite otros modos de ventanas múltiples).

Cambios en la API

Android 8.0 presenta un objeto nuevo, PictureInPictureParams, que se pasa a métodos PIP para especificar el comportamiento que debe tener una actividad cuando se encuentra en el modo PIP. Este objeto especifica propiedades, como la relación de aspecto priorizada de la actividad.

Los métodos PIP existentes descritos en Agregar imagen en imagen ahora se pueden usar en todos los dispositivos Android, no solo en Android TV. Además, Android 8.0 proporciona los siguientes métodos para admitir el modo PIP:

  • Activity.enterPictureInPictureMode(PictureInPictureParams args): activa el modo de imagen en imagen para la actividad. La relación de aspecto de la actividad y otros ajustes de configuración se especifican a través de args. Si algún campo en args se encuentra vacío, el sistema usa los valores fijados la última vez que llamaste a Activity.setPictureInPictureParams().

    La actividad especificada se ubica en una esquina de la pantalla; el resto de esta última se abarca con la actividad previa. La actividad que ingresa en el modo PIP entra en un estado de pausa, pero permanece activa. Si el usuario presiona la actividad en el modo PIP, el sistema muestra un menú con el cual el usuario podrá interactuar. Ningún evento táctil alcanza la actividad mientras funciona en el modo PIP.

  • Activity.setPictureInPictureParams(): actualiza los ajustes de configuración del modo PIP de una actividad. Si la actividad se encuentra actualmente en el modo PIP, las configuraciones se actualizan. Esto resulta útil si la relación de aspecto de una actividad cambia. Si la actividad no se encuentra en el modo PIP, se usan estos ajustes de configuración independientemente del método enterPictureInPictureMode() que llames.

Fuentes para descargar

Android 8.0 y la biblioteca de compatibilidad 26 de Android te permiten solicitar fuentes desde una app del proveedor en lugar de agrupar las fuentes en el APK o permitir que este las descargue. Esta función reduce el tamaño de tu APK, aumenta el índice de éxito de la instalación de apps y permite que varias apps compartan la misma fuente.

Para obtener más información sobre la descarga de fuentes, consulta Fuentes descargables.

Fuentes en XML

Android 8.0 presenta una función nueva, fuentes en XML, que te permite usar fuentes como recursos. Esto significa, que no hay necesidad de integrar fuentes como recursos. Las fuentes se compilan en el archivo R y están disponibles en el sistema como un recurso de manera automática. Puedes acceder a estas fuentes con la ayuda de un nuevo tipo de recurso: font.

La biblioteca de compatibilidad 26 proporciona una compatibilidad completa con esta función en dispositivos con la API 14 y versiones posteriores.

Para obtener más información sobre el uso de fuentes como recursos y la obtención de fuentes de sistema, consulta Fuentes en XML.

Ajuste automático de tamaño de TextView

Android 8.0 te permite configurar el valor de expansión o contracción de tu texto automáticamente según el tamaño de TextView. Esto significa que es mucho más sencillo optimizar el tamaño de texto en diferentes pantallas o con contenido dinámico. Para obtener más información sobre el ajuste automático de tamaño de TextView en Android 8.0, consulta Ajuste automático de tamaño de TextView.

Íconos adaptables

Android 8.0 presenta íconos lanzadores adaptables. Los íconos adaptables admiten efectos visuales y pueden mostrar diferentes formas en los diferentes modelos de dispositivos. Para obtener información sobre cómo crear íconos adaptables, consulta la guía de funciones Íconos adaptables de la Preview.

Administración de color

Los desarrolladores de apps de imagen para Android ahora pueden aprovechar los nuevos dispositivos que ofrecen pantallas capaces de reproducir una amplia gama de colores. Para mostrar imágenes coloridas, las apps deberán habilitar un indicador en su manifiesto (por actividad) y cargar mapas de bits con un perfil de gran cantidad de colores integrado (AdobeRGB, Pro Photo RGB, DCI-P3, etc.).

WebView API

Android 8.0 ofrece varias API para ayudarte a administrar los objetos WebView que muestran contenido web en tu app. Estas API, que mejoran la estabilidad y la seguridad de tu aplicación, son las siguientes:

  • Version API
  • Google SafeBrowsing API
  • Termination Handle API
  • Renderer Importance API

Para obtener más información sobre cómo usar estas API, consulta Administración de WebViews.

Fijación de combinaciones de teclas y widgets

En Android 8.0, se presenta la fijación de combinaciones de teclas y widgets en la app. En tu aplicación, puedes crear combinaciones de teclas y widgets fijados para los lanzadores admitidos, según lo permita el usuario.

Para obtener más información, consulta la guía de funciones Fijación de combinaciones de teclas y Widgets de la Preview.

Relación de aspecto máxima de la pantalla

Las apps orientadas a Android 7.1 (nivel de API 25) o versiones anteriores tienen una relación de aspecto de pantalla máxima predeterminada de 1.86. Las apps orientadas a Android 8.0 o versiones posteriores no tienen una relación de aspecto máxima predeterminada. Si es necesario que para tu app se fije una relación de aspecto máxima, usa el atributo maxAspectRatio en el archivo de manifiesto que define tu actividad.

Compatibilidad con múltiples pantallas

A partir de Android 8.0, la plataforma ofrece compatibilidad mejorada con varias pantallas. Si una actividad admite un modo con ventanas múltiples y se ejecuta en un dispositivo con visualizaciones múltiples, los usuarios pueden mover la actividad de una visualización a otra. Cuando una app inicia una actividad, puede especificar la visualización en la que debe ejecutarse dicha actividad.

Nota: Si una actividad admite un modo de ventanas múltiples, Android 8.0 habilita automáticamente la compatibilidad con visualizaciones múltiples para esa actividad. Tienes que probar tu app para asegurarte de que funcione de modo adecuado en un entorno de visualizaciones múltiples.

Solo puede haber una actividad por vez en el estado de reanudación, incluso si la app tiene visualizaciones múltiples. La actividad con enfoque está en el estado reanudado; todas las demás actividades visibles se pausan, pero no se detienen. Para obtener más información sobre el ciclo de vida de las actividades cuando varias actividades son visibles, consulta Ciclo de vida en el modo de ventanas múltiples.

Cuando un usuario mueve una actividad de una visualización a otra, el sistema modifica el tamaño de la actividad y emite cambios de tiempo de ejecución según sea necesario. Tu actividad puede administrar el cambio de configuración por sí misma o permitir que el sistema destruya el proceso que contiene tu actividad y la vuelva a crear con las nuevas dimensiones. Para obtener más información, consulta Manejar cambios de configuración.

ActivityOptions proporciona dos métodos nuevos para admitir varias pantallas:

setLaunchDisplayId()
Especifica la visualización en la cual se debe mostrar la actividad cuando se inicia.
getLaunchDisplayId()
Muestra la pantalla de lanzamiento actual de la actividad.

El shell de abd se extiende para admitir varias pantallas. El comando de shell shell start ahora se puede usar para lanzar una actividad y especificar la pantalla de destino de esta:

adb shell start <activity_name> --display <display_id>

Márgenes y relleno con diseño unificado

Android 8.0 te permite especificar las situaciones en que los lados opuestos de un elemento View usan el mismo margen o relleno. Específicamente, ahora puedes usar los siguientes atributos en tus archivos XML de diseño:

Nota: Si personalizas la lógica de tu app de modo que se admitan diferentes idiomas y culturas, incluida la orientación del texto, ten en cuenta que estos atributos no afectan los valores de layout_marginStart, layout_marginEnd, paddingStart ni paddingEnd. Puedes configurar estos valores tú mismo, además de los nuevos atributos de diseño horizontal y vertical, para crear un comportamiento de diseño que dependa de la orientación del texto.

Captura de puntero

Para algunas apps, como las de juegos, escritorio remoto y clientes de virtualización, controlar el puntero del mouse representa un gran beneficio. La captura del puntero es una función nueva de Android 8.0 que proporciona dicho control al proporcionar todos los eventos del mouse en una vista seleccionada en tu app.

A partir de Android 8.0, una View en tu app podrá solicitar una captura de puntero y definir un receptor para procesar los eventos capturados de puntero. En este modo, el puntero del mouse permanece escondido. La vista puede liberar la captura de puntero cuando ya no necesita la información del mouse. El sistema también puede liberar la captura de puntero cuando la vista pierde el foco; por ejemplo, cuando el usuario abre otra app.

Para obtener información sobre cómo usar esta función en tu app, consulta Captura de puntero.

Categorías de apps

Android 8.0 permite que cada app declare una categoría a la que pertenezca, cuando corresponda. Estas categorías se usan para agrupar apps de propósitos o funciones similares cuando se presentan a los usuarios; por ejemplo, uso de datos, uso de batería o uso de almacenamiento. Puedes definir una categoría para tu app configurando el atributo android:appCategory en la etiqueta <application> del manifiesto.

Lanzador de Android TV

En Android 8.0 se incluye una nueva experiencia de pantalla de inicio de Android TV centrada en el contenido, que se encuentra disponible para el emulador de Android TV y la imagen de dispositivo de Nexus Player para Android 8.0. La nueva pantalla de inicio organiza el contenido de video en filas que corresponden a canales, y una app del sistema completa cada una de estas con programas. Las apps pueden publicar varios canales y los usuarios pueden configurar los canales que desean ver en la pantalla de inicio. En la pantalla de inicio de Android TV también se incluye una fila Watch Next, que se completa con programas de apps según los hábitos de visualización del usuario. Las apps también pueden proveer vistas previas de video, que se reproducen automáticamente cuando un usuario se centra en un programa. Las API para los canales y programas completos son parte de las TvProvider API, que se distribuyen como un módulo de la biblioteca de compatibilidad de Android en Android 8.0.

AnimatorSet

A partir de Android 8.0, la AnimatorSet API admite la búsqueda y la reproducción en sentido inverso. La búsqueda te permite configurar la posición de la animación fijada en un punto específico en el tiempo. La reproducción en sentido inverso es útil si tu app incluye animaciones para acciones que se puedan deshacer. En lugar de definir dos conjuntos de animaciones separadas, puedes reproducir el mismo en sentido inverso.

Entrada y navegación

Clústeres de navegación con teclado

Si una actividad en tu app usa una jerarquía de vistas compleja, como la de la Figura 2, considera organizar grupos de elementos de IU en clústeres para que la navegación por teclado entre ellos sea más sencilla. Los usuarios pueden presionar Meta+Tab, o Search+Tab en dispositivos Chromebook para navegar de un clúster a otro. Algunos buenos ejemplos de clústeres son paneles laterales, barras de navegación, áreas de contenido principal y elementos que pueden contener muchos elementos primarios.

Actividad de ejemplo que incluye cinco clústeres de navegación que el usuario puede explorar usando la combinación de teclas de clúster de navegación por teclado. Clústeres que aparecen en la siguiente disposición: panel superior, panel lateral izquierdo, área de contenido principal, panel inferior y botón de acción flotante.
Figura 2: Actividad que contiene 5 clústeres de navegación.

Para hacer un clúster a partir de un elemento View o ViewGroup, fija el atributo android:keyboardNavigationCluster en true en el archivo XML de diseño del elemento o pasa true a setKeyboardNavigationCluster() en la lógica de IU de tu app.

Nota: No es posible anidar clústeres; no obstante, los clústeres no anidados pueden aparecer en diferentes niveles de la jerarquía. Si intentas anidar clústeres, el marco de trabajo solo considerará el elemento ViewGroup que se encuentra más arriba como un clúster.

En dispositivos con pantallas táctiles, puedes fijar en true el elemento android:touchscreenBlocksFocus de un objeto ViewGroup designado de clúster para permitir la navegación solo hacia adentro y afuera de dicho clúster. Si aplicas esta configuración a un clúster, los usuarios no podrán usar la tecla Tab ni las teclas de flechas para navegar hacia adentro o afuera del clúster. En lugar de ello, deberán presionar la combinación de teclas de navegación de clústeres.

Foco predeterminado de las vistas

En Android 8.0, puedes asignar la View que debe recibir foco después de que se reanude una actividad (re)creada y el usuario presione una tecla de navegación del teclado, como Tab. Para aplicar este ajuste “enfocado de forma predeterminada”, fija en true el atributo android:focusedByDefault de un elemento View en el archivo XML de diseño que contiene el elemento de IU o pasa true a setFocusedByDefault() en la lógica de IU de tu app.

Sistema

Nuevos detectores StrictMode

En Android 8.0 se agregan tres detectores StrictMode nuevos para ayudar a identificar posibles errores en tu app:

  • detectUnbufferedIo() determinará el momento en que la aplicación lea o escriba datos sin almacenamiento en búfer, lo cual puede afectar drásticamente el rendimiento.
  • detectContentUriWithoutPermission() determinará el momento en que tu aplicación no otorgue, no por accidente, permisos a otra aplicación al iniciar fuera de tu aplicación una actividad.
  • detectUntaggedSockets() determinará el momento en que exista tráfico de red en tu app sin usar setThreadStatsTag(int) a fin de etiquetar el tráfico para depuración.

Datos almacenados en caché

Android 8.0 ofrece mejor orientación y comportamientos respecto de los datos almacenados en caché. Cada aplicación ahora recibe una cuota de espacio en disco para datos almacenados en caché, como lo muestra getCacheQuotaBytes(UUID).

Cuando el sistema deba liberar espacio en el disco, comenzará por borrar los archivos almacenados en caché de las aplicaciones que más hayan superado su cuota asignada. Por lo tanto, si mantienes el volumen de datos almacenados en caché en valores inferiores al de la cuota asignada, tus archivos almacenados en caché estarán entre los últimos del sistema que se borrarán cuando sea necesario. Cuando el sistema determine los archivos almacenados en caché que borrará dentro de tu aplicación, dará prioridad a los archivos más antiguos (la antigüedad se determinará por la fecha y hora de modificación).

También hay dos comportamientos nuevos que puedes habilitar por cada directorio para controlar la manera en que el sistema elimina tus datos almacenados en caché:

  • StorageManager.setCacheBehaviorAtomic() se puede usar para indicar que un directorio y todo su contenido se deben eliminar como una sola unidad atómica.
  • setCacheBehaviorTombstone(File, boolean) se puede usar para indicar que los archivos dentro de un directorio, en lugar de eliminarse, se trunquen hasta una extensión de 0 bytes y que el archivo vacío quede intacto.

Por último, cuando necesites asignar espacio en disco para archivos grandes, ten en cuenta la nueva allocateBytes(FileDescriptor, long) API, que borrará automáticamente los archivos almacenados en caché pertenecientes a otras aplicaciones (según sea necesario) para poder cumplir con tu solicitud. Cuando debas decidir si el dispositivo tiene suficiente espacio en disco para tus nuevos datos, llama a getAllocatableBytes(UUID) en lugar de usar getUsableSpace(), ya que el primero abarcará todos los datos almacenados en caché que el sistema intente borrar por ti.

Paginación de proveedores de contenido

Hemos actualizado proveedores de contenido a fin de incluir compatibilidad con la carga de un conjunto de datos grande, de a una página a la vez. Por ejemplo, una app de fotografía con miles de imágenes puede consultar un subconjunto de los datos que se presentarán en una página. Cada página de resultados que muestra un proveedor de contenido está representada por un único objeto Cursor. Un cliente y un proveedor deben implementar paginación para usar esta función.

Para obtener información detallada sobre los cambios en los proveedores de contenido, consulta ContentProvider y ContentProviderClient.

Solicitudes de actualización de contenido

Ahora, las clases ContentProvider y ContentResolver incluyen un método refresh(), lo cual permite a los clientes saber con más facilidad si la información que solicitan está actualizada.

Puedes agregar lógica de actualización de contenido personalizado extendiendo ContentProvider. Asegúrate de anular el método refresh() para mostrar true, lo cual indicará a los clientes de tu proveedor que tú mismo has intentado actualizar los datos.

La app de tu cliente puede solicitar contenido de manera explícita actualizado llamando a un método diferente, también llamado refresh(). Al llamar a este método, pasa el URI de los datos que se actualizarán.

Nota: Debido a que tal vez solicites datos por una red, debes invocar a refresh() del lado del cliente solo cuando haya un indicio importante de que el contenido ha caducado. El motivo más común para realizar este tipo de actualización de contenido es en respuesta a un gesto de deslizamiento para actualizar, mediante el cual se solicita explícitamente que la IU actual muestre contenido actualizado.

Mejoras de JobScheduler

Android 8.0 presenta varias mejoras para JobScheduler. Estas mejoras permiten que tu app pueda cumplir de manera más sencilla con los nuevos límites de ejecución de segundo plano, ya que generalmente puedes usar trabajos programados para reemplazar los servicios de segundo plano o receptores de transmisiones implícitas ahora restringidos.

Entre las actualizaciones de JobScheduler se incluye lo siguiente:

  • Ahora puedes asociar una cola de trabajo con un trabajo programado. Para agregar un elemento de trabajo a la cola de una tarea, llama a JobScheduler.enqueue(). Cuando la tarea se encuentra en ejecución, puede tomar trabajo pendiente de la cola y procesarlo. Esta funcionabilidad maneja muchos de los casos de uso que previamente hubiesen realizado llamadas para iniciar servicios en segundo plano, en especial aquellos que implementan IntentService.
  • Ahora puedes llamar a JobInfo.Builder.setClipData() para asociar un elemento ClipData con un trabajo. Esta opción te permite asociar otorgamientos de permisos de URI con un trabajo, de manera similar a cómo se pueden propagar estos permisos a Context.startService(). También puedes usar otorgamientos de permisos de URI con intents en colas de trabajo.
  • Los trabajos programados ahora son compatibles con varias restricciones nuevas:
    JobInfo.isRequireStorageNotLow()
    El trabajo no se ejecuta si el almacenamiento disponible del dispositivo es bajo.
    JobInfo.isRequireBatteryNotLow()
    El trabajo no se ejecuta si el nivel de batería está en el límite crítico o en un valor inferior; este es el nivel en el cual se muestra el diálogo de sistema de precaución por batería baja en el dispositivo.
    NETWORK_TYPE_METERED
    La tarea solicita una conexión de red medida, como sucede con la mayoría de los planes de datos móviles.

Almacén de datos personalizados

Android 8.0 te permite proporcionar un almacén de datos personalizados a tus preferencias, lo cual puede resultar útil si tu app almacena las preferencias en una nube o una base de datos local, o si las preferencias son específicas del dispositivo. Para obtener más información sobre la implementación de un almacén de datos, consulta Almacén de datos personalizados.

Cambio de firma de findViewById()

Todas las instancias del método findViewById() ahora muestran <T extends View> T en lugar de View. Este cambio tiene las siguientes implicaciones:

  • Esto puede hacer que el código existente ahora tenga un tipo de valor devuelto ambiguo; por ejemplo, si están someMethod(View) y someMethod(TextView), el resultado de una llamada es findViewById().
  • Si se usa lenguaje fuente Java 8, se requiere una transmisión explícita a View cuando el tipo de valor devuelto no tiene restricciones (por ejemplo, assertNotNull(findViewById(...)).someViewMethod()).
  • El tipo de valor devuelto de las anulaciones de métodos findViewById() que no sean definitivos (por ejemplo, Activity.findViewById()) deberá actualizarse.

Mejoras de medios

VolumeShaper

Hay una clase VolumeShaper nueva. Puedes usarla para realizar breves transiciones de volumen automatizados, como fundido de entrada, fundido de salida y fundido cruzado.

Mejoras de foco de audio

Las apps de audio comparten la salida de audio en un dispositivo solicitando y abandonando el foco del audio. Una app maneja los cambios en el foco iniciando o deteniendo la reproducción, o atenuando su volumen. Hay una clase AudioFocusRequest nueva. Con esta clase, las apps tienen capacidades nuevas al manejar cambios en el foco de audio: atenuación automática y aumento demorado de foco.

Métricas de medios

Un nuevo método getMetrics() muestra un objeto PersistableBundle que contiene información sobre la configuración y el rendimiento, expresada como un mapa de atributos y valores. El método getMetrics() se define para estas clases de medios:

Las métricas se recopilan de forma separada para cada instancia y persisten mientras dure la instancia. Si no hay métricas disponibles, el método muestra el valor null. Las métricas reales que se muestran dependen de la clase.

MediaPlayer

En Android 8.0 se agregan varios métodos nuevos para la clase MediaPlayer. Estos métodos pueden mejorar la manera en la que tu app controla la reproducción multimedia de diferentes maneras:

MediaPlayer ahora admite encriptación al mismo nivel.

MediaRecorder

  • MediaRecorder ahora admite el formato MPEG2_TS, que es útil para realizar transmisiones:
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);

    consulta MediaRecorder.OutputFormat.

  • MediaMuxer ahora puede controlar cualquier cantidad de transmisiones de audio y video. Ya no estás limitado a una pista de audio o una pista de video. Usa addTrack() para mezclar tantas pistas como desees.
  • MediaMuxer también puede agregar una o más pistas de metadatos con información por fotograma definida por el usuario. Tu aplicación es la que define el formato de los metadatos. La pista de metadatos solo es compatible con contenedores MP4.

Los metadatos pueden ser útiles para el procesamiento sin conexión. Por ejemplo, las señales giroscópicas del sensor podrían usarse para la estabilización de video.

Al agregar una pista de metadatos, el formato mime de la pista debe comenzar con el prefijo "application/". Escribir metadatos es lo mismo que escribir datos de audio y video, con la excepción de que los datos no provienen de un MediaCodec. En su lugar, la aplicación pasa un ByteBuffer con una marca de tiempo asociada al método writeSampleData(). La marca de tiempo debe encontrarse en la misma base de tiempo que las pistas de audio y video.

El archivo MP4 que se genera usa el TextMetaDataSampleEntry definido en la sección 12.3.3.2 de ISOBMFF para indicar el formato MIME de los metadatos. Cuando se usa MediaExtractor para extraer el archivo con pista de metadatos, el formato MIME de los metadatos se extrae en MediaFormat.

Control de reproducción de audio

Android 8.0 te permite realizar solicitudes y consultas relacionadas con la producción de sonido de un dispositivo. Los siguientes aspectos de control sobre la reproducción del audio hacen que sea más sencillo para tu servicio producir sonido solo cuando las condiciones del dispositivo son favorables.

Tipo de uso de audio nuevo para el Asistente de Google

La clase AudioAttributes tiene un tipo de sonido nuevo, USAGE_ASSISTANT, que corresponde a las respuestas que el Asistente de Google proporciona en un dispositivo.

Cambios en la reproducción de audio del dispositivo

Si deseas que tu servicio comience a producir sonido solo cuando se encuentre activa una configuración específica de audio del dispositivo, puedes usar la clase AudioManager para registrar una instancia de AudioManager.AudioPlaybackCallback, cuyo método onPlaybackConfigChanged() te ayuda a identificar el conjunto de atributos de audio actualmente activo.

Solicitudes explícitas de foco de audio

Tu servicio puede enviar una solicitud más precisa para recibir foco de audio en todo el dispositivo usando el método requestAudioFocus(). Pasa un objeto AudioFocusRequest, que se crea usando AudioFocusRequest.Builder. En esta clase de generador, puedes especificar las siguientes opciones:

  • El tipo de foco que deseas obtener, como AUDIOFOCUS_GAIN_TRANSIENT o AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.
  • Si tu servicio debe continuar con menor volumen o pausarse por completo cuando otro servicio de audio reciba el foco del dispositivo.
  • Si tu servicio puede esperar a obtener foco hasta que el dispositivo esté listo.

Nota: Cuando compiles tu instancia de AudioFocusRequest, si indicas que tu servicio puede esperar para producir un sonido llamando a setAcceptsDelayedFocusGain(), también deberás llamar a setOnAudioFocusChangeListener() para que tu servicio determine el momento en que pueda comenzar a producir sonido.

Acceso mejorado a archivos multimedia

El marco de trabajo de acceso a almacenamiento (SAF) permite que las apps expongan un DocumentsProvider personalizado, que puede proporcionar a otras apps acceso a archivos en una fuente de datos. De hecho, un proveedor de documentos incluso puede proporcionar acceso a archivos almacenados en la red o que usan un protocolo como el protocolo de transferencia multimedia (MTP).

No obstante, el acceso a archivos multimedia de gran tamaño desde una fuente de datos remota presenta algunos desafíos:

  • Los reproductores multimedia requieren acceso que admita búsquedas para un archivo a través de un proveedor de documentos. Cuando un archivo multimedia de gran tamaño se encuentre en una fuente de datos remota, el proveedor de documentos deberá obtener todos los datos por adelantado y crear un descriptor de archivo de resumen. El reproductor multimedia no puede reproducir el archivo sin el descriptor de archivo, por lo que la reproducción no comenzará hasta que el proveedor de documentos termine de descargar el archivo.
  • Los administradores de colecciones multimedia, como las apps de fotos, deben atravesar una serie de URI de acceso para alcanzar los medios almacenados en una tarjeta SD externa a través de carpetas determinadas. Este patrón de acceso hace que las operaciones masivas con medios (como el movimiento, la copia y la eliminación) se vuelvan bastante lentas.
  • Los administradores de colecciones multimedia no pueden determinar la ubicación de un documento según su URI. Esto hace que para estos tipos de apps resulte más difícil permitir que los usuarios elijan la ubicación en la que guardarán un archivo multimedia.

Android 8.0 direcciona cada uno de estos desafíos mejorando el marco de trabajo de acceso a almacenamiento.

Proveedores de documentos personalizados

A partir de Android 8.0, el marco de trabajo de acceso a almacenamiento permite a los proveedores de documentos personalizados crear descriptores de archivos que admitan búsquedas para archivos que residan en una fuente de datos remota. El SAF puede abrir un archivo para obtener un descriptor de archivos que admitan búsquedas. Luego, el SAF proporciona solicitudes de bytes discretas al proveedor de documentos. Esta función permite a un proveedor de documentos mostrar el rango de bytes exacto que una aplicación de reproducción multimedia solicita, en lugar de almacenar en caché el archivo completo por adelantado.

Para usar esta función, debes llamar al nuevo método StorageManager.openProxyFileDescriptor(). El método openProxyFileDescriptor() acepta un objeto ProxyFileDescriptorCallback como callback. El SAF invoca el callback cuando una aplicación cliente realiza operaciones relacionadas con archivos en el descriptor de archivos que muestra el proveedor de documentos.

Acceso directo a documentos

A partir de Android 8.0, puedes usar el método getDocumentUri() para obtener un URI que haga referencia al mismo documento que el del mediaUri determinado. Sin embargo, debido a que el URI que se muestra está respaldado por un DocumentsProvider, los administradores de la colecciones multimedia pueden acceder al documento directamente, sin tener que explorar árboles de directorios determinados. Como resultado, los administradores de medios pueden realizar operaciones relacionadas con archivos en el documento de manera considerablemente más rápida.

Advertencia: El método getDocumentUri() solo localiza archivos multimedia; no otorga a las apps permiso para acceder a esos archivos. Para obtener más información sobre cómo conseguir un permiso para acceder a los archivos multimedia, consulta la documentación de referencia.

Rutas de acceso a los documentos

Al usar el marco de trabajo de acceso a almacenamiento en Android 8.0, puedes emplear el método findDocumentPath() disponible en las clases DocumentsContract y DocumentsProvider para determinar la ruta de acceso desde la raíz de un sistema de archivos con el ID de un documento. El método muestra esta ruta de acceso en un objeto DocumentsContract.Path. En los casos en que un sistema de archivos tenga varias rutas de acceso definidas para el mismo documento, el método mostrará la ruta de acceso que se use con mayor frecuencia para alcanzar el documento con el ID determinado.

Esta funcionalidad es especialmente útil en las siguientes situaciones:

  • Tu app usa un diálogo “Guardar como” en el que se muestra la ubicación de un documento en particular.
  • Tu app muestra carpetas en una vista con resultados de búsqueda y debe cargar los documentos secundarios que se encuentran dentro de una carpeta especial si el usuario la selecciona.

Nota: Si tu app tiene permiso para acceder solo a algunos de los documentos de la ruta de acceso, el valor de findDocumentPath() que se muestra solo incluye las carpetas y los documentos a los que tu app puede acceder.

Conectividad

Reconocimiento de Wi-Fi

En Android 8.0, se incorpora compatibilidad con el reconocimiento de Wi-Fi, que se basa en la especificación Neighbor Awareness Networking (NAN). Los dispositivos que cuenten con el hardware de reconocimiento de Wi-Fi adecuado, las aplicaciones y los dispositivos cercanos pueden realizar detecciones y establecer comunicaciones a través de Wi-Fi sin un punto de acceso por Internet. Estamos trabajando con nuestros socios de hardware para integrar la tecnología de reconocimiento de Wi-Fi a los dispositivos lo antes posible. Para obtener información sobre cómo integrar el reconocimiento de Wi-Fi a tu app, consulta Reconocimiento de Wi-Fi.

Bluetooth

En Android 8.0, se amplía la compatibilidad con Bluetooth de la plataforma mediante la adición de las siguientes funciones:

  • Compatibilidad con AVRCP 1.4 estándar, lo que permite explorar la biblioteca de canciones.
  • Compatibilidad con Bluetooth Low-Energy (BLE) 5.0 estándar.
  • Integración del códec de Sony LDAC a la pila Bluetooth.

Sincronización de dispositivos complementarios

Android 8.0 proporciona las API que te permiten personalizar el diálogo de solicitud de sincronización al intentar realizar la sincronización con dispositivos complementarios a través de Bluetooth, BLE y Wi-Fi. Para obtener más información, consulta la Sincronización de dispositivos complementarios.

Para obtener información sobre el uso de Bluetooth en Android, consulta la guía de Bluetooth. Si deseas información sobre los cambios de Bluetooth específicos para Android 8.0, consulta la sección Bluetooth de la página Cambios de comportamiento de Android 8.0.

Uso compartido

Uso compartido inteligente

Android 8.0 incorpora las preferencias compartidas y personalizadas de los usuarios y determina mejor cuáles son las apps correctas con las que deben compartirse elementos según cada tipo de contenido. Por ejemplo, si un usuario toma una foto de un recibo, Android 8.0 puede sugerir una app de seguimiento de gastos- Si el usuario se toma una selfie, una app de redes sociales puede manejar mejor la imagen. Android 8.0 automáticamente incorpora todos estos patrones según las preferencias personalizadas de los usuarios.

El uso compartido inteligente funciona para tipos de contenido que no sean image; por ejemplo, audio, video, text y URL, entre otros.

Para habilitar el uso compartido inteligente, agrega una ArrayList de hasta tres anotaciones en cadena para la intent que comparte el contenido. Las anotaciones deben describir los componentes o temas principales en el contenido. En el siguiente ejemplo de código se muestra la forma de agregar anotaciones a la intent:

ArrayList<String> annotations = new ArrayList<>();

annotations.add("topic1");
annotations.add("topic2");
annotations.add("topic3");

intent.putStringArrayListExtra(
    Intent.EXTRA_CONTENT_ANNOTATIONS,
    annotations
);

Para obtener información detallada sobre las anotaciones de uso compartido inteligente, consulta EXTRA_CONTENT_ANNOTATIONS.

Selección de texto inteligente

En dispositivos compatibles, Android 8.0 habilita a las apps para que ayuden a los usuarios a interactuar con el texto de maneras más significativas. Cuando los usuarios presionan de manera prolongada una palabra en una entidad (un formato reconocido, como una dirección o el nombre de un restaurant), el sistema selecciona toda la entidad. El usuario ve una barra de herramientas flotante que indica una app que puede manejar la entidad de texto seleccionada. Por ejemplo, si el sistema reconoce una dirección, puede dirigir al usuario hacia la app de Maps.

La entidades reconocidas por el sistema incluyen direcciones, URL, números de teléfono y direcciones de correo electrónico. Para obtener más información, consulta TextClassifier.

Accesibilidad

Android 8.0 admite las siguientes funciones de accesibilidad para los desarrolladores que creen sus propios servicios de accesibilidad. Para obtener más información sobre cómo hacer que tu app sea más accesible, consulta Accesibilidad.

Botón de accesibilidad

Con tu servicio de accesibilidad, ahora se puede solicitar que aparezca un botón de accesibilidad dentro del área de navegación del sistema. Esto ofrece a los usuarios un método rápido para activar la funcionalidad de tu servicio desde cualquier espacio en sus dispositivos. Para ello, agrega el indicador FLAG_REQUEST_ACCESSIBILITY_BUTTON en el atributo android:accessibilityFlags de un objeto AccessibilityServiceInfo. Luego puedes registrar callbacks usando registerAccessibilityButtonCallback().

Nota: Esta función está disponible solo en dispositivos que proporcionan un área de navegación representada mediante software. Usa siempre isAccessibilityButtonAvailable() y responde a los cambios según la disponibilidad del botón de accesibilidad implementando onAvailabilityChanged(). De esa manera, los usuarios siempre podrán acceder a la funcionabilidad de tu servicio, incluso si el botón de accesibilidad no es compatible o deja de estar disponible.

Ajuste de volumen independiente

En Android 8.0 se presenta la categoría de volumen STREAM_ACCESSIBILITY, que te permite controlar el volumen de salida de audio de tu servicio de accesibilidad independientemente de los demás sonidos del dispositivo.

Si deseas usar este nuevo tipo de transmisión para controlar el volumen de accesibilidad, configura la opción FLAG_ENABLE_ACCESSIBILITY_VOLUME dentro de tu servicio de accesibilidad. Luego puedes cambiar el volumen del audio de accesibilidad del dispositivo usando adjustStreamVolume().

Gestos de huella digital

Tu servicio de accesibilidad también puede responder a un mecanismo de interacción alternativo, los deslizamientos direccionales (arriba, abajo, izquierda, derecha) en un sensor de huellas digitales del dispositivo. Para recibir callbacks sobre estas interacciones, completa la siguiente secuencia de pasos:

  1. Declara el permiso USE_FINGERPRINT y la capacidad CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES.
  2. Configura el indicador FLAG_REQUEST_FINGERPRINT_GESTURES en el atributo android:accessibilityFlags.
  3. Regístrate para recibir callbacks usando registerFingerprintGestureCallback().

Recuerda que no todos los dispositivos incluyen sensores de huellas digitales. Puedes usar el método isHardwareDetected() para determinar si un dispositivo admite el sensor. Incluso en dispositivos que incluyen un sensor de huellas digitales, tu servicio puede usar el sensor solo cuando no esté en uso para fines de autenticación. Para determinar el momento en que el sensor está disponible, llama al método isGestureDetectionAvailable() e implementa el callback onGestureDetectionAvailabilityChanged().

Resalte de primer nivel

Para determinar las ubicaciones de caracteres visibles en un objeto TextView, puedes pasar EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY como el primer argumento a refreshWithExtraData(). Luego se carga un objeto Bundle, que proporcionas como segundo argumento para refreshWithExtraData(), a fin de incluir una matriz de objetos Rect. Cada objeto Rect representa el cuadro delimitador de un carácter específico.

Si tu servicio usa un objeto TextToSpeech para establecer el contenido que aparece en pantalla, puedes obtener información de sincronización más precisa sobre el momento en que los motores de texto a voz comienzan a articular palabras individuales sintetizadas, siempre que el motor de texto a voz proporcione esta información. Cuando se prevé que un motor comienza a reproducir audio para un rango específico de texto, la API de texto a voz notifica a tu servicio que la voz para el rango de texto comienza a usar el método onRangeStart().

Si creas tu propia implementación de TextToSpeechService, puedes admitir esta nueva funcionalidad usando el método rangeStart().

Valores de rango unilaterales estandarizados

Algunas instancias de AccessibilityNodeInfo usan una instancia de AccessibilityNodeInfo.RangeInfo para indicar que un elemento de IU puede tomar un rango de valores. Al crear un rango usando RangeInfo.obtain(), o al recuperar los valores extremos del rango usando getMin() y getMax(), considera que Android 8.0 cuenta con definiciones estandarizadas de rangos unilaterales:

Texto indicado

En Android 8.0 se incluyen varios métodos para interactuar con el texto indicado de un objeto de texto editable.

  • Los métodos isShowingHintText() y setShowingHintText() indican y determinan, respectivamente, si el contenido del texto actual del nodo representa el texto indicado de este. Si el nodo no contiene texto editable, nunca debe contener texto indicado.
  • Para acceder al texto indicado, usa getHintText(). Aun cuando un objeto no muestre texto indicado, una llamada a getHintText() se realizará correctamente.

Distribución continua de gestos

Tu servicio ahora puede especificar secuencias de trazos que pertenecen al mismo gesto programático usando el argumento final, willContinue, en el constructor GestureDescription.StrokeDescription.

Seguridad y privacidad

Permisos

Android 8.0 presenta varios permisos nuevos relacionados con la telefonía:

  • El permiso ANSWER_PHONE_CALLS permite a tu app responder llamadas telefónicas entrantes mediante programación. Para controlar una llamada telefónica entrante en tu app, puedes usar el método acceptRingingCall().
  • El permiso READ_PHONE_NUMBERS otorga a tu app acceso de lectura a los números telefónicos almacenados en un dispositivo.

Estos permisos se clasifican como peligrosos y son parte del grupo de permisos PHONE.

Acceso a la cuenta nueva y las API de detección

Android 8.0 presenta varias mejoras respecto de la forma en que las apps obtienen acceso a las cuentas de los usuarios. Para las cuentas que controlan, los autenticadores pueden usar su propia política a fin de decidir si ocultan o muestran cuentas a una aplicación. El sistema Android rastrea las aplicaciones que pueden acceder a una cuenta específica.

En las versiones previas de Android, las aplicaciones que intentaban rastrear la lista de cuentas de usuarios debían obtener actualizaciones de todas las cuentas, incluidas las cuentas con tipos no relacionados. Android 8.0 agrega el método addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]), el cual permite que en las aplicaciones se especifique una lista de tipos de cuentas para las cuales deben recibirse cambios de cuentas.

Cambios en las API

AccountManager proporciona seis métodos nuevos para que los autenticadores administren las apps que pueden detectar una cuenta:

Android 8.0 presenta dos valores de nombre de paquete especiales a fin de especificar los niveles de visibilidad para aplicaciones que no se configuraron con el método setAccountVisibility(android.accounts.Account, java.lang.String, int). El valor de visibilidad PACKAGE_NAME_KEY_LEGACY_VISIBLE se emplea en las aplicaciones que tienen el permiso GET_ACCOUNTS, y versiones de destino de Android anteriores a Android 8.0, o cuyas firmas coincidan con el autenticador de cualquier versión de Android. PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE proporciona un valor de visibilidad predeterminado para aplicaciones que no configuran previamente y para las que no se aplica PACKAGE_NAME_KEY_LEGACY_VISIBLE.

Para obtener más información sobre las nuevas API de acceso y detección de cuentas, consulta la referencia de AccountManager y OnAccountsUpdateListener.

API para Navegación Segura de Google

La clase WebView ahora incluye una API para Navegación Segura a fin de mejorar la seguridad de la navegación web. Para obtener más información, consulta API para Navegación Segura de Google.

Prueba

Pruebas de instrumentación

Android 8.0 proporciona los siguientes elementos de compatibilidad adicional para las pruebas de instrumentación de tu app.

Ejecución en procesos de apps no predeterminadas

Ahora puedes especificar que una prueba de instrumentación particular se debe ejecutar en un proceso fuera del proceso predeterminado de tu app. Esta configuración es útil si tu app contiene varias actividades que se ejecuten en procesos diferentes.

Para definir la instrumentación de un proceso no predeterminado, navega hacia tu archivo de manifiesto y luego hacia el elemento <instrumentation> deseado. Agrega el atributo android:targetProcess y fija su valor en una de las siguientes alternativas:

  • el nombre de un proceso en particular;
  • una lista de nombres de procesos separados por comas;
  • un comodín ("*"), que permite ejecutar la instrumentación en cualquier proceso lanzado que ejecute código en el paquete especificado en el atributo android:targetPackage.

Mientras tu prueba de instrumentación se encuentre en ejecución, podrás verificar el proceso sometido a prueba por esta llamando getProcessName().

Informar resultados durante una prueba

Ahora puedes informar resultados durante tu prueba de instrumentación, en lugar de hacerlo cuando finalice, llamando addResults().

Intents falsos para pruebas

Para facilitar la creación de pruebas de IU independientes y aisladas para las actividades de tu app, Android 8.0 presenta el método onStartActivity(). Este método se anula en una subclase personalizada de la clase Instrumentation.ActivityMonitor para manejar una intent en especial que tu clase de prueba invoca.

Cuando tu clase de prueba invoca la intent, el método muestra un objeto auxiliar Instrumentation.ActivityResult en lugar de ejecutar la intent. Al usar esta lógica de intents falsas en tus pruebas, puedes focalizarte en el modo en que tu actividad prepara y maneja la intent que pasas a una actividad diferente o a una app totalmente diferente.

Tiempo de ejecución y herramientas

Optimizaciones de plataforma

Android 8.0 incorpora a la plataforma optimizaciones de tiempo de ejecución y de otros aspectos que dan como resultado varias mejoras del rendimiento. Entre estas optimizaciones se incluyen la recolección de elementos no usados de compactación simultánea, un uso más eficiente de la memoria y la ubicación de código.

Estas optimizaciones reducen los tiempos de inicio y mejoran el rendimiento del SO y de las apps.

Compatibilidad Java actualizada

En Android 8.0, se agrega compatibilidad con varias OpenJDK Java API adicionales:

Para obtener más información sobre las clases y los métodos que contienen estos paquetes recientemente agregados, consulta la documentación de referencia de la API.

Si deseas usar las funciones del lenguaje Java 8 en Android Studio, debes descargar la última versión preliminar.

API actualizadas del marco de trabajo ICU4J de Android

Android 8.0 extiende las ICU4J Android Framework API, un subconjunto de las API de ICU4J, para que los desarrolladores de apps lo usen en el paquete android.icu. Estas API usan datos de ubicación que están presentes en el dispositivo, para que puedas reducir la superficie de APK sin compilar las bibliotecas ICU4J en el APK.

Tabla 1: Versiones ICU, CLDR y Unicode usadas en Android.

Nivel de Android API Versión de ICU Versión de CLDR Versión Unicode
Android 7.0 (nivel de API 24), Android 7.1 (nivel de API 25) 56 28 8.0
Android 8.0 58.2 30.0.3 9.0
Si deseas obtener más información sobre las actualizaciones de las ICU4J API admitidas, lee las notas de la versión.

Android para empresas

Se han presentado las nuevas funciones y API empresariales para dispositivos con Android 8.0. Entre los aspectos destacados, se incluyen los siguientes:

  • Los perfiles de trabajo en dispositivos completamente administrados permiten a las empresas separar los datos de trabajo de los personales y administrar ambos.
  • La delegación de API permite a los propietarios de dispositivos y perfiles asignar la administración de apps a otras aplicaciones.
  • Las mejoras en la experiencia del usuario en el flujo de aprovisionamiento (incluso opciones nuevas de personalización) reducen el tiempo de configuración.
  • Los controles nuevos sobre los sistemas Bluetooth y de Wi-Fi, las copias de seguridad y la seguridad permiten a las empresas administrar más aspectos el dispositivo. El registro de actividad de red ayuda a las empresas a realizar un seguimiento de los problemas.

Para obtener más información sobre estas y otras API y funciones empresariales nuevas de Android, consulta Android en la empresa.