Android 10 incluye cambios de comportamiento que podrían afectar a tu app.
Los cambios que se indican en esta página se aplican a tu app cuando se ejecuta
en Android 10, independientemente de la targetSdkVersion de la app. Debes probar tu app y, luego, modificarla según corresponda para admitir estos cambios.
Si el valor de targetSdkVersion de tu app es 29 o superior, también deberás admitir cambios adicionales. Asegúrate de leer los cambios de comportamiento de las apps orientadas al nivel 29 para obtener más detalles.
Nota: Además de los cambios que se indican en esta página, Android 10 presenta una gran cantidad de cambios y restricciones basados en la privacidad, incluidos los siguientes:
- Acceso en segundo plano a la ubicación del dispositivo
- Inicio de actividades en segundo plano
- Información de afinidad de contactos
- Aleatorización de direcciones MAC
- Metadatos de la cámara
- Modelo de permisos
Estos cambios afectan a todas las apps y mejoran la privacidad del usuario. Para obtener más información sobre cómo admitir estos cambios, consulta la página Cambios de privacidad.
Restricciones en interfaces no SDK
Para garantizar la estabilidad y compatibilidad de las apps, la plataforma comenzó a restringir las interfaces que no pertenecen al SDK que tu app puede usar en Android 9 (nivel de API 28). Android 10 incluye listas actualizadas de interfaces restringidas que no pertenecen al SDK, basadas en la colaboración con desarrolladores de Android y las pruebas internas más recientes. Nuestro objetivo es asegurarnos de que las alternativas públicas estén disponibles antes de restringir las interfaces que no pertenecen al SDK.
Si no orientas tu app a Android 10 (nivel de API 29), es posible que algunos de estos cambios no te afecten de inmediato. Sin embargo, aunque actualmente puedes usar algunas interfaces que no pertenecen al SDK (según el nivel de API al que esté orientada la app), utilizar cualquier método o campo que no pertenezca al SDK siempre implica un gran riesgo de error para tu app.
En caso de no saber con certeza si tu app usa este tipo de interfaces, puedes probarla para verificarlo. Si tu app depende de interfaces que no pertenezcan al SDK, deberías planificar una migración hacia otras alternativas que sí lo hagan. Sin embargo, sabemos que algunas apps tienen casos prácticos válidos para usarlas. Si no encuentras una alternativa al uso de una interfaz que no pertenece al SDK para una función de tu app, deberías solicitar una nueva API pública.
Para obtener más información, consulta Actualizaciones de las restricciones de interfaces que no pertenecen al SDK en Android 10 y Restricciones en interfaces que no pertenecen al SDK.
Navegación por gestos
A partir de Android 10, los usuarios pueden habilitar la navegación por gestos en todo el dispositivo. Si un usuario habilita la navegación por gestos, se verán afectadas todas las apps del dispositivo, independientemente de si se orientan al nivel de API 29. Por ejemplo, si el usuario desliza el dedo desde el borde de la pantalla, el sistema interpreta ese gesto como una navegación hacia atrás, a menos que una app anule específicamente ese gesto para partes de la pantalla.
Para que tu app sea compatible con la navegación por gestos, deberás extender el contenido de la app de borde a borde y controlar los gestos en conflicto de forma adecuada. Para obtener más información, consulta la documentación sobre la navegación por gestos.
NDK
En Android 10, se incluyen los siguientes cambios en el NDK.
Los objetos compartidos no pueden contener reubicaciones de texto
En Android 6.0 (nivel de API 23), se inhabilitó el uso de reubicaciones de texto en objetos compartidos. El código se debe cargar tal como está y no se debe modificar. Este cambio mejora la seguridad y los tiempos de carga de la app.
SELinux aplica esta restricción en las apps orientadas a Android 10 o versiones posteriores. Si estas apps siguen usando objetos compartidos que contienen reubicaciones de texto, corren un alto riesgo de fallar.
Cambios en las bibliotecas Bionic y las rutas de vinculador dinámico
A partir de Android 10, varias rutas de acceso son vínculos simbólicos en lugar de archivos normales. Es posible que las apps que dependen de que las rutas de acceso sean archivos normales no funcionen:
/system/lib/libc.so->/apex/com.android.runtime/lib/bionic/libc.so/system/lib/libm.so->/apex/com.android.runtime/lib/bionic/libm.so/system/lib/libdl.so->/apex/com.android.runtime/lib/bionic/libdl.so/system/bin/linker->/apex/com.android.runtime/bin/linker
Estos cambios también se aplican a las variantes de 64 bits del archivo, con lib/ reemplazado por lib64/.
Para la compatibilidad, los symlinks se proporcionan en las rutas de acceso anteriores. Por ejemplo,
/system/lib/libc.so es un symlink a
/apex/com.android.runtime/lib/bionic/libc.so. Por lo tanto, dlopen(“/system/lib/libc.so”) sigue funcionando, pero las apps encontrarán la diferencia cuando intenten examinar las bibliotecas cargadas leyendo /proc/self/maps o algo similar, lo que no es habitual, pero descubrimos que algunas apps lo hacen como parte de su proceso contra hackeos. Si es así, las rutas de acceso de /apex/… se deben agregar como rutas de acceso válidas para los archivos de Bionic.
Bibliotecas y objetos binarios del sistema asignados a memoria de solo ejecución
A partir de Android 10, los segmentos ejecutables de las bibliotecas y los objetos binarios del sistema se asignan a la memoria de solo ejecución (no legible) como una técnica de endurecimiento contra los ataques de reutilización de código. Si tu app realiza operaciones de lectura en segmentos de memoria marcados como de solo ejecución, ya sea por un error, una vulnerabilidad o una inspección de memoria intencional, el sistema envía un indicador SIGSEGV a tu app.
Para identificar si este comportamiento causó una falla, examina el archivo de tombstone relacionado en /data/tombstones/. Una falla relacionada con la ejecución solo contiene el siguiente mensaje de anulación:
Cause: execute-only (no-read) memory access error; likely due to data in .text.
Para solucionar este problema y realizar operaciones como la inspección de memoria, es posible marcar los segmentos de solo ejecución como de lectura y ejecución llamando a mprotect(). Sin embargo, te recomendamos que vuelvas a establecerlo en solo ejecución, ya que este parámetro de configuración de permisos de acceso proporciona una mejor protección para tu app y los usuarios.
Seguridad
Android 10 incluye los siguientes cambios de seguridad.
TLS 1.3 habilitado de forma predeterminada
En Android 10 y versiones posteriores, TLS 1.3 está habilitado de forma predeterminada para todas las conexiones de TLS. A continuación, se muestran algunos detalles importantes sobre nuestra implementación de TLS 1.3:
- Los conjuntos de cifrado de TLS 1.3 no se pueden personalizar. Aquellos que son compatibles siempre están habilitados cuando TLS 1.3 está habilitado. Se ignorará cualquier intento de inhabilitarlos con una llamada a
setEnabledCipherSuites(). - Cuando se negocia TLS 1.3, se llama a los objetos
HandshakeCompletedListenerantes de que se agreguen sesiones a la caché de sesiones. (En TLS 1.2 y otras versiones anteriores, se llama a estos objetos después de que se agregan las sesiones a la caché de sesiones). - En algunas situaciones en las que las instancias de
SSLEnginearrojanSSLHandshakeExceptionen versiones anteriores de Android, estas instancias, en cambio, arrojanSSLProtocolExceptionen Android 10 y versiones posteriores. - No se admite el modo 0-RTT.
Si lo deseas, puedes obtener un SSLContext que tenga TLS 1.3 inhabilitado con una llamada a
SSLContext.getInstance("TLSv1.2").
También puedes habilitar o inhabilitar versiones de protocolo por conexión si
llamas a setEnabledProtocols()
en un objeto correspondiente.
Los certificados firmados con SHA-1 no son confiables en TLS
En Android 10, los certificados que usan el algoritmo de hash SHA-1 no se consideran confiables en las conexiones de TLS. La AC raíz no emite esos certificados desde 2016, y ya no se consideran confiables en Chrome ni en otros navegadores importantes.
Fallará cualquier intento de establecer conexión con un sitio que presente un certificado que usa SHA-1.
Mejoras y cambios en el comportamiento de KeyChain
Algunos navegadores, como Google Chrome, les permiten a los usuarios elegir un certificado cuando un servidor TLS envía un mensaje de solicitud de certificado como parte de un protocolo de enlace TLS. A partir de Android 10, los objetos KeyChain respetan los emisores y los parámetros de especificación de claves cuando llaman a KeyChain.choosePrivateKeyAlias() para mostrarles a los usuarios un mensaje de selección de certificado. En particular, esta instrucción no contiene opciones que no cumplen con las especificaciones del servidor.
Si no hay ningún certificado disponible para que el usuario seleccione, como sucede cuando no hay ninguno que cumpla con las especificaciones del servidor o un dispositivo no tiene certificados instalados, no se mostrará la solicitud de selección de certificado.
Además, en Android 10 o versiones posteriores, no es necesario tener un bloqueo de pantalla del dispositivo para importar claves o certificados de la AC al objeto KeyChain.
Otros cambios en la criptografía y en TLS
Se realizaron pequeños cambios en las bibliotecas de criptografía y TLS que se aplicarán en Android 10:
- Los cifrados AES/GCM/NoPadding y ChaCha20/Poly1305/NoPadding devuelven tamaños de búfer más precisos desde
getOutputSize(). - El conjunto de algoritmos de cifrado
TLS_FALLBACK_SCSVse omite de los intentos de conexión con un protocolo máximo de TLS 1.2 o superior. Como se incorporaron mejoras en las implementaciones del servidor TLS, no recomendamos revertir a la configuración de TLS externo. En su lugar, recomendamos basarse en la negociación de versiones de TLS. - ChaCha20-Poly1305 es un alias para ChaCha20/Poly1305/NoPadding.
- Los nombres de hosts con puntos finales no se consideran nombres de hosts de SNI válidos.
- Se respeta la extensión supported_signature_algorithms admitida en
CertificateRequestcuando se elige una clave de firma para respuestas de certificados. - Las claves de firma opacas, como las del almacén de claves de Android, se pueden usar con firmas RSA-PSS en TLS.
Transmisiones por Wi-Fi directo
En Android 10, las siguientes transmisiones relacionadas con Wi-Fi Direct no son fijas:
Si tu app dependía de recibir estas transmisiones en el momento del registro porque eran persistentes, usa el método get() adecuado en la inicialización para obtener la información.
Capacidades de reconocimiento de Wi-Fi
Android 10 agrega compatibilidad para facilitar la creación de sockets TCP/UDP con rutas de acceso de datos de Wi-Fi Aware. Para crear un socket TCP/UDP que se conecte a un ServerSocket, el dispositivo cliente
debe conocer la dirección IPv6 y el puerto del servidor. Antes, esto debía comunicarse fuera de banda, por ejemplo, con mensajes de capa 2 de BT o Wi-Fi Aware, o descubrirse dentro de la banda con otros protocolos, como mDNS. Con Android 10, la información se puede comunicar como parte de la configuración de la red.
El servidor puede realizar cualquiera de las siguientes acciones:
- Inicializa un
ServerSockety configura o recupera el puerto que se usará. - Especificar la información del puerto como parte de la solicitud de red de reconocimiento de Wi-Fi
En la siguiente muestra de código, se indica cómo especificar la información del puerto como parte de la solicitud de red:
Kotlin
val ss = ServerSocket() val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("some-password") .setPort(ss.localPort) .build() val myNetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(ns) .build()
Java
ServerSocket ss = new ServerSocket(); WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier .Builder(discoverySession, peerHandle) .setPskPassphrase(“some-password”) .setPort(ss.getLocalPort()) .build(); NetworkRequest myNetworkRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(ns) .build();
Luego, el cliente realiza una solicitud de red de Wi-Fi Aware para obtener la IPv6 y el puerto que proporciona el servidor:
Kotlin
val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { ... } override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { ... } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { ... val ti = networkCapabilities.transportInfo if (ti is WifiAwareNetworkInfo) { val peerAddress = ti.peerIpv6Addr val peerPort = ti.port } } override fun onLost(network: Network) { ... } }; connMgr.requestNetwork(networkRequest, callback)
Java
callback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { ... } @Override public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { ... } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { ... TransportInfo ti = networkCapabilities.getTransportInfo(); if (ti instanceof WifiAwareNetworkInfo) { WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti; Inet6Address peerAddress = info.getPeerIpv6Addr(); int peerPort = info.getPort(); } } @Override public void onLost(Network network) { ... } }; connMgr.requestNetwork(networkRequest, callback);
SYSTEM_ALERT_WINDOW en dispositivos Go
Las apps que se ejecutan en dispositivos con Android 10 (edición Go) no pueden recibir el permiso SYSTEM_ALERT_WINDOW. Esto se debe a que dibujar ventanas de superposición usa demasiada memoria, lo que es particularmente perjudicial para el rendimiento de los dispositivos Android con poca memoria.
Si una app que se ejecuta en un dispositivo con la edición Go que ejecuta Android 9 o una versión anterior recibe el permiso SYSTEM_ALERT_WINDOW, la app lo conservará incluso si el dispositivo se actualiza a Android 10. Sin embargo, las apps que aún no tengan ese permiso no podrán obtenerlo después de que se actualice el dispositivo.
Si una app en un dispositivo Go envía un intent con la acción ACTION_MANAGE_OVERLAY_PERMISSION, el sistema rechaza automáticamente la solicitud y lleva al usuario a una pantalla de Configuración que indica que no se permite el permiso porque ralentiza el dispositivo. Si una app en un dispositivo Go llama a Settings.canDrawOverlays(), el método siempre devuelve un valor falso. Nuevamente, estas restricciones no se aplican a las apps que recibieron el permiso SYSTEM_ALERT_WINDOW antes de que el dispositivo se actualizara a Android 10.
Advertencias para las apps orientadas a versiones anteriores de Android
Los dispositivos que ejecutan Android 10 o versiones posteriores advierten a los usuarios la primera vez que ejecutan cualquier app orientada a Android 5.1 (nivel de API 22) o versiones anteriores. Si la app requiere que el usuario otorgue permisos, también se le dará la oportunidad de ajustar los permisos de la app antes de que se le permita ejecutarla por primera vez.
Debido a los requisitos de API objetivo de Google Play, un usuario ve estas advertencias solo cuando ejecuta una app que no se actualizó recientemente. En el caso de las apps que se distribuyen a través de otras tiendas, se aplicarán requisitos similares de nivel de API objetivo durante 2019. Para obtener más información sobre estos requisitos, consulta Ampliación de los requisitos de nivel de API objetivo en 2019.
Eliminación de conjuntos de cifrado SHA-2 CBC
Se quitaron de la plataforma los siguientes conjuntos de cifrado SHA-2 CBC:
TLS_RSA_WITH_AES_128_CBC_SHA256TLS_RSA_WITH_AES_256_CBC_SHA256TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Estos conjuntos de algoritmos de cifrado son menos seguros que los similares que usan GCM, y la mayoría de los servidores admiten las variantes GCM y CBC de estos conjuntos o no admiten ninguna de ellas.
Uso de apps
Android 10 presenta los siguientes cambios en el comportamiento relacionados con el uso de apps:
Mejoras en el uso de la app de UsageStats: Android 10 hace un seguimiento preciso del uso de las apps con UsageStats cuando se usan en el modo de pantalla dividida o de pantalla en pantalla. Además, Android 10 hace un seguimiento correcto del uso de las apps instantáneas.
Escala de grises por app: Android 10 puede establecer un modo de visualización en escala de grises por app.
Estado de distracción por app: Android 10 puede configurar de forma selectiva las apps en un "estado de distracción" en el que se suprimen sus notificaciones y no aparecen como apps sugeridas.
Suspensión y reproducción: En Android 10, las apps suspendidas no pueden reproducir audio.
Cambios en la conexión HTTPS
Si una app que ejecuta Android 10 pasa null a setSSLSocketFactory(), se produce una IllegalArgumentException. En las versiones anteriores, pasar null en setSSLSocketFactory() tenía el mismo efecto que pasar el valor de fábrica predeterminado actual.
La biblioteca android.preference dejó de estar disponible
La biblioteca android.preference dejó de estar disponible a partir de Android 10.
En su lugar, los desarrolladores deben usar la biblioteca de preferencias de AndroidX, que forma parte de Android Jetpack. Para obtener recursos adicionales que te ayuden en la migración y el desarrollo, consulta la Guía de configuración actualizada, junto con nuestra app de ejemplo pública y la documentación de referencia.
Cambios en la biblioteca de utilidades de archivos ZIP
Android 10 presenta los siguientes cambios en las clases del paquete java.util.zip, que controla los archivos ZIP. Estos cambios hacen que el comportamiento de la biblioteca sea más coherente entre Android y otras plataformas que usan java.util.zip.
Inflater
En las versiones anteriores, algunos métodos de la clase Inflater arrojaban una IllegalStateException si se invocaban después de una llamada a end().
En Android 10, estos métodos arrojan una NullPointerException en su lugar.
ZipFile
En Android 10 y versiones posteriores, el constructor para ZipFile que toma argumentos de tipo File, int y Charset no arroja una ZipException si el archivo ZIP proporcionado no contiene ningún archivo.
ZipOutputStream
En Android 10 y versiones posteriores, el método finish() de ZipOutputStream no arroja una ZipException si intenta escribir un flujo de salida para un archivo ZIP que no contiene ningún archivo.
Cambios en la cámara
Muchas apps que usan la cámara suponen que, si el dispositivo está en una configuración vertical, el dispositivo físico también está en la orientación vertical, como se describe en Orientación de la cámara. Esta era una suposición segura en el pasado, pero eso cambió con la expansión de los factores de forma disponibles, como los dispositivos plegables. Esa suposición en estos dispositivos puede generar una visualización incorrectamente rotada o escalada (o ambas) del visor de la cámara.
Las aplicaciones que se orientan al nivel de API 24 o versiones posteriores deben establecer de forma explícita android:resizeableActivity y proporcionar la funcionalidad necesaria para controlar la operación multiventana.
Seguimiento del uso de batería
A partir de Android 10, SystemHealthManager restablece sus estadísticas de uso de batería cada vez que se desconecta el dispositivo después de un evento de carga importante. En términos generales, un evento de carga importante es cuando el dispositivo se cargó por completo o cuando pasó de estar casi agotado a casi cargado.
Antes de Android 10, las estadísticas de uso de batería se restablecían cada vez que se desconectaba el dispositivo, sin importar qué tan poco hubiera cambiado el nivel de batería.
Baja de Android Beam
En Android 10, daremos de baja oficialmente Android Beam, una función anterior para iniciar el uso compartido de datos entre dispositivos a través de la comunicación de campo cercano (NFC). También daremos de baja varias de las APIs de NFC relacionadas. Android Beam sigue estando disponible de forma opcional para los socios fabricantes de dispositivos que quieran usarlo, pero ya no se encuentra en desarrollo activo. Sin embargo, Android seguirá admitiendo otras APIs y capacidades de NFC, y los casos de uso, como la lectura de etiquetas y los pagos, seguirán funcionando como se espera.
Cambio de comportamiento de java.math.BigDecimal.stripTrailingZeros()
BigDecimal.stripTrailingZeros() ya no conserva los ceros finales como un caso especial si el valor de entrada es cero.
Cambios en el comportamiento de java.util.regex.Matcher y Pattern
Se cambió el resultado de split() para que ya no comience con un String vacío ("") cuando haya una coincidencia de ancho cero al principio de la entrada. Esto también
afecta a String.split(). Por ejemplo, "x".split("") ahora devuelve {"x"}, mientras que solía devolver {"", "x"} en versiones anteriores de Android.
"aardvark".split("(?=a)" ahora devuelve {"a", "ardv", "ark"} en lugar de {"", "a", "ardv", "ark"}.
También se mejoró el comportamiento de las excepciones para los argumentos no válidos:
appendReplacement(StringBuffer, String)ahora arroja unaIllegalArgumentExceptionen lugar deIndexOutOfBoundsExceptionsi elStringde reemplazo termina con una barra inversa sola, lo que no es válido. Ahora, se arroja la misma excepción si elStringde reemplazo termina con un$. Anteriormente, no se generaba ninguna excepción en esta situación.replaceFirst(null)ya no llama areset()enMatchersi arroja unaNullPointerException. Ahora, también se arrojaNullPointerExceptioncuando no hay coincidencias. Anteriormente, solo se arrojaba cuando había una coincidencia.start(int group),end(int group)ygroup(int group)ahora arrojan unaIndexOutOfBoundsExceptionmás general si el índice del grupo está fuera de los límites. Anteriormente, estos métodos arrojabanArrayIndexOutOfBoundsException.
El ángulo predeterminado para GradientDrawable ahora es TOP_BOTTOM
En Android 10, si defines un GradientDrawable en XML y no proporcionas una medición de ángulo, la orientación del gradiente se establece de forma predeterminada en TOP_BOTTOM.
Este es un cambio con respecto a las versiones anteriores de Android, en las que el valor predeterminado era LEFT_RIGHT.
Como solución alternativa, si actualizas a la versión más reciente de AAPT2, la herramienta establece una medición de ángulo de 0 para las apps heredadas si no se especifica ninguna medición de ángulo.
Registro de objetos serializados con el SUID predeterminado
A partir de Android 7.0 (nivel de API 24), la plataforma realizó una corrección en el serialVersionUID predeterminado para los objetos serializables. Esta corrección no afectó a las apps que se orientaban al nivel de API 23 o uno inferior.
A partir de Android 10, si una app se orienta al nivel de API 23 o uno anterior y depende del serialVersionUID predeterminado, antiguo e incorrecto, el sistema registra una advertencia y sugiere una corrección de código.
Específicamente, el sistema registra una advertencia si se cumplen todas las siguientes condiciones:
- La app se orienta al nivel de API 23 o uno anterior.
- Se serializa una clase.
- La clase serializada usa el
serialVersionUIDpredeterminado, en lugar de establecer unserialVersionUIDde forma explícita. - El valor predeterminado de
serialVersionUIDes diferente del que tendríaserialVersionUIDsi la app se orientara al nivel de API 24 o uno superior.
Esta advertencia se registra una vez por cada clase afectada.
El mensaje de advertencia incluye una corrección sugerida, que consiste en establecer de forma explícita el atributo serialVersionUID en el valor predeterminado que se calcularía si la app se orientara al nivel de API objetivo 24 o uno superior. Si usas esa corrección, puedes asegurarte de que, si un objeto de esa clase se serializa en una app orientada al nivel de API 23 o uno anterior, las apps orientadas al nivel 24 o uno posterior lo leerán correctamente, y viceversa.
Cambios en java.io.FileChannel.map()
A partir de Android 10, no se admite FileChannel.map() para archivos no estándar, como /dev/zero, cuyo tamaño no se puede cambiar con truncate(). Las versiones anteriores de Android ignoraban el errno que mostraba truncate(), pero Android 10 arroja una IOException. Si necesitas el comportamiento anterior,
debes usar código nativo.