Cambios de comportamiento: todas las apps

Android 9 (nivel 28 de API) presenta varios cambios en el sistema de Android. Los siguientes cambios de comportamiento se aplican a todas las apps cuando se ejecutan en la plataforma de Android 9, independientemente del nivel de API al que se orienten. Todos los desarrolladores deben revisar estos cambios y modificar sus apps para admitirlos correctamente, cuando corresponda.

Para conocer los cambios que solo afectan a las apps orientadas al nivel de API 28 o versiones posteriores, consulta Cambios en el comportamiento: apps orientadas a la API nivel 28 y versiones posteriores.

Administración de energía

Android 9 presenta funciones nuevas para mejorar la administración de batería del dispositivo. Estos cambios, junto con las funciones que ya estaban presentes antes de Android 9, ayudan a garantizar que los recursos del sistema estén disponibles para las apps que más los necesitan.

Para obtener más información, consulta Administración de energía.

Cambios en la privacidad

Para mejorar la privacidad del usuario, Android 9 presenta varios cambios de comportamiento, como limitar el acceso de las apps en segundo plano a los sensores del dispositivo, restringir la información recuperada de las búsquedas de Wi-Fi y nuevas reglas y grupos de permisos relacionados con las llamadas telefónicas, el estado del teléfono y las búsquedas de Wi-Fi.

Estos cambios afectan a todas las apps que se ejecutan en Android 9, independientemente de la versión del SDK de destino.

Acceso limitado a los sensores en segundo plano

Android 9 limita la capacidad de las apps en segundo plano para acceder a la entrada del usuario y a los datos de sensores. Si tu app se ejecuta en segundo plano en un dispositivo con Android 9, el sistema le aplicará las siguientes restricciones:

  • Tu app no puede acceder al micrófono ni a la cámara.
  • Los sensores que usan el modo de generación de informes continuo, como acelerómetros y giroscopios, no reciben eventos.
  • Los sensores que usan los modos de informes ante un cambio o por única vez no reciben eventos.

Si tu app necesita detectar eventos de sensores en dispositivos que ejecutan Android 9, usa un servicio en primer plano.

Acceso restringido a los registros de llamadas

Android 9 introduce el grupo de permisos CALL_LOG y mueve los permisos READ_CALL_LOG, WRITE_CALL_LOG y PROCESS_OUTGOING_CALLS a este grupo. En versiones anteriores de Android, estos permisos se encontraban en el grupo de permisos PHONE.

Este grupo de permisos CALL_LOG brinda a los usuarios un mejor control y visibilidad para las apps que necesitan acceso a información sensible sobre las llamadas telefónicas, como la lectura de registros de llamadas telefónicas y la identificación de números de teléfono.

Si tu app requiere acceso a registros de llamadas o necesita procesar llamadas salientes, debes solicitar explícitamente estos permisos del grupo de permisos CALL_LOG. De lo contrario, se produce una SecurityException.

Nota: Debido a que estos permisos cambiaron de grupo y se otorgan durante el tiempo de ejecución, es posible que el usuario rechace el acceso de tu app a la información de registros de llamadas telefónicas. En este caso, tu app debería poder controlar la falta de acceso a la información con facilidad.

Si tu app ya sigue las prácticas recomendadas de permisos de tiempo de ejecución, puede controlar el cambio en el grupo de permisos.

Acceso restringido a los números de teléfono

Las apps que se ejecutan en Android 9 no pueden leer números de teléfono ni estados del teléfono sin primero obtener el permiso READ_CALL_LOG, además de los otros permisos que requieren los casos de uso de tu app.

Los números de teléfono asociados con llamadas entrantes y salientes son visibles en la transmisión del estado del teléfono, como en el caso de las llamadas entrantes y salientes, y se puede acceder a ellos desde la clase PhoneStateListener. Sin embargo, sin el permiso READ_CALL_LOG, el campo de número de teléfono que se proporciona en las transmisiones PHONE_STATE_CHANGED y a través de PhoneStateListener estará vacío.

