Cambios de comportamiento en Android 7.0

Además de nuevas funciones y capacidades, Android 7.0 incluye diversos cambios de 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 tu app 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 la app a los recursos del sistema, además de la forma en que esta interactúa con otras apps mediante ciertos intents implícitos.

Descanso

Esta función, que se introdujo en Android 6.0 (nivel de API 23), mejora la duración de la batería, ya que aplaza las actividades de la CPU y la red cuando un usuario deja un dispositivo desconectado, quieto y con la pantalla apagada. Android 7.0 ofrece mejoras adicionales a esta función mediante la aplicación de un subconjunto de restricciones de CPU y red mientras el dispositivo está desconectado con la pantalla apagada, pero no necesariamente con la pantalla apagada, pero no necesariamente con la pantalla apagada.

Ilustración de cómo Descanso aplica el primer nivel de restricciones de actividad del sistema para mejorar la duración de batería

Figura 1: Ilustración de cómo Descanso aplica el primer nivel de restricciones de actividad del sistema para mejorar la duración de batería.

Cuando un dispositivo funciona con batería y la pantalla estuvo apagada durante un tiempo determinado, se activa el modo Descanso en el dispositivo y se 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 de Descanso a las alarmas PowerManager.WakeLock, AlarmManager, GPS y búsqueda de Wi-Fi. Independientemente de que se apliquen 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.

Ilustración de cómo Descanso aplica un segundo nivel de restricciones de actividad del sistema después de que el dispositivo permanece quieto durante un tiempo determinado

Figura 2: Ilustración de cómo Descanso aplica un segundo nivel de restricciones de actividad del sistema después de que el dispositivo permanece quieto durante un tiempo determinado.

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), como se describe en Cómo optimizar para Descanso y App Standby. De todas maneras, deberás 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. La eliminación de estas transmisiones puede beneficiar de forma sustancial el rendimiento del dispositivo y la experiencia del usuario.

Los dispositivos móviles experimentan cambios de conectividad frecuentes, como cuando se alternan entre Wi-Fi y datos móviles. Actualmente, las apps pueden supervisar los cambios de conectividad registrando un receptor para la transmisión CONNECTIVITY_ACTION implícita en su manifiesto. Debido a que muchas apps se registran para recibir esta transmisión, un solo cambio de red puede provocar 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 corregir estos problemas, en Android 7.0 se aplican las siguientes optimizaciones:

Si tu app usa alguno de estos intents, debes quitar las dependencias en ellos lo antes posible para poder orientar dispositivos con Android 7.0 de manera correcta. El framework de Android proporciona 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 específicas, como una conexión a una red no medida. Incluso puedes usar JobScheduler para reaccionar a los cambios 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 la manera de 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:

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 forma más fácil de otorgar este permiso es usar la clase FileProvider. Para obtener más información sobre permisos y uso compartido de 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 baja 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 el posible impacto en la experiencia del usuario.

Zoom de la pantalla

Android 7.0 permite a los usuarios configurar el Tamaño de pantalla, 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 podrán hacer zoom en la pantalla más allá del ancho mínimo de sw320dp, que es el ancho de un Nexus 4, un teléfono común mediano.

Pantalla en la que se muestra el tamaño sin zoom de un dispositivo que ejecuta una imagen del sistema de Android 7.0
Pantalla que muestra el efecto de aumentar el tamaño de la pantalla de un dispositivo que ejecuta una imagen del sistema de Android 7.0

Figura 3: En la pantalla de la derecha, se muestra el efecto de aumentar el tamaño de visualización de un dispositivo que ejecuta una imagen del sistema de Android 7.0.

Cuando cambia la densidad del dispositivo, el sistema notifica a las apps de las siguientes maneras:

  • Si una app tiene como objetivo el nivel de API 23 o uno inferior, el sistema finaliza automáticamente todos los procesos en segundo plano. Es decir, si un usuario deja de usar 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 les notificará a esos procesos sobre el cambio de configuración como se describe en Cómo controlar los cambios en el tiempo de ejecución, como si hubiera cambiado la orientación del dispositivo.
  • Si una app se orienta a Android 7.0, se notifica a todos los procesos (en primer y segundo plano) el cambio en la configuración, como se describe en Cómo controlar los cambios en el tiempo de ejecución.

