Características y API de Android 8.0

Android 8.0 (nivel de API 26) presenta una variedad de funciones y capacidades nuevas para usuarios y desarrolladores. En este documento, se destacan las novedades para desarrolladores.

Asegúrate de consultar también los cambios de comportamiento en Android 8.0 para obtener información sobre las áreas en las que los cambios de la plataforma podrían afectar tus apps.

Experiencia del usuario

Modo de imagen en imagen

Pantalla en pantalla en Android 8.0.

Android 8.0 (nivel de API 26) permite iniciar actividades en el modo de pantalla en pantalla (PIP). PIP es un tipo especial de modo multiventana que se usa principalmente para la reproducción de videos. Originalmente, el modo de PIP solo estaba disponible para Android TV. Android 8.0 hace que la función esté disponible en otros dispositivos Android.

Cuando una actividad se encuentra en modo de PIP, se encuentra en estado de pausa, pero debería seguir mostrando contenido. Por este motivo, debes asegurarte de que tu app no pause la reproducción en su controlador onPause(). En cambio, 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 multiventana.

Para especificar que tu actividad puede usar el modo de PIP, establece android:supportsPictureInPicture en verdadero en el manifiesto. (A partir de Android 8.0, PIP no requiere el atributo del manifiesto android:resizeableActivity. Sin embargo, debes establecer android:resizeableActivity como "true" si tu actividad admite otros modos multiventana).

Android 8.0 (nivel de API 26) presenta un objeto nuevo, PictureInPictureParams, que pasas a métodos de PIP para especificar cómo debe comportarse una actividad cuando está en modo de PIP. Este objeto especifica propiedades, como la relación de aspecto preferida de la actividad.

Los métodos de PIP existentes que se describen en Cómo agregar pantalla en pantalla 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 de PIP:

  • Activity.enterPictureInPictureMode(PictureInPictureParams args): Coloca la actividad en el modo de pantalla en pantalla. args especifica la relación de aspecto y otros parámetros de configuración de la actividad. Si algún campo de args está vacío, el sistema usa los valores establecidos la última vez que llamaste a Activity.setPictureInPictureParams().

    La actividad especificada se coloca en una esquina de la pantalla; el resto de esta se llena con la actividad anterior que estaba en pantalla. La actividad que ingresa al modo de PIP entra en estado de pausa, pero permanece iniciada. Si el usuario presiona la actividad de PIP, el sistema muestra un menú con el que el usuario puede interactuar; ningún evento táctil alcanza la actividad mientras se encuentra en estado de PIP.

  • Activity.setPictureInPictureParams(): Actualiza los parámetros de configuración de PIP de una actividad. Si la actividad se encuentra actualmente en modo de PIP, se actualiza la configuración. Esto es útil si cambia la relación de aspecto de la actividad. Si la actividad no está en modo de PIP, se usan estos parámetros de configuración independientemente del método enterPictureInPictureMode() que llames.

Notificaciones

En Android 8.0 (nivel de API 26), rediseñamos las notificaciones para proporcionar una manera más fácil y coherente de administrar la configuración y el comportamiento de las notificaciones. Entre estos cambios, se incluyen los siguientes:

    Un menú de notificaciones de presión prolongada en Android 8.0 (nivel de API 26)

    Los usuarios pueden mantener presionados los íconos de selector de apps para ver las notificaciones en Android 8.0.

  • Canales de notificaciones: Android 8.0 presenta canales de notificaciones 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 notificaciones. Para obtener información sobre cómo implementar canales de notificaciones, consulta Cómo administrar canales de notificaciones.
  • Puntos de notificación: Android 8.0 admite la visualización de puntos o insignias en los íconos de selector de apps. Los puntos de notificación reflejan la presencia de notificaciones que el usuario aún no descartó ni actuó. Para obtener información sobre cómo trabajar con los puntos de notificación, consulta Insignias de notificaciones.
  • Posponer: Los usuarios pueden posponer las notificaciones, lo que hace que desaparezcan durante un tiempo antes de volver a aparecer. Las notificaciones vuelven a aparecer 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: Puedes configurar un tiempo de espera cuando creas una notificación con setTimeoutAfter(). Puedes usar este método para especificar la duración después de la 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 configurar el texto que aparece cuando creas un vínculo a la configuración de notificaciones de tu app desde una notificación que usa el intent Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES. El sistema puede proporcionar los siguientes extras 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: Los usuarios pueden descartar las notificaciones por su cuenta y las apps pueden quitarlas de manera programática. Para determinar cuándo y por qué se descarta una notificación, implementa el método onNotificationRemoved() de la clase NotificationListenerService.
  • Colores de fondo: Puedes establecer y habilitar un color de fondo para una notificación. Solo debes usar esta función en las notificaciones de las tareas en curso que son fundamentales para que el usuario las vea de un vistazo. Por ejemplo, puedes establecer un color de fondo para las notificaciones relacionadas con la ruta en auto o una llamada telefónica en curso. También puedes establecer el color de fondo que quieras con setColor(). Hacerlo te permite usar setColorized() para habilitar el uso de un color de fondo para una notificación.
  • Estilo del mensaje: En Android 8.0, las notificaciones que usan la clase MessagingStyle muestran más contenido en su forma contraída. Debes usar la clase MessagingStyle para las notificaciones relacionadas con la mensajería. También puedes usar el método addHistoricMessage() para proporcionar contexto a una conversación agregando mensajes históricos a las notificaciones relacionadas con los mensajes.

