Changements de comportement dans Android 8.0

En plus de nouvelles fonctionnalités, Android 8.0 (niveau d'API 26) apporte diverses modifications au comportement du système et de l'API. Ce document met en évidence 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 de façon à les prendre en charge correctement, le cas échéant.

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

Parmi les changements introduits par Android 8.0 (niveau d'API 26) pour améliorer l'autonomie de la batterie, lorsque votre application passe à l'état mis en cache sans composants actifs, le système libère les wakelocks qu'elle contient.

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 qui s'exécutent en arrière-plan ont désormais des limites quant à leur liberté d'accès aux services en arrière-plan.
  • Les applications ne peuvent pas utiliser leur fichier manifeste pour s'inscrire à la plupart des diffusions implicites (c'est-à-dire des diffusions 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 à partir de 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 alors qu'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 lorsqu'elles sont en arrière-plan. Cependant, l'application doit appeler la méthode startForeground() de ce service dans les cinq secondes suivant la création du service.

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

Limites de localisation en arrière-plan sur Android

Pour préserver la batterie, l'expérience utilisateur et l'état du système, les applications en arrière-plan reçoivent moins de mises à jour de position 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 notifications de position, y compris les services Google Play.

Ces modifications affectent les API suivantes:

  • Fused Location Provider (FLP)
  • Géorepérage
  • Mesures GNSS
  • Gestionnaire d'établissements
  • 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 Fused Location Provider (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 Limites de localisation en arrière-plan.

Raccourcis d'application

Android 8.0 (niveau d'API 26) apporte les modifications suivantes aux raccourcis d'application:

  • La diffusion com.android.launcher.action.INSTALL_SHORTCUT n'a plus aucun effet sur votre application, car il s'agit désormais d'une diffusion implicite et privée. À 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 d'anciens raccourcis de lanceur.
  • Les raccourcis créés à l'aide de requestPinShortcut() et ceux 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 leurs 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.

Langues et internationalisation

Android 7.0 (niveau d'API 24) a introduit le concept de la possibilité de spécifier des paramètres régionaux 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 les paramètres régionaux de la catégorie DISPLAY par défaut. Sous 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) utilise également Locale.getDefault() lorsque la valeur displayScript spécifiée pour l'argument Locale n'est pas disponible.

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

  • L'appel de Currency.getDisplayName(null) génère une erreur NullPointerException, correspondant au comportement documenté.
  • L'analyse du nom du fuseau horaire a été modifiée. Auparavant, les appareils Android utilisaient la valeur d'horloge système échantillonnée au moment du 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 est incorrecte au moment du démarrage ou dans d'autres cas plus rares.

    Dans des cas courants, la logique d'analyse utilise la bibliothèque ICU et la valeur d'horloge système actuelle lors de l'analyse des noms de fuseau horaire. 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:

Ces fenêtres apparaissent toujours sous celles 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 changements de comportement pour les applications ciblant Android 8.0.

Saisie et navigation

Avec l'avènement des applications Android sous ChromeOS et d'autres facteurs de forme importants, tels que les tablettes, nous constatons un retour de l'utilisation de la navigation au clavier dans les applications Android. Dans Android 8.0 (niveau d'API 26), nous avons réajusté l'utilisation du clavier en tant que périphérique d'entrée de navigation. Nous avons ainsi créé un modèle plus fiable et prévisible pour la navigation par flèches et par onglets.

Nous avons notamment apporté les modifications suivantes au comportement de sélection des éléments:

  • Si vous n'avez défini aucune couleur d'état de sélection pour un objet View (que ce soit son drawable de premier plan ou d'arrière-plan), le framework définit désormais une couleur de mise en surbrillance par défaut pour View. Ce surlignage est un drawable d'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 ciblage des éléments d'interface utilisateur, vous pouvez activer l'option pour les développeurs Dessin > Afficher les contours de la mise en page. Dans Android 8.0, cette option affiche une icône "X" sur l'élément sélectionné.

En outre, tous les éléments de la barre d'outils dans Android 8.0 sont automatiquement des clusters de navigation au clavier, ce qui permet aux utilisateurs de naviguer plus facilement dans et hors de chaque barre d'outils dans son ensemble.

Pour savoir comment améliorer la prise en charge de la navigation au clavier dans votre application, consultez le guide Prendre en charge la navigation au clavier.

Remplir automatiquement les formulaires Web

Maintenant que le framework de saisie automatique Android est compatible avec la fonctionnalité de saisie automatique, les méthodes suivantes liées aux objets WebView ont été modifiées pour les applications installées sur les appareils équipés d'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) apporte les modifications suivantes en matière d'accessibilité:

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

    Si les objets View de votre application utilisent la gestion tactile personnalisée, vérifiez qu'ils fonctionnent toujours avec TalkBack. Il vous suffira peut-être d'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é connaissent désormais toutes les instances ClickableSpan dans les objets TextView de votre application.

Pour découvrir comment rendre votre application plus accessible, consultez Accessibilité.

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

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

  • Les requêtes OPTIONS sans corps comportent un en-tête Content-Length: 0. Auparavant, elles n'avaient pas d'en-tête Content-Length.
  • HttpURLConnection normalise les URL contenant des chemins d'accès vides en ajoutant une barre oblique après le nom d'hôte ou d'autorité. Par exemple, il convertit http://example.com en http://example.com/.
  • Un sélecteur de proxy personnalisé défini via ProxySélecteur.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 être basée uniquement 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 proposait une solution de contournement qui permettait d'accepter les étiquettes vides dans les noms d'hôte, ce qui constitue une utilisation illégale des URI. Cette solution était destinée à assurer la compatibilité avec les anciennes versions de libcore. Les développeurs qui n'utilisent pas correctement l'API verront le message ADB suivant: "L'URI example.com comporte des libellés vides dans le nom d'hôte. Ce format est incorrect et ne sera pas accepté dans les prochaines versions d'Android. Android 8.0 supprime cette solution de contournement. Le système renvoie la valeur "null" pour les URI incorrects.

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

      Le système n'envoie plus d'en-tête proxy-Authorization sur une ressource HttpConnection(s)URLConnection acheminée par tunnel au proxy lors de la configuration du tunnel. Au lieu de cela, le système génère un en-tête proxy-Authorization et l'envoie au proxy lorsque celui-ci envoie le code 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 proxy qui configure le tunnel. Au lieu de cela, 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 exception SocketException en cas d'échec de la méthode connect() précédemment exécutée.
    • 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 le protocole ICMP avant de revenir au protocole TCP Echo.
    • Certains hôtes qui bloquent le port 7 (TCP Echo), tels que google.com, peuvent désormais devenir accessibles s'ils acceptent le protocole ICMP Echo.
    • Pour les hôtes véritablement inaccessibles, cette modification signifie que le temps est passé deux fois avant le retour de l'appel.

Bluetooth

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

  • La méthode getBytes() ne fait aucune hypothèse concernant 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. Ils doivent plutôt évaluer la longueur du tableau obtenu.
  • Les appareils compatibles avec le Bluetooth 5 peuvent renvoyer une longueur de données supérieure à la valeur maximale précédente de 60 octets environ.
  • Si un appareil distant ne fournit pas de réponse d'analyse, une taille inférieure à 60 octets peut également être renvoyée.

Connectivité fluide

Android 8.0 (niveau d'API 26) apporte un certain nombre d'améliorations aux paramètres Wi-Fi pour faciliter le choix du réseau Wi-Fi offrant la meilleure expérience utilisateur. Voici quelques modifications spécifiques:

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

Sécurité

Android 8.0 inclut les modifications de sécurité suivantes:

  • La plate-forme n'est plus compatible avec SSLv3.
  • Lorsque vous établissez une connexion HTTPS à un serveur qui implémente de manière incorrecte la négociation de protocole TLS, HttpsURLConnection ne tente plus de revenir à une version antérieure du protocole TLS et d'effectuer une nouvelle tentative.
  • Android 8.0 (niveau d'API 26) applique un filtre SECCOMP (Secure Computing) à toutes les applications. La liste des appels système autorisés est limitée à ceux exposés via bionic. Bien que plusieurs autres appels système soient fournis pour assurer la rétrocompatibilité, nous vous déconseillons de les utiliser.
  • Les objets WebView de votre application s'exécutent désormais en mode multiprocessus. Le contenu Web est géré dans un processus distinct et isolé de celui de l'application parent pour une sécurité renforcée.
  • 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 non s'appuyer directement sur le format du répertoire.
  • Pour en savoir plus sur les améliorations de la sécurité liées à l'utilisation des bibliothèques natives, consultez la page Bibliothèques natives.

De plus, Android 8.0 (niveau d'API 26) introduit les modifications suivantes liées à l'installation d'applications inconnues provenant 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 consignes supplémentaires sur la sécurité de votre application, consultez Sécurité pour les développeurs Android.

Confidentialité

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

  • La plate-forme gère désormais les identifiants différemment.
    • Pour les applications installées avant une OTA vers une version d'Android 8.0 (niveau d'API 26) (niveau d'API 26), la valeur de ANDROID_ID reste la même, sauf si elle a été désinstallée, puis réinstallée après l'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 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 et 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 qui exécutent différentes clés de signature sur le même appareil 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 entraîne la modification de la clé de signature de package.
    • Sur les appareils livrés avec les services Google Play et l'identifiant publicitaire, vous devez utiliser un identifiant publicitaire. Il s'agit d'un système simple et standard qui permet de monétiser les applications. L'identifiant publicitaire est un identifiant unique et réinitialisable par l'utilisateur, destiné à la publicité. 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 produit 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 ne ferme pas l'application lorsqu'une exception non détecté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 précédentes de la plate-forme, le système n'aurait pas enregistré la trace de la pile d'exceptions.

Nous vous recommandons de toujours appeler le gestionnaire par défaut dans les implémentations Thread.UncaughtExceptionHandler personnalisées. Les applications qui suivent cette recommandation ne sont pas affectées par le changement apporté à 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 conséquences suivantes:

  • Par conséquent, le code existant peut désormais comporter un type renvoyé ambigu, par exemple si someMethod(View) et someMethod(TextView) acceptent le résultat d'un appel à findViewById().
  • Lorsque vous utilisez le langage source Java 8, cela nécessite une conversion explicite en View lorsque le type renvoyé est sans contrainte (par exemple, assertNotNull(findViewById(...)).someViewMethod())).
  • Le type renvoyé doit être mis à jour pour les remplacements de méthodes findViewById() non finales (par exemple, Activity.findViewById()).

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 des données d'utilisation pour chaque contact. Ces données d'utilisation fournissent des informations pour 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 qu'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. Sous Android 8.0 (niveau d'API 26) ou version ultérieure, les requêtes pour 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 de la collecte

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 cohérent avec 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). Ces modifications incluent les éléments suivants:

  • Nouveaux comportements pour aider les applications à accepter les profils professionnels sur les appareils entièrement gérés.
  • Modifications apportées à la gestion des mises à jour du système, à la vérification 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 "Recents" (Éléments récents) et le VPN permanent.

Pour voir toutes les modifications apportées par Android 8.0 (niveau d'API 26) et leur impact potentiel sur 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 se compilent pour Android 8.0, ou qui définissent targetSdkVersion sur Android 8.0 ou version ultérieure doivent modifier leurs applications pour prendre 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:

  • Les fenêtres d'alerte d'une application apparaissent toujours sous des 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 de l'écran.
  • En ouvrant le volet des notifications, les utilisateurs peuvent accéder aux paramètres permettant d'empêcher une application d'afficher les fenêtres d'alerte affichées à l'aide du type de fenêtre TYPE_APPLICATION_OVERLAY.

Notifications de modifications 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 les autorisations appropriées aidera à protéger votre application contre les modifications de contenu provenant d'applications malveillantes et vous empêchera de divulguer des données potentiellement privées à des applications malveillantes.

Afficher l'objectif

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

Correspondance user-agent dans la détection du navigateur

Android 8.0 (niveau d'API 26) ou version ultérieure incluent la chaîne d'identifiant de build OPR. Certaines correspondances de structure peuvent entraîner une erreur d'identification avec Opera d'un navigateur autre qu'Opera. Voici un exemple de correspondance de structure:

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 Autorisations d'installation d'applications inconnues.

Pour obtenir des consignes supplémentaires sur la sécurité de votre application, consultez 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 pouvoir accéder à un compte, les applications doivent utiliser AccountManager.newChooseAccountIntent() ou une méthode spécifique à l'authentificateur. Après avoir obtenu l'accès aux comptes, une application 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 les nouvelles méthodes ajoutées pour l'accès au compte et la visibilité, consultez Accès au compte 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 des 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.
  • Abandon de Build.SERIAL. Les applications ayant besoin de connaître le numéro de série du matériel doivent utiliser la nouvelle méthode Build.getSerial(), qui nécessite l'autorisation READ_PHONE_STATE.
  • L'API LauncherApps n'autorise plus les applications de profil professionnel à obtenir des informations sur le profil principal. Lorsqu'un utilisateur utilise un profil professionnel, l'API LauncherApps se comporte comme si aucune application n'était installée dans d'autres profils du même groupe de profils. Comme précédemment, les tentatives d'accès à des profils non liés entraînent des exceptions SecurityExceptions.

Autorisations

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

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

Par exemple, supposons qu'une application répertorie à 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 inférieur, le système accorde également l'autorisation WRITE_EXTERNAL_STORAGE en même temps, car elle 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 l'autorisation READ_EXTERNAL_STORAGE à ce moment-là. Toutefois, si l'application demande par la suite WRITE_EXTERNAL_STORAGE, le système accorde immédiatement ce droit sans afficher d'invite.

Contenus multimédias

  • Le framework peut effectuer lui-même une atténuation audio automatique. Dans ce cas, lorsqu'une autre application demande le ciblage avec AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, l'application ciblée 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 pour remplacer ce comportement pour les applications qui doivent être mises en pause au lieu de réduire la capacité.
  • Lorsque l'utilisateur répond à un appel téléphonique, le son des flux multimédias actifs est coupé pendant toute la durée de l'appel.
  • Toutes les API liées à l'audio doivent utiliser AudioAttributes plutôt que des types de flux audio pour décrire le cas d'utilisation de la lecture audio. Continuez à utiliser les types de flux audio pour les commandes de volume uniquement. Les autres utilisations des types de flux fonctionnent toujours (par exemple, l'argument streamType du constructeur AudioTrack obsolète), mais le système consigne cette erreur comme une erreur.
  • Lorsque vous utilisez un AudioTrack, si l'application demande un tampon audio suffisamment volumineux, le framework essaie d'utiliser la sortie du tampon de profondeur, si elle est disponible.
  • Sous Android 8.0 (niveau d'API 26), la gestion des événements du 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 restent 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 l'achemine vers l'application qui a lu localement 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 du bouton multimédia.
    3. Si la session multimédia de l'application a été publiée, le système envoie l'événement du bouton multimédia au 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 charge accessible en écriture et exécutable. Certaines applications peuvent cesser de fonctionner en raison de ce changement si elles comportent des bibliothèques natives avec des segments de charge incorrects. Il s'agit d'une mesure de sécurité.

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

Les modifications apportées à l'éditeur de liens sont liées au niveau d'API ciblé par une application. En cas de modification de l'éditeur de liens 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ù se produit la modification de l'éditeur de liens, Logcat affiche un avertissement.

Gestion de la collecte

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

Cette modification permet à Collections.sort() de bénéficier 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 de la 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 possible de remplacer List.sort() par une implémentation basée sur List.toArray(), Arrays.sort() et ListIterator.set(). Par 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. Par 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'effectuez cette dernière que parce que vous souhaitez qu'une méthode sort() soit disponible à tous les niveaux d'API, envisagez de lui attribuer un nom unique, tel que sortCompat(), au lieu de remplacer sort().

  • Mise à jour de Collections.sort(), qui est désormais comptabilisé 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), une itération sur un ArrayList et l'appel de sort() au cours 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.

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

Comportement de chargement des classes

Android 8.0 (niveau d'API 26) vérifie que les chargeurs de classes n'enfreignent pas les hypothèses de l'environnement d'exécution 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()), du bytecode Dalvik ou de JNI. La plate-forme n'intercepte pas les appels directs de Java à la méthode loadClass() et ne vérifie pas les résultats de ces appels. Ce comportement ne devrait pas affecter le fonctionnement des chargeurs de classe performants.

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 permet de détecter 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 est introuvable, car cette signature n'est pas valide. Il devrait s'agir de Ljava/lang/String;.

Cela diffère d'un appel JNI à FindClass()java/lang/String est un nom complet valide.

Android 8.0 (niveau d'API 26) ne permet pas de faire en sorte que plusieurs chargeurs de classes tentent de définir des classes à l'aide du même objet DexFile. Si vous tentez de le faire, l'environnement d'exécution Android génère une erreur InternalError avec le message "Autoriser l'enregistrement du fichier dex <filename> avec plusieurs chargeurs de classes".

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

Remarque : Vous pouvez créer plusieurs chargeurs de classes faisant référence au même conteneur de fichiers APK ou JAR du système de fichiers. Cela n'entraîne normalement pas 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 sur ces fichiers au lieu 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 classes sont considérés comme compatibles avec le chargement en parallèle. Lorsque plusieurs threads se font concurrence pour charger la même classe avec le même chargeur de classe, le premier thread qui termine l'opération l'emporte, et le résultat est utilisé pour les autres. Ce comportement se produit que le chargeur de classe ait renvoyé la même classe ou une autre classe, ou qu'il ait généré une exception. La plate-forme ignore silencieusement ces exceptions.

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