Changements de comportement dans Android 7.0

En plus des nouvelles fonctionnalités, Android 7.0 apporte plusieurs modifications de comportement du système et des API. Ce document met en évidence certaines des principales modifications que vous devez comprendre et prendre en compte dans vos applications.

Si vous avez déjà publié une application pour Android, sachez qu'elle peut être affectée par ces modifications de la plate-forme.

Batterie et mémoire

Android 7.0 inclut des modifications de 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 avoir une incidence sur l'accès de votre application aux ressources système, ainsi que sur la manière dont elle interagit avec d'autres applications via certains intents implicites.

Sommeil

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

Illustration de la façon dont Doze 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 Doze applique un premier niveau de restrictions d'activité système pour améliorer l'autonomie de la batterie.

Lorsqu'un appareil fonctionne sur 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 au réseau des applications, et reporte les tâches et les synchronisations. Si l'appareil est à l'arrêt pendant un certain temps après avoir activé le mode Doze, le système applique le reste des restrictions Doze aux alarmes PowerManager.WakeLock et AlarmManager, au GPS et aux recherches Wi-Fi. Que certaines ou toutes les restrictions Doze soient appliquées, le système réveille l'appareil pour de courtes périodes de maintenance, pendant lesquelles les applications sont autorisées à accéder au réseau et peuvent exécuter des tâches/synchronisations différées.

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

Figure 2. Illustration montrant comment Doze applique un deuxième niveau de restrictions d'activité système une fois que l'appareil est à l'arrêt pendant un certain temps.