Para leer los números de teléfono del estado del teléfono, actualiza tu app a fin de solicitar los permisos necesarios según tu caso de uso:

Acceso restringido a la ubicación del Wi-Fi y a la información de conexión

En Android 9, los requisitos de permisos para que una app realice búsquedas de Wi-Fi son más estrictos que en versiones anteriores. Para obtener más información, consulta Restricciones de búsqueda de Wi-Fi.

También se aplican restricciones similares al método getConnectionInfo(), que muestra un objeto WifiInfo que describe la conexión Wi-Fi actual. Solo puedes usar los métodos de este objeto para recuperar valores de SSID y BSSID si la app que realiza la llamada tiene los siguientes permisos:

  • ACCESS_FINE_LOCATION o ACCESS_COARSE_LOCATION
  • ACCESS_WIFI_STATE

Para recuperar el SSID o BSSID, también es necesario que los servicios de ubicación estén habilitados en el dispositivo (en Configuración > Ubicación).

Se quitó información de los métodos del servicio de Wi-Fi

En Android 9, los siguientes eventos y transmisiones no reciben información sobre la ubicación del usuario ni los datos de identificación personal:

La transmisión del sistema NETWORK_STATE_CHANGED_ACTION desde Wi-Fi ya no contiene SSID (anteriormente EXTRA_SSID), BSSID (anteriormente EXTRA_BSSID) ni información de conexión (anteriormente EXTRA_NETWORK_INFO). Si tu app necesita esta información, llama a getConnectionInfo().

La información de telefonía ahora depende del parámetro de ubicación del dispositivo

Si el usuario inhabilitó la ubicación del dispositivo en un dispositivo con Android 9, los siguientes métodos no proporcionarán resultados:

Restricciones para el uso de interfaces que no pertenecen al SDK

Para garantizar la estabilidad y compatibilidad de las apps, la plataforma restringe el uso de algunos métodos y campos que no pertenecen al SDK. Estas restricciones se aplican si intentas acceder a estos métodos y campos directamente, mediante reflexión o mediante JNI. En Android 9, tu app puede seguir accediendo a estas interfaces restringidas. La plataforma usa avisos y entradas de registro para llamar tu atención sobre estas interfaces. Si tu app muestra ese aviso, es importante que sigas una estrategia de implementación diferente de la interfaz restringida. Si crees que no es posible usar ninguna estrategia alternativa, puedes informar un error para solicitar que se reconsidere la restricción.

En Restricciones sobre interfaces que no pertenecen al SDK, encontrarás más información importante. Te recomendamos revisarla para asegurarte de que la app siga funcionando correctamente.

Cambios en el comportamiento de seguridad

Cambios de seguridad del dispositivo

En Android 9, se agregan varias funciones que mejoran la seguridad de tu app, independientemente de la versión a la que esta se oriente.

Cambios en la implementación de TLS

La implementación de TLS del sistema experimentó varios cambios en Android 9:

Si deseas obtener más información para realizar solicitudes web seguras en una app para Android, consulta Un ejemplo de HTTPS.

Filtro de SECCOMP más estricto

En Android 9 se imponen más restricciones a las llamadas al sistema disponibles para las apps. Este comportamiento es una extensión del filtro de SECCOMP que incluye Android 8.0 (nivel de API 26).

Cambios criptográficos

Android 9 presenta varios cambios en la implementación y el control de los algoritmos criptográficos.

Implementaciones de parámetros y algoritmos de Conscrypt

Android 9 proporciona implementaciones adicionales de parámetros de algoritmos en Conscrypt. Estos parámetros incluyen AES, DESEDE, OAEP y EC. Las versiones de Bouncy Castle de estos parámetros y muchos algoritmos dejaron de estar disponibles a partir de Android 9.

Si tu app se orienta a Android 8.1 (nivel de API 27) o versiones anteriores, recibirás una advertencia cuando solicites la implementación de Bouncy Castle de uno de estos algoritmos obsoletos. Sin embargo, si las orientas a Android 9, estas solicitudes arrojan una NoSuchAlgorithmException.

