Changements de comportement dans Android 7.0

En plus de nouvelles fonctionnalités, Android 7.0 inclut divers changements de comportement du système et des API. Ce document présente certains des principaux changements que vous devez comprendre et prendre en compte dans vos applications.

Si vous avez déjà publié une application pour Android, sachez que ces modifications de la plate-forme peuvent l'affecter.

Batterie et mémoire

Android 7.0 inclut des modifications du comportement du système visant à améliorer l'autonomie de la batterie des appareils et à réduire l'utilisation de la RAM. Ces modifications peuvent affecter l'accès de votre application aux ressources système, ainsi que la façon dont elle interagit avec d'autres applications à l'aide de certains intents implicites.

Sommeil

Introduit dans Android 6.0 (niveau d'API 23), le mode Doze améliore l'autonomie de la batterie en différant les activités du processeur et les activités réseau lorsqu'un utilisateur laisse un appareil débranché, immobile et avec l'écran éteint. Android 7.0 apporte d'autres améliorations au mode Doze en appliquant un sous-ensemble de restrictions du processeur et du réseau lorsque l'appareil est débranché avec l'écran éteint, mais pas nécessairement immobile, par exemple lorsqu'un téléphone est dans la poche d'un utilisateur.

Illustration montrant comment le mode Sommeil applique un premier niveau de restrictions d'activité système pour améliorer l'autonomie de la batterie

Figure 1. Illustration de la façon dont le mode Sommeil applique un premier niveau de restrictions d'activité du système pour améliorer l'autonomie de la batterie.

Lorsqu'un appareil est alimenté par batterie et que l'écran est éteint depuis un certain temps, l'appareil passe en mode Sommeil et applique le premier sous-ensemble de restrictions : il désactive l'accès réseau des applications, et reporte les tâches et les synchronisations. Si l'appareil reste immobile pendant un certain temps après l'activation du mode Doze, le système applique les autres restrictions du mode Doze aux alarmes PowerManager.WakeLock et AlarmManager, au GPS et aux recherches de réseaux Wi-Fi. Que certaines ou toutes les restrictions du mode Doze soient appliquées, le système réveille l'appareil pendant de brefs intervalles de maintenance, au cours desquels les applications sont autorisées à accéder au réseau et peuvent exécuter les tâches/synchronisations différées.

Illustration montrant comment le mode Sommeil applique un deuxième niveau de restrictions d'activité du système après que l'appareil est resté immobile pendant un certain temps

Figure 2. Illustration montrant comment le mode Doze applique un deuxième niveau de restrictions d'activité du système après que l'appareil est resté immobile pendant un certain temps.

Notez que l'activation de l'écran ou le branchement de l'appareil désactive le mode Doze et supprime ces restrictions de traitement. Le comportement supplémentaire n'affecte pas les recommandations ni les bonnes pratiques d'adaptation de votre application à la version précédente du mode Sommeil introduite dans Android 6.0 (niveau d'API 23), comme indiqué dans Optimiser pour les modes Sommeil et Mise en veille des applications. Vous devez toujours suivre ces recommandations, par exemple en utilisant Firebase Cloud Messaging (FCM) pour envoyer et recevoir des messages, et commencer à planifier des mises à jour pour tenir compte du comportement supplémentaire du mode Doze.

Projet Svelte : optimisations en arrière-plan

Android 7.0 supprime trois diffusions implicites afin d'optimiser l'utilisation de la mémoire et la consommation d'énergie. Cette modification est nécessaire, car les diffusions implicites démarrent fréquemment des applications qui se sont enregistrées pour les écouter en arrière-plan. La suppression de ces diffusions peut améliorer considérablement les performances de l'appareil et l'expérience utilisateur.

Les appareils mobiles subissent de fréquents changements de connectivité, par exemple lorsqu'ils passent du Wi-Fi aux données mobiles. Actuellement, les applications peuvent surveiller les changements de connectivité en enregistrant un récepteur pour la diffusion implicite CONNECTIVITY_ACTION dans leur fichier manifeste. Étant donné que de nombreuses applications s'enregistrent pour recevoir cette diffusion, un seul commutateur réseau peut toutes les réveiller et traiter la diffusion en même temps.