Autofill Framework

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

Android 8.0 (nivel de API 26) facilita la tarea de completar formularios, como los de acceso o tarjetas de crédito, gracias a la introducción de Autofill Framework. Las apps existentes y nuevas funcionan con Autofill Framework después de que el usuario habilita 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 Descripción general de Autofill Framework.

Fuentes descargables

Android 8.0 (nivel de API 26) y la biblioteca de compatibilidad de Android 26 te permiten solicitar fuentes de una aplicación de proveedor en lugar de agrupar fuentes en el APK o permitir que este las descargue. Esta función reduce el tamaño del APK, aumenta la tasa 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 (nivel de API 26) presenta una nueva función, fuentes en XML, que te permite usar las fuentes como recursos. Esto significa que no es necesario agrupar las fuentes como recursos. Las fuentes se compilan en un archivo R y están disponibles automáticamente en el sistema como recurso. Luego, puedes acceder a ellas con la ayuda de un nuevo tipo de recurso, font.

La biblioteca de compatibilidad 26 proporciona compatibilidad total con esta función en dispositivos que ejecutan la versión 14 de la API y versiones posteriores.

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

Ajuste automático de tamaño de TextView

Android 8.0 (nivel de API 26) te permite establecer el tamaño de expansión o contracción del texto automáticamente según el tamaño de TextView. Esto significa que es mucho más fácil optimizar el tamaño del 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 (nivel de API 26) presenta íconos de selector adaptables. Los íconos adaptables admiten efectos visuales y pueden mostrar diferentes formas en los distintos modelos de dispositivos. Para obtener información sobre cómo crear íconos adaptables, consulta la guía Íconos adaptables.

Administración de color

Los desarrolladores de apps de imagen para Android ahora pueden aprovechar los nuevos dispositivos que tienen una pantalla compatible con una amplia gama de colores. Para mostrar imágenes de un gamut amplio, las apps deberán habilitar una marca en su manifiesto (por actividad) y cargar mapas de bits con un perfil amplio de colores incorporado (AdobeRGB, Pro Photo RGB, DCI-P3, etcétera).

WebView API

Android 8.0 proporciona varias API para ayudarte a administrar los objetos WebView que muestran contenido web en tu app. Entre estas API, que mejoran la estabilidad y seguridad de la app, se incluye lo siguiente:

  • API de versión
  • Google SafeBrowsing API
  • Termination Handle API
  • API de Renderer Importance

Para obtener más información sobre cómo usar estas APIs, consulta Cómo administrar WebViews.

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

Fijación de combinaciones de teclas y widgets

Android 8.0 (API nivel 26) presenta la fijación de accesos directos y widgets en la app. En tu app, puedes crear accesos directos fijos y widgets para los selectores admitidos, según lo permita el usuario.

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

Relación de aspecto máxima de la pantalla

Android 8.0 (nivel de API 26) presenta cambios sobre la configuración de la relación de aspecto máxima de una app.

En primer lugar, Android 8.0 presenta el atributo maxAspectRatio, que puedes usar para configurar la relación de aspecto máxima de tu app. Además, en Android 8.0 y versiones posteriores, la relación de aspecto máxima predeterminada de una app es la relación de aspecto nativa del dispositivo en el que se ejecuta la app.

Para obtener más información sobre cómo declarar la relación de aspecto máxima, consulta Compatibilidad con diferentes pantallas.

Compatibilidad con pantallas múltiples