Otros cambios

En Android 9, se introducen varios cambios adicionales relacionados con la criptografía:

  • Cuando se usan claves PBE, si Bouncy Castle espera un vector de inicialización (IV) y tu app no proporciona uno, recibes una advertencia.
  • La implementación de Conscrypt del algoritmo de cifrado ARC4 te permite especificar ARC4/ECB/NoPadding o ARC4/NONE/NoPadding.
  • Se quitó el proveedor de criptografía de arquitectura de criptografía de Java (JCA). Como resultado, si tu app llama a SecureRandom.getInstance("SHA1PRNG", "Crypto"), se produce una NoSuchProviderException.
  • Si tu app analiza las claves RSA desde búferes que son más grandes que la estructura de claves, dejará de producirse una excepción.

Para obtener más información sobre el uso de las capacidades criptográficas de Android, consulta Criptografía.

Ya no se admiten los archivos encriptados seguros de Android

Android 9 quita por completo la compatibilidad con los archivos encriptados seguros de Android (ASEC).

En Android 2.2 (nivel de API 8), Android introdujo los ASEC para admitir la funcionalidad de apps en tarjetas SD. En Android 6.0 (nivel de API 23), la plataforma introdujo una tecnología de dispositivo de almacenamiento adoptable que los desarrolladores pueden usar en lugar de los ASEC.

Actualización de las bibliotecas de ICU

Android 9 usa la versión 60 de la biblioteca de ICU. Android 8.0 (nivel de API 26) y Android 8.1 (nivel de API 27) usan ICU 58.

ICU se usa para proporcionar APIs públicas debajo de android.icu package y se usa internamente en la plataforma de Android para admitir la internacionalización. Por ejemplo, se usa para implementar clases de Android en java.util, java.text y android.text.format.

La actualización de ICU 60 incluye muchos cambios pequeños pero útiles, como la compatibilidad con datos de Emoji 5.0 y los formatos de fecha y hora mejorados, como se documenta en las notas de la versión de ICU 59 e ICU 60.

Cambios destacados en esta actualización:

  • Cambió la forma en que la plataforma administra las zonas horarias.
    • La plataforma maneja mejor las zonas GMT y UTC; UTC ya no es sinónimo de GMT.

      ICU proporciona nombres de zonas traducidos para GMT y UTC. Este cambio afecta el comportamiento de formato y análisis de android.icu para zonas como "GMT", "Etc/GMT", "UTC", "Etc/UTC" y "Zulú".

    • java.text.SimpleDateFormat ahora usa ICU a fin de proporcionar nombres visibles para UTC /GMT. Esto significa lo siguiente:
      • El formato de zzzz genera una string localizada larga para muchas configuraciones regionales. Anteriormente, producía “UTC” para UTC y strings como “GMT+00:00” para GMT.
      • El análisis de zzzz reconoce strings como "hora universal coordinada" y "hora del meridiano de Greenwich".
      • Es posible que las apps tengan problemas de compatibilidad si suponen que se muestran "UTC" o "GMT+00:00" para zzzz en todos los idiomas.
    • Cambió el comportamiento de java.text.DateFormatSymbols.getZoneStrings():
      • Al igual que con SimpleDateFormat, UTC y GMT ahora tienen nombres largos. Las variantes de DST de los nombres de zona horaria para la zona UTC, como "UTC", "Etc/UTC" y "Zulú", se convierten en GMT+00:00, que es el resguardo estándar cuando no hay nombres disponibles, en lugar de la cadena hard-coded UTC.
      • Algunos IDs de zona se reconocen correctamente como sinónimos de otras zonas, de modo que Android encuentra cadenas para IDs de zonas arcaicas, como Eire, que antes no se podían resolver.
    • Asia/Hanói ya no es una zona reconocida. Por este motivo, java.util.TimeZones.getAvailableIds() no muestra este valor y java.util.TimeZone.getTimeZone() no lo reconoce. Este comportamiento es coherente con el comportamiento android.icu existente.
  • El método android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String) puede arrojar una ParseException incluso cuando se analiza un texto de moneda legítima. Para evitar este problema, usa NumberFormat.parseCurrency, disponible a partir de Android 7.0 (nivel de API 24), para el texto de moneda de estilo PLURALCURRENCYSTYLE.