De même, dans les versions précédentes d'Android, les applications pouvaient s'enregistrer pour recevoir des diffusions ACTION_NEW_PICTURE et ACTION_NEW_VIDEO implicites d'autres applications, comme l'appareil photo. Lorsqu'un utilisateur prend une photo avec l'application Appareil photo, ces applications se réveillent pour traiter la diffusion.

Pour réduire ces problèmes, Android 7.0 applique les optimisations suivantes :

  • Les applications ciblant Android version 7.0 (niveau 24 d'API) et ultérieures ne reçoivent pas les diffusions CONNECTIVITY_ACTION s'ils déclarent leur récepteur de diffusion dans le fichier manifeste. Les applications continueront à recevoir des diffusions CONNECTIVITY_ACTION si elles enregistrent leur BroadcastReceiver auprès de Context.registerReceiver() et que ce contexte est toujours valide.
  • Le système n'envoie plus de diffusions ACTION_NEW_PICTURE ni ACTION_NEW_VIDEO. Cette optimisation concerne toutes les applications, pas seulement celles qui ciblent Android 7.0.

Si votre application utilise l'un de ces intents, supprimez les dépendances dès que possible afin de pouvoir cibler correctement les appareils équipés d'Android 7.0. Le framework Android fournit plusieurs solutions pour réduire le besoin de ces diffusions implicites. Par exemple, l'API JobScheduler fournit un mécanisme robuste pour planifier les opérations réseau lorsque certaines conditions, telles qu'une connexion à un réseau sans compteur, sont remplies. Vous pouvez même utiliser JobScheduler pour réagir aux changements apportés aux fournisseurs de contenu.

Pour en savoir plus sur les optimisations en arrière-plan dans Android 7.0 (niveau d'API 24) et sur la façon d'adapter votre application, consultez Optimisations en arrière-plan.

Modifications des autorisations

Android 7.0 inclut des modifications des autorisations qui peuvent affecter votre application.

Modifications des autorisations du système de fichiers

Afin d'améliorer la sécurité des fichiers privés, l'accès au répertoire privé des applications ciblant Android 7.0 ou version ultérieure est limité (0700). Ce paramètre empêche la fuite des métadonnées des fichiers privés, telles que leur taille ou leur existence. Cette modification des autorisations a plusieurs effets secondaires :

  • Le propriétaire ne doit plus assouplir les autorisations des fichiers privés. Toute tentative en ce sens à l'aide de MODE_WORLD_READABLE et/ou de MODE_WORLD_WRITEABLE déclenchera une SecurityException.

    Remarque : Pour l'instant, cette restriction n'est pas entièrement appliquée. Les applications peuvent toujours modifier les autorisations de leur répertoire privé à l'aide d'API natives ou de l'API File. Cependant, nous vous déconseillons fortement d'assouplir les autorisations d'accès au répertoire privé.

  • La transmission d'URI file:// en dehors du domaine du package peut laisser le récepteur avec un chemin inaccessible. Par conséquent, les tentatives de transmission d'un URI file:// déclenchent une erreur FileUriExposedException. La méthode recommandée pour partager le contenu d'un fichier privé consiste à utiliser FileProvider.
  • DownloadManager ne peut plus partager de fichiers stockés de manière privée par nom de fichier. Les anciennes applications peuvent se retrouver avec un chemin d'accès inaccessible lors de l'accès à COLUMN_LOCAL_FILENAME. Les applications ciblant Android 7.0 ou version ultérieure déclenchent une SecurityException lorsqu'elles tentent d'accéder à COLUMN_LOCAL_FILENAME. Les anciennes applications qui définissent l'emplacement de téléchargement sur un emplacement public à l'aide de DownloadManager.Request.setDestinationInExternalFilesDir() ou DownloadManager.Request.setDestinationInExternalPublicDir() peuvent toujours accéder au chemin d'accès dans COLUMN_LOCAL_FILENAME. Toutefois, cette méthode est fortement déconseillée. La méthode privilégiée pour accéder à un fichier exposé par DownloadManager consiste à utiliser ContentResolver.openFileDescriptor().

Partager des fichiers entre des applications

Pour les applications ciblant Android 7.0, le framework Android applique la règle d'API StrictMode qui interdit l'exposition des URI file:// en dehors de votre application. Si un intent contenant un URI de fichier quitte votre application, celle-ci échoue avec une exception FileUriExposedException.

Pour partager des fichiers entre des applications, vous devez envoyer un URI content:// et accorder une autorisation d'accès temporaire à l'URI. Le moyen le plus simple d'accorder cette autorisation consiste à utiliser la classe FileProvider. Pour en savoir plus sur les autorisations et le partage de fichiers, consultez Partager des fichiers.

Améliorations liées à l'accessibilité

Android 7.0 inclut des modifications visant à améliorer l'ergonomie de la plate-forme pour les utilisateurs malvoyants ou souffrant d'une déficience visuelle. En général, ces modifications ne nécessitent pas de modifier le code de votre application. Toutefois, vous devez examiner ces fonctionnalités et les tester avec votre application pour évaluer les impacts potentiels sur l'expérience utilisateur.

Zoom sur l'écran

Android 7.0 permet aux utilisateurs de définir la taille d'affichage, qui agrandit ou réduit tous les éléments à l'écran, améliorant ainsi l'accessibilité de l'appareil pour les utilisateurs souffrant d'une déficience visuelle. Les utilisateurs ne peuvent pas zoomer sur l'écran au-delà d'une largeur d'écran minimale de sw320dp, qui correspond à la largeur d'un Nexus 4, un téléphone de taille moyenne courant.

Écran montrant la taille d'affichage sans zoom d'un appareil exécutant une image système Android 7.0
Écran montrant l'effet de l'augmentation de la taille d'affichage d'un appareil exécutant une image système Android 7.0

Figure 3. L'écran de droite montre l'effet de l'augmentation de la taille d'affichage d'un appareil exécutant une image système Android 7.0.

Lorsque la densité de l'appareil change, le système en informe les applications en cours d'exécution de la manière suivante :

  • Si une application cible le niveau d'API 23 ou inférieur, le système arrête automatiquement tous ses processus en arrière-plan. Cela signifie que si un utilisateur quitte une telle application pour ouvrir l'écran Paramètres et modifier le paramètre Taille d'affichage, le système arrête l'application de la même manière qu'en cas de mémoire insuffisante. Si l'application comporte des processus de premier plan, le système les informe de la modification de configuration, comme décrit dans Gérer les modifications d'exécution, comme si l'orientation de l'appareil avait changé.
  • Si une application cible Android 7.0, tous ses processus (premier plan et arrière-plan) sont informés de la modification de configuration, comme décrit dans Gérer les modifications d'exécution.

La plupart des applications n'ont pas besoin d'être modifiées pour prendre en charge cette fonctionnalité, à condition qu'elles respectent les bonnes pratiques Android. Points spécifiques à vérifier :

  • Testez votre application sur un appareil dont la largeur d'écran est de sw320dp et assurez-vous qu'elle fonctionne correctement.
  • Lorsque la configuration de l'appareil change, mettez à jour toutes les informations mises en cache dépendantes de la densité, telles que les bitmaps mis en cache ou les ressources chargées à partir du réseau. Vérifiez si des modifications de configuration ont été apportées lorsque l'application reprend après avoir été mise en pause.

    Remarque : Si vous mettez en cache des données dépendantes de la configuration, il est judicieux d'inclure des métadonnées pertinentes, telles que la taille d'écran ou la densité de pixels appropriées pour ces données. L'enregistrement de ces métadonnées vous permet de décider si vous devez actualiser les données mises en cache après une modification de la configuration.

  • Évitez de spécifier des dimensions avec des unités px, car elles ne s'adaptent pas à la densité de l'écran. Spécifiez plutôt les dimensions en unités de pixels indépendants de la densité (dp).

Paramètres visuels dans l'assistant de configuration

Android 7.0 inclut les paramètres de vision sur l'écran d'accueil, où les utilisateurs peuvent configurer les paramètres d'accessibilité suivants sur un nouvel appareil : Geste d'agrandissement, Taille de police, Taille d'affichage et TalkBack. Cette modification augmente la visibilité des bugs liés aux différents paramètres d'écran. Pour évaluer l'impact de cette fonctionnalité, vous devez tester vos applications avec ces paramètres activés. Vous trouverez les paramètres sous Paramètres > Accessibilité.

Association d'applications NDK à des bibliothèques de plate-forme

À partir d'Android 7.0, le système empêche les applications d'établir une liaison dynamique avec des bibliothèques non NDK, ce qui peut entraîner le plantage de votre application. Ce changement de comportement vise à créer une expérience dans l'application cohérente entre les mises à jour de la plate-forme et les différents appareils. Même si votre code n'est pas associé à des bibliothèques privées, il est possible qu'une bibliothèque statique tierce de votre application le soit. Par conséquent, tous les développeurs doivent s'assurer que leurs applications ne plantent pas sur les appareils équipés d'Android 7.0. Si votre application utilise du code natif, vous ne devez utiliser que les API NDK publiques.

Votre application peut tenter d'accéder aux API de la plate-forme privée de trois manières :

  • Votre application accède directement à des bibliothèques de plate-forme privées. Vous devez mettre à jour votre application pour inclure sa propre copie de ces bibliothèques ou utiliser les API NDK publiques.
  • Votre application utilise une bibliothèque tierce qui accède à des bibliothèques de plates-formes privées. Même si vous êtes certain que votre application n'accède pas directement à des bibliothèques privées, vous devez quand même la tester pour ce scénario.
  • Votre application fait référence à une bibliothèque qui n'est pas incluse dans son APK. Par exemple, cela peut se produire si vous avez essayé d'utiliser votre propre copie d'OpenSSL, mais que vous avez oublié de l'intégrer à l'APK de votre application. L'application peut s'exécuter normalement sur les versions de la plate-forme Android qui incluent libcrypto.so. Toutefois, l'application peut planter sur les versions ultérieures d'Android qui n'incluent pas cette bibliothèque (par exemple, Android 6.0 et versions ultérieures). Pour résoudre ce problème, assurez-vous d'intégrer toutes vos bibliothèques non-NDK à votre APK.

Les applications ne doivent pas utiliser de bibliothèques natives qui ne sont pas incluses dans le NDK, car elles peuvent être modifiées ou supprimées d'une version d'Android à l'autre. Le passage d'OpenSSL à BoringSSL est un exemple de ce type de changement. De plus, comme il n'existe aucune exigence de compatibilité pour les bibliothèques de plates-formes non incluses dans le NDK, différents appareils peuvent offrir différents niveaux de compatibilité.

Afin de réduire l'impact que cette restriction peut avoir sur les applications actuellement publiées, un ensemble de bibliothèques très utilisées (comme libandroid_runtime.so, libcutils.so, libcrypto.so et libssl.so) sont temporairement accessibles sur Android 7.0 (niveau d'API 24) pour les applications ciblant le niveau d'API 23 ou une version antérieure. Si votre application charge l'une de ces bibliothèques, logcat génère un avertissement et un toast s'affiche sur l'appareil cible pour vous en informer. Si vous voyez ces avertissements, vous devez mettre à jour votre application pour inclure sa propre copie de ces bibliothèques ou n'utiliser que les API NDK publiques. Les futures versions de la plate-forme Android pourraient restreindre complètement l'utilisation des bibliothèques privées et entraîner le plantage de votre application.

Toutes les applications génèrent une erreur d'exécution lorsqu'elles appellent une API qui n'est ni publique, ni temporairement accessible. Par conséquent, System.loadLibrary et dlopen(3) renvoient tous deux NULL, ce qui peut entraîner le plantage de votre application. Vous devez examiner le code de votre application pour supprimer l'utilisation des API de plate-forme privées et tester minutieusement vos applications à l'aide d'un appareil ou d'un émulateur exécutant Android 7.0 (niveau d'API 24). Si vous ne savez pas si votre application utilise des bibliothèques privées, vous pouvez consulter logcat pour identifier l'erreur d'exécution.