Notez que l'activation de l'écran ou la connexion de l'appareil met fin à la mise en veille et supprime ces restrictions de traitement. Ce comportement supplémentaire n'a aucune incidence sur les recommandations et les bonnes pratiques pour adapter votre application à la version précédente de Doze introduite dans Android 6.0 (niveau d'API 23), comme indiqué dans la section Optimiser pour Doze et le mode veille de l'application. 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 de Doze.

Projet Svelte: optimisations en arrière-plan

Android 7.0 supprime trois diffusions implicites afin d'optimiser à la fois 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 avoir un impact positif important sur les performances des appareils et l'expérience utilisateur.

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

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

Pour atténuer 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 ou ACTION_NEW_VIDEO. Cette optimisation affecte 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 Android 7.0. Le framework Android fournit plusieurs solutions pour atténuer 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 non facturé à l'usage, sont remplies. Vous pouvez même utiliser JobScheduler pour réagir aux modifications apportées 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 l'adaptation de votre application, consultez la section Optimisations en arrière-plan.

Modifications des autorisations

Android 7.0 apporte des modifications aux autorisations qui peuvent affecter votre application.

Modifications des autorisations du système de fichiers

Pour 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 de métadonnées de fichiers privés, telles que leur taille ou leur existence. Cette modification d'autorisation a plusieurs effets secondaires:

  • Les autorisations des fichiers privés ne doivent plus être assouplies par le propriétaire. Toute tentative de le faire à l'aide de MODE_WORLD_READABLE et/ou de MODE_WORLD_WRITEABLE déclenchera une SecurityException.

    Remarque:Pour le moment, 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. Toutefois, nous vous déconseillons fortement d'assouplir les autorisations du répertoire privé.

  • Transmettre des URI file:// en dehors du domaine du package peut laisser le destinataire avec un chemin inaccessible. Par conséquent, les tentatives de transmission d'un URI file:// déclenchent un 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 en privé par nom de fichier. Les anciennes applications peuvent se retrouver avec un chemin inaccessible lorsqu'elles accèdent à COLUMN_LOCAL_FILENAME. Les applications ciblant Android 7.0 ou version ultérieure déclenchent une SecurityException lorsque vous tentez 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. Le moyen le plus simple d'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 le règlement de l'API StrictMode qui interdit l'exposition d'URI file:// en dehors de votre application. Si un intent contenant un URI de fichier quitte votre application, l'application é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 sur 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 destinées à améliorer l'usabilité de la plate-forme pour les utilisateurs ayant une déficience visuelle ou une vision réduite. En général, ces modifications ne devraient pas nécessiter de modifications de code dans 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, ce qui améliore l'accessibilité de l'appareil pour les utilisateurs ayant une déficience visuelle. Les utilisateurs ne peuvent pas faire un zoom avant au-delà d'une largeur minimale de sw320dp, qui correspond à la largeur d'un Nexus 4, un téléphone de taille moyenne courant.

Écran affichant la taille d'affichage non agrandie de l'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 avertit les applications en cours d'exécution comme suit:

  • Si une application cible le niveau d'API 23 ou inférieur, le système supprime automatiquement tous ses processus en arrière-plan. Cela signifie que si un utilisateur quitte une telle application pour ouvrir l'écran Settings (Paramètres) et modifie le paramètre Display size (Taille d'affichage), le système ferme l'application de la même manière qu'en cas de faible mémoire. Si l'application comporte des processus de premier plan, le système les informe de la modification de configuration, comme décrit dans la section 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 du changement de configuration, comme décrit dans la section Gérer les modifications apportées à l'environnement d'exécution.

La plupart des applications n'ont pas besoin d'apporter de modifications 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 sw320dp et assurez-vous qu'elle fonctionne correctement.
  • Lorsque la configuration de l'appareil change, mettez à jour toutes les informations mises en cache dépendant de la densité, telles que les bitmaps mis en cache ou les ressources chargées à partir du réseau. Recherchez les modifications de configuration lorsque l'application reprend l'état "Suspendue".

    Remarque:Si vous mettez en cache des données dépendantes de la configuration, nous vous recommandons 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 configuration.

  • Évitez de spécifier des dimensions avec des unités px, car elles ne sont pas mises à l'échelle en fonction de la densité de l'écran. Spécifiez plutôt des dimensions avec des 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 de bienvenue, où les utilisateurs peuvent configurer les paramètres d'accessibilité suivants sur un nouvel appareil : geste de zoom, taille de police, taille de l'écran 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 des applications du NDK aux bibliothèques de la plate-forme

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

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

  • Votre application accède directement aux 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 aux bibliothèques de plate-forme privées. Même si vous êtes certain que votre application n'accède pas directement aux bibliothèques privées, nous vous recommandons de la tester pour ce scénario.
  • Votre application fait référence à une bibliothèque qui n'est pas incluse dans son APK. Cela peut se produire, par exemple, 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 changer ou être supprimées entre les différentes versions d'Android. Le passage d'OpenSSL à BoringSSL en est un exemple. 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 de cette restriction sur les applications actuellement publiées, un ensemble de bibliothèques utilisées de manière significative (telles que libandroid_runtime.so, libcutils.so, libcrypto.so et libssl.so) est temporairement accessible sur Android 7.0 (niveau d'API 24) pour les applications ciblant le niveau d'API 23 ou 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 qu'elle inclue sa propre copie de ces bibliothèques ou n'utiliser que les API NDK publiques. Les futures versions de la plate-forme Android peuvent limiter 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 n'êtes pas sûr que 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 que vous devez attendre 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 d'exécution via le liant dynamique Comportement d'Android 7.0 (niveau d'API 24) Comportement futur de la plate-forme Android
NDK public Tout Accessible Fonctionne comme prévu Fonctionne comme prévu
Privé (bibliothèques privées temporairement accessibles) 23 ou version antérieure Accessible temporairement Fonctionne comme prévu, mais vous recevez un avertissement Logcat. Erreur d'exécution
Privé (bibliothèques privées temporairement accessibles) 24 ou ultérieure Restricted (Limité) Erreur d'exécution Erreur d'exécution
Privé (autre) Tout Restricted (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 ne provoquent 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 associées dynamiquement à des API de plate-forme privée. L'outil readelf d'Android 7.0DK vous permet de générer une liste de toutes les bibliothèques partagées associées dynamiquement à un fichier .so donné en exécutant la commande suivante:

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

Mettre à jour votre appli

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 publiques du NDK.
  • 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 de regrouper toutes vos bibliothèques autres que le NDK avec votre APK.
  • Utilisez des fonctions JNI standards au lieu de getJavaVM et getJNIEnv à partir 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 property_get privé de libcutils.so. Pour ce faire, utilisez __system_property_get avec les éléments suivants:
    #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 serait d'éviter d'utiliser ces propriétés.

  • Utilisez une version locale du symbole SSL_ctrl à partir de libcrypto.so. Par exemple, vous devez lier statiquement libcyrpto.a dans votre fichier .so, ou inclure une version liée dynamiquement de libcrypto.so à partir de BoringSSL/OpenSSL et la 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 apportées à l'installation de certificats, à la réinitialisation de mot de passe, à la gestion des utilisateurs secondaires et à l'accès aux identifiants d'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 certificat délégué avant que le DPC puisse le définir. Pour les applications de profil et de propriétaire de l'appareil ciblant Android 7.0 (niveau d'API 24), vous devez installer l'installateur de certificat délégué avant que l'outil de contrôle des règles relatives aux appareils (DPC) 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 de 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 ni en modifier ceux 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 de l'appareil et du profil 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 de gestion de compte, même si des restrictions utilisateur DISALLOW_MODIFY_ACCOUNTS sont en place.
  • Les propriétaires d'appareils peuvent gérer plus facilement les utilisateurs secondaires. Lorsqu'un appareil fonctionne 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 des appareils peuvent accéder aux identifiants de leurs appareils. Le propriétaire d'un appareil peut accéder à l'adresse MAC Wi-Fi de l'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 travail" contrôle l'accès aux applications professionnelles. Lorsque le mode Travail est désactivé, le lanceur d'applications du système indique que les applications professionnelles ne sont pas disponibles en les affichant en gris. Réactiver le 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 d'autorité de certification doit être installé séparément dans le stockage des identifiants approuvés via l'UI des paramètres, avec un format encodé DER sous 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 équipé d'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 spécifique au 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 liée à l'utilisateur. Le nouvel état n'est renvoyé que si l'outil 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.
  • Dans Android 7.0, plusieurs méthodes qui affectent normalement l'ensemble de l'appareil se comportent différemment si un profil professionnel est installé avec un défi 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 DevicePolicyManager.getParentProfileInstance().) Par exemple, DevicePolicyManager.lockNow() ne verrouille que le profil professionnel, au lieu de verrouiller 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'ensemble de l'appareil est verrouillé.

Conservation des annotations

Android 7.0 corrige un bug qui entraînait l'ignorance de la visibilité des annotations. Ce problème a permis à l'environnement d'exécution d'accéder à des annotations auxquelles il n'aurait pas dû. Ces annotations comprenaient:

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

Si votre application s'est appuyée sur ce comportement, veuillez ajouter une stratégie 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 par défaut TLS/SSL

Android 7.0 apporte les modifications suivantes à la configuration TLS/SSL par défaut utilisée par les applications pour 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 par défaut de RC4 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 afin de mettre en place 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 de confidentialité persistante (ECDHE) doivent être activées et recommandé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 dans 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 modifications de comportement ne s'appliquent qu'aux applications qui ciblent Android 7.0 (niveau d'API 24) ou version ultérieure. Les applications qui compilent avec Android 7.0 ou 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 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 génère une exception lors de la tentative de désérialisation d'instances de la classe qui ont été sérialisées sur une version antérieure ou sérialisées 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 affectée avec la valeur stream classdesc serialVersionUID du message d'erreur, par exemple 1234 dans ce cas. Ce changement respecte toutes les bonnes pratiques d'écriture de code de sérialisation et fonctionne sur toutes les versions d'Android.

Le bug spécifique corrigé était lié à la présence de méthodes d'initialiseur statiques, c'est-à-dire <clinit>. Conformément à 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 du bug, le calcul vérifiait également la présence d'un initialiseur statique dans la super-classe si une classe n'en avait pas.

Pour clarifier, cette modification n'affecte pas les applications qui ciblent un niveau d'API 23 ou inférieur, 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 élégante. Sinon, il plante lorsque l'utilisateur le restaure à partir de "Récents".

    Vous devez tester votre application pour vous assurer que ce comportement ne se produit pas. Pour ce faire, provoquez un plantage identique en fermant manuellement l'application via DDMS.

    Les applications ciblant Android 7.0 (niveau d'API 24) ou version ultérieure ne sont pas automatiquement supprimées en cas de changement de densité. Toutefois, elles peuvent malgré tout mal réagir aux modifications 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 (Setting > Display > Font size), puis en restaurant l'application à partir de "Recents" (Éléments récents).
  • En raison d'un bug dans les versions précédentes d'Android, le système n'a pas signalé l'écriture sur 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 provoque des erreurs ANR et des à-coups.
  • La famille de méthodes Debug.startMethodTracing() stocke désormais par défaut la sortie dans le répertoire spécifique au package sur l'espace de stockage partagé, au lieu du 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 maintenant commencé à vérifier si de grandes charges utiles 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 en mode silencieux. Un exemple courant est le stockage de trop de données dans Activity.onSaveInstanceState(), ce qui entraîne l'émission d'une RuntimeException par ActivityThread.StopInfo lorsque votre application cible Android 7.0.
  • Si une application publie des tâches Runnable sur 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 élément dans un View à partir d'un thread autre que le thread d'interface utilisateur 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 boucleur, l'application peut exposer la tâche Runnable.
  • Si une application sur Android 7.0 avec l'autorisation DELETE_PACKAGES tente de supprimer un package, mais qu'une autre application l'a installé, le système nécessite une confirmation de l'utilisateur. Dans ce scénario, les applications doivent s'attendre à STATUS_PENDING_USER_ACTION comme état de retour lorsqu'elles appellent PackageInstaller.uninstall().
  • Le fournisseur JCA appelé Crypto est obsolète, car son seul algorithme, SHA1PRNG, présente une faiblesse 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 (Le fournisseur de sécurité "Crypto" est obsolète dans Android N).