Además de nuevas funciones y capacidades, Android 7.0 incluye varios cambios en el comportamiento del sistema y de la API. En este documento, se destacan algunos de los cambios clave que debes comprender y tener en cuenta en tus apps.
Si publicaste anteriormente una app para Android, ten en cuenta que esta podría verse afectada por estos cambios en la plataforma.
Batería y memoria
Android 7.0 incluye cambios en el comportamiento del sistema para mejorar la duración de la batería de los dispositivos y reducir el uso de RAM. Estos cambios pueden afectar el acceso de tu app a los recursos del sistema, además de la forma en que tu app interactúa con otras apps mediante ciertos intents implícitos.
Descanso
Descanso, presentado en Android 6.0 (nivel de API 23), mejora la duración de la batería aplazando las actividades de la CPU y la red cuando un usuario deja un dispositivo desenchufado, quieto y con la pantalla apagada. Android 7.0 ofrece mejoras adicionales a Descanso mediante la aplicación de un subconjunto de restricciones de CPU y red mientras el dispositivo está desenchufado con la pantalla apagada, pero no necesariamente con el teléfono celular cuando el usuario está desenchufado (por ejemplo, cuando el usuario está desenchufado).
Cuando un dispositivo funciona con la batería y la pantalla permanece apagada durante un tiempo determinado, el dispositivo activa el modo Descanso y aplica el primer subconjunto de restricciones: desactiva el acceso a la red de las apps y aplaza tareas y sincronizaciones. Si el dispositivo permanece inactivo durante un tiempo determinado después de activar el modo Descanso, el sistema aplica el resto de las restricciones del modo Descanso a las alarmas PowerManager.WakeLock
, AlarmManager
, GPS y escaneos de Wi-Fi. Independientemente de si se aplican algunas o todas las restricciones de Descanso, el sistema activa el dispositivo durante períodos de mantenimiento breves, durante los cuales las aplicaciones tienen acceso a la red y pueden ejecutar cualquier tarea o sincronización aplazada.
Ten en cuenta que, cuando se activa la pantalla o se enchufa el dispositivo, se desactiva el modo Descanso y se quitan estas restricciones de procesamiento. El comportamiento adicional no afecta las recomendaciones ni las prácticas recomendadas para adaptar tu app a la versión anterior de Descanso, presentada en Android 6.0 (nivel de API 23), según se describe en Cómo optimizar para Descanso y App Standby. Aun así, debes seguir esas recomendaciones, como usar Firebase Cloud Messaging (FCM) para enviar y recibir mensajes, y comenzar a planificar actualizaciones para adaptarse al comportamiento adicional de Descanso.
Project Svelte: Optimizaciones en segundo plano
Android 7.0 quita tres transmisiones implícitas para ayudar a optimizar el uso de la memoria y el consumo de energía. Este cambio es necesario porque las transmisiones implícitas suelen iniciar apps que se registran para escucharlas en segundo plano. Quitar estas transmisiones puede mejorar considerablemente el rendimiento del dispositivo y la experiencia del usuario.
Los dispositivos móviles cambian de conectividad con frecuencia, como cuando se alterna entre Wi-Fi y datos móviles. Actualmente, las apps pueden supervisar los cambios en la conectividad registrando un receptor para la transmisión CONNECTIVITY_ACTION
implícita en su manifiesto. Dado que muchas apps se registran para recibir esta transmisión, un solo cambio de red puede hacer que todas se activen y procesen la transmisión a la vez.
Del mismo modo, en versiones anteriores de Android, las apps podían registrarse para recibir transmisiones implícitas de ACTION_NEW_PICTURE
y ACTION_NEW_VIDEO
de otras apps, como Cámara. Cuando un usuario toma una foto con la app de Cámara, estas apps se activan para procesar la transmisión.
Para solucionar estos problemas, en Android 7.0 se aplican las siguientes optimizaciones:
- Las apps que se orientan a Android 7.0 (nivel de API 24) y versiones posteriores no recibirán transmisiones de
CONNECTIVITY_ACTION
si declaran su receptor de emisión en el manifiesto. Las apps seguirán recibiendo transmisiones deCONNECTIVITY_ACTION
si registran suBroadcastReceiver
conContext.registerReceiver()
, y ese contexto sigue siendo válido. - El sistema ya no envía transmisiones
ACTION_NEW_PICTURE
oACTION_NEW_VIDEO
. Esta optimización afecta a todas las apps, no solo a las orientadas a Android 7.0.
Si la app usa alguno de estos intents, debes quitarles las dependencias lo antes posible para poder orientar los dispositivos con Android 7.0 correctamente.
El framework de Android ofrece varias soluciones para mitigar la necesidad de estas transmisiones implícitas. Por ejemplo, la API de JobScheduler
proporciona un mecanismo sólido para programar operaciones de red cuando se cumplen condiciones especificadas, como una conexión a una red no medida. Incluso puedes usar JobScheduler
para reaccionar a los cambios realizados en los proveedores de contenido.
Para obtener más información sobre las optimizaciones en segundo plano en Android 7.0 (nivel de API 24) y cómo adaptar tu app, consulta Optimizaciones en segundo plano.
Cambios en los permisos
En Android 7.0, se incorporan cambios en permisos que pueden afectar tu app.
Cambios en los permisos del sistema de archivos
Para mejorar la seguridad de los archivos privados, el directorio privado de las apps orientadas a Android 7.0 o versiones posteriores tiene acceso restringido (0700
). Esta configuración evita la filtración de metadatos de archivos privados, como su tamaño o existencia. Este cambio en los permisos tiene varios efectos secundarios:
-
El propietario ya no debe flexibilizar los permisos de archivo de los archivos privados, y un intento de hacerlo con
MODE_WORLD_READABLE
oMODE_WORLD_WRITEABLE
activará unaSecurityException
.Nota: A partir de ahora, esta restricción no se aplicará plenamente. Las apps aún pueden modificar los permisos de sus directorios privados con las APIs nativas o la API de
File
. Sin embargo, no recomendamos reducir los permisos para el directorio privado. -
Pasar URIs de
file://
fuera del dominio del paquete puede dejar al receptor con una ruta de acceso inaccesible. Por lo tanto, los intentos de pasar un URIfile://
activan unaFileUriExposedException
. La forma recomendada de compartir el contenido de un archivo privado es conFileProvider
. -
El
DownloadManager
ya no puede compartir archivos almacenados de forma privada por nombre de archivo. Las aplicaciones heredadas pueden terminar con una ruta de acceso inaccesible cuando acceden aCOLUMN_LOCAL_FILENAME
. Las apps orientadas a Android 7.0 o versiones posteriores activan unaSecurityException
cuando intentan acceder aCOLUMN_LOCAL_FILENAME
. Las aplicaciones heredadas que establecen la ubicación de descarga en una ubicación pública conDownloadManager.Request.setDestinationInExternalFilesDir()
oDownloadManager.Request.setDestinationInExternalPublicDir()
aún pueden acceder a la ruta de acceso enCOLUMN_LOCAL_FILENAME
. Sin embargo, no es recomendable usar este método. La forma preferida de acceder a un archivo expuesto porDownloadManager
es usarContentResolver.openFileDescriptor()
.
Intercambio de archivos entre apps
En el caso de las apps orientadas a Android 7.0, el framework de Android aplica la política de la API StrictMode
que prohíbe exponer los URI de file://
fuera de la app. Si un intent que contiene un URI de archivo sale de tu app, esta falla con una excepción FileUriExposedException
.
Para compartir archivos entre aplicaciones, debes enviar un URI content://
y otorgar un permiso de acceso temporal en el URI. La manera más fácil de otorgar este permiso es usar la clase FileProvider
. Para obtener más información sobre permisos y cómo compartir archivos, consulta Cómo compartir archivos.
Mejoras de accesibilidad
En Android 7.0, se incluyen cambios destinados a mejorar la usabilidad de la plataforma para los usuarios con visión reducida o discapacidad visual. Por lo general, estos cambios no deben requerir modificaciones en el código de tu app. Sin embargo, debes revisar estas funciones y probarlas con tu app para evaluar los posibles impactos en la experiencia del usuario.
Zoom de la pantalla
Android 7.0 permite a los usuarios configurar Tamaño de visualización, que amplía o contrae todos los elementos de la pantalla, lo que mejora la accesibilidad del dispositivo para los usuarios con baja visión. Los usuarios no pueden acercar la pantalla más allá del ancho mínimo de sw320dp, que es el ancho de un Nexus 4, un teléfono común de tamaño mediano.
Cuando cambia la densidad del dispositivo, el sistema notifica a las apps en ejecución de las siguientes maneras:
- Si una app tiene como objetivo el nivel de API 23 o uno inferior, el sistema cierra automáticamente todos los procesos en segundo plano. Eso significa que, si un usuario abandona esa app para abrir la pantalla Configuración y cambia la configuración de Tamaño de visualización, el sistema cierra la app de la misma manera que lo haría en una situación de poca memoria. Si la app tiene procesos en primer plano, el sistema notifica a esos procesos el cambio de configuración según se describe en Cómo controlar los cambios en el tiempo de ejecución, como si la orientación del dispositivo hubiera cambiado.
- Si una app se orienta a Android 7.0, todos sus procesos (en primer y segundo plano) reciben una notificación del cambio de configuración, como se describe en Cómo controlar los cambios en tiempo de ejecución.
En la mayoría de las apps no se necesitan cambios para admitir esta función, siempre y cuando sigan las prácticas recomendadas de Android. Verificaciones específicas que deben realizarse:
- Prueba tu app en un dispositivo con un ancho de pantalla de
sw320dp
y asegúrate de que funcione bien. - Cuando cambie la configuración del dispositivo, actualiza la información almacenada en caché que dependa de la densidad, como los mapas de bits o recursos almacenados en caché que se carguen desde la red. Busca cambios en la configuración cuando se reanude la actividad de la app, después de la pausa.
Nota: Si almacenas en caché datos que dependen de la configuración, te recomendamos que incluyas metadatos relevantes, como el tamaño de pantalla adecuado o la densidad de píxeles para esos datos. Guardar estos metadatos te permite decidir si necesitas actualizar los datos almacenados en caché después de un cambio de configuración.
- Evita especificar dimensiones con unidades px, ya que no escalan con la densidad de pantalla. En cambio, especifica las dimensiones con unidades de píxeles independientes de la densidad (
dp
).
Vision Settings en el asistente de configuración
Android 7.0 incluye Vision Settings en la pantalla de bienvenida, en la que los usuarios pueden configurar las siguientes opciones de accesibilidad en un nuevo dispositivo: Gesto de ampliación, Tamaño de fuente, Tamaño de visualización y TalkBack. Este cambio aumenta la visibilidad de errores relacionados con diferentes configuraciones de pantalla. Para evaluar el impacto de esta función, debes probar tus apps con estos parámetros de configuración habilitados. Puedes encontrar los parámetros de configuración en Configuración > Accesibilidad.
Apps del NDK con vínculos a bibliotecas de plataformas
A partir de Android 7.0, el sistema evita que las apps se vinculen de forma dinámica con bibliotecas que no pertenezcan al NDK, lo que puede provocar que tu app falle. El objetivo de este cambio en el comportamiento es crear una experiencia de app coherente en todas las actualizaciones de la plataforma y en diferentes dispositivos. Si bien es posible que tu código no se vincule con bibliotecas privadas, es posible que una biblioteca estática de terceros de tu app lo esté haciendo. Por lo tanto, todos los desarrolladores deben asegurarse de que sus apps no fallen en dispositivos que ejecutan Android 7.0. Si tu app usa código nativo, solo debes usar APIs públicas del NDK.
Tu app podría intentar acceder a las APIs de plataformas privadas de las siguientes tres maneras:
- Tu app accede directamente a bibliotecas de plataformas privadas. Debes actualizar tu app para incluir su propia copia de esas bibliotecas o usar las APIs públicas del NDK.
- Tu app usa una biblioteca de terceros que accede a bibliotecas de plataformas privadas. Incluso si tienes la certeza de que tu app no accede a bibliotecas privadas de forma directa, debes probarla en este caso.
- Tu app hace referencia a una biblioteca que no está incluida en su APK. Por ejemplo, esto podría suceder si intentas usar tu propia copia de OpenSSL, pero olvidas empaquetarla con el APK de la app. La app puede ejecutarse normalmente en versiones de la plataforma de Android que incluyan
libcrypto.so
. Sin embargo, la app podría fallar en versiones posteriores de Android que no incluyan esta biblioteca (como Android 6.0 y versiones posteriores). Para solucionar este problema, asegúrate de agrupar todas las bibliotecas que no pertenezcan al NDK con tu APK.
Las apps no deben usar bibliotecas nativas que no estén incluidas en el NDK, ya que pueden cambiar o quitarse entre diferentes versiones de Android. El cambio de OpenSSL a BoringSSL es un ejemplo de ese cambio. Además, debido a que no existen requisitos de compatibilidad para bibliotecas de plataformas no incluidas en el NDK, los diferentes dispositivos pueden ofrecer diferentes niveles de compatibilidad.
Para reducir el impacto que esta restricción puede tener en las apps lanzadas actualmente, se puede acceder temporalmente a un conjunto de bibliotecas que se usa de manera significativa, como libandroid_runtime.so
, libcutils.so
, libcrypto.so
y libssl.so
, en Android 7.0 (nivel de API 24) para las apps que se orientan al nivel de API 23 o versiones anteriores. Si tu app carga una de estas bibliotecas, logcat genera una advertencia y aparece un aviso en el dispositivo de destino para notificarte. Si ves estas advertencias, debes actualizar tu app para incluir su propia copia de esas bibliotecas o usar solo las APIs públicas del NDK. Las versiones futuras de la plataforma de Android podrían restringir el uso de bibliotecas privadas por completo y hacer que tu app falle.
Todas las apps generan un error de entorno de ejecución cuando llaman a una API a la que no se puede acceder de forma pública ni temporal. Como resultado, System.loadLibrary
y dlopen(3)
muestran NULL
y pueden provocar que tu app falle. Debes revisar el código de tu app para quitar el uso de APIs de plataformas privadas y probar por completo tus apps con un dispositivo o emulador que ejecute Android 7.0 (nivel de API 24). Si no sabes con certeza si tu app usa bibliotecas privadas, puedes verificar logcat para identificar el error en el tiempo de ejecución.
En la siguiente tabla, se describe el comportamiento que deberías esperar de una app según su uso de bibliotecas nativas privadas y su nivel de API objetivo (android:targetSdkVersion
).
Bibliotecas | Nivel de API objetivo | Acceso en tiempo de ejecución por medio de un vinculador dinámico | Comportamiento de Android 7.0 (nivel de API 24) | Comportamiento de la plataforma Android futura |
---|---|---|---|---|
Pública incluida en el NDK | Cualquiera | Fácil acceso | Funciona como se espera. | Funciona como se espera. |
Privada (bibliotecas privadas temporalmente disponibles) | 23 o inferior | Temporalmente disponible | Funciona como se espera, pero aparece una advertencia de logcat. | Error en tiempo de ejecución |
Privada (bibliotecas privadas temporalmente disponibles) | 24 o superior | Restringido | Error en tiempo de ejecución | Error en tiempo de ejecución |
Privada (otra) | Cualquiera | Restringido | Error en tiempo de ejecución | Error en tiempo de ejecución |
Verifica si tu app usa bibliotecas privadas
Para ayudarte a identificar problemas al cargar bibliotecas privadas, logcat puede generar una advertencia o un error de tiempo de ejecución. Por ejemplo, si tu app está orientada al nivel de API 23 o anterior, e intenta acceder a una biblioteca privada en un dispositivo con Android 7.0, es posible que veas una advertencia similar a la siguiente:
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so" ("/system/lib/libandroid_runtime.so") needed or dlopened by "/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120
Estas advertencias de logcat te indican qué biblioteca intenta acceder a una API de plataforma privada, pero no provocarán que tu app falle. Sin embargo, si la app se orienta al nivel de API 24 o superior, logcat genera el siguiente error de tiempo de ejecución y tu app puede fallar:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace" at java.lang.Runtime.loadLibrary0(Runtime.java:977) at java.lang.System.loadLibrary(System.java:1602)
También es posible que veas estos resultados de logcat si tu app usa bibliotecas de terceros que vinculan dinámicamente API de plataformas privadas. La herramienta readelf de Android 7.0DK te permite generar una lista de todas las bibliotecas compartidas vinculadas de forma dinámica de un archivo .so
determinado mediante la ejecución del siguiente comando:
aarch64-linux-android-readelf -dW libMyLibrary.so
Actualiza tu app
A continuación, se incluyen algunos pasos que puedes seguir para corregir estos tipos de errores y asegurarte de que tu app no falle en futuras actualizaciones de la plataforma:
- Si tu app usa bibliotecas de plataformas privadas, debes actualizarla para incluir su propia copia de esas bibliotecas o usar las APIs públicas del NDK.
- Si tu app usa una biblioteca de terceros que accede a símbolos privados, comunícate con el autor de la biblioteca para actualizarla.
- Asegúrate de incluir todas las bibliotecas que no pertenezcan al NDK en tu APK.
- Usa funciones estándar de JNI en lugar de
getJavaVM
ygetJNIEnv
delibandroid_runtime.so
:AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
- Usa
__system_property_get
en lugar del símbolo privadoproperty_get
delibcutils.so
. Para ello, usa__system_property_get
y agrega lo siguiente:#include <sys/system_properties.h>
Nota: La disponibilidad y el contenido de las propiedades del sistema no se prueban a través de CTS. Una mejor solución sería evitar usar estas propiedades por completo.
- Usa una versión local del símbolo
SSL_ctrl
delibcrypto.so
. Por ejemplo, debes vincular estáticamentelibcyrpto.a
en tu archivo.so
o incluir una versión delibcrypto.so
vinculada de forma dinámica de BoringSSL/OpenSSL y empaquetarla en tu APK.
Android for Work
Android 7.0 contiene cambios para apps orientadas a Android for Work, como cambios en la instalación de certificados, el restablecimiento de contraseñas, la administración de usuarios secundarios y el acceso a identificadores de dispositivos. Si compilas apps para entornos de Android for Work, debes revisar estos cambios y modificar tu app según corresponda.
- Debes instalar un instalador de certificados delegados para que el DPC pueda configurarlo. En el caso de las apps de propietarios de perfiles y de dispositivos orientadas a Android 7.0 (nivel de API 24), debes instalar el instalador de certificados delegados antes de que el controlador de política del dispositivo (DPC) llame a
DevicePolicyManager.setCertInstallerPackage()
. Si aún no está instalado, el sistema arroja unaIllegalArgumentException
. - Las restricciones de restablecimiento de contraseñas para administradores de dispositivos ahora se aplican a los propietarios de perfiles. Los administradores de dispositivos ya no pueden usar
DevicePolicyManager.resetPassword()
para borrar contraseñas ni cambiar las que ya están establecidas. Pueden establecer una contraseña, pero solo cuando el dispositivo no tiene contraseña, PIN ni patrón. - Los propietarios de dispositivos y perfiles pueden administrar cuentas incluso si se establecen restricciones. Los propietarios de dispositivos y perfiles pueden llamar a las APIs de administración de cuentas incluso si se aplican restricciones de usuario de
DISALLOW_MODIFY_ACCOUNTS
. - Los propietarios de dispositivos pueden administrar usuarios secundarios de manera más sencilla. Cuando un dispositivo se ejecuta en el modo de propietario de dispositivo, se establece automáticamente la restricción
DISALLOW_ADD_USER
. Esto evita que los usuarios creen usuarios secundarios no administrados. Además, los métodosCreateUser()
ycreateAndInitializeUser()
dejaron de estar disponibles; los reemplaza el nuevo métodoDevicePolicyManager.createAndManageUser()
. - Los propietarios de dispositivos pueden acceder a identificadores de dispositivos. El propietario de un dispositivo puede acceder a la dirección MAC de Wi-Fi de un dispositivo mediante
DevicePolicyManager.getWifiMacAddress()
. Si nunca se habilitó la conexión Wi-Fi en el dispositivo, este método muestra un valor denull
. - La configuración Work Mode controla el acceso a las apps de trabajo. Cuando el modo de trabajo está desactivado, el selector del sistema indica que las apps de trabajo no están disponibles atenuándolas. Si habilitas el modo de trabajo nuevamente, se restablecerá el comportamiento normal.
- Cuando se instala un archivo PKCS #12 que contiene una cadena de certificados de cliente y la clave privada correspondiente de la IU de configuración, el certificado de CA de la cadena ya no se instala en el almacenamiento de credenciales de confianza. Esto no afecta el resultado de
KeyChain.getCertificateChain()
cuando las apps intentan recuperar la cadena de certificados de cliente más tarde. Si es necesario, el certificado de CA debe instalarse en el almacenamiento de credenciales de confianza a través de la IU de configuración por separado, con un formato de codificación DER en una extensión de archivo .crt o .cer. - A partir de Android 7.0, el almacenamiento y la inscripción con huellas dactilares se administran por usuario. Si el cliente de Device Policy (DPC) de un propietario de perfil se orienta al nivel de API 23 (o anterior) en un dispositivo con Android 7.0 (nivel de API 24), el usuario aún puede establecer la huella digital en el dispositivo, pero las aplicaciones de trabajo no pueden acceder a la huella digital del dispositivo. Cuando el DPC se orienta al nivel de API 24 o superior, el usuario puede configurar la huella digital específicamente para el perfil de trabajo desde Configuración > Seguridad > Seguridad del perfil de trabajo.
DevicePolicyManager.getStorageEncryptionStatus()
muestra un nuevo estado de encriptaciónENCRYPTION_STATUS_ACTIVE_PER_USER
para indicar que la encriptación está activa y que la clave de encriptación está vinculada al usuario. El nuevo estado solo se muestra si el DPC se orienta al nivel de API 24 y a niveles superiores. En el caso de las apps que se orientan a niveles de API anteriores, se muestraENCRYPTION_STATUS_ACTIVE
, incluso si la clave de encriptación es específica del usuario o perfil.- En Android 7.0, varios métodos que normalmente afectarían a todo el dispositivo se comportan de manera diferente si este tiene un perfil de trabajo instalado con una comprobación de trabajo separada. En lugar de afectar a todo el dispositivo, estos métodos se aplican solo al perfil de trabajo. (La lista completa de dichos métodos se encuentra en la documentación de
DevicePolicyManager.getParentProfileInstance()
). Por ejemplo,DevicePolicyManager.lockNow()
bloquea solo el perfil de trabajo, en lugar de bloquear todo el dispositivo. Para cada uno de estos métodos, puedes obtener el comportamiento anterior llamando al método en la instancia superior deDevicePolicyManager
; para obtener este superior, llama aDevicePolicyManager.getParentProfileInstance()
. Por ejemplo, si llamas al métodolockNow()
de la instancia superior, se bloqueará todo el dispositivo.
Retención de anotaciones
Android 7.0 soluciona un error por el cual se ignoraba la visibilidad de las anotaciones. Este problema permitió que el tiempo de ejecución accediera a anotaciones a las que no debería haber podido acceder. Entre estas anotaciones, se incluyen las siguientes:
VISIBILITY_BUILD
: Diseñado para ser visible solo en el tiempo de compilación.VISIBILITY_SYSTEM
: destinada a ser visible en el tiempo de ejecución, pero solo al sistema subyacente
Si tu app se basó en este comportamiento, agrega una política de retención a las anotaciones que deben estar disponibles en el tiempo de ejecución. Para ello, usa @Retention(RetentionPolicy.RUNTIME)
.
Cambios en la configuración predeterminada de TLS/SSL
Android 7.0 realiza los siguientes cambios en la configuración predeterminada de TLS/SSL que usan las apps para el tráfico HTTPS y otro tráfico TLS/SSL:
- Se inhabilitaron los conjuntos de algoritmos de cifrado RC4.
- Ahora los conjuntos de algoritmos de cifrado CHACHA20-POLY1305 están habilitados.
Si RC4 está inhabilitado de forma predeterminada, es posible que se generen fallas en la conectividad HTTPS o TLS/SSL cuando el servidor no negocia los conjuntos de algoritmos de cifrado modernos. La solución preferida es mejorar la configuración del servidor para habilitar conjuntos de algoritmos y protocolos de cifrado más sólidos y modernos. Lo ideal sería que se habiliten TLSv1.2 y AES-GCM; además, que se habiliten los conjuntos de algoritmos de cifrado de confidencialidad directa (ECDHE) y que estos sean preferidos.
Una alternativa es modificar la app para que use un SSLSocketFactory
personalizado y se comunique con el servidor. La fábrica debe diseñarse para crear instancias SSLSocket
que tengan habilitados algunos de los conjuntos de algoritmos de cifrado requeridos por el servidor, además de los conjuntos de algoritmos de cifrado predeterminados.
Nota: Estos cambios no corresponden a WebView
.
Apps orientadas a Android 7.0
Estos cambios en el comportamiento se aplican exclusivamente a las apps orientadas a Android 7.0 (nivel de API 24) o versiones posteriores. Las apps que se compilan con Android 7.0 o que establecen targetSdkVersion
en Android 7.0 o versiones posteriores deben modificar sus apps para admitir estos comportamientos de manera correcta, cuando corresponda.
Cambios en la serialización
Android 7.0 (nivel de API 24) corrigió un error en el cálculo del serialVersionUID predeterminado en el que no coincidía con la especificación.
Las clases que implementan Serializable
y no especifican un campo serialVersionUID
explícito podrían ver un cambio en su serialVersionUID predeterminado, lo que generaría una excepción cuando se intentaba deserializar instancias de la clase que se serializaron en una versión anterior o que se serializaron mediante una app orientada a una versión anterior. El mensaje de error será similar al siguiente:
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
Para solucionar estos problemas, se requiere agregar un campo serialVersionUID
a cualquier clase afectada con el valor de stream classdesc
serialVersionUID
del mensaje de error, p.ej., 1234
en este caso. Ese cambio cumple con todas las prácticas recomendadas para escribir código de serialización y funcionará en todas las versiones de Android.
El error específico que se corrigió estaba relacionado con la presencia de métodos de inicializador estáticos, es decir, <clinit>
. De acuerdo con la especificación, la presencia o ausencia de un método de inicializador estático en la clase afectará el serialVersionUID predeterminado calculado para esa clase.
Antes de la corrección de errores, el cálculo también verificaba la superclase en busca de un inicializador estático si una clase no tenía uno.
Para aclarar, este cambio no afecta a las apps orientadas al nivel de API 23 o versiones anteriores, a las clases que tienen un campo serialVersionUID
o a las clases que tienen un método de inicializador estático.
Otros aspectos importantes
- Cuando una app se ejecuta en Android 7.0, pero está orientada a un nivel de API inferior y el usuario cambia el tamaño de pantalla, el proceso de la app finaliza. La app debe poder manejar correctamente esta situación. De lo contrario, fallará cuando el usuario la restablezca desde Recents.
Debes probar tu app para asegurarte de que este comportamiento no ocurra. Puedes hacerlo provocando una falla idéntica cuando se cierra la app de forma manual mediante DDMS.
Las apps orientadas a Android 7.0 (nivel de API 24) y versiones posteriores no finalizan automáticamente por cambios de densidad. Sin embargo, es posible que respondan en forma deficiente a los cambios de configuración.
- En Android 7.0, las apps deben tener capacidad para manejar correctamente los cambios de configuración y no deben fallar en inicios posteriores. Para verificar el comportamiento de la app, cambia el tamaño de la fuente (Configuración > Pantalla > Tamaño de fuente) y restablece la app desde Recientes.
-
Debido a un error en versiones anteriores de Android, el sistema no indicaba la escritura a un socket TCP en el subproceso principal como un incumplimiento de modo estricto. Android 7.0 resuelve este error.
Las apps que muestran este comportamiento ahora arrojan una
android.os.NetworkOnMainThreadException
. En general, realizar operaciones de red en el subproceso principal no es una buena idea, ya que estas operaciones suelen tener una latencia alta que provoca ANR y bloqueos. -
De forma predeterminada, la familia de métodos
Debug.startMethodTracing()
ahora almacena los resultados en el directorio específico del paquete en el almacenamiento compartido, en lugar de hacerlo en el nivel superior de la tarjeta SD. Esto significa que las apps ya no necesitan solicitar el permisoWRITE_EXTERNAL_STORAGE
para usar estas APIs. -
Muchas APIs de plataforma comenzaron a verificar si se envían cargas útiles grandes a través de transacciones
Binder
, y el sistema ahora vuelve a mostrarTransactionTooLargeExceptions
comoRuntimeExceptions
, en lugar de registrarlas o suprimirlas silenciosamente. Un ejemplo común es almacenar demasiados datos enActivity.onSaveInstanceState()
, lo que hace queActivityThread.StopInfo
arroje unaRuntimeException
cuando tu app se orienta a Android 7.0. -
Si una app publica tareas
Runnable
en unView
, yView
no está conectado a una ventana, el sistema pone en cola la tareaRunnable
con elView
; la tareaRunnable
no se ejecuta hasta queView
se adjunta a una ventana. Este comportamiento corrige los siguientes errores:- Si una app publica en una
View
desde un subproceso que no sea el subproceso de IU de la ventana prevista,Runnable
puede ejecutarse en el subproceso incorrecto como resultado. - Si la tarea
Runnable
se publicaba desde un subproceso que no fuera un subproceso de looper, la app podría exponer la tareaRunnable
.
- Si una app publica en una
-
Si una app en Android 7.0 con el permiso
DELETE_PACKAGES
intenta borrar un paquete instalado por otra app, el sistema requiere la confirmación del usuario. En esta situación, las apps deben esperarSTATUS_PENDING_USER_ACTION
como el estado que se muestra cuando invocan aPackageInstaller.uninstall()
. - El proveedor de JCA llamado Crypto está obsoleto porque su único algoritmo (SHA1PRNG) es débil en términos criptográficos. Las apps ya no pueden usar SHA1PRNG para derivar claves (de forma no segura) porque este proveedor ya no está disponible. Para obtener más información, consulta la entrada de blog El proveedor de seguridad "Crypto" quedó obsoleto en Android N.