Le tableau suivant décrit le comportement attendu d'une application en fonction de son utilisation de bibliothèques natives privées et de son niveau d'API cible (android:targetSdkVersion).

Bibliothèques Niveau d'API cible Accès à l'environnement d'exécution à l'aide de l'éditeur de liens dynamique Comportement d'Android 7.0 (niveau d'API 24) Comportement futur de la plate-forme Android
NDK Public Tous Accessible Fonctionne comme prévu Fonctionne comme prévu
Privé (bibliothèques privées temporairement accessibles) 23 ou moins Temporairement accessible Fonctionne comme prévu, mais vous recevez un avertissement logcat. Erreur d'exécution
Privé (bibliothèques privées temporairement accessibles) 24 ou plus Limité Erreur d'exécution Erreur d'exécution
Privé (autre) Tous Limité Erreur d'exécution Erreur d'exécution

Vérifier si votre application utilise des bibliothèques privées

Pour vous aider à identifier les problèmes de chargement des bibliothèques privées, logcat peut générer un avertissement ou une erreur d'exécution. Par exemple, si votre application cible le niveau d'API 23 ou une version antérieure et tente d'accéder à une bibliothèque privée sur un appareil équipé d'Android 7.0, un avertissement semblable à celui-ci peut s'afficher :

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

Ces avertissements logcat vous indiquent quelle bibliothèque tente d'accéder à une API de plate-forme privée, mais n'entraînent pas le plantage de votre application. Toutefois, si l'application cible le niveau d'API 24 ou supérieur, logcat génère l'erreur d'exécution suivante et votre application peut planter :

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)