A partir de Android 8.0 (nivel de API 26), la plataforma ofrece compatibilidad mejorada con varias pantallas. Si una actividad admite el modo multiventana y se ejecuta en un dispositivo con varias pantallas, los usuarios pueden mover la actividad de una pantalla a otra. Cuando una app inicia una actividad, puede especificar en qué pantalla se debe ejecutar.

Nota: Si una actividad admite el modo multiventana, Android 8.0 habilita automáticamente la compatibilidad con pantallas múltiples para esa actividad. Debes probar tu app para asegurarte de que funcione de manera adecuada en un entorno de varias pantallas.

Solo puede haber una actividad a la vez en el estado de reanudación, incluso si la app tiene varias pantallas. La actividad enfocada se encuentra en 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 multiventana.

Cuando un usuario mueve una actividad de una pantalla a otra, el sistema modifica el tamaño de la actividad y emite cambios en el tiempo de ejecución según sea necesario. Tu actividad puede controlar 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 Cómo controlar los cambios de configuración.

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

setLaunchDisplayId()
Especifica en qué pantalla debe mostrarse la actividad cuando se inicia.
getLaunchDisplayId()
Muestra la pantalla de inicio actual de la actividad.

El shell de abd se extiende para admitir varias pantallas. Ahora se puede usar el comando shell start para iniciar una actividad y especificar la visualización de destino de esta:

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

Márgenes y relleno con diseño unificado

Android 8.0 (nivel de API 26) facilita la especificación de situaciones en las que los lados opuestos de un elemento View usan el mismo margen o padding. Específicamente, ahora puedes usar los siguientes atributos en tus archivos en formato XML de diseño:

Nota: Si personalizas la lógica de tu app para admitir diferentes idiomas y culturas, incluida la direcció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 por tu cuenta, además de los nuevos atributos de diseño vertical y horizontal, para crear un comportamiento de diseño que dependa de la dirección del texto.

Captura de puntero

Algunas apps, como las de juegos, escritorio remoto y clientes de virtualización, se benefician mucho de tener el control del puntero del mouse. La captura de puntero es una función nueva de Android 8.0 (nivel de API 26) que proporciona ese control entregando todos los eventos del mouse en una vista enfocada de tu app.

A partir de Android 8.0, un View de tu app puede solicitar la captura de puntero y definir un objeto de escucha para procesar los eventos de puntero capturados. En este modo, el puntero del mouse está oculto. La vista puede liberar la captura del puntero cuando ya no necesita la información del mouse. El sistema también puede liberar la captura del puntero cuando la vista pierde el enfoque, por ejemplo, cuando el usuario abre otra app.

Si quieres obtener información para usar esta función en tu app, consulta Captura de puntero.

Categorías de apps

Android 8.0 (nivel de API 26) permite que cada app declare una categoría a la que pertenezca, cuando corresponda. Estas categorías se usan para agrupar apps con propósitos o funciones similares cuando se presentan a los usuarios, como 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 de manifiesto <application>.

Lanzador de Android TV

Android 8.0 (nivel de API 26) incluye una nueva experiencia de pantalla principal de Android TV centrada en el contenido, que está disponible con el emulador de Android TV y la imagen del dispositivo Nexus Player para Android 8.0. En la nueva pantalla principal, se organiza el contenido de video en filas correspondientes a canales, que una app del sistema completa con programas. Las apps pueden publicar varios canales, y los usuarios pueden configurar los canales que deseen ver en la pantalla principal. La pantalla principal de Android TV también incluye una fila Ver a continuación, que se propaga con los programas de las apps según los hábitos de visualización del usuario. Las apps también pueden proporcionar vistas previas de video, que se reproducen automáticamente cuando un usuario se enfoca en un programa. Las APIs para propagar canales y programas forman parte de las APIs de TvProvider, que se distribuyen como un módulo de la biblioteca de compatibilidad de Android con Android 8.0.

AnimatorSet

A partir de Android 8.0 (nivel de API 26), la API de AnimatorSet ahora admite la búsqueda y el juego inverso. La búsqueda te permite establecer la posición de la animación establecida en un momento específico. La reproducción en sentido inverso es útil si tu app incluye animaciones para acciones que se pueden deshacer. En lugar de definir dos conjuntos de animaciones separados, puedes reproducir el mismo en sentido inverso.

Entrada y navegación

Clústeres de navegación con teclado

Si una actividad de tu app usa una jerarquía de vistas compleja, como la de la Figura 2, procura organizar grupos de elementos de la IU en clústeres para facilitar la navegación con teclado entre ellos. 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 incluyen los paneles laterales, las barras de navegación, las áreas de contenido principal y los elementos que pueden contener muchos elementos secundarios.

