Changements de comportement : toutes les applications

Android 10 inclut des modifications de comportement susceptibles d'affecter votre application. Les modifications listées sur cette page s'appliquent à votre application lorsqu'elle s'exécute sur Android 10, quel que soit le targetSdkVersion de l'application. Vous devez tester votre application et la modifier si nécessaire afin de prendre en charge ces modifications correctement.

Si la valeur targetSdkVersion de votre application est égale ou supérieure à 29, vous devrez également prendre en charge d'autres modifications. Pour en savoir plus, veillez à lire Modifications du comportement des applications ciblant l'API 29.

Remarque  : En plus des modifications listées sur cette page, Android 10 introduit un grand nombre de modifications et de restrictions liées à la confidentialité, y compris les suivantes :

  • Accès en arrière-plan à la position de l'appareil
  • Démarrage des activités en arrière-plan
  • Informations sur l'affinité des contacts
  • Sélection aléatoire de l'adresse MAC
  • Métadonnées de la caméra
  • Modèle d'autorisations

Ces modifications concernent toutes les applications et améliorent la confidentialité des utilisateurs. Pour savoir comment prendre en charge ces modifications, consultez la page Modifications apportées à la confidentialité.

Restrictions des interfaces hors SDK

Pour garantir la stabilité et la compatibilité des applications, la plate-forme a commencé à limiter les interfaces non SDK que votre application peut utiliser dans Android 9 (niveau d'API 28). Android 10 inclut des listes à jour d'interfaces non SDK limitées grâce à la collaboration avec les développeurs Android et aux derniers tests internes. Notre objectif est de nous assurer que des alternatives publiques sont disponibles avant de limiter les interfaces non SDK.

Si vous ne ciblez pas Android 10 (niveau d'API 29), certaines de ces modifications ne vous affecteront peut-être pas immédiatement. Cependant, bien que vous puissiez actuellement utiliser certaines interfaces non SDK (en fonction du niveau d'API cible de votre application), l'utilisation d'un champ ou d'une méthode non SDK présente toujours un risque élevé d'endommager votre application.

Si vous n'êtes pas sûr que votre application utilise des interfaces non SDK, vous pouvez tester votre application pour le savoir. Si votre application repose sur des interfaces non SDK, vous devriez commencer à planifier une migration vers des alternatives SDK. Nous comprenons néanmoins que certaines applications ont des cas d'utilisation valides pour utiliser des interfaces non SDK. Si vous ne trouvez pas d'alternative à l'utilisation d'une interface non SDK pour une fonctionnalité de votre application, vous devriez demander une nouvelle API publique.

Pour en savoir plus, consultez Mises à jour des restrictions d'interface non SDK dans Android 10 et Restrictions concernant les interfaces non SDK.

Navigation par gestes

À partir d'Android 10, les utilisateurs peuvent activer la navigation par gestes sur l'ensemble de l'appareil. Si un utilisateur active la navigation par gestes, cela affecte toutes les applications sur l'appareil, que l'application cible ou non le niveau d'API 29. Par exemple, si l'utilisateur balaye l'écran depuis le bord, le système interprète ce geste comme une navigation "Retour", sauf si une application remplace spécifiquement ce geste pour certaines parties de l'écran.

Pour rendre votre application compatible avec la navigation par gestes, vous devez étendre le contenu de l'application de bord à bord et gérer correctement les gestes conflictuels. Pour en savoir plus, consultez la documentation sur la navigation par gestes.

NDK

Android 10 inclut les modifications NDK suivantes.

Les objets partagés ne peuvent pas contenir de relocalisations de texte

Android 6.0 (niveau d'API 23) interdit l'utilisation des réadressages de code dans les objets partagés. Le code doit être chargé tel quel et ne doit pas être modifié. Ce changement améliore les temps de chargement et la sécurité des applications.

SELinux applique cette restriction aux applications qui ciblent Android 10 ou version ultérieure. Si ces applications continuent d'utiliser des objets partagés contenant des relocalisations de texte, elles risquent fortement de ne plus fonctionner.

Modifications apportées aux bibliothèques Bionic et aux chemins de l'éditeur de liens dynamiques

Depuis Android 10, plusieurs chemins d'accès sont des liens symboliques au lieu de fichiers classiques. Les applications qui s'appuient sur des chemins d'accès en tant que fichiers réguliers peuvent ne plus fonctionner :

  • /system/lib/libc.so -> /apex/com.android.runtime/lib/bionic/libc.so
  • /system/lib/libm.so -> /apex/com.android.runtime/lib/bionic/libm.so
  • /system/lib/libdl.so -> /apex/com.android.runtime/lib/bionic/libdl.so
  • /system/bin/linker -> /apex/com.android.runtime/bin/linker

Ces modifications s'appliquent également aux variantes 64 bits du fichier, avec lib/ remplacé par lib64/.

Pour assurer la compatibilité, les liens symboliques sont fournis aux anciens chemins d'accès. Par exemple, /system/lib/libc.so est un lien symbolique vers /apex/com.android.runtime/lib/bionic/libc.so. Ainsi, dlopen(“/system/lib/libc.so”) continue de fonctionner, mais les applications constateront la différence lorsqu'elles essaieront d'examiner les bibliothèques chargées en lisant /proc/self/maps ou une commande similaire. Ce n'est pas habituel, mais nous avons constaté que certaines applications le font dans le cadre de leur processus anti-piratage. Si tel est le cas, les chemins /apex/… doivent être ajoutés en tant que chemins valides pour les fichiers Bionic.

Binaires/bibliothèques système mappés sur la mémoire en mode exécution uniquement

À partir d'Android 10, les segments exécutables des binaires et des bibliothèques système sont mappés en mémoire en mode exécution uniquement (non lisible) en tant que technique de renforcement contre les attaques par réutilisation de code. Si votre application effectue des opérations de lecture dans des segments de mémoire marqués comme exécutables uniquement (que ce soit en raison d'un bug, d'une faille ou d'une inspection intentionnelle de la mémoire), le système envoie un signal SIGSEGV à votre application.

Pour déterminer si ce comportement a provoqué un plantage, examinez le fichier tombstone associé dans /data/tombstones/. Un plantage lié à l'exécution uniquement contient le message d'abandon suivant :

Cause: execute-only (no-read) memory access error; likely due to data in .text.

Pour contourner ce problème et effectuer des opérations telles que l'inspection de la mémoire, il est possible de marquer les segments en mode exécution uniquement comme lecture+exécution en appelant mprotect(). Toutefois, nous vous recommandons vivement de le rétablir sur "Exécuter uniquement" par la suite, car ce paramètre d'autorisation d'accès offre une meilleure protection à votre application et à vos utilisateurs.

Sécurité

Android 10 inclut les modifications de sécurité suivantes.

TLS 1.3 activé par défaut

Sur Android 10 ou version ultérieure, TLS 1.3 est activé par défaut pour toutes les connexions TLS. Voici quelques détails importants sur notre mise en œuvre de TLS 1.3 :

  • Les suites de chiffrement TLS 1.3 ne peuvent pas être personnalisées. Les suites de chiffrement TLS 1.3 prises en charge sont toujours activées lorsque TLS 1.3 est activé. Toute tentative de désactivation en appelant setEnabledCipherSuites() est ignorée.
  • Lorsque TLS 1.3 est négocié, les objets HandshakeCompletedListener sont appelés avant que les sessions ne soient ajoutées au cache de session. (Dans TLS 1.2 et d'autres versions antérieures, ces objets sont appelés après l'ajout des sessions au cache de session.)
  • Dans certains cas où les instances SSLEngine génèrent une exception SSLHandshakeException sur des versions antérieures d'Android, elles génèrent une exception SSLProtocolException sur Android 10 ou version ultérieure.
  • Le mode 0-RTT n'est pas pris en charge.

Si vous le souhaitez, vous pouvez obtenir un SSLContext pour lequel TLS 1.3 est désactivé en appelant SSLContext.getInstance("TLSv1.2"). Vous pouvez également activer ou désactiver des versions de protocole pour chaque connexion en appelant setEnabledProtocols() sur un objet approprié.

Les certificats signés avec SHA-1 ne sont pas approuvés dans TLS

Dans Android 10, les certificats qui utilisent l'algorithme de hachage SHA-1 ne sont pas approuvés dans les connexions TLS. Les autorités de certification racine n'ont pas délivré de certificats de ce type depuis 2016 et ne sont plus approuvées dans Chrome ni dans les autres principaux navigateurs.

Toute tentative de connexion échoue si elle est destinée à un site qui présente un certificat SHA-1.

Modifications et améliorations du comportement de KeyChain

Certains navigateurs, tels que Google Chrome, permettent aux utilisateurs de choisir un certificat lorsqu'un serveur TLS envoie un message de demande de certificat dans le cadre d'un handshake TLS. À partir d'Android 10, les objets KeyChain respectent les émetteurs et les paramètres de spécification de clé lors de l'appel de KeyChain.choosePrivateKeyAlias() pour afficher une invite de sélection de certificat aux utilisateurs. Il convient de noter que cette invite ne contient pas d'options non conformes aux spécifications du serveur.

Si aucun certificat sélectionnable par l'utilisateur n'est disponible (par exemple, si aucun certificat ne correspond aux spécifications du serveur ou si un appareil ne dispose d'aucun certificat installé), l'invite de sélection de certificat ne s'affiche pas du tout.

De plus, il n'est pas nécessaire sous Android 10 ou version ultérieure de verrouiller l'écran de l'appareil pour importer des clés ou des certificats CA dans un objet KeyChain.

Autres modifications apportées au protocole TLS et à la cryptographie

Plusieurs modifications mineures ont été apportées aux bibliothèques TLS et de cryptographie dans Android 10 :

  • Les algorithmes de chiffrement AES/GCM/NoPadding et ChaCha20/Poly1305/NoPadding renvoient des tailles de mémoire tampon plus précises à partir de getOutputSize().
  • La suite de chiffrement TLS_FALLBACK_SCSV est omise pour les tentatives de connexion avec un protocole maximal TLS 1.2 ou supérieur. En raison des améliorations apportées aux implémentations des serveurs TLS, nous vous déconseillons de tenter un remplacement externe TLS. Nous vous recommandons plutôt de vous fier à la négociation de version TLS.
  • ChaCha20-Poly1305 est un alias de ChaCha20/Poly1305/NoPadding.
  • Les noms d'hôte se terminant par un point ne sont pas considérés comme des noms d'hôte SNI valides.
  • L'extension supported_signature_algorithms de CertificateRequest est respectée lors du choix d'une clé de signature pour les réponses de certificat.
  • Les clés de signature opaques, comme celles d'Android Keystore, peuvent être utilisées avec des signatures RSA-PSS dans TLS.

Émissions Wi-Fi Direct

Sur Android 10, les diffusions suivantes liées à Wi-Fi Direct ne sont pas persistantes :

Si votre application s'est appuyée sur la réception de ces diffusions lors de l'enregistrement parce qu'elles étaient persistantes, utilisez la méthode get() appropriée lors de l'initialisation pour obtenir les informations à la place.

Fonctionnalités Wi-Fi Aware

Android 10 facilite la création de sockets TCP/UDP à l'aide des chemins de données Wi-Fi Aware. Pour créer un socket TCP/UDP se connectant à un ServerSocket, l'appareil client doit connaître l'adresse IPv6 et le port du serveur. Auparavant, cela devait être communiqué hors bande, par exemple en utilisant la messagerie de couche 2 BT ou Wi-Fi Aware, ou découvert en bande à l'aide d'autres protocoles, tels que mDNS. Avec Android 10, les informations peuvent être communiquées lors de la configuration du réseau.

Le serveur peut effectuer l'une des opérations suivantes :

  • Initialisez un ServerSocket et définissez ou obtenez le port à utiliser.
  • Spécifiez les informations sur le port dans la requête de réseau Wi-Fi Aware.

L'exemple de code suivant montre comment spécifier les informations de port dans la requête réseau :

Kotlin

val ss = ServerSocket()
val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
  .setPskPassphrase("some-password")
  .setPort(ss.localPort)
  .build()

val myNetworkRequest = NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build()

Java

ServerSocket ss = new ServerSocket();
WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier
  .Builder(discoverySession, peerHandle)
  .setPskPassphrase(some-password)
  .setPort(ss.getLocalPort())
  .build();

NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build();

Le client effectue ensuite une requête réseau Wi-Fi Aware pour obtenir l'adresse IPv6 et le port fournis par le serveur :

Kotlin

val callback = object : ConnectivityManager.NetworkCallback() {
  override fun onAvailable(network: Network) {
    ...
  }
  
  override fun onLinkPropertiesChanged(network: Network,
      linkProperties: LinkProperties) {
    ...
  }

  override fun onCapabilitiesChanged(network: Network,
      networkCapabilities: NetworkCapabilities) {
    ...
    val ti = networkCapabilities.transportInfo
    if (ti is WifiAwareNetworkInfo) {
       val peerAddress = ti.peerIpv6Addr
       val peerPort = ti.port
    }
  }
  override fun onLost(network: Network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback)

Java

callback = new ConnectivityManager.NetworkCallback() {
  @Override
  public void onAvailable(Network network) {
    ...
  }
  @Override
  public void onLinkPropertiesChanged(Network network,
      LinkProperties linkProperties) {
    ...
  }
  @Override
  public void onCapabilitiesChanged(Network network,
      NetworkCapabilities networkCapabilities) {
    ...
    TransportInfo ti = networkCapabilities.getTransportInfo();
    if (ti instanceof WifiAwareNetworkInfo) {
       WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti;
       Inet6Address peerAddress = info.getPeerIpv6Addr();
       int peerPort = info.getPort();
    }
  }
  @Override
  public void onLost(Network network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback);

SYSTEM_ALERT_WINDOW sur les appareils Go

Les applications exécutées sur des appareils Android 10 (édition Go) ne peuvent pas recevoir l'autorisation SYSTEM_ALERT_WINDOW. En effet, le dessin de fenêtres superposées utilise une quantité excessive de mémoire, ce qui nuit particulièrement aux performances des appareils Android disposant de peu de mémoire.

Si une application exécutée sur un appareil Go Edition équipé d'Android 9 ou version antérieure reçoit l'autorisation SYSTEM_ALERT_WINDOW, elle la conserve même si l'appareil est mis à niveau vers Android 10. Toutefois, les applications qui ne disposent pas déjà de cette autorisation ne peuvent pas l'obtenir après la mise à niveau de l'appareil.

Si une application sur un appareil Go envoie un intent avec l'action ACTION_MANAGE_OVERLAY_PERMISSION, le système refuse automatiquement la requête et redirige l'utilisateur vers un écran Paramètres indiquant que l'autorisation n'est pas autorisée, car elle ralentit l'appareil. Si une application sur un appareil Go appelle Settings.canDrawOverlays(), la méthode renvoie toujours la valeur "false". Là encore, ces restrictions ne s'appliquent pas aux applications qui ont reçu l'autorisation SYSTEM_ALERT_WINDOW avant la mise à niveau de l'appareil vers Android 10.

Avertissements pour les applications ciblant d'anciennes versions d'Android

Les appareils équipés d'Android 10 ou version ultérieure avertissent les utilisateurs la première fois qu'ils exécutent une application ciblant Android 5.1 (niveau d'API 22) ou version antérieure. Si l'application exige que l'utilisateur accorde des autorisations, il a également la possibilité d'ajuster les autorisations de l'application avant qu'elle ne soit autorisée à s'exécuter pour la première fois.

En raison des exigences de Google Play concernant l'API cible, un utilisateur ne voit ces avertissements que lorsqu'il exécute une application qui n'a pas été mise à jour récemment. Pour les applications distribuées sur d'autres plates-formes, des exigences similaires concernant le niveau d'API cible sont entrées en vigueur en 2019. Pour en savoir plus sur ces exigences, consultez Élargissement des exigences liées au niveau d'API cible en 2019.

Suppression des suites de chiffrement SHA-2 CBC

Les suites de chiffrement SHA-2 CBC suivantes ont été supprimées de la plate-forme :

  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

Ces suites de chiffrement sont moins sécurisées que les suites de chiffrement similaires qui utilisent GCM. La plupart des serveurs sont compatibles avec les variantes GCM et CBC de ces suites de chiffrement, ou avec aucune d'elles.

Consommation par application

Android 10 introduit les changements de comportement suivants liés à l'utilisation des applications :

  • Améliorations apportées à l'utilisation de l'application UsageStats : Android 10 suit précisément l'utilisation des applications avec UsageStats lorsque les applications sont utilisées en mode Écran partagé ou Picture-in-picture. De plus, Android 10 suit correctement l'utilisation des applications instantanées.

  • Niveaux de gris par application : Android 10 permet de définir un mode d'affichage en niveaux de gris pour chaque application.

  • État de distraction par application – <0x0A

  • Suspension et lecture : dans Android 10, les applications suspendues ne peuvent pas lire de contenu audio.

Modifications des connexions HTTPS

Si une application exécutant Android 10 transmet null à setSSLSocketFactory(), une exception IllegalArgumentException se produit. Dans les versions précédentes, transmettre null à setSSLSocketFactory() avait le même effet que transmettre la fabrique par défaut actuelle.

La bibliothèque android.preference est obsolète

La bibliothèque android.preference est obsolète depuis Android 10. Les développeurs doivent plutôt utiliser la bibliothèque de préférences AndroidX, qui fait partie d'Android Jetpack. Pour obtenir des ressources supplémentaires qui vous aideront à migrer et à développer, consultez le Guide des paramètres mis à jour, ainsi que notre exemple d'application publique et la documentation de référence.

Modifications apportées à la bibliothèque d'utilitaires de fichiers ZIP

Android 10 introduit les modifications suivantes dans les classes du package java.util.zip, qui gère les fichiers ZIP. Ces modifications rendent le comportement de la bibliothèque plus cohérent entre Android et les autres plates-formes qui utilisent java.util.zip.

Inflateur

Dans les versions précédentes, certaines méthodes de la classe Inflater généraient une IllegalStateException si elles étaient appelées après un appel à end(). Dans Android 10, ces méthodes génèrent plutôt une NullPointerException.

ZipFile

Dans Android 10 et versions ultérieures, le constructeur pour ZipFile qui accepte des arguments de type File, int et Charset ne génère pas de ZipException si le fichier ZIP fourni ne contient aucun fichier.

ZipOutputStream

Dans Android 10 et versions ultérieures, la méthode finish() dans ZipOutputStream ne génère pas de ZipException si elle tente d'écrire un flux de sortie pour un fichier ZIP qui ne contient aucun fichier.

Changements de caméra

De nombreuses applications utilisant l'appareil photo supposent que si l'appareil est en configuration portrait, l'appareil physique est également en orientation portrait, comme décrit dans Orientation de l'appareil photo. Cette hypothèse était sûre par le passé, mais elle a changé avec l'expansion des facteurs de forme disponibles, tels que les appareils pliables. Cette hypothèse sur ces appareils peut entraîner une rotation ou une mise à l'échelle incorrecte (ou les deux) de l'affichage du viseur de l'appareil photo.

Les applications qui ciblent le niveau d'API 24 ou supérieur doivent définir explicitement android:resizeableActivity et fournir les fonctionnalités nécessaires pour gérer le fonctionnement en mode multifenêtre.

Suivi de l'utilisation de la batterie

À partir d'Android 10, SystemHealthManager réinitialise ses statistiques d'utilisation de la batterie chaque fois que l'appareil est débranché après un événement de recharge majeur. En général, un événement de recharge majeur se produit lorsque l'appareil est complètement rechargé ou lorsque sa batterie est passée d'un niveau presque vide à un niveau presque plein.

Avant Android 10, les statistiques d'utilisation de la batterie étaient réinitialisées chaque fois que l'appareil était débranché, même si le niveau de la batterie n'avait que très peu changé.

Arrêt d'Android Beam

Dans Android 10, nous abandonnons officiellement Android Beam, une ancienne fonctionnalité permettant d'initier le partage de données entre appareils via la technologie NFC (Near Field Communication). Nous abandonnons également plusieurs API NFC associées. Android Beam reste disponible en option pour les partenaires fabricants d'appareils qui souhaitent l'utiliser, mais il n'est plus en développement actif. Android continuera de prendre en charge d'autres fonctionnalités et API NFC. Les cas d'utilisation tels que la lecture de tags et les paiements continueront de fonctionner comme prévu.

Modification du comportement de java.math.BigDecimal.stripTrailingZeros()

BigDecimal.stripTrailingZeros() ne conserve plus les zéros de fin comme cas particulier si la valeur d'entrée est zéro.

Modifications du comportement de java.util.regex.Matcher et Pattern

Le résultat de split() a été modifié pour ne plus commencer par un String vide ("") lorsqu'il y a une correspondance de largeur nulle au début de l'entrée. Cela affecte également String.split(). Par exemple, "x".split("") renvoie désormais {"x"}, alors qu'il renvoyait {"", "x"} sur les anciennes versions d'Android. "aardvark".split("(?=a)" renvoie désormais {"a", "ardv", "ark"} au lieu de {"", "a", "ardv", "ark"}.

Le comportement des exceptions pour les arguments non valides a également été amélioré :

  • appendReplacement(StringBuffer, String) génère désormais une IllegalArgumentException au lieu de IndexOutOfBoundsException si la String de remplacement se termine par une barre oblique inverse seule, ce qui est illégal. La même exception est désormais générée si le remplacement String se termine par un $. Auparavant, aucune exception n'était générée dans ce scénario.
  • replaceFirst(null) n'appelle plus reset() sur Matcher s'il génère une NullPointerException. NullPointerException est désormais également généré en l'absence de correspondance. Auparavant, elle n'était déclenchée qu'en cas de correspondance.
  • start(int group), end(int group) et group(int group) génèrent désormais un IndexOutOfBoundsException plus général si l'index de groupe est hors limites. Auparavant, ces méthodes généraient ArrayIndexOutOfBoundsException.

L'angle par défaut de GradientDrawable est désormais TOP_BOTTOM

Dans Android 10, si vous définissez un GradientDrawable dans XML et que vous ne fournissez pas de mesure d'angle, l'orientation du dégradé est définie par défaut sur TOP_BOTTOM. Il s'agit d'un changement par rapport aux versions précédentes d'Android, où la valeur par défaut était LEFT_RIGHT.

Pour contourner ce problème, si vous passez à la dernière version d'AAPT2, l'outil définit une mesure d'angle de 0 pour les anciennes applications si aucune mesure d'angle n'est spécifiée.

Journalisation des objets sérialisés à l'aide du SUID par défaut

À partir d'Android 7.0 (niveau d'API 24), la plate-forme a corrigé le serialVersionUID par défaut pour les objets sérialisables. Ce correctif n'a pas affecté les applications ciblant le niveau d'API 23 ou inférieur.

À partir d'Android 10, si une application cible le niveau d'API 23 ou inférieur et s'appuie sur l'ancienne valeur par défaut incorrecte serialVersionUID, le système enregistre un avertissement et suggère une correction du code.

Plus précisément, le système consigne un avertissement si toutes les conditions suivantes sont remplies :

  • L'application cible le niveau d'API 23 ou inférieur.
  • Une classe est sérialisée.
  • La classe sérialisée utilise le serialVersionUID par défaut au lieu de définir explicitement un serialVersionUID.
  • La valeur par défaut serialVersionUID est différente de celle de serialVersionUID si l'application ciblait le niveau d'API 24 ou supérieur.

Cet avertissement est consigné une fois pour chaque classe concernée. Le message d'avertissement inclut une solution suggérée, qui consiste à définir explicitement serialVersionUID sur la valeur par défaut qui serait calculée si l'application ciblait le niveau d'API 24 ou supérieur. En utilisant ce correctif, vous pouvez vous assurer que si un objet de cette classe est sérialisé sur une application qui cible le niveau d'API 23 ou inférieur, l'objet sera correctement lu par les applications qui ciblent le niveau 24 ou supérieur, et inversement.

Modifications de java.io.FileChannel.map()

À partir d'Android 10, FileChannel.map() n'est pas compatible avec les fichiers non standards, comme /dev/zero, dont la taille ne peut pas être modifiée à l'aide de truncate(). Les versions précédentes d'Android avalaient l'errno renvoyé par truncate(), mais Android 10 génère une IOException. Si vous avez besoin de l'ancien comportement, vous devez utiliser du code natif.