Cambios de prueba de Android

Android 9 presenta varios cambios en la biblioteca y la estructura de clases del framework de Android Test. Estos cambios ayudan a los desarrolladores a usar APIs públicas compatibles con el framework, pero también permiten una mayor flexibilidad en la compilación y ejecución de pruebas con bibliotecas de terceros o lógica personalizada.

Bibliotecas que se quitaron del framework

Android 9 reorganiza las clases basadas en JUnit en tres bibliotecas: android.test.base, android.test.runner y android.test.mock. Este cambio te permite ejecutar pruebas con una versión de JUnit que funcione mejor con las dependencias de tu proyecto. Esta versión de JUnit puede ser diferente a la que proporciona android.jar.

Para obtener más información sobre cómo se organizan las clases basadas en JUnit en estas bibliotecas y sobre cómo preparar el proyecto de tu app para escribir y ejecutar pruebas, consulta Cómo configurar un proyecto para Android Test.

Cambios en la compilación del paquete de pruebas

Se quitó el método addRequirements() de la clase TestSuiteBuilder y la clase TestSuiteBuilder en sí dejó de estar disponible. El método addRequirements() requería que los desarrolladores proporcionaran argumentos cuyos tipos fueran APIs ocultas, con lo cual estas no eran válidas.

Decodificador UTF para Java

UTF-8 es el grupo de caracteres predeterminado en Android. Una secuencia de bytes UTF-8 se puede decodificar con un constructor String, como String(byte[] bytes).

El decodificador UTF-8 en Android 9 sigue los estándares Unicode de manera más estricta que en las versiones anteriores. Se incluyen los siguientes cambios:

  • La forma no corta de UTF-8, como <C0, AF>, se trata como incorrecta.
  • La forma subrogada de UTF-8, como U+D800..U+DFFF, se trata como incorrecta.
  • La subparte máxima se reemplaza por una sola U+FFFD. Por ejemplo, en la secuencia de bytes “41 C0 AF 41 F4 80 80 41”, las subsecciones máximas son “C0”, “AF” y “F4 80 80”. “F4 80 80” puede ser la subsecuencia inicial de “F4 80 80 80”, pero “C0” no puede ser la subsecuencia inicial de ninguna secuencia de unidades de código bien formada. Por lo tanto, el resultado debe ser “A\ufffd\ufffdA\ufffdA”.
  • Para decodificar una secuencia modificada UTF-8 o CESU-8 en Android 9 o versiones posteriores, usa el método DataInputStream.readUTF() o el método NewStringUTF() de JNI.

Verificación del nombre de host con un certificado

RFC 2818 describe dos métodos para hacer coincidir un nombre de dominio con un certificado: mediante los nombres disponibles dentro de la extensión subjectAltName (SAN) o, en ausencia de una extensión SAN, volviendo a commonName (CN).

Sin embargo, el resguardo de CN dejó de estar disponible en RFC 2818. Por este motivo, Android ya no usa CN. Para verificar un nombre de host, el servidor debe presentar un certificado con un SAN coincidente. Los certificados que no contienen un SAN que coincide con el nombre de host ya no se consideran confiables.

Las búsquedas de direcciones de red pueden causar incumplimientos de red

Las búsquedas de direcciones de red que requieren resolución de nombres pueden implicar E/S de red y, por lo tanto, se consideran operaciones de bloqueo. Las operaciones de bloqueo en el subproceso principal pueden provocar pausas o bloqueos.

La clase StrictMode es una herramienta de desarrollo que ayuda a los desarrolladores a detectar problemas en su código.

En Android 9 y versiones posteriores, StrictMode detecta los incumplimientos de red causados por las búsquedas de direcciones de red que requieren resolución de nombres.