Actividad de ejemplo que incluye cinco clústeres de navegación que el usuario puede navegar con la combinación de teclas para clústeres de navegación con teclado. Los clústeres 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 convertir un elemento View o ViewGroup en un clúster, configura el atributo android:keyboardNavigationCluster como true en el archivo en formato XML de diseño del elemento o pasa true a setKeyboardNavigationCluster() en la lógica de la IU de tu app.

Nota: Los clústeres no se pueden anidar, aunque los clústeres no anidados pueden aparecer en diferentes niveles de la jerarquía. Si intentas anidar clústeres, el framework solo tratará el elemento ViewGroup superior como un clúster.

En los dispositivos que tienen pantallas táctiles, puedes establecer el elemento android:touchscreenBlocksFocus de un objeto ViewGroup designado por el clúster en true para permitir la navegación solo dentro y fuera de ese clúster. Si aplicas esta configuración a un clúster, los usuarios no podrán usar la tecla Tab ni las teclas de flecha para navegar dentro o fuera del clúster. En su lugar, deberán presionar la combinación de teclado de navegación del clúster.

Foco predeterminado de las vistas

En Android 8.0 (nivel de API 26), puedes asignar el View que debería recibir el foco después de que se reanude una actividad (re)creada y el usuario presione una tecla de navegación del teclado, como la tecla Tab. Para aplicar este parámetro de configuración "enfocado de forma predeterminada", configura el atributo android:focusedByDefault de un elemento View como true en el archivo en formato XML de diseño que contiene el elemento de la IU o pasa true a setFocusedByDefault() en la lógica de la IU de tu app.

Salida de voz

Las actividades y los servicios pueden usar instancias de TextToSpeech para dictar y pronunciar el contenido. A partir de Android 8.0 (nivel de API 26), tu app puede obtener información de sincronización más precisa sobre el momento en que un motor de texto a voz comienza a pronunciar palabras individuales sintetizadas, siempre que el motor proporcione esta información. Puedes usar esta funcionalidad para llamar la atención sobre palabras específicas a medida que el motor de texto a voz las pronuncia.

Para usar estas mejoras del motor de texto a voz en tu app, registra una instancia de UtteranceProgressListener. Como parte del proceso de registro, incluye un controlador para el método onRangeStart().

El motor de texto a voz llama a rangeStart() para grabar el momento en el que espera que comience la reproducción de audio de un rango específico de texto. Cuando el audio de ese rango de texto comienza la reproducción, se ejecuta el método onRangeStart() de tu app. Luego, tu app puede responder a esta devolución de llamada, por ejemplo, destacando el rango de texto asociado con el enunciado.

Para obtener más información sobre el seguimiento del progreso de reproducción de un motor de texto a voz, consulta la referencia de la clase UtteranceProgressListener.

Sistema

Nuevos detectores StrictMode

Android 8.0 (nivel de API 26) agrega tres detectores StrictMode nuevos para ayudar a identificar posibles errores en tu app:

Datos almacenados en caché

Android 8.0 (nivel de API 26) ofrece mejores pautas y comportamientos en torno a los datos almacenados en caché. Cada app ahora recibe una cuota de espacio en disco para datos almacenados en caché, como lo muestra getCacheQuotaBytes(UUID).

Cuando el sistema necesite liberar espacio en el disco, comenzará por borrar los archivos almacenados en caché de las apps que más superen su cuota asignada. Por lo tanto, si mantienes los datos almacenados en caché por debajo de la cuota asignada, tus archivos almacenados en caché serán algunos de los últimos del sistema que se borrarán cuando sea necesario. Cuando el sistema decida qué archivos almacenados en caché borrar dentro de tu app, tendrá en cuenta los archivos más antiguos primero (según lo determinado por la hora de modificación).

También hay dos comportamientos nuevos que puedes habilitar por directorio para controlar cómo el sistema libera tus datos almacenados en caché:

  • Se puede usar StorageManager.setCacheBehaviorAtomic() para indicar que un directorio y todo su contenido deben borrarse como una sola unidad atómica.
  • Se puede usar setCacheBehaviorTombstone(File, boolean) para indicar que, en lugar de borrar los archivos dentro de un directorio, se deben truncar para que tengan una longitud de 0 bytes y que el archivo vacío quede intacto.