La mayoría de las apps no necesitan hacer cambios para admitir esta función, siempre que sigan las prácticas recomendadas de Android. Verificaciones específicas que deben realizarse:

  • Prueba tu app en un dispositivo con un ancho de pantalla 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 los recursos almacenados en caché que se carguen desde la red. Comprueba si hay cambios de 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 la 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 los siguientes parámetros de accesibilidad en un dispositivo nuevo: Gesto de ampliación, Tamaño de fuente, Tamaño de la pantalla y TalkBack. Este cambio aumenta la visibilidad de los 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 la configuración en Configuración > Accesibilidad.

Apps del NDK con vínculos a bibliotecas de plataformas

A partir de Android 7.0, el sistema impide que las apps se vinculen de forma dinámica con bibliotecas que no pertenezcan al NDK, lo que puede hacer 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 diferentes dispositivos. Si bien es posible que tu código no esté vinculado 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 con Android 7.0. Si tu app usa código nativo, solo debes usar las APIs públicas del NDK.

Existen tres maneras en las que tu app podría intentar acceder a las APIs de plataformas privadas:

  • 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 estás seguro de que tu app no accede directamente a las bibliotecas privadas, debes probarla para esta situación.
  • 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 tu 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 porque 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 hay 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 considerablemente (como libandroid_runtime.so, libcutils.so, libcrypto.so y libssl.so) en Android 7.0 (nivel de API 24) para las apps orientadas al nivel de API 23 o versiones anteriores. Si tu app carga una de esas 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 por completo el uso de bibliotecas privadas 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 hacer 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 estás seguro de si tu app usa bibliotecas privadas, puedes consultar 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 Accesible 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 con la carga de 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 versiones posteriores, 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 se vinculan de forma dinámica a APIs 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 la 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 y getJNIEnv de libandroid_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 privado property_get de libcutils.so. Para ello, usa __system_property_get con lo siguiente:
    #include <sys/system_properties.h>
    

    Nota: La disponibilidad y el contenido de las propiedades del sistema no se prueban a través del CTS. Una mejor solución sería evitar usar estas propiedades por completo.

  • Usa una versión local del símbolo SSL_ctrl de libcrypto.so. Por ejemplo, debes vincular libcyrpto.a de forma estática en tu archivo .so o incluir una versión de libcrypto.so de BoringSSL/OpenSSL vinculada de forma dinámica y empaquetarla en tu APK.

Android for Work

Android 7.0 contiene cambios para apps orientadas a Android for Work, como modificaciones en la instalación de certificados, el restablecimiento de contraseñas, la administración secundaria de usuarios 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 el instalador no está instalado, el sistema arroja un IllegalArgumentException.
  • 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. Aun así, 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 Account Management incluso si se aplican restricciones de usuario 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, se establece automáticamente la restricción DISALLOW_ADD_USER. Esto evita que los usuarios creen usuarios secundarios no administrados. Además, los métodos CreateUser() y createAndInitializeUser() dejaron de estar disponibles; los reemplaza el nuevo método DevicePolicyManager.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 a través de DevicePolicyManager.getWifiMacAddress(). Si nunca se habilitó la conexión Wi-Fi en el dispositivo, este método muestra un valor de null.
  • La configuración Work Mode controla el acceso a las apps de trabajo. Cuando este modo está desactivado, el selector del sistema indica que las apps de trabajo no están disponibles atenuándolas. Si vuelves a habilitar el modo de trabajo, 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 la AC 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 del cliente más tarde. Si es necesario, se debe instalar el certificado de la AC en el almacenamiento de credenciales de confianza a través de la IU de configuración por separado, con un formato codificado en DER con 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 configurar 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 si va a Configuración > Seguridad > Seguridad del perfil de trabajo.
  • DevicePolicyManager.getStorageEncryptionStatus() muestra un nuevo estado de encriptación ENCRYPTION_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 muestra ENCRYPTION_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 independiente. En lugar de afectar a todo el dispositivo, estos métodos se aplican solo al perfil de trabajo. (La lista completa de estos métodos se encuentra en la documentación de DevicePolicyManager.getParentProfileInstance()). Por ejemplo, DevicePolicyManager.lockNow() bloquea solo el perfil de trabajo, en lugar de todo el dispositivo. Para cada uno de estos métodos, puedes obtener el comportamiento anterior llamando al método en la instancia superior de DevicePolicyManager; para obtener este superior, llamando a DevicePolicyManager.getParentProfileInstance(). Por ejemplo, si llamas al método lockNow() de la instancia superior, se bloquea 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ñada para ser visible solo en el tiempo de compilación.
  • VISIBILITY_SYSTEM: destinada a ser visible en el tiempo de ejecución, pero solo para el sistema subyacente.

