Changements de comportement dans Android 8.0

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

La plupart de ces modifications affectent toutes les applications, quelle que soit la version d'Android qu'elles ciblent. Cependant, plusieurs modifications ne concernent que les applications ciblant Android 8.0. Pour plus de clarté, cette page est divisée en deux sections: Modifications pour toutes les applications et Modifications pour les applications ciblant Android 8.0.

Modifications pour toutes les applications

Ces modifications de comportement s'appliquent à toutes les applications lorsqu'elles s'exécutent sur la plate-forme Android 8.0 (niveau d'API 26), quel que soit le niveau d'API qu'elles ciblent. Tous les développeurs doivent examiner ces modifications et modifier leurs applications pour les prendre en charge correctement, le cas échéant.

Limites d'exécution en arrière-plan

L'une des modifications apportées par Android 8.0 (niveau d'API 26) pour améliorer l'autonomie de la batterie est la suivante : lorsque votre application passe à l'état mise en cache, sans composants actifs, le système libère tous les wakelocks détenus par l'application.

De plus, pour améliorer les performances de l'appareil, le système limite certains comportements des applications qui ne s'exécutent pas au premier plan. Plus spécifiquement :

  • Les applications exécutées en arrière-plan sont désormais limitées dans la façon dont elles peuvent accéder aux services en arrière-plan.
  • Les applications ne peuvent pas utiliser leurs fichiers manifestes pour s'enregistrer pour la plupart des diffusions implicites (c'est-à-dire des annonces qui ne sont pas spécifiquement ciblées sur l'application).

Par défaut, ces restrictions ne s'appliquent qu'aux applications qui ciblent O. Toutefois, les utilisateurs peuvent activer ces restrictions pour n'importe quelle application depuis l'écran Settings (Paramètres), même si l'application n'a pas ciblé O.