Por último, cuando necesites asignar espacio en disco para archivos grandes, considera usar la nueva API de allocateBytes(FileDescriptor, long), que borrará de forma automática los archivos almacenados en caché pertenecientes a otras apps (según sea necesario) para cumplir con tu solicitud. Cuando decidas si el dispositivo tiene suficiente espacio en el disco para almacenar tus datos nuevos, llama a getAllocatableBytes(UUID) en lugar de usar getUsableSpace(), ya que el primero considerará todos los datos almacenados en caché que el sistema está dispuesto a borrar por ti.

Paginación de proveedores de contenido

Actualizamos los proveedores de contenido a fin de que incluyan compatibilidad para cargar un conjunto de datos grande, de a una página a la vez. Por ejemplo, una app de fotos 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 solo objeto Cursor. Un cliente y un proveedor deben implementar la 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 que facilita que los clientes sepan si la información que solicitan está actualizada.

Puedes agregar una lógica de actualización de contenido personalizado extendiendo ContentProvider. Asegúrate de anular el método refresh() para mostrar true, lo que indica a los clientes de tu proveedor que intentaste actualizar los datos por tu cuenta.

Tu app cliente puede solicitar contenido actualizado de forma explícita llamando a un método diferente, también llamado refresh(). Cuando llames a este método, pasa el URI de los datos que deseas actualizar.

Nota: Debido a que tal vez solicites datos a través de una red, debes invocar a refresh() desde el lado del cliente solo cuando haya una indicación fuerte de que el contenido está inactivo. El motivo más común para realizar este tipo de actualización de contenido es en respuesta a un gesto de deslizar para actualizar, en el que se solicita de forma explícita que la IU actual muestre contenido actualizado.

Mejoras de JobScheduler

Android 8.0 (nivel de API 26) presenta varias mejoras a JobScheduler. Estas mejoras facilitan que tu app cumpla con los nuevos límites de ejecución en segundo plano, ya que, por lo general, puedes usar trabajos programados para reemplazar los servicios en segundo plano ahora restringidos o los receptores de emisión implícitos.

Entre las actualizaciones de JobScheduler, se incluyen las siguientes:

  • Ahora puedes asociar una cola de trabajo con un trabajo programado. Para agregar un elemento de trabajo a la cola de un trabajo, llama a JobScheduler.enqueue(). Cuando la tarea se encuentra en ejecución, puede tomar trabajo pendiente de la cola y procesarlo. Esta funcionalidad controla muchos de los casos de uso que antes habrían llamado para iniciar un servicio en segundo plano, en particular los servicios que implementan IntentService.
  • La biblioteca de compatibilidad de Android 26.0.0 presenta una nueva clase JobIntentService, que proporciona la misma funcionalidad que IntentService, pero usa trabajos en lugar de servicios cuando se ejecuta en Android 8.0 (nivel de API 26) o versiones posteriores.
  • Ahora puedes llamar a JobInfo.Builder.setClipData() para asociar un 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 admiten varias restricciones nuevas:
    JobInfo.isRequireStorageNotLow()
    No se ejecuta el trabajo si hay poco almacenamiento disponible en el dispositivo.
    JobInfo.isRequireBatteryNotLow()
    No se ejecuta la tarea si el nivel de batería está al límite o por debajo del umbral crítico. Este es el nivel en el que el dispositivo muestra el diálogo del sistema de advertencia de batería baja.
    NETWORK_TYPE_METERED
    El trabajo requiere una conexión de red de uso medido, como la mayoría de los planes de datos móviles.

Almacén de datos personalizados

Android 8.0 (nivel de API 26) te permite proporcionar un almacén de datos personalizado según tus preferencias, lo que puede ser útil si tu app almacena las preferencias en una nube o en una base de datos local, o si son específicas del dispositivo. Para obtener más información sobre la implementación del almacén de datos, consulta Almacén de datos personalizado.

Mejoras de medios

VolumeShaper

Hay una nueva clase VolumeShaper. Úsalo para realizar transiciones de volumen automatizadas cortas, como fundido de entrada, fundido de salida y fundido cruzado. Consulta Cómo controlar la amplitud con VolumeShaper para obtener más información.

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 nueva clase AudioFocusRequest. Si usas esta clase como parámetro de requestAudioFocus(), las apps tendrán capacidades nuevas para controlar los cambios en el foco de audio: la disminución automática del volumen y la ganancia de foco demorada.

Métricas de medios

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

Las métricas se recopilan por separado para cada instancia y se conservan durante toda la vida útil de la instancia. Si no hay métricas disponibles, el método muestra un valor nulo. Las métricas reales que se muestran dependen de la clase.

MediaPlayer

A partir de Android 8.0 (nivel de API 26), MediaPlayer puede reproducir material protegido por DRM y medios encriptados a nivel de muestra de HLS.