Si tu app se basa en este comportamiento, agrega una política de retención a las anotaciones que deben estar disponibles durante 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 fallen en la conectividad HTTPS o TLS/SSL cuando el servidor no negocia conjuntos de cifrado modernos. La solución preferida es mejorar la configuración del servidor para habilitar conjuntos y protocolos de cifrado más sólidos y modernos. Lo ideal es que se habiliten TLSv1.2 y AES-GCM, así como que se habiliten los conjuntos de cifrado de confidencialidad directa (ECDHE) y se prefieran.

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 de 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 están relacionados con WebView.

Apps orientadas a Android 7.0

Estos cambios de 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 configuran targetSdkVersion en Android 7.0 o versiones posteriores deben modificarlas para que admitan correctamente estos comportamientos, cuando corresponda.

Cambios en la serialización

Android 7.0 (nivel de API 24) corrigió un error en el cálculo del serialVersionUID predeterminado por 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 al intentar 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, es necesario 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 inicialización estáticos, es decir, <clinit>. Según la especificación, la presencia o ausencia de un método de inicialización 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.

A modo de aclaración, este cambio no afecta a las apps orientadas al nivel de API 23 o versiones anteriores, a las clases que tienen un campo serialVersionUID ni 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 se orienta a un nivel de API inferior, y el usuario cambia el tamaño de visualización, el proceso de la app finaliza. La app debe tener capacidad para 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. Para ello, causa una falla idéntica cuando finalizas 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 debido a los cambios de densidad. Sin embargo, es posible que respondan de manera deficiente a los cambios de configuración.

  • En Android 7.0, las apps deben poder 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 en un socket TCP en el subproceso principal como una infracción de modo estricto. Android 7.0 resuelve este error. Las apps que muestran este comportamiento ahora arrojan un android.os.NetworkOnMainThreadException. En general, no es recomendable realizar operaciones de red en el subproceso principal, ya que estas operaciones suelen tener una latencia alta que provoca ANR y bloqueos.
  • La familia de métodos Debug.startMethodTracing() ahora almacena de forma predeterminada 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 permiso WRITE_EXTERNAL_STORAGE para usar estas APIs.
  • Muchas APIs de plataforma comenzaron a verificar si hay cargas útiles grandes que se envíen a través de transacciones Binder, y el sistema ahora vuelve a arrojar TransactionTooLargeExceptions como RuntimeExceptions, en lugar de registrarlas o suprimirlas silenciosamente. Un ejemplo común es almacenar demasiados datos en Activity.onSaveInstanceState(), lo que hace que ActivityThread.StopInfo arroje una RuntimeException cuando tu app se orienta a Android 7.0.
  • Si una app publica tareas Runnable en una View y View no está adjunta a una ventana, el sistema pone en cola la tarea Runnable con el View; la tarea Runnable no se ejecutará hasta que View esté adjunta a una ventana. Este comportamiento corrige los siguientes errores:
    • Si una app publicaba en un View desde un subproceso que no fuera el de la IU de la ventana prevista, es posible que Runnable se ejecute en el subproceso incorrecto.
    • Si la tarea Runnable se publicó desde un subproceso que no fuera un subproceso de looper, la app podría exponer la tarea Runnable.
  • Si una app en Android 7.0 con el permiso DELETE_PACKAGES intenta borrar un paquete, pero otra app lo instaló, el sistema requiere la confirmación del usuario. En este caso, las apps deberían esperar que el estado que se muestra sea STATUS_PENDING_USER_ACTION cuando invoquen a PackageInstaller.uninstall().
  • El proveedor de JCA llamado Crypto está obsoleto porque su único algoritmo, SHA1PRNG, es débil desde el punto de vista criptográfico. 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 sobre el proveedor de seguridad "Crypto" que dejó de estar disponible en Android N.