Android 8.0 (niveau d'API 26) inclut également les modifications suivantes apportées à des méthodes spécifiques:

  • La méthode startService() génère désormais une IllegalStateException si une application ciblant Android 8.0 tente de l'utiliser dans une situation où elle n'est pas autorisée à créer des services d'arrière-plan.
  • La nouvelle méthode Context.startForegroundService() démarre un service de premier plan. Le système permet aux applications d'appeler Context.startForegroundService() même lorsque l'application est en arrière-plan. Toutefois, l'application doit appeler la méthode startForeground() de ce service dans les cinq secondes suivant sa création.

Pour en savoir plus, consultez la section Limites d'exécution en arrière-plan.

Limites de localisation en arrière-plan Android

Pour préserver l'autonomie de la batterie, l'expérience utilisateur et l'état du système, les applications en arrière-plan reçoivent des mises à jour de position moins fréquemment lorsqu'elles sont utilisées sur un appareil équipé d'Android 8.0. Ce changement de comportement affecte toutes les applications qui reçoivent des mises à jour de position, y compris les services Google Play.

Ces modifications concernent les API suivantes:

  • Fused Location Provider (FLP)
  • Géorepérage
  • Mesures GNSS
  • Gestionnaire de zones géographiques
  • Gestionnaire Wi-Fi

Pour vous assurer que votre application s'exécute comme prévu, procédez comme suit:

  • Examinez la logique de votre application et assurez-vous d'utiliser les dernières API de localisation.
  • Vérifiez que votre application présente le comportement attendu pour chaque cas d'utilisation.
  • Envisagez d'utiliser le FusedLocationProvider (FLP) ou le géorepérage pour gérer les cas d'utilisation qui dépendent de la position actuelle de l'utilisateur.

Pour en savoir plus sur ces modifications, consultez la section Limites d'emplacement en arrière-plan.

Raccourcis d'application

Android 8.0 (niveau d'API 26) inclut les modifications suivantes apportées aux raccourcis d'application:

  • La diffusion com.android.launcher.action.INSTALL_SHORTCUT n'a plus aucun effet sur votre application, car elle est désormais une diffusion privée et implicite. À la place, vous devez créer un raccourci d'application à l'aide de la méthode requestPinShortcut() de la classe ShortcutManager.
  • L'intent ACTION_CREATE_SHORTCUT peut désormais créer des raccourcis d'application que vous gérez à l'aide de la classe ShortcutManager. Cet intent peut également créer d'anciens raccourcis de lanceur qui n'interagissent pas avec ShortcutManager. Auparavant, cet intent ne pouvait créer que des anciens raccourcis de lanceur.
  • Les raccourcis créés à l'aide de requestPinShortcut() et les raccourcis créés dans une activité qui gère l'intent ACTION_CREATE_SHORTCUT sont désormais des raccourcis d'application à part entière. Par conséquent, les applications peuvent désormais les mettre à jour à l'aide des méthodes de ShortcutManager.
  • Les anciens raccourcis conservent les fonctionnalités des versions précédentes d'Android, mais vous devez les convertir manuellement en raccourcis d'application dans votre application.

Pour en savoir plus sur les modifications apportées aux raccourcis d'application, consultez le guide de la fonctionnalité Épingler des raccourcis et des widgets.

Paramètres régionaux et internationalisation

Android 7.0 (niveau d'API 24) a introduit la possibilité de spécifier une locale de catégorie par défaut, mais certaines API ont continué à utiliser la méthode générique Locale.getDefault(), sans arguments, alors qu'elles auraient dû utiliser la locale de catégorie DISPLAY par défaut. Dans Android 8.0 (niveau d'API 26), les méthodes suivantes utilisent désormais Locale.getDefault(Category.DISPLAY) au lieu de Locale.getDefault():

Locale.getDisplayScript(Locale) revient également à Locale.getDefault() lorsque la valeur displayScript spécifiée pour l'argument Locale n'est pas disponible.

Voici d'autres modifications liées aux paramètres régionaux et à l'internationalisation:

  • L'appel de Currency.getDisplayName(null) génère une exception NullPointerException, ce qui correspond au comportement documenté.
  • L'analyse du nom du fuseau horaire a été modifiée. Auparavant, les appareils Android utilisaient la valeur de l'horloge système échantillonnée au démarrage pour mettre en cache les noms de fuseau horaire utilisés pour analyser les dates et heures. Par conséquent, l'analyse peut être affectée négativement si l'horloge système était incorrecte au démarrage ou dans d'autres cas plus rares.

    Dans les cas courants, la logique d'analyse utilise ICU et la valeur actuelle de l'horloge système lors de l'analyse des noms de fuseaux horaires. Cette modification fournit des résultats plus corrects, qui peuvent différer des versions antérieures d'Android lorsque votre application utilise des classes telles que SimpleDateFormat.

  • Android 8.0 (niveau d'API 26) met à jour la version d'ICU vers la version 58.

Fenêtres d'alerte

Si une application utilise l'autorisation SYSTEM_ALERT_WINDOW et utilise l'un des types de fenêtres suivants pour tenter d'afficher des fenêtres d'alerte au-dessus d'autres applications et fenêtres système:

...alors ces fenêtres apparaissent toujours sous les fenêtres qui utilisent le type de fenêtre TYPE_APPLICATION_OVERLAY. Si une application cible Android 8.0 (niveau d'API 26), elle utilise le type de fenêtre TYPE_APPLICATION_OVERLAY pour afficher les fenêtres d'alerte.

Pour en savoir plus, consultez la section Types de fenêtres courants pour les fenêtres d'alerte dans les modifications de comportement des applications ciblant Android 8.0.

Saisie et navigation

Avec l'arrivée des applications Android sur ChromeOS et d'autres facteurs de forme de grande taille, tels que les tablettes, la navigation au clavier est de nouveau utilisée dans les applications Android. Dans Android 8.0 (niveau d'API 26), nous avons repensé l'utilisation du clavier comme dispositif d'entrée de navigation, ce qui a donné un modèle plus fiable et prévisible pour la navigation basée sur les flèches et les onglets.

Plus précisément, nous avons apporté les modifications suivantes au comportement de mise au point des éléments:

  • Si vous n'avez défini aucune couleur d'état de focus pour un objet View (son drawable de premier plan ou d'arrière-plan), le framework définit désormais une couleur de surbrillance de focus par défaut pour le View. Cette mise en surbrillance de l'élément sélectionné est un élément drawable de type "ondulation" basé sur le thème de l'activité.

    Si vous ne souhaitez pas qu'un objet View utilise cette mise en surbrillance par défaut lorsqu'il est sélectionné, définissez l'attribut android:defaultFocusHighlightEnabled sur false dans le fichier XML de mise en page contenant View, ou transmettez false à setDefaultFocusHighlightEnabled() dans la logique d'UI de votre application.

  • Pour tester l'impact de la saisie au clavier sur le focus de l'élément d'interface utilisateur, vous pouvez activer l'option pour les développeurs Dessin > Afficher les limites de la mise en page. Dans Android 8.0, cette option affiche une icône X sur l'élément actuellement sélectionné.

De plus, tous les éléments de la barre d'outils sous Android 8.0 sont automatiquement des clusters de navigation au clavier, ce qui permet aux utilisateurs de naviguer plus facilement dans chaque barre d'outils et de la quitter dans son intégralité.

Pour en savoir plus sur l'amélioration de la prise en charge de la navigation au clavier dans votre application, consultez le guide Prise en charge de la navigation au clavier.

Remplissage automatique des formulaires Web

Maintenant que le framework Autofill Android est compatible avec la fonctionnalité de saisie automatique, les méthodes suivantes liées aux objets WebView ont changé pour les applications installées sur des appareils exécutant Android 8.0 (niveau d'API 26):

WebSettings
WebViewDatabase
  • L'appel de clearFormData() n'a plus aucun effet.
  • La méthode hasFormData() renvoie désormais false. Auparavant, cette méthode renvoyait true lorsque le formulaire contenait des données.

Accessibilité

Android 8.0 (niveau d'API 26) inclut les modifications d'accessibilité suivantes:

  • Le framework d'accessibilité convertit désormais tous les gestes de double appui en actions ACTION_CLICK. Ce changement permet à TalkBack de se comporter davantage comme les autres services d'accessibilité.

    Si les objets View de votre application utilisent une gestion tactile personnalisée, vous devez vérifier qu'ils fonctionnent toujours avec TalkBack. Il se peut que vous n'ayez qu'à enregistrer le gestionnaire de clics utilisé par vos objets View. Si TalkBack ne reconnaît toujours pas les gestes effectués sur ces objets View, remplacez performAccessibilityAction().

  • Les services d'accessibilité sont désormais conscients de toutes les instances ClickableSpan dans les objets TextView de votre application.

Pour savoir comment rendre votre application plus accessible, consultez la section Accessibilité.

Mise en réseau et connectivité HTTP(S)

Android 8.0 (niveau d'API 26) inclut les modifications de comportement suivantes concernant la mise en réseau et la connectivité HTTP(S) :

  • Les requêtes OPTIONS sans corps comportent un en-tête Content-Length: 0. Auparavant, il n'y avait pas d'en-tête Content-Length.
  • HttpURLConnection normalise les URL contenant des chemins vides en ajoutant une barre oblique après le nom de l'hôte ou de l'autorité. Par exemple, elle convertit http://example.com en http://example.com/.
  • Un sélecteur de proxy personnalisé défini via ProxySelector.setDefault() ne cible que l'adresse (schéma, hôte et port) d'une URL demandée. Par conséquent, la sélection du proxy peut uniquement être basée sur ces valeurs. Une URL transmise à un sélecteur de proxy personnalisé n'inclut pas le chemin, les paramètres de requête ni les fragments de l'URL demandée.
  • Les URI ne peuvent pas contenir de libellés vides.

    Auparavant, la plate-forme acceptait un contournement pour accepter les libellés vides dans les noms d'hôte, ce qui constitue une utilisation illégale des URI. Cette solution consistait à assurer la compatibilité avec les anciennes versions de libcore. Les développeurs qui utilisent de manière incorrecte l'API verront un message ADB: "L'URI example..com comporte des libellés vides dans le nom d'hôte. Cette valeur est incorrecte et ne sera pas acceptée dans les prochaines versions d'Android." Android 8.0 supprime cette solution de contournement. Le système renvoie la valeur nulle pour les URI mal formés.

  • L'implémentation d'HttpsURLConnection dans Android 8.0 n'effectue pas de remplacement de version de protocole TLS/SSL non sécurisé.
  • La gestion de la tunnelisation des connexions HTTP(S) a changé comme suit :
    • Lors du tunnelage d'une connexion HTTPS sur une connexion, le système place correctement le numéro de port (:443) dans la ligne "Host" lors de l'envoi de ces informations à un serveur intermédiaire. Auparavant, le numéro de port ne s'affichait que dans la ligne CONNECT.
    • Le système n'envoie plus d'en-têtes user-agent et proxy-authorization à partir d'une requête en tunnel au serveur proxy.

      Le système n'envoie plus d'en-tête d'autorisation de proxy sur une Http(s)URLConnection en tunnel au proxy lors de la configuration du tunnel. À la place, le système génère un en-tête d'autorisation de proxy et l'envoie au proxy lorsque celui-ci envoie HTTP 407 en réponse à la requête initiale.

      De même, le système ne copie plus l'en-tête user-agent de la requête acheminée par tunnel vers la requête de proxy qui configure le tunnel. À la place, la bibliothèque génère un en-tête user-agent pour cette requête.

  • La méthode send(java.net.DatagramPacket) génère une SocketException si la méthode connect() précédemment exécutée a échoué.
    • DatagramSocket.connect() définit une pendingSocketException en cas d'erreur interne. Avant Android 8.0, un appel recv() ultérieur générait une SocketException, même si un appel send() aurait réussi. Par souci de cohérence, les deux appels génèrent désormais une exception SocketException.
  • InetAddress.isReachable() tente d'utiliser ICMP avant de revenir au protocole d'écho TCP.
    • Certains hôtes qui bloquent le port 7 (écho TCP), comme google.com, peuvent désormais être accessibles s'ils acceptent le protocole ICMP Echo.
    • Pour les hôtes vraiment inaccessibles, ce changement signifie que le temps passé est doublé avant le retour de l'appel.

Bluetooth

Android 8.0 (niveau d'API 26) apporte les modifications suivantes à la longueur des données que la méthode ScanRecord.getBytes() récupère:

  • La méthode getBytes() ne fait aucune hypothèse sur le nombre d'octets reçus. Par conséquent, les applications ne doivent pas s'appuyer sur un nombre minimal ou maximal d'octets renvoyés. À la place, ils doivent évaluer la longueur du tableau obtenu.
  • Les appareils compatibles avec la version 5 de Bluetooth peuvent renvoyer une longueur de données supérieure à la longueur maximale précédente d'environ 60 octets.
  • Si un appareil distant ne fournit pas de réponse d'analyse, moins de 60 octets peuvent également être renvoyés.

Connectivité fluide

Android 8.0 (niveau d'API 26) apporte plusieurs améliorations aux paramètres Wi-Fi pour faciliter le choix du réseau Wi-Fi qui offre la meilleure expérience utilisateur. Voici les modifications apportées:

  • Amélioration de la stabilité et de la fiabilité.
  • Une interface utilisateur plus lisible et plus intuitive.
  • Un seul menu de préférences Wi-Fi consolidé.
  • Sur les appareils compatibles, activation automatique du Wi-Fi lorsqu'un réseau enregistré de haute qualité est à proximité.

Sécurité

Android 8.0 inclut les modifications suivantes liées à la sécurité:

  • La plate-forme n'est plus compatible avec SSLv3.
  • Lors de l'établissement d'une connexion HTTPS à un serveur qui implémente de manière incorrecte la négociation de la version du protocole TLS, HttpsURLConnection ne tente plus de contourner le problème en revenant à des versions antérieures du protocole TLS et en réessayant.
  • Android 8.0 (niveau d'API 26) applique un filtre de calcul sécurisé (SECCOMP) à toutes les applications. La liste des appels système autorisés est limitée à celles exposées via bionic. Bien que plusieurs autres appels système soient fournis pour la rétrocompatibilité, nous vous déconseillons de les utiliser.
  • Les objets WebView de votre application s'exécutent désormais en mode multiprocessus. Pour renforcer la sécurité, le contenu Web est géré dans un processus distinct et isolé du processus de l'application contenant.
  • Vous ne pouvez plus supposer que les APK se trouvent dans des répertoires dont le nom se termine par -1 ou -2. Les applications doivent utiliser sourceDir pour obtenir le répertoire et ne pas s'appuyer directement sur le format du répertoire.
  • Pour en savoir plus sur les améliorations de sécurité liées à l'utilisation des bibliothèques natives, consultez la section Bibliothèques natives.

En outre, Android 8.0 (niveau d'API 26) introduit les modifications suivantes concernant l'installation d'applications inconnues à partir de sources inconnues:

Pour en savoir plus sur l'installation d'applications inconnues, consultez le guide Autorisations d'installation d'applications inconnues.

Pour obtenir des conseils supplémentaires sur la sécurisation de votre application, consultez la section Sécurité pour les développeurs Android.

Confidentialité

Android 8.0 (niveau d'API 26) apporte les modifications liées à la confidentialité suivantes à la plate-forme.

  • La plate-forme gère désormais les identifiants différemment.
    • Pour les applications installées avant une mise à jour OTA vers une version d'Android 8.0 (niveau d'API 26), la valeur de ANDROID_ID reste la même, sauf si elle est désinstallée, puis réinstallée après la mise à jour OTA. Pour conserver les valeurs lors des désinstallations après l'OTA, les développeurs peuvent associer les anciennes et les nouvelles valeurs à l'aide de la sauvegarde de clé-valeur.
    • Pour les applications installées sur un appareil exécutant Android 8.0, la valeur de ANDROID_ID est désormais limitée par clé de signature d'application, ainsi que par utilisateur. La valeur de ANDROID_ID est unique pour chaque combinaison de clé de signature d'application, d'utilisateur et d'appareil. Par conséquent, les applications exécutées sur le même appareil avec des clés de signature différentes ne voient plus le même ID Android (même pour le même utilisateur).
    • La valeur de ANDROID_ID ne change pas lors de la désinstallation ou de la réinstallation du package, tant que la clé de signature est la même (et que l'application n'a pas été installée avant une OTA vers une version d'Android 8.0).
    • La valeur de ANDROID_ID ne change pas, même si une mise à jour du système modifie la clé de signature du package.
    • Sur les appareils livrés avec les services Google Play et l'identifiant publicitaire, vous devez utiliser l' identifiant publicitaire. L'identifiant publicitaire est un système simple et standard permettant de monétiser les applications. Il s'agit d'un identifiant publicitaire unique et réinitialisable par l'utilisateur. Il est fourni par les services Google Play.

      Les autres fabricants d'appareils doivent continuer à fournir ANDROID_ID.

  • L'interrogation de la propriété système net.hostname génère un résultat nul.

Journalisation des exceptions non détectées

Si une application installe un Thread.UncaughtExceptionHandler qui n'appelle pas le Thread.UncaughtExceptionHandler par défaut, le système n'arrête pas l'application lorsqu'une exception non interceptée se produit. À partir d'Android 8.0 (niveau d'API 26), le système consigne la trace de la pile d'exception dans cette situation. Dans les versions antérieures de la plate-forme, le système ne consignait pas la trace de la pile d'exception.

Nous vous recommandons que les implémentations Thread.UncaughtExceptionHandler personnalisées appellent toujours le gestionnaire par défaut. Les applications qui suivent cette recommandation ne sont pas affectées par le changement d'Android 8.0.

Modification de la signature findViewById()

Toutes les instances de la méthode findViewById() renvoient désormais <T extends View> T au lieu de View. Cette modification a les implications suivantes:

  • Par conséquent, le code existant peut maintenant présenter un type renvoyé ambigu, par exemple si someMethod(View) et someMethod(TextView) reçoivent le résultat d'un appel à findViewById().
  • Lorsque vous utilisez le langage source Java 8, cela nécessite un cast explicite vers View lorsque le type de retour n'est pas contraint (par exemple, assertNotNull(findViewById(...)).someViewMethod())).
  • Les forçages des méthodes findViewById() non finales (par exemple, Activity.findViewById()) devront être mis à jour.

Modification des statistiques d'utilisation du fournisseur de contacts

Dans les versions précédentes d'Android, le composant Contacts Provider permet aux développeurs d'obtenir les données d'utilisation de chaque contact. Ces données d'utilisation fournissent des informations sur chaque adresse e-mail et chaque numéro de téléphone associé à un contact, y compris le nombre de fois où le contact a été contacté et la dernière fois où il a été contacté. Les applications qui demandent l'autorisation READ_CONTACTS peuvent lire ces données.

Les applications peuvent toujours lire ces données si elles demandent l'autorisation READ_CONTACTS. Sur Android 8.0 (niveau d'API 26) ou version ultérieure, les requêtes sur les données d'utilisation renvoient des approximations plutôt que des valeurs exactes. Le système Android conserve les valeurs exactes en interne. Cette modification n'affecte donc pas l'API de saisie semi-automatique.

Ce changement de comportement affecte les paramètres de requête suivants:

Gestion des collections

AbstractCollection.removeAll() et AbstractCollection.retainAll() génèrent désormais toujours une NullPointerException. Auparavant, NullPointerException n'était pas généré lorsque la collection était vide. Cette modification rend le comportement conforme à la documentation.

Android Enterprise

Android 8.0 (niveau d'API 26) modifie le comportement de certaines API et fonctionnalités pour les applications d'entreprise, y compris les outils de contrôle des règles relatives aux appareils (DPC). Voici les modifications apportées:

  • Nouveaux comportements pour aider les applications à prendre en charge les profils professionnels sur les appareils entièrement gérés.
  • Modifications apportées à la gestion des mises à jour du système, à la validation des applications et à l'authentification afin d'améliorer l'intégrité de l'appareil et du système.
  • Améliorations apportées à l'expérience utilisateur pour le provisionnement, les notifications, l'écran "Récents" et le VPN permanent.

Pour consulter toutes les modifications apportées à Android 8.0 (niveau d'API 26) pour l'entreprise et découvrir comment elles peuvent affecter votre application, consultez Android dans l'entreprise.

Applications ciblant Android 8.0

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

Fenêtres d'alerte

Les applications qui utilisent l'autorisation SYSTEM_ALERT_WINDOW ne peuvent plus utiliser les types de fenêtres suivants pour afficher des fenêtres d'alerte au-dessus d'autres applications et fenêtres système:

À la place, les applications doivent utiliser un nouveau type de fenêtre appelé TYPE_APPLICATION_OVERLAY.

Lorsque vous utilisez le type de fenêtre TYPE_APPLICATION_OVERLAY pour afficher des fenêtres d'alerte pour votre application, tenez compte des caractéristiques suivantes du nouveau type de fenêtre:

  • Les fenêtres d'alerte d'une application apparaissent toujours sous les fenêtres système critiques, telles que la barre d'état et les IME.
  • Le système peut déplacer ou redimensionner les fenêtres qui utilisent le type de fenêtre TYPE_APPLICATION_OVERLAY pour améliorer la présentation à l'écran.
  • En ouvrant le volet des notifications, les utilisateurs peuvent accéder aux paramètres pour empêcher une application d'afficher des fenêtres d'alerte à l'aide du type de fenêtre TYPE_APPLICATION_OVERLAY.

Notifications de modification du contenu

Android 8.0 (niveau d'API 26) modifie le comportement de ContentResolver.notifyChange() et registerContentObserver(Uri, boolean, ContentObserver) pour les applications ciblant Android 8.0.

Ces API nécessitent désormais qu'un ContentProvider valide soit défini pour l'autorité dans tous les URI. Définir un ContentProvider valide avec des autorisations appropriées permet de protéger votre application contre les modifications de contenu par des applications malveillantes et d'éviter de divulguer des données potentiellement privées à des applications malveillantes.

Mise au point de l'affichage

Les objets View cliquables sont désormais également sélectionnables par défaut. Si vous souhaitez qu'un objet View soit cliquable, mais ne puisse pas être sélectionné, définissez l'attribut android:focusable sur false dans le fichier XML de mise en page contenant le View, ou transmettez false à setFocusable() dans la logique d'UI de votre application.

Correspondance des user-agents dans la détection des navigateurs

Android 8.0 (niveau d'API 26) ou version ultérieure inclut la chaîne d'identifiant de build OPR. Certaines correspondances de modèles peuvent entraîner une mauvaise identification d'un navigateur autre qu'Opera par la logique de détection de navigateur. Voici un exemple de correspondance de modèle:

if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}

Pour éviter les problèmes liés à une telle identification incorrecte, utilisez une chaîne autre que OPR comme correspondance de format pour le navigateur Opera.

Sécurité

Les modifications suivantes affectent la sécurité dans Android 8.0 (niveau d'API 26):

  • Si la configuration de la sécurité réseau de votre application désactive la prise en charge du trafic en texte clair, les objets WebView de votre application ne peuvent pas accéder aux sites Web via HTTP. Chaque objet WebView doit utiliser HTTPS à la place.
  • Le paramètre système Autoriser les sources inconnues a été supprimé. À sa place, l'autorisation Installer des applications inconnues gère les installations d'applications inconnues provenant de sources inconnues. Pour en savoir plus sur cette nouvelle autorisation, consultez le guide sur les autorisations d'installation d'applications inconnues.

Pour obtenir des conseils supplémentaires sur la sécurisation de votre application, consultez la section Sécurité pour les développeurs Android.

Accès au compte et visibilité

Sous Android 8.0 (niveau d'API 26), les applications ne peuvent plus accéder aux comptes utilisateur, sauf si l'authentificateur en est le propriétaire ou si l'utilisateur accorde cet accès. L'autorisation GET_ACCOUNTS n'est plus suffisante. Pour être autorisées à accéder à un compte, les applications doivent utiliser AccountManager.newChooseAccountIntent() ou une méthode spécifique à l'authentificateur. Une fois qu'une application a obtenu l'accès aux comptes, elle peut appeler AccountManager.getAccounts() pour y accéder.

Android 8.0 abandonne LOGIN_ACCOUNTS_CHANGED_ACTION. Les applications doivent plutôt utiliser addOnAccountsUpdatedListener() pour obtenir des informations sur les comptes pendant l'exécution.

Pour en savoir plus sur les nouvelles API et méthodes ajoutées pour l'accès et la visibilité des comptes, consultez la section Accès aux comptes et visibilité dans la section "Nouvelles API" de ce document.

Confidentialité

Les modifications suivantes affectent la confidentialité dans Android 8.0 (niveau d'API 26).

  • Les propriétés système net.dns1, net.dns2, net.dns3 et net.dns4 ne sont plus disponibles, ce qui améliore la confidentialité sur la plate-forme.
  • Pour obtenir des informations réseau telles que les serveurs DNS, les applications disposant de l'autorisation ACCESS_NETWORK_STATE peuvent enregistrer un objet NetworkRequest ou NetworkCallback. Ces classes sont disponibles sur Android 5.0 (niveau d'API 21) ou version ultérieure.
  • Build.SERIAL est obsolète. Les applications qui ont besoin de connaître le numéro de série du matériel doivent plutôt utiliser la nouvelle méthode Build.getSerial(), qui nécessite l'autorisation READ_PHONE_STATE.
  • L'API LauncherApps n'autorise plus les applications du profil professionnel à obtenir des informations sur le profil principal. Lorsqu'un utilisateur se trouve dans un profil professionnel, l'API LauncherApps se comporte comme si aucune application n'était installée dans les autres profils du même groupe de profils. Comme précédemment, les tentatives d'accès à des profils sans rapport génèrent des SecurityExceptions.

Autorisations

Avant Android 8.0 (niveau d'API 26), si une application demandait une autorisation au moment de l'exécution et que celle-ci était accordée, le système lui accordait également de manière incorrecte le reste des autorisations appartenant au même groupe d'autorisations et enregistrées dans le fichier manifeste.

Pour les applications ciblant Android 8.0, ce comportement a été corrigé. L'application ne se voit accorder que les autorisations qu'elle a explicitement demandées. Toutefois, une fois que l'utilisateur a accordé une autorisation à l'application, toutes les demandes d'autorisations ultérieures dans ce groupe d'autorisations sont accordées automatiquement.

Par exemple, supposons qu'une application liste à la fois READ_EXTERNAL_STORAGE et WRITE_EXTERNAL_STORAGE dans son fichier manifeste. L'application demande l'autorisation READ_EXTERNAL_STORAGE et l'utilisateur l'accorde. Si l'application cible le niveau d'API 25 ou une version antérieure, le système accorde également WRITE_EXTERNAL_STORAGE en même temps, car il appartient au même groupe d'autorisations STORAGE et est également enregistré dans le fichier manifeste. Si l'application cible Android 8.0 (niveau d'API 26), le système n'accorde que READ_EXTERNAL_STORAGE à ce moment-là. Toutefois, si l'application demande ultérieurement WRITE_EXTERNAL_STORAGE, le système accorde immédiatement ce droit sans envoyer d'invite à l'utilisateur.

Contenus multimédias

  • Le framework peut effectuer seul le masquage automatique du son. Dans ce cas, lorsqu'une autre application demande la priorité avec AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, l'application qui a la priorité réduit son volume, mais ne reçoit généralement pas de rappel onAudioFocusChange() et ne perd pas la priorité audio. De nouvelles API sont disponibles afin d'ignorer ce comportement pour les applications qui doivent être mises en pause au lieu de baisser.
  • Lorsque l'utilisateur reçoit un appel téléphonique, les flux multimédias actifs sont coupés pendant toute la durée de l'appel.
  • Toutes les API liées à l'audio doivent utiliser AudioAttributes au lieu des types de flux audio pour décrire le cas d'utilisation de la lecture audio. Continuez à utiliser les types de flux audio uniquement pour les commandes de volume. D'autres utilisations des types de flux fonctionnent toujours (par exemple, l'argument streamType du constructeur AudioTrack obsolète), mais le système les consigne en tant qu'erreur.
  • Lorsque vous utilisez un AudioTrack, si l'application demande une mémoire tampon audio suffisamment grande, le framework tente d'utiliser la sortie de la mémoire tampon profonde si elle est disponible.
  • Dans Android 8.0 (niveau d'API 26), la gestion des événements de bouton multimédia est différente :
    1. Le traitement des boutons multimédias dans une activité d'interface utilisateur n'a pas changé: les activités de premier plan sont toujours prioritaires pour la gestion des événements de boutons multimédias.
    2. Si l'activité de premier plan ne gère pas l'événement du bouton multimédia, le système achemine l'événement vers l'application qui a lu en local le dernier contenu audio. L'état actif, les indicateurs et l'état de lecture d'une session multimédia ne sont pas pris en compte pour déterminer quelle application reçoit les événements de bouton multimédia.
    3. Si la session multimédia de l'application a été libérée, le système envoie l'événement de bouton multimédia à l'MediaButtonReceiver de l'application, le cas échéant.
    4. Dans tous les autres cas, le système ignore l'événement du bouton multimédia.

Bibliothèques natives

Dans les applications ciblant Android 8.0 (niveau d'API 26), les bibliothèques natives ne se chargent plus si elles contiennent un segment de chargement à la fois en lecture et exécutable. En raison de ce changement, certaines applications peuvent cesser de fonctionner si leurs bibliothèques natives présentent des segments de chargement incorrects. Il s'agit d'une mesure de renforcement de la sécurité.

Pour en savoir plus, consultez la section Segments en lecture et exécutables.

Les modifications apportées à Linker sont liées au niveau d'API ciblé par une application. Si un changement de l'éditeur de liens se produit au niveau de l'API ciblée, l'application ne peut pas charger la bibliothèque. Si vous ciblez un niveau d'API inférieur à celui où le changement de l'éditeur de liens se produit, Logcat affiche un avertissement.

Gestion des collections

Dans Android 8.0 (niveau d'API 26), Collections.sort() est implémenté au-dessus de List.sort(). L'inverse était vrai dans Android 7.x (niveaux d'API 24 et 25) : l'implémentation par défaut de List.sort() était appelée Collections.sort().

Cette modification permet à Collections.sort() de tirer parti des implémentations List.sort() optimisées, mais présente les contraintes suivantes:

  • Les implémentations de List.sort() ne doivent pas appeler Collections.sort(), car cela entraînerait un débordement de pile en raison d'une récursion infinie. Si vous souhaitez utiliser le comportement par défaut dans votre implémentation de List, évitez de remplacer sort().

    Si une classe parente implémente sort() de manière inappropriée, il est généralement acceptable de remplacer List.sort() par une implémentation basée sur List.toArray(), Arrays.sort() et ListIterator.set(). Exemple :

    @Override
    public void sort(Comparator<? super E> c) {
      Object[] elements = toArray();
      Arrays.sort(elements, c);
      ListIterator<E> iterator = (ListIterator<Object>) listIterator();
      for (Object element : elements) {
        iterator.next();
        iterator.set((E) element);
      }
    }

    Dans la plupart des cas, vous pouvez également remplacer List.sort() par une implémentation qui délègue à différentes implémentations par défaut en fonction du niveau d'API. Exemple :

    @Override
    public void sort(Comparator<? super E> comparator) {
      if (Build.VERSION.SDK_INT <= 25) {
        Collections.sort(this);
      } else {
        super.sort(comparator);
      }
    }

    Si vous n'utilisez ce dernier que parce que vous souhaitez qu'une méthode sort() soit disponible à tous les niveaux d'API, envisagez de lui donner un nom unique, tel que sortCompat(), au lieu de remplacer sort().

  • Collections.sort() est désormais considéré comme une modification structurelle dans les implémentations de liste qui appellent sort(). Par exemple, dans les versions de la plate-forme antérieures à Android 8.0 (niveau d'API 26), l'itération sur un ArrayList et l'appel de sort() dessus au milieu de l'itération auraient généré une ConcurrentModificationException si le tri avait été effectué en appelant List.sort(). Collections.sort() n'a pas généré d'exception.

    Ce changement rend le comportement de la plate-forme plus cohérent: les deux approches génèrent désormais une ConcurrentModificationException.

Comportement de chargement de classe

Android 8.0 (niveau d'API 26) vérifie que les chargeurs de classe ne volent pas les hypothèses du runtime lors du chargement de nouvelles classes. Ces vérifications sont effectuées que la classe soit référencée à partir de Java (à partir de forName()), de bytecode Dalvik ou de JNI. La plate-forme n'intercepte pas les appels directs de Java vers la méthode loadClass(), ni ne vérifie les résultats de ces appels. Ce comportement ne devrait pas affecter le bon fonctionnement des chargeurs de classe.

La plate-forme vérifie que le descripteur de la classe renvoyé par le chargeur de classe correspond au descripteur attendu. Si le descripteur renvoyé ne correspond pas, la plate-forme génère une erreur NoClassDefFoundError et stocke dans l'exception un message détaillé indiquant l'écart.

La plate-forme vérifie également que les descripteurs des classes demandées sont valides. Cette vérification détecte les appels JNI qui chargent indirectement des classes telles que GetFieldID(), en transmettant des descripteurs non valides à ces classes. Par exemple, un champ avec la signature java/lang/String n'est pas trouvé, car cette signature n'est pas valide. Elle doit être Ljava/lang/String;.

Il s'agit d'un appel JNI à FindClass(), où java/lang/String est un nom complet valide.

Android 8.0 (niveau d'API 26) n'autorise pas plusieurs chargeurs de classe à essayer de définir des classes à l'aide du même objet DexFile. Si vous essayez de le faire, le runtime Android génère une erreur InternalError avec le message "Tentative d'enregistrement du fichier dex <filename> avec plusieurs chargeurs de classe".

L'API DexFile est désormais obsolète. Nous vous recommandons vivement d'utiliser l'un des chargeurs de classe de la plate-forme, y compris PathClassLoader ou BaseDexClassLoader.

Remarque : Vous pouvez créer plusieurs chargeurs de classe qui référencent le même conteneur de fichier APK ou JAR à partir du système de fichiers. Cela n'entraîne généralement pas beaucoup de surcharge de mémoire: si les fichiers DEX du conteneur sont stockés au lieu d'être compressés, la plate-forme peut effectuer une opération mmap dessus plutôt que de les extraire directement. Toutefois, si la plate-forme doit extraire le fichier DEX du conteneur, le référencement d'un fichier DEX de cette manière peut consommer beaucoup de mémoire.

Dans Android, tous les chargeurs de classe sont considérés comme compatibles avec le parallélisme. Lorsque plusieurs threads s'affrontent pour charger la même classe avec le même chargeur de classe, le premier thread à terminer l'opération gagne, et le résultat est utilisé pour les autres threads. Ce comportement se produit que le chargeur de classe ait renvoyé la même classe, une classe différente ou une exception. La plate-forme ignore ces exceptions en mode silencieux.

Attention : Dans les versions de la plate-forme antérieures à Android 8.0 (niveau d'API 26), le fait de contourner ces hypothèses peut entraîner la définition de la même classe plusieurs fois, la corruption du tas de mémoire due à la confusion de la classe et d'autres effets indésirables.