Android 8.0 presenta un nuevo comando seekTo() sobrecargado que proporciona un control detallado cuando se busca un fotograma. Incluye un segundo parámetro que especifica un modo de búsqueda:

  • SEEK_PREVIOUS_SYNC mueve la posición del contenido multimedia a un marco de sincronización (o clave) asociado con una fuente de datos que se encuentra justo antes o en el momento determinado.
  • SEEK_NEXT_SYNC mueve la posición del contenido multimedia a un marco de sincronización (o clave) asociado con una fuente de datos que se encuentra justo después o en el momento determinado.
  • SEEK_CLOSEST_SYNC mueve la posición del contenido multimedia a un marco de sincronización (o clave) asociado con una fuente de datos que se encuentre más cerca o en un momento determinado.
  • SEEK_CLOSEST mueve la posición del contenido multimedia a un fotograma (no necesariamente una sincronización ni un fotograma clave) asociado con una fuente de datos que se encuentra más cerca o en un momento determinado.

Cuando realizas búsquedas continuas, las apps deben usar cualquiera de los modos SEEK_ en lugar de SEEK_CLOSEST, que se ejecuta relativamente más lento, pero puede ser más preciso.

MediaRecorder

  • MediaRecorder ahora admite el formato MPEG2_TS, que es útil para la transmisión:

    Kotlin

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS)
    

    Java

    mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);
    

    consulta MediaRecorder.OutputFormat

  • Ahora, MediaMuxer 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 todas las pistas que quieras.
  • MediaMuxer también puede agregar una o más pistas de metadatos que contengan 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 realizar estabilización de video.

Cuando se agrega 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 video y audio, excepto que los datos no provienen de un MediaCodec. En cambio, la app pasa un ByteBuffer con una marca de tiempo asociada al método writeSampleData(). La marca de tiempo tiene que estar en la misma base de tiempo que las pistas de video y audio.

El archivo MP4 generado 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 la pista de metadatos, el formato MIME de los metadatos se extraerá en MediaFormat.

Acceso mejorado a archivos multimedia

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

Sin embargo, el acceso a archivos multimedia grandes 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. En los casos en que un archivo multimedia grande reside en una fuente de datos remota, el proveedor de documentos debe recuperar todos los datos por adelantado y crear un descriptor de archivo de instantánea. El reproductor multimedia no puede reproducir el archivo sin el descriptor de archivo, por lo que la reproducción no podrá comenzar hasta que el proveedor de documentos termine de descargar el archivo.
  • Los administradores de colecciones de contenido multimedia, como las apps de fotos, deben atravesar una serie de URI de acceso para alcanzar el contenido multimedia almacenado en una tarjeta SD externa por medio de carpetas específicas. Este patrón de acceso hace que las operaciones masivas en los medios, como mover, copiar y borrar, son bastante lentas.
  • Los administradores de colecciones de contenido multimedia no pueden determinar la ubicación de un documento según su URI. Esto dificulta que estos tipos de apps permitan que los usuarios elijan dónde guardar un archivo multimedia.

Android 8.0 aborda cada uno de estos desafíos mejorando el framework de acceso al almacenamiento.

Proveedores de documentos personalizados

A partir de Android 8.0, el framework de acceso al almacenamiento permite a los proveedores de documentos personalizados crear descriptores de archivos que admiten búsquedas para archivos que residen en una fuente de datos remota. El SAF puede abrir un archivo para obtener un descriptor de archivos nativo que admita búsquedas. Luego, el SAF entrega solicitudes de bytes discretos al proveedor de documentos. Esta función permite que un proveedor de documentos muestre el rango exacto de bytes que solicitó una app de reproducción multimedia, en lugar de almacenar en caché todo el archivo por adelantado.

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

Acceso directo a documentos

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

Precaución: El método getDocumentUri() solo ubica los archivos multimedia; no otorga permiso a las apps para acceder a ellos. Si quieres obtener más información para obtener permiso de acceso a los archivos multimedia, consulta la documentación de referencia.

Rutas de acceso a los documentos

Cuando usas el framework de acceso al almacenamiento en Android 8.0 (nivel de API 26), puedes usar el método findDocumentPath(), disponible en las clases DocumentsContract y DocumentsProvider, para determinar la ruta desde la raíz de un sistema de archivos según 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 tiene varias rutas definidas para el mismo documento, el método muestra la ruta que se usa con mayor frecuencia para llegar al documento con el ID determinado.

Esta funcionalidad es especialmente útil en las siguientes situaciones:

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

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

