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 video. Originalmente, el modo PIP estaba disponible solo 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 su lugar, 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, configura android:supportsPictureInPicture
como verdadero en el manifiesto.
(A partir de Android 8.0, PIP no requiere el atributo de 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 los 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 especifican la relación de aspecto de la actividad y otros parámetros de configuración. Si algún campo en args está vacío, el sistema usa los valores establecidos la última vez que llamaste aActivity.setPictureInPictureParams()
.La actividad especificada se coloca en una esquina de la pantalla; el resto de la pantalla se llena con la actividad anterior que se estaba mostrando. La actividad que ingresa al modo de PIP entra en el 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 el 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, las configuraciones se actualizan; 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étodoenterPictureInPictureMode()
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 el comportamiento y la configuración de las notificaciones. Entre estos cambios, se incluyen los siguientes:
- 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 deseas mostrar. En la interfaz de usuario, se hace referencia a los canales de notificaciones como categorías de notificación. 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 utilizó. Para obtener información sobre cómo trabajar con 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 que vuelvan 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 tras 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 con el intentNotification.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
yNOTIFICATION_ID
. - Descarte de notificaciones: Los usuarios pueden descartar las notificaciones por sí mismos, 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 claseNotificationListenerService
. - Colores de fondo: Puedes configurar y habilitar un color de fondo para una notificación. Solo debes usar esta función en notificaciones de tareas en curso que son fundamentales para que el usuario las vea de un vistazo. Por ejemplo, puedes configurar un color de fondo para las notificaciones relacionadas con la ruta en auto o una llamada telefónica en curso. También puedes configurar el color de fondo deseado con
setColor()
. De esta manera, podrás usarsetColorized()
para habilitar el uso de un color de fondo en una notificación. - Estilo de mensajería: En Android 8.0, las notificaciones que usan la clase
MessagingStyle
muestran más contenido en su forma contraída. Debes usar la claseMessagingStyle
para las notificaciones relacionadas con la mensajería. También puedes usar el métodoaddHistoricMessage()
para proporcionar contexto a una conversación agregando mensajes históricos a las notificaciones relacionadas con los mensajes.
![Un menú de notificaciones de presión prolongada en Android 8.0 (nivel de API 26)](https://developer.android.google.cn/static/images/about/versions/oreo/notification-long-press.png?authuser=5&hl=es)
Los usuarios pueden mantener presionados los íconos del selector de apps para ver las notificaciones en Android 8.0.
Autofill Framework
La creación de cuentas, el acceso y las transacciones con tarjetas de crédito llevan tiempo y pueden generar errores. Los usuarios pueden frustrarse fácilmente con apps que requieren este tipo de tareas repetitivas.
Con la introducción de Autofill Framework, Android 8.0 (nivel de API 26) facilita la tarea de completar formularios, como los de acceso y tarjetas de crédito. 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 agruparlas 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 función nueva, Fuentes en XML, que te permite usar las fuentes como recursos. Esto significa que no es necesario empaquetar 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 tipo de recurso nuevo: 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 configurar el tamaño 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 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 una variedad de formas en diferentes modelos de dispositivos. Para obtener información sobre cómo crear íconos adaptables, consulta la guía sobre íconos adaptables.
Administración de color
Los desarrolladores de apps de generación de imágenes para Android ahora pueden aprovechar los dispositivos nuevos que tienen una amplia gama de pantallas compatibles con la imagen. Para mostrar imágenes de una amplia gama, las apps deberán habilitar una marca en su manifiesto (por actividad) y cargar mapas de bits con un perfil de amplia gama 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. Estas API, que mejoran la estabilidad y seguridad de tu app, incluyen lo siguiente:
- API de versión
- Google SafeBrowsing API
- Termination Handle API
- API de Renderer Importance
Si quieres obtener más información para usar estas APIs, consulta Cómo administrar WebViews.
La clase WebView
ahora incluye una API de Safe Browsing para mejorar la seguridad de la navegación web. Si deseas obtener más información, consulta API de Google Safe Browsing.
Fijación de combinaciones de teclas y widgets
Android 8.0 (nivel de API 26) presenta la fijación de accesos directos y widgets en la app. En tu app, puedes crear accesos directos y widgets fijados para los selectores admitidos, sujeto al permiso del usuario.
Para obtener más información, consulta la guía de funciones Cómo fijar accesos directos y widgets.
Relación de aspecto máxima de la pantalla
Android 8.0 (nivel de API 26) incorpora cambios en 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.
Para obtener más información sobre cómo declarar la relación de aspecto máxima, consulta Compatibilidad con varias 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 la actividad.
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 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 la actividad 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 si es 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 manejar los cambios de configuración.
ActivityOptions
proporciona dos métodos nuevos para admitir varias pantallas:
setLaunchDisplayId()
- Especifica en qué pantalla se debe mostrar 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.
El comando shell start
ahora se puede usar 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 XML de diseño:
-
layout_marginVertical
, que definelayout_marginTop
ylayout_marginBottom
al mismo tiempo -
layout_marginHorizontal
, que definelayout_marginLeft
ylayout_marginRight
al mismo tiempo -
paddingVertical
, que definepaddingTop
ypaddingBottom
al mismo tiempo -
paddingHorizontal
, que definepaddingLeft
ypaddingRight
al mismo tiempo
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
o
paddingEnd
. Puedes configurar estos valores por tu cuenta, además de los nuevos atributos de diseño verticales y horizontales, 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 si tienes 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 objeto View
de tu app puede solicitar una captura de puntero y definir un objeto de escucha para procesar los eventos de puntero capturados. El puntero del mouse está oculto en este modo. 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 de 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 en clústeres 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 del 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. La nueva pantalla principal organiza el contenido de video en filas correspondientes a los 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 la 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 videos, que se reproducen automáticamente cuando un usuario se enfoca en un programa. Las APIs para completar 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 punto específico en el tiempo. 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 animación 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 el teclado entre ellos. Los usuarios pueden presionar Meta + Tab o Búsqueda + 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 podrían 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.](https://developer.android.google.cn/static/images/about/versions/oreo/keyboard-navigation-clusters.png?authuser=5&hl=es)
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 pueden utilizar la tecla Tab ni las teclas de flecha para navegar hacia o desde el clúster; en su lugar, deben 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 bien 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 hablar 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 comienza la reproducción del audio de ese rango de texto, 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 la frase.
Si quieres obtener más información para realizar un 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:
detectUnbufferedIo()
detectará el momento en que la app lea o escriba datos sin almacenamiento en búfer, lo que puede afectar drásticamente el rendimiento.detectContentUriWithoutPermission()
detectará si tu app olvida otorgar permisos a otra app por accidente cuando inicia una actividad fuera de ella.detectUntaggedSockets()
detectará cuándo la app realiza el tráfico de red sin usarsetThreadStatsTag(int)
para etiquetar el tráfico con fines de depuración.
Datos almacenados en caché
Android 8.0 (nivel de API 26) ofrece mejores orientaciones y comportamientos en torno a los datos almacenados en caché. Ahora, cada app recibe una cuota de espacio en disco para los 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 tus 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, considerará primero los archivos más antiguos (según lo determine 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 se deben borrar como una sola unidad atómica. - Se puede usar
setCacheBehaviorTombstone(File, boolean)
para indicar que, en lugar de borrar archivos dentro de un directorio, se deben truncar para que tengan 0 bytes de longitud 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á automáticamente los archivos almacenados en caché que pertenezcan a otras apps (según sea necesario) para satisfacer tu solicitud. A fin de decidir 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 tendrá en cuenta 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 para que incluyan compatibilidad con la carga de un conjunto de datos grande, 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 para presentarlos en una página. Cada página de resultados que muestra un proveedor de contenido está representada por un solo objeto Cursor. Tanto un cliente como 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
Las clases ContentProvider
y ContentResolver
ahora incluyen un método refresh()
, lo que permite a los clientes saber con más facilidad 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 les indicará 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 se actualizarán.
Nota: Dado que es posible que solicites datos a través de una red, debes invocar a refresh()
desde el cliente solo cuando haya una indicación clara 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, que 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 permiten que tu app cumpla con más facilidad 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ícitas.
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 aquellos que implementanIntentService
. -
La biblioteca de compatibilidad de Android 26.0.0 presenta una nueva clase
JobIntentService
, que proporciona la misma funcionalidad queIntentService
, 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 unClipData
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 aContext.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()
- El trabajo no se ejecuta si hay poco almacenamiento disponible en el dispositivo.
JobInfo.isRequireBatteryNotLow()
- El trabajo no se ejecuta si el nivel de batería es igual o inferior al umbral crítico. Este es el nivel en el que el dispositivo muestra el diálogo del sistema 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 las preferencias 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 automáticas cortas, como fundido de entrada, de salida y atenuación cruzada.
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 cuando controlan los cambios en el foco de audio: disminución automática del volumen y obtención de foco demorado.
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:
MediaPlayer.getMetrics()
MediaRecorder.getMetrics()
MediaCodec.getMetrics()
MediaExtractor.getMetrics()
Las métricas se recopilan por separado para cada instancia y se conservan durante toda su vida útil. 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 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 de contenido multimedia a un fotograma 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 de contenido multimedia a un fotograma 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 de contenido multimedia a un fotograma de sincronización (o clave) asociado con una fuente de datos que se encuentre más cerca o en el momento determinado.SEEK_CLOSEST
mueve la posición de contenido multimedia a un fotograma (no necesariamente una sincronización o un fotograma clave) asociado con una fuente de datos ubicada más cerca o en el 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
MediaMuxer
ahora puede controlar cualquier cantidad de transmisiones de audio y video. Ya no estás limitado a una pista de audio ni una pista de video. UsaaddTrack()
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 se podrían usar para realizar la 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 usas MediaExtractor
para extraer el archivo con 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 acceso a otras apps 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 de 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. Cuando 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 puede 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 llegar al contenido multimedia almacenado en una tarjeta SD externa a través de carpetas con alcance. Este patrón de acceso hace que las operaciones masivas con contenido multimedia (como mover, copiar y borrar) sean bastante lentas.
- Los administradores de colecciones de contenido multimedia no pueden determinar la ubicación de un documento debido a 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 archivo 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 reproductor 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 relacionadas con 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 la colección de contenido multimedia pueden acceder al documento directamente, sin tener que atravesar árboles de directorios determinados.
Como resultado, los administradores de contenido multimedia pueden realizar operaciones de archivos en el documento con mucha más rapidez.
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 permisos 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 a partir de 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" en el que se 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 en una carpeta particular si el usuario selecciona esa carpeta.
Nota: Si tu app tiene permiso para acceder únicamente a algunos de los documentos de la ruta de acceso, el valor que se muestra de findDocumentPath()
incluye únicamente 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 específica. Tu app puede recuperar el conjunto de parámetros de configuración activos actualmente llamando 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 cambien 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 implementar la tecnología de reconocimiento de Wi-Fi en los dispositivos lo antes posible. Para obtener información sobre cómo integrar Wi-Fi Aware en tu app, consulta Wi-Fi Aware.
Bluetooth
Android 8.0 (nivel de API 26) enriquece la compatibilidad con Bluetooth de la plataforma agregando 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.
Si deseas obtener más información para usar Bluetooth en Android, consulta la guía de Bluetooth. Para ver 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 de 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 para cada tipo de contenido cuáles son las apps adecuadas 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 se toma una selfie, una app de redes sociales puede manejar mejor la imagen. Android 8.0 aprende automáticamente todos estos patrones en función de 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 cadenas 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 comprobar si una cadena coincide con un tipo de entidad clasificador 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:
- Una nueva categoría de volumen para ajustar el volumen de accesibilidad
- Gestos de huella digital como mecanismo de entrada
- Capacidades de texto a voz multilingüe
- Un acceso directo de accesibilidad basado en hardware para acceder rápidamente a un servicio de accesibilidad preferido.
- Compatibilidad con gestos continuos o secuencias programáticas de trazos.
- Un botón de accesibilidad para invocar una de varias funciones de accesibilidad habilitadas (disponible solo en dispositivos que usan un área de navegación procesada por software)
- Valores de rango unilateral estandarizado.
- Varias funciones para procesar texto más fácilmente, incluidos texto sugerido y las ubicaciones de los caracteres de texto en pantalla.
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 manera programática. Para controlar una llamada telefónica entrante en tu app, puedes usar el métodoacceptRingingCall()
. - El permiso
READ_PHONE_NUMBERS
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) presenta varias mejoras sobre 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 ocultarán las cuentas de una app o se las mostrarán a ella. El sistema Android realiza 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 obtener actualizaciones de todas las cuentas, incluidas aquellas con 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 cuenta para los 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:
setAccountVisibility(android.accounts.Account, java.lang.String, int)
: Establece el nivel de visibilidad para una combinación de cuenta de usuario y paquete específica.-
getAccountVisibility(android.accounts.Account, java.lang.String)
: Obtiene el nivel de visibilidad de una cuenta de usuario específica y una combinación de paquete. -
getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String)
: Permite que los autenticadores obtengan las cuentas y los niveles de visibilidad para un paquete determinado. -
getPackagesAndVisibilityForAccount(android.accounts.Account)
: Permite que los autenticadores obtengan valores de visibilidad almacenados para una cuenta determinada. -
addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>)
: Permite que los autenticadores inicialicen los valores de visibilidad de una cuenta. -
addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[])
: Agrega un objeto de escuchaOnAccountsUpdateListener
al objetoAccountManager
. El sistema llama a este objeto de escucha cada vez que cambia la lista de cuentas del dispositivo.
Android 8.0 (nivel de API 26) presenta dos valores de nombre de paquete especiales para especificar los niveles de visibilidad de 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 objetivo de Android anteriores a Android 8.0, o cuyas firmas coinciden 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 no se aplica PACKAGE_NAME_KEY_LEGACY_VISIBLE
.
Para obtener más información sobre las nuevas APIs de acceso a la cuenta y descubrimiento, consulta la referencia de AccountManager
y OnAccountsUpdateListener
.
Prueba
Pruebas de instrumentación
Android 8.0 (nivel de API 26) 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 ejecutan en procesos diferentes.
Para definir la instrumentación de un proceso no predeterminado, navega al archivo de manifiesto y, luego, al elemento
<instrumentation>
deseado. 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 atributoandroid:targetPackage
Mientras se ejecuta la prueba de instrumentación, puedes llamar a getProcessName()
para verificar qué proceso está probando.
Informar resultados durante una prueba
Ahora puedes informar los resultados mientras se ejecuta la prueba de instrumentación,
en lugar de hacerlo después, llamando a 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 (nivel de API 26) presenta el método onStartActivity()
. Debes anular 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 tu clase de prueba invoca el intent, el método muestra un objeto stub Instrumentation.ActivityResult
en lugar de ejecutar el intent. Si usas esta lógica de intent simulada en tus pruebas, te podrás enfocar en cómo tu actividad prepara y controla el intent que pasas a una actividad diferente o a una app completamente diferente.
Tiempo de ejecución y herramientas
Optimizaciones de plataforma
Android 8.0 (nivel de API 26) incorpora a la plataforma optimizaciones de tiempo de ejecución y de otro tipo que generan una serie de mejoras en el 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 del SO y de las apps.
Se actualizó la compatibilidad con el lenguaje Java.
Android 8.0 (nivel de API 26) agrega compatibilidad para varias API de OpenJDK Java adicionales:
java.time
de OpenJDK 8.java.nio.file
yjava.lang.invoke
de OpenJDK 7.
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 los dispositivos que ejecutan Android 8.0 (nivel de API 26). Los aspectos destacados incluyen lo siguiente:
- Los perfiles de trabajo en dispositivos completamente administrados permiten que las empresas separen el trabajo de los datos personales y, al mismo tiempo, administran 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 de Bluetooth, Wi-Fi, copia de seguridad y seguridad permiten a las empresas administrar más aspectos del dispositivo. Los registros de actividad de red ayudan a las empresas a rastrear los problemas.
Para obtener más información sobre estas y otras APIs y funciones nuevas de Android Enterprise, consulta Android en la empresa.