No debes enviar tus apps con StrictMode habilitado. Si lo haces, tus apps pueden experimentar excepciones, como NetworkOnMainThreadException, cuando usen los métodos detectNetwork() o detectAll() para obtener una política que detecte incumplimientos de red.

Resolver una dirección IP numérica no se considera una operación de bloqueo. La resolución de la dirección IP numérica funciona de la misma manera que en versiones anteriores a Android 9.

Etiquetado de sockets

En las versiones de plataforma anteriores a Android 9, si un socket se etiqueta con el método setThreadStatsTag(), este no se etiqueta cuando se envía a otro proceso mediante la IPC de enlace con un contenedor ParcelFileDescriptor.

En Android 9 y versiones posteriores, la etiqueta del socket se conserva cuando se envía a otro proceso mediante IPC de Binder. Este cambio puede afectar las estadísticas del tráfico de red, por ejemplo, cuando se usa el método queryDetailsForUidTag().

Si deseas conservar el comportamiento de las versiones anteriores, que quita la etiqueta de un socket que se envía a otro proceso, puedes llamar a untagSocket() antes de enviar el socket.

Cantidad informada de bytes disponibles en el socket

El método available() muestra 0 cuando se llama después de invocar el método shutdownInput().

Informes más detallados de capacidades de red para VPN

En Android 8.1 (nivel de API 27) y versiones anteriores, la clase NetworkCapabilities solo informaba un conjunto limitado de información para VPN, como TRANSPORT_VPN, pero omitía NET_CAPABILITY_NOT_VPN. Esta información limitada hacía que fuera difícil determinar si el uso de una VPN generaría cargos para el usuario de la app. Por ejemplo, la verificación de NET_CAPABILITY_NOT_METERED no determinaba si las redes subyacentes eran de uso medido o no.

En Android 9 y versiones posteriores, cuando una VPN llama al método setUnderlyingNetworks(), el sistema de Android combina los transportes y las capacidades de cualquier red subyacente y muestra el resultado como las capacidades de red efectivas de la red VPN.

En Android 9 y versiones posteriores, las apps que ya buscan NET_CAPABILITY_NOT_METERED recibirán las capacidades de red de la VPN y las redes subyacentes.

Los archivos de la carpeta xt_qtaguid ya no están disponibles para las apps

A partir de Android 9, las apps no pueden tener acceso de lectura directo a los archivos de la carpeta /proc/net/xt_qtaguid. Esto se realiza para garantizar la coherencia con algunos dispositivos que no incluyen estos archivos.

Las APIs públicas que dependen de estos archivos, TrafficStats y NetworkStatsManager, siguen funcionando según lo previsto. Sin embargo, es posible que las funciones cutils no compatibles, como qtaguid_tagSocket(), no funcionen como se espera (o que no funcionen en absoluto) en diferentes dispositivos.

Ahora se aplica el requisito de FLAG_ACTIVITY_NEW_TASK

Con Android 9, no puedes iniciar una actividad desde un contexto sin actividad, a menos que pases la marca de intent FLAG_ACTIVITY_NEW_TASK. Si intentas iniciar una actividad sin pasar esta marca, esta no se iniciará y el sistema imprimirá un mensaje en el registro.

Cambios en la rotación de pantalla

A partir de Android 9, hay cambios significativos en el modo de rotación vertical. En Android 8.0 (nivel de API 26), los usuarios podían activar o desactivar los modos de rotación de rotación automática y vertical con una configuración de tarjeta o pantalla de Quicksettings. Se cambió el nombre del modo de retrato a bloqueo de rotación, y permanece activo cuando se desactiva la rotación automática. No se realizaron cambios en el modo de rotación automática.

Cuando el dispositivo está en modo de bloqueo de rotación, los usuarios pueden bloquear la pantalla en cualquier rotación que admita la Actividad superior visible. Una Activity no debe suponer que siempre se renderizará en modo vertical. Si la Activity superior se puede renderizar en varias rotaciones en el modo de rotación automática, las mismas opciones deberían estar disponibles en el modo de rotación bloqueada, con algunas excepciones según la configuración screenOrientation de la Activity (consulta la tabla a continuación).