Cómo supervisar la reproducción de audio

El servicio del sistema AudioManager mantiene una lista de objetos AudioPlaybackConfiguration activos, cada uno de los cuales contiene información sobre una sesión de reproducción de audio en particular. Tu app puede recuperar el conjunto de configuraciones activas si llama a getActivePlaybackConfigurations().

A partir de Android 8.0 (nivel de API 26), puedes registrar una devolución de llamada que notifique a tu app cuando se hayan modificado uno o más objetos AudioPlaybackConfiguration. Para ello, llama a registerAudioPlaybackCallback() y pasa una instancia de AudioManager.AudioPlaybackCallback. La clase AudioManager.AudioPlaybackCallback contiene el método onPlaybackConfigChanged(), al que el sistema llama cuando cambia la configuración de reproducción de audio.

Conectividad

Reconocimiento de Wi-Fi

Android 8.0 (nivel de API 26) agrega compatibilidad con el reconocimiento de Wi-Fi, que se basa en la especificación de Neighbor Awareness Networking (NAN). En los dispositivos con el hardware de reconocimiento de Wi-Fi adecuado, las apps y los dispositivos cercanos pueden detectar y comunicarse a través de Wi-Fi sin un punto de acceso a Internet. Estamos trabajando con nuestros socios de hardware para llevar 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

Android 8.0 (nivel de API 26) enriquece 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 (nivel de API 26) proporciona APIs que te permiten personalizar el diálogo de solicitud de vinculación cuando intentas realizar la vinculación con dispositivos complementarios mediante Bluetooth, BLE y Wi-Fi. Para obtener más información, consulta Sincronización de dispositivos complementarios.

Para obtener más información sobre el uso de Bluetooth en Android, consulta la guía de Bluetooth. Para conocer los cambios de Bluetooth específicos de Android 8.0 (nivel de API 26), consulta la sección Bluetooth de la página Cambios de comportamiento en Android 8.0.

Uso compartido

Uso compartido inteligente

Android 8.0 (nivel de API 26) aprende sobre las preferencias de uso compartido personalizadas de los usuarios y comprende mejor cada tipo de contenido con cuáles son las apps correctas para compartir. 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 controlar mejor la imagen. Android 8.0 aprende automáticamente todos estos patrones según las preferencias personalizadas de los usuarios.

El uso compartido inteligente funciona para tipos de contenido distintos de image, como audio, video, text, URL, etcétera.

Para habilitar el uso compartido inteligente, agrega un ArrayList de hasta tres anotaciones de strings al intent que comparte el contenido. Las anotaciones deben describir los componentes o temas principales del contenido. En el siguiente ejemplo de código, se muestra cómo agregar anotaciones al intent:

Kotlin

val annotations: ArrayList<String> = arrayListOf(
        "topic1",
        "topic2",
        "topic3"
)

intent.putStringArrayListExtra(
        Intent.EXTRA_CONTENT_ANNOTATIONS,
        annotations
)

Java

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.

Clasificador de texto

En los dispositivos compatibles, las apps pueden usar un nuevo clasificador de texto para verificar si una string coincide con un tipo de entidad clasificadora conocido y obtener alternativas de selección sugeridas. Las 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 (nivel de API 26) admite varias funciones de accesibilidad nuevas para los desarrolladores que crean sus propios servicios de accesibilidad:

Si quieres obtener más información para mejorar la accesibilidad de tu app, consulta Accesibilidad.

Seguridad y privacidad

Permisos

Android 8.0 (nivel de API 26) presenta varios permisos nuevos relacionados con la telefonía:

  • El permiso ANSWER_PHONE_CALLS permite que tu app responda llamadas telefónicas entrantes de forma programática. Para controlar una llamada telefónica entrante en tu app, puedes usar el método acceptRingingCall().
  • El permiso READ_PHONE_NUMBERS le otorga a tu app acceso de lectura a los números de teléfono almacenados en un dispositivo.

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

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

Android 8.0 (nivel de API 26) incluye varias mejoras respecto a la forma en que las apps obtienen acceso a las cuentas de usuario. En el caso de las cuentas que administran, los autenticadores pueden usar su propia política para decidir si ocultan las cuentas de una app o se las muestran a ella. El sistema Android hace un seguimiento de las aplicaciones que pueden acceder a una cuenta en particular.

En versiones anteriores de Android, las apps que querían hacer un seguimiento de la lista de cuentas de usuario debían recibir actualizaciones sobre todas las cuentas, incluidas las que tenían tipos no relacionados. Android 8.0 agrega el método addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]), que permite que las apps especifiquen una lista de tipos de cuentas para las que se deben recibir cambios de cuentas.