Vous pouvez également voir ces sorties logcat si votre application utilise des bibliothèques tierces qui sont liées de manière dynamique à des API de plate-forme privées. L'outil readelf du NDK Android 7.0 vous permet de générer une liste de toutes les bibliothèques partagées associées de manière dynamique d'un fichier .so donné en exécutant la commande suivante :

aarch64-linux-android-readelf -dW libMyLibrary.so

Mettez à jour votre application

Voici quelques étapes à suivre pour corriger ces types d'erreurs et vous assurer que votre application ne plante pas lors des futures mises à jour de la plate-forme :

  • Si votre application utilise des bibliothèques de plate-forme privées, vous devez la mettre à jour pour inclure sa propre copie de ces bibliothèques ou utiliser les API NDK publiques.
  • Si votre application utilise une bibliothèque tierce qui accède à des symboles privés, contactez l'auteur de la bibliothèque pour la mettre à jour.
  • Assurez-vous d'empaqueter toutes vos bibliothèques non-NDK avec votre APK.
  • Utilisez les fonctions JNI standards au lieu de getJavaVM et getJNIEnv de libandroid_runtime.so :
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • Utilisez __system_property_get au lieu du symbole privé property_get de libcutils.so. Pour ce faire, utilisez __system_property_get avec l'inclusion suivante :
    #include <sys/system_properties.h>

    Remarque : La disponibilité et le contenu des propriétés système ne sont pas testés via CTS. Une meilleure solution consisterait à éviter d'utiliser ces propriétés.

  • Utilisez une version locale du symbole SSL_ctrl de libcrypto.so. Par exemple, vous devez lier de manière statique libcyrpto.a dans votre fichier .so ou inclure une version de libcrypto.so liée de manière dynamique à partir de BoringSSL/OpenSSL et l'empaqueter dans votre APK.