Las actividades que solicitan una orientación específica (por ejemplo, screenOrientation=landscape) ignoran la preferencia de bloqueo del usuario y se comportan del mismo modo que en Android 8.0.

La preferencia de orientación de la pantalla se puede establecer en el nivel de Activity en el manifiesto de Android o de manera programática con setRequestedOrientation().

El modo de bloqueo de rotación funciona estableciendo la preferencia de rotación del usuario que usa WindowManager cuando controla la rotación de la actividad. La preferencia de rotación del usuario se puede cambiar en los siguientes casos. Ten en cuenta que hay un sesgo para volver a la rotación natural del dispositivo, que normalmente es vertical para los dispositivos con factores de forma de teléfonos:

  • Cuando el usuario acepta una sugerencia de rotación, la preferencia de rotación cambia a la sugerencia.
  • Cuando el usuario cambia a una app vertical forzada (incluida la pantalla de bloqueo o el selector), la preferencia de rotación cambia al modo vertical.

En la siguiente tabla, se resume el comportamiento de rotación de las orientaciones comunes de la pantalla:

Orientación de pantalla Comportamiento
sin especificar, usuario En la rotación automática y el bloqueo de rotación, la Actividad se puede renderizar en posición horizontal o vertical (y viceversa). Se prevé compatibilidad con diseños verticales y horizontales.
Horizontal de usuarios En la rotación automática y el bloqueo de rotación, la Activity se puede renderizar en modo horizontal o horizontal inverso. Se prevé asistencia solo para diseños horizontales.
userPortrait En la rotación automática y el bloqueo de rotación, la actividad se puede renderizar en el modo vertical o vertical inverso. Se prevé compatibilidad solo con diseños verticales.
Usuariocompleto En la rotación automática y el bloqueo de rotación, la Actividad se puede renderizar en posición horizontal o vertical (y viceversa). Se prevé compatibilidad con diseños verticales y horizontales.

Los usuarios del bloqueo de rotación tendrán la opción de aplicar el bloqueo al modo vertical inverso, que suele ser de 180°.
sensor, fullSensor, sensorPortrait y sensorLandscape La preferencia del modo de bloqueo de rotación se ignora y se trata como si el giro automático estuviera activo. Solo debe usarse en circunstancias excepcionales, con especial consideración de la experiencia del usuario.

La baja del cliente HTTP de Apache afecta a las apps con ClassLoader no estándar

En Android 6.0, quitamos la compatibilidad con el cliente HTTP de Apache. Este cambio no afecta a la gran mayoría de las apps que no se orientan a Android 9 o versiones posteriores. Sin embargo, el cambio puede afectar a ciertas apps que usan una estructura ClassLoader no estándar, incluso si las apps no se orientan a Android 9 o versiones posteriores.

Una app puede verse afectada si usa un ClassLoader no estándar que se delega al ClassLoader de forma explícita. En cambio, estas apps deben delegar a la app ClassLoader cuando buscan clases en org.apache.http.*. Si delegan al ClassLoader del sistema, las apps fallarán en Android 9 o versiones posteriores con un NoClassDefFoundError, debido a que el sistema ya no conoce esas clases ClassLoader. Para evitar problemas similares en el futuro, en general, las apps deben cargar las clases a través de la app ClassLoader, en lugar de acceder directamente al ClassLoader del sistema.

Cómo enumerar cámaras

Las apps que se ejecutan en dispositivos con Android 9 pueden descubrir todas las cámaras disponibles llamando a getCameraIdList(). Una app no debe suponer que el dispositivo tiene una sola cámara trasera o frontal.

Por ejemplo, si tu app tiene un botón para alternar entre la cámara frontal y la posterior, puede haber más de una cámara frontal o posterior para elegir. Debes revisar la lista de cámaras, examinar las características de cada una de ellas y decidir qué cámaras exponer al usuario.