Cambios en la API

AccountManager proporciona seis métodos nuevos para ayudar a los autenticadores a administrar qué apps pueden ver una cuenta:

Android 8.0 (nivel de API 26) incluye dos valores especiales de nombre de paquete a fin de especificar los niveles de visibilidad para las 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 aplica a las apps que tienen el permiso GET_ACCOUNTS y a versiones de destino de Android anteriores a Android 8.0, o cuyas firmas coincidan con el autenticador que se orienta a cualquier versión de Android. PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE proporciona un valor de visibilidad predeterminado para las apps que no se configuraron con anterioridad y para las que PACKAGE_NAME_KEY_LEGACY_VISIBLE no es aplicable.

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

Prueba

Pruebas de instrumentación

Android 8.0 (nivel de API 26) proporciona los siguientes elementos adicionales de compatibilidad 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 en 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 ejecutan en procesos diferentes.

Para definir la instrumentación de un proceso no predeterminado, navega a tu archivo de manifiesto y, luego, al elemento <instrumentation> que desees. Agrega el atributo android:targetProcess y establece su valor en una de las siguientes opciones:

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

Mientras se ejecuta la prueba de instrumentación, puedes llamar a getProcessName() para verificar el proceso que está probando.

Informar resultados durante una prueba

Ahora puedes informar resultados mientras se ejecuta la prueba de instrumentación, en lugar de hacerlo después, llamando a addResults().

Intents falsos para pruebas

A fin de facilitar la creación de pruebas de IU independientes y aisladas para las actividades de tu app, en Android 8.0 (nivel de API 26) se presenta el método onStartActivity(). Anula este método en una subclase personalizada de la clase Instrumentation.ActivityMonitor para controlar un intent en particular que tu clase de prueba invoca.

Cuando la clase de prueba invoca el intent, el método muestra un objeto Instrumentation.ActivityResult de stub en lugar de ejecutar el intent. Si usas esta lógica de intent ficticio en tus pruebas, puedes enfocarte en la forma en que tu actividad prepara y controla el intent que pasas a una actividad diferente o a una app completamente distinta.

Tiempo de ejecución y herramientas

Optimizaciones de plataforma

Android 8.0 (nivel de API 26) trae como resultado optimizaciones de tiempo de ejecución y de otro tipo a la plataforma, lo que genera varias mejoras de rendimiento. Estas optimizaciones incluyen la recolección de elementos no utilizados de compactación simultánea, un uso más eficiente de la memoria y la localidad del código.

Estas optimizaciones reducen los tiempos de inicio y mejoran el rendimiento tanto en el SO como en las apps.

Compatibilidad actualizada con el lenguaje Java

Android 8.0 (nivel de API 26) agrega compatibilidad con varias API de OpenJDK Java adicionales:

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

Si deseas usar funciones del lenguaje Java 8 en Android Studio, debes descargar la versión preliminar más reciente.

API actualizadas del marco de trabajo ICU4J de Android

Android 8.0 (nivel de API 26) extiende las APIs del framework de ICU4J de Android, que es un subconjunto de las APIs de ICU4J, para que los desarrolladores de apps las usen con el paquete android.icu. Estas APIs usan datos de localización presentes en el dispositivo, por lo que puedes reducir tu huella de APK sin compilar las bibliotecas de ICU4J en el APK.

Tabla 1: Versiones de ICU, CLDR y Unicode que se usan 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 (nivel de API 26) 58.2 30.0.3 9.0

Para obtener más información sobre la internacionalización en Android, incluida la compatibilidad con ICU4J, consulta Internacionalización en Android.

Android para empresas

Se introdujeron nuevas funciones y APIs empresariales para dispositivos con Android 8.0 (nivel de API 26). Entre los más destacados, se incluyen los siguientes:

  • Los perfiles de trabajo en dispositivos completamente administrados permiten a las empresas separar los datos laborales de los personales y, al mismo tiempo, administrar ambos.
  • La delegación de API permite que los propietarios de dispositivos y perfiles asignen la administración de apps a otras aplicaciones.
  • Las mejoras en la experiencia del usuario en el flujo de aprovisionamiento (incluidas las nuevas opciones de personalización) reducen el tiempo de configuración.
  • Los nuevos controles sobre Bluetooth, Wi-Fi, copias de seguridad y seguridad permiten que las empresas administren una mayor parte del 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 nuevas de Android Enterprise, consulta Android en la empresa.