Android for Work

Android 7.0 contient des modifications pour les applications qui ciblent Android for Work, y compris des modifications concernant l'installation des certificats, la réinitialisation du mot de passe, la gestion des utilisateurs secondaires et l'accès aux identifiants de l'appareil. Si vous créez des applications pour des environnements Android for Work, vous devez examiner ces modifications et modifier votre application en conséquence.

  • Vous devez installer un programme d'installation de certificats délégués avant que le DPC puisse le définir. Pour les applications de propriétaire de profil et de propriétaire d'appareil ciblant Android 7.0 (niveau d'API 24), vous devez installer le programme d'installation de certificat délégué avant que le contrôleur de règles relatives aux appareils (DPC, Device Policy Controller) n'appelle DevicePolicyManager.setCertInstallerPackage(). Si le programme d'installation n'est pas déjà installé, le système génère une erreur IllegalArgumentException.
  • Les restrictions de réinitialisation du mot de passe pour les administrateurs d'appareils s'appliquent désormais aux propriétaires de profils. Les administrateurs d'appareils ne peuvent plus utiliser DevicePolicyManager.resetPassword() pour effacer les mots de passe ou modifier ceux qui sont déjà définis. Les administrateurs de l'appareil peuvent toujours définir un mot de passe, mais uniquement lorsque l'appareil n'a pas de mot de passe, de code ni de schéma.
  • Les propriétaires d'appareils et de profils peuvent gérer les comptes même si des restrictions sont définies. Les propriétaires d'appareils et de profils peuvent appeler les API Account Management même si des restrictions d'utilisateur DISALLOW_MODIFY_ACCOUNTS sont en place.
  • Les propriétaires d'appareils peuvent gérer les utilisateurs secondaires. Lorsqu'un appareil est exécuté en mode propriétaire de l'appareil, la restriction DISALLOW_ADD_USER est automatiquement définie. Cela empêche les utilisateurs de créer des utilisateurs secondaires non gérés. De plus, les méthodes CreateUser() et createAndInitializeUser() sont obsolètes. Elles sont remplacées par la nouvelle méthode DevicePolicyManager.createAndManageUser().
  • Les propriétaires d'appareils peuvent accéder aux identifiants des appareils. Un propriétaire d'appareil peut accéder à l'adresse MAC Wi-Fi d'un appareil à l'aide de DevicePolicyManager.getWifiMacAddress(). Si le Wi-Fi n'a jamais été activé sur l'appareil, cette méthode renvoie la valeur null.
  • Le paramètre "Mode professionnel" contrôle l'accès aux applications professionnelles. Lorsque le mode professionnel est désactivé, le lanceur d'applications du système indique que les applications professionnelles ne sont pas disponibles en les grisant. La réactivation du mode professionnel rétablit le comportement normal.
  • Lors de l'installation d'un fichier PKCS #12 contenant une chaîne de certificats client et la clé privée correspondante à partir de l'interface utilisateur des paramètres, le certificat CA de la chaîne n'est plus installé dans le stockage des identifiants de confiance. Cela n'affecte pas le résultat de KeyChain.getCertificateChain() lorsque les applications tentent de récupérer la chaîne de certificats client ultérieurement. Si nécessaire, le certificat CA doit être installé dans le stockage des identifiants de confiance à l'aide de l'UI des paramètres, au format DER avec une extension de fichier .crt ou .cer.
  • À partir d'Android 7.0, l'enregistrement et le stockage des empreintes digitales sont gérés par utilisateur. Si le client Device Policy (DPC) d'un propriétaire de profil cible le niveau d'API 23 (ou inférieur) sur un appareil exécutant Android 7.0 (niveau d'API 24), l'utilisateur peut toujours définir une empreinte digitale sur l'appareil, mais les applications professionnelles ne peuvent pas y accéder. Lorsque le DPC cible le niveau d'API 24 ou supérieur, l'utilisateur peut définir une empreinte digitale spécifiquement pour le profil professionnel en accédant à Paramètres > Sécurité > Sécurité du profil professionnel.
  • Un nouvel état de chiffrement ENCRYPTION_STATUS_ACTIVE_PER_USER est renvoyé par DevicePolicyManager.getStorageEncryptionStatus() pour indiquer que le chiffrement est actif et que la clé de chiffrement est associée à l'utilisateur. Le nouvel état n'est renvoyé que si le DPC cible le niveau d'API 24 ou supérieur. Pour les applications ciblant des niveaux d'API antérieurs, ENCRYPTION_STATUS_ACTIVE est renvoyé, même si la clé de chiffrement est spécifique à l'utilisateur ou au profil.
  • Sous Android 7.0, plusieurs méthodes qui affectent normalement l'ensemble de l'appareil se comportent différemment si l'appareil dispose d'un profil professionnel installé avec un test d'authentification professionnel distinct. Plutôt que d'affecter l'ensemble de l'appareil, ces méthodes ne s'appliquent qu'au profil professionnel. (La liste complète de ces méthodes est disponible dans la documentation de DevicePolicyManager.getParentProfileInstance().) Par exemple, DevicePolicyManager.lockNow() ne verrouille que le profil professionnel, et non l'ensemble de l'appareil. Pour chacune de ces méthodes, vous pouvez obtenir l'ancien comportement en appelant la méthode sur l'instance parente de DevicePolicyManager. Vous pouvez obtenir ce parent en appelant DevicePolicyManager.getParentProfileInstance(). Par exemple, si vous appelez la méthode lockNow() de l'instance parente, l'appareil entier est verrouillé.

Conservation des annotations

Android 7.0 corrige un bug qui ignorait la visibilité des annotations. Ce problème permettait à l'environnement d'exécution d'accéder à des annotations auxquelles il n'aurait pas dû avoir accès. Ces annotations incluaient :

  • VISIBILITY_BUILD : destiné à n'être visible qu'au moment de la compilation.
  • VISIBILITY_SYSTEM : destiné à être visible au moment de l'exécution, mais uniquement par le système sous-jacent.

Si votre application s'appuie sur ce comportement, ajoutez une règle de conservation aux annotations qui doivent être disponibles au moment de l'exécution. Pour ce faire, utilisez @Retention(RetentionPolicy.RUNTIME).

Modifications de la configuration TLS/SSL par défaut

Android 7.0 apporte les modifications suivantes à la configuration TLS/SSL par défaut utilisée par les applications pour le trafic HTTPS et d'autres trafics TLS/SSL :

  • Les suites de chiffrement RC4 sont désormais désactivées.
  • Les suites de chiffrement CHACHA20-POLY1305 sont désormais activées.

La désactivation de RC4 par défaut peut entraîner des interruptions de la connectivité HTTPS ou TLS/SSL lorsque le serveur ne négocie pas les suites de chiffrement modernes. La solution privilégiée consiste à améliorer la configuration du serveur pour activer des suites et des protocoles de chiffrement plus puissants et plus modernes. Idéalement, TLSv1.2 et AES-GCM doivent être activés, et les suites de chiffrement à confidentialité persistante (ECDHE) doivent être activées et privilégiées.

Vous pouvez également modifier l'application pour qu'elle utilise un SSLSocketFactory personnalisé pour communiquer avec le serveur. La fabrique doit être conçue pour créer des instances SSLSocket pour lesquelles certaines des suites de chiffrement requises par le serveur sont activées, en plus des suites de chiffrement par défaut.

Remarque : Ces modifications ne concernent pas WebView.

Applications ciblant Android 7.0

Ces changements de comportement s'appliquent exclusivement aux applications qui ciblent Android 7.0 (niveau d'API 24) ou version ultérieure. Les applications qui compilent sur Android 7.0 ou qui définissent targetSdkVersion sur Android 7.0 ou version ultérieure doivent modifier leurs applications pour qu'elles prennent en charge ces comportements, le cas échéant.

Modifications de la sérialisation

Android 7.0 (niveau d'API 24) a corrigé un bug dans le calcul du serialVersionUID par défaut, qui ne correspondait pas à la spécification.

Les classes qui implémentent Serializable et ne spécifient pas de champ serialVersionUID explicite peuvent voir leur serialVersionUID par défaut modifié, ce qui entraîne une exception lors de la tentative de désérialisation des instances de la classe qui ont été sérialisées sur une version antérieure ou par une application ciblant une version antérieure. Le message d'erreur ressemblera à ceci :

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

Pour résoudre ces problèmes, vous devez ajouter un champ serialVersionUID à toute classe concernée avec la valeur stream classdesc serialVersionUID du message d'erreur, par exemple 1234 dans ce cas. Cette modification respecte toutes les recommandations de bonnes pratiques pour l'écriture de code de sérialisation et fonctionnera sur toutes les versions d'Android.

Le bug spécifique qui a été corrigé était lié à la présence de méthodes d'initialisation statiques, c'est-à-dire <clinit>. Selon la spécification, la présence ou l'absence d'une méthode d'initialisation statique dans la classe affecte le serialVersionUID par défaut calculé pour cette classe. Avant la correction de bug, le calcul vérifiait également la super-classe pour un initialiseur statique si une classe n'en avait pas.

Pour rappel, cette modification n'affecte pas les applications qui ciblent les niveaux d'API 23 ou inférieurs, les classes comportant un champ serialVersionUID ou les classes comportant une méthode d'initialisation statique.

Autres points importants

  • Lorsqu'une application s'exécute sur Android 7.0, mais cible un niveau d'API inférieur, et que l'utilisateur modifie la taille d'affichage, le processus de l'application est arrêté. L'application doit pouvoir gérer ce scénario de manière appropriée. Sinon, elle plante lorsque l'utilisateur la restaure à partir de l'écran "Récents".

    Vous devez tester votre application pour vous assurer que ce comportement ne se produit pas. Pour ce faire, vous pouvez provoquer un plantage identique en forçant l'arrêt de l'application manuellement à l'aide de DDMS.

    Les applications ciblant Android 7.0 (niveau d'API 24) ou version ultérieure ne sont pas automatiquement arrêtées en cas de changement de densité. Toutefois, elles peuvent toujours mal réagir aux changements de configuration.

  • Les applications sur Android 7.0 doivent pouvoir gérer correctement les modifications de configuration et ne doivent pas planter lors des démarrages suivants. Vous pouvez vérifier le comportement de l'application en modifiant la taille de la police (Paramètres > Affichage > Taille de la police), puis en restaurant l'application à partir de l'écran "Récents".
  • En raison d'un bug dans les versions précédentes d'Android, le système ne signalait pas l'écriture dans un socket TCP sur le thread principal comme une violation du mode strict. Android 7.0 corrige ce bug. Les applications qui présentent ce comportement génèrent désormais une exception android.os.NetworkOnMainThreadException. En général, effectuer des opérations réseau sur le thread principal est une mauvaise idée, car ces opérations ont généralement une latence élevée qui entraîne des erreurs ANR et des à-coups.
  • La famille de méthodes Debug.startMethodTracing() stocke désormais par défaut les résultats dans le répertoire spécifique à votre package sur l'espace de stockage partagé, et non au niveau supérieur de la carte SD. Cela signifie que les applications n'ont plus besoin de demander l'autorisation WRITE_EXTERNAL_STORAGE pour utiliser ces API.
  • De nombreuses API de plate-forme ont commencé à vérifier si des charges utiles volumineuses sont envoyées via des transactions Binder. Le système renvoie désormais TransactionTooLargeExceptions en tant que RuntimeExceptions, au lieu de les consigner ou de les supprimer de manière silencieuse. Par exemple, si vous stockez trop de données dans Activity.onSaveInstanceState(), ActivityThread.StopInfo génère une erreur RuntimeException lorsque votre application cible Android 7.0.
  • Si une application publie des tâches Runnable dans un View et que le View n'est pas associé à une fenêtre, le système met en file d'attente la tâche Runnable avec le View. La tâche Runnable ne s'exécute pas tant que le View n'est pas associé à une fenêtre. Ce comportement corrige les bugs suivants :
    • Si une application a publié un View à partir d'un thread autre que le thread UI de la fenêtre prévue, le Runnable peut s'exécuter sur le mauvais thread.
    • Si la tâche Runnable a été publiée à partir d'un thread autre qu'un thread de boucle, l'application peut exposer la tâche Runnable.
  • Si une application sur Android 7.0 disposant de l'autorisation DELETE_PACKAGES tente de supprimer un package, mais qu'une autre application l'a installé, le système demande confirmation à l'utilisateur. Dans ce scénario, les applications doivent s'attendre à recevoir l'état de retour STATUS_PENDING_USER_ACTION lorsqu'elles appellent PackageInstaller.uninstall().
  • Le fournisseur JCA appelé Crypto est obsolète, car son seul algorithme, SHA1PRNG, est faible d'un point de vue cryptographique. Les applications ne peuvent plus utiliser SHA1PRNG pour dériver des clés (de manière non sécurisée), car ce fournisseur n'est plus disponible. Pour en savoir plus, consultez l'article de blog Security "Crypto" provider deprecated in Android N (Abandon du fournisseur de sécurité "Crypto" dans Android N).