Pour mieux contrôler les fichiers et limiter l'encombrement, Android 10 inclut un nouveau modèle de stockage pour les applications, appelé espace de stockage cloisonné. L'espace de stockage cloisonné modifie la façon dont les applications stockent les fichiers et y accèdent sur la mémoire de stockage externe d'un appareil. Pour que votre application soit compatible avec cette fonctionnalité, suivez les bonnes pratiques décrites dans ce guide pour les cas d'utilisation les plus courants. Ces derniers sont classés dans deux catégories : gestion des fichiers multimédias et gestion des fichiers non multimédias.
Dans de nombreux cas, votre application crée des fichiers auxquels d'autres applications n'ont pas besoin d'accéder ou ne doivent pas accéder. Le système fournit des emplacements de stockage spécifiques à l'application pour gérer ces fichiers.
Pour découvrir comment stocker des fichiers et y accéder sur Android, consultez les guides de formation relatifs au stockage.
Gérer les fichiers multimédias
Cette section décrit certains des cas d'utilisation courants liées à la gestion des fichiers multimédias (fichiers vidéo, image et audio), et explique l'approche globale que votre application peut utiliser. Le tableau suivant récapitule chacun de ces cas d'utilisation et renvoie vers chacune des sections contenant des informations supplémentaires.
Cas d'utilisation | Résumé |
---|---|
Afficher tous les fichiers image ou vidéo | Utilisez la même approche pour toutes les versions d'Android. |
Afficher les images ou les vidéos d'un dossier donné | Utilisez la même approche pour toutes les versions d'Android. |
Accéder aux informations de géolocalisation des photos | Optez pour une seule approche si votre application utilise un espace de stockage cloisonné. Optez pour une approche distincte si l'espace de stockage cloisonné a été désactivé pour votre application. |
Définir l'emplacement de stockage pour les nouveaux téléchargements | Optez pour une seule approche si votre application utilise un espace de stockage cloisonné. Optez pour une approche distincte si l'espace de stockage cloisonné a été désactivé pour votre application. |
Exporter les fichiers multimédias des utilisateurs vers un appareil | Utilisez la même approche pour toutes les versions d'Android. |
Modifier ou supprimer plusieurs fichiers multimédias en une seule opération | Choisissez une seule approche pour Android 11. Pour Android 10, désactivez l'espace de stockage cloisonné et choisissez l'approche pour Android 9 ou version antérieure. |
Importer une seule image qui existe déjà | Utilisez la même approche pour toutes les versions d'Android. |
Capturer une seule image | Utilisez la même approche pour toutes les versions d'Android. |
Partager des fichiers multimédias avec d'autres applications | Utilisez la même approche pour toutes les versions d'Android. |
Partager des fichiers multimédias avec une application spécifique | Utilisez la même approche pour toutes les versions d'Android. |
Accéder à des fichiers à partir du code ou de bibliothèques utilisant des chemins d'accès directs | Choisissez une seule approche pour Android 11. Pour Android 10, désactivez l'espace de stockage cloisonné et choisissez l'approche pour Android 9 ou version antérieure. |
Afficher des fichiers image ou vidéo issus de plusieurs dossiers
Interroger une collection multimédia à l'aide de l'API query()
Pour filtrer ou trier les fichiers multimédias, ajustez les paramètres projection
, selection
, selectionArgs
et sortOrder
.
Afficher les images ou les vidéos d'un dossier donné
Adoptez cette approche :
- Conformément aux bonnes pratiques décrites dans cette section, demandez l'autorisation
READ_EXTERNAL_STORAGE
. - Récupérez les fichiers multimédias en fonction de la valeur de
MediaColumns.DATA
, qui contient le chemin absolu du système de fichiers vers l'élément multimédia sur le disque.
Remarque : Lorsque vous accédez à un fichier multimédia existant, vous pouvez utiliser la valeur de la colonne DATA
dans votre logique. Cela est dû au fait que cette valeur contient un chemin d'accès valide.
Toutefois, ne partez pas du principe que le fichier est toujours disponible. Préparez-vous à gérer les éventuelles erreurs d'E/S basées sur les fichiers.
Pour créer ou mettre à jour un fichier multimédia, n'utilisez pas la colonne DATA
. Préférez les colonnes DISPLAY_NAME
et RELATIVE_PATH
.
Accéder aux informations de géolocalisation des photos
Si votre application utilise un espace de stockage cloisonné, suivez la procédure décrite dans cette section du guide sur le stockage de fichiers multimédias.
Définir l'emplacement de stockage pour les nouveaux téléchargements
Si votre application utilise un espace de stockage cloisonné, tenez compte de l'emplacement où vous choisissez de stocker les fichiers multimédias que vous téléchargez.
Si d'autres applications ont besoin d'accéder à ces fichiers, pensez à utiliser des collections multimédias bien définies pour les téléchargements ou les collections de documents.
Sur Android 11 et versions ultérieures, les autres applications ne peuvent pas accéder aux fichiers situés dans votre répertoire externe spécifique à l'application, même si vous utilisez DownloadManager
pour récupérer ces fichiers.
Exporter les fichiers multimédias des utilisateurs vers un appareil
Définissez un emplacement par défaut approprié pour stocker les fichiers multimédias des utilisateurs :
- Les utilisateurs peuvent choisir de rendre leurs fichiers multimédias lisibles par d'autres applications à l'aide d'un espace de stockage spécifique à ces applications ou d'un espace de stockage partagé.
- Donnez aux utilisateurs la possibilité d'exporter des fichiers depuis des répertoires spécifiques à l'application vers un emplacement plus accessible. Utilisez les collections d'images, de vidéos et de fichiers audio de MediaStore pour exporter des fichiers multimédias vers la galerie de l'appareil.
Modifier ou supprimer plusieurs fichiers multimédias en une seule opération
Incorporez une logique basée sur les versions d'Android sur lesquelles votre application s'exécute.
Exécution sur Android 11
Adoptez cette approche :
- Créez un intent en attente pour la requête d'écriture ou de suppression de votre application à l'aide de
MediaStore.createWriteRequest()
ou deMediaStore.createTrashRequest()
, puis demandez à l'utilisateur d'autoriser la modification d'un ensemble de fichiers en appelant cet intent. Évaluez la réponse de l'utilisateur :
- Si l'autorisation est accordée, procédez à la modification ou à la suppression.
- Si l'autorisation n'a pas été accordée, expliquez à l'utilisateur pourquoi la fonctionnalité de votre application nécessite cette autorisation.
Découvrez comment gérer des groupes de fichiers multimédias à l'aide de ces méthodes, disponibles sur Android 11 ou version ultérieure.
Exécution sur Android 10
Si votre application cible Android 10 (niveau d'API 29), désactivez l'espace de stockage cloisonné et continuez à utiliser l'approche spécifique à Android 9 ou version antérieure pour effectuer cette opération.
Exécution sur Android 9 ou version antérieure
Adoptez cette approche :
- Conformément aux bonnes pratiques décrites dans cette section, demandez l'autorisation
WRITE_EXTERNAL_STORAGE
. - Utilisez l'API
MediaStore
pour modifier ou supprimer les fichiers multimédias.
Importer une seule image qui existe déjà
Lorsque vous souhaitez importer une seule image qui existe déjà (par exemple, pour la photo d'un profil utilisateur), votre application peut utiliser sa propre UI pour l'opération ou peut utiliser le sélecteur système.
Utiliser votre propre interface utilisateur
Adoptez cette approche :
- Conformément aux bonnes pratiques décrites dans cette section, demandez l'autorisation
READ_EXTERNAL_STORAGE
. - Utilisez l'API
query()
pour interroger une collection multimédia. - Affichez les résultats dans l'interface utilisateur personnalisée de votre application.
Utiliser le sélecteur système
Utilisez l'intent ACTION_GET_CONTENT
, qui demande à l'utilisateur de choisir une image à importer.
Si vous souhaitez filtrer les types d'images que le sélecteur de système présente à l'utilisateur, vous avez le choix entre setType()
ou EXTRA_MIME_TYPES
.
Capturer une seule image
Lorsque vous souhaitez capturer une seule image à utiliser dans votre application (par exemple, pour l'afficher comme photo de profil d'un utilisateur), utilisez l'intent ACTION_IMAGE_CAPTURE
pour demander à l'utilisateur l'autorisation de prendre une photo avec l'appareil photo de son appareil. Le système stockera la photo capturée dans la table MediaStore.Images
.
Partager des fichiers multimédias avec d'autres applications
Utilisez la méthode insert()
pour ajouter des enregistrements directement dans MediaStore. Pour en savoir plus, consultez la section Ajouter un élément du guide sur le stockage multimédia.
Partager des fichiers multimédias avec une application spécifique
Utilisez le composant FileProvider
d'Android, comme décrit dans le guide Configurer le partage de fichiers.
Accéder à des fichiers à partir du code ou de bibliothèques utilisant des chemins d'accès directs
Incorporez une logique basée sur les versions d'Android sur lesquelles votre application s'exécute.
Exécution sur Android 11
Adoptez cette approche :
- Conformément aux bonnes pratiques décrites dans cette section, demandez l'autorisation
READ_EXTERNAL_STORAGE
. - Accédez aux fichiers à l'aide de leur chemin direct.
Pour en savoir plus, consultez la section expliquant comment ouvrir des fichiers multimédias à l'aide des chemins d'accès directs aux fichiers.
Exécution sur Android 10
Si votre application cible Android 10 (niveau d'API 29), désactivez l'espace de stockage cloisonné et continuez à utiliser l'approche spécifique à Android 9 ou version antérieure pour effectuer cette opération.
Exécution sur Android 9 ou version antérieure
Adoptez cette approche :
- Conformément aux bonnes pratiques décrites dans cette section, demandez l'autorisation
WRITE_EXTERNAL_STORAGE
. - Accédez aux fichiers à l'aide de leur chemin direct.
Gérer les fichiers non multimédias
Cette section décrit certains des cas d'utilisation courants liés à la gestion des fichiers non multimédias, et explique l'approche globale que votre application peut utiliser. Le tableau suivant récapitule chacun de ces cas d'utilisation et renvoie vers chacune des sections contenant des informations supplémentaires.
Cas d'utilisation | Résumé |
---|---|
Ouvrir un fichier de document | Utilisez la même approche pour toutes les versions d'Android. |
Écrire dans des fichiers stockés sur des volumes de stockage secondaires | Choisissez une seule approche pour Android 11. Utilisez une approche distincte pour les versions antérieures d'Android. |
Migrer des fichiers existants depuis un ancien emplacement de stockage | Si possible, migrez vos fichiers vers un espace de stockage cloisonné. Désactivez le stockage cloisonné pour Android 10 si nécessaire. |
Partager du contenu avec d'autres applications | Utilisez la même approche pour toutes les versions d'Android. |
Mettre en cache les fichiers non multimédias | Utilisez la même approche pour toutes les versions d'Android. |
Exporter des fichiers non multimédias vers un appareil | Optez pour une seule approche si votre application utilise un espace de stockage cloisonné. Optez pour une approche distincte si l'espace de stockage cloisonné a été désactivé pour votre application. |
Ouvrir un fichier de document
Utilisez l'intent ACTION_OPEN_DOCUMENT
pour demander à l'utilisateur de sélectionner un fichier à ouvrir à l'aide du sélecteur système. Si vous souhaitez filtrer les types de fichiers que le sélecteur système présente à l'utilisateur, vous avez le choix entre setType()
ou .EXTRA_MIME_TYPES
Par exemple, vous pouvez rechercher tous les fichiers PDF, ODT et TXT à l'aide du code suivant :
Kotlin
startActivityForResult( Intent(Intent.ACTION_OPEN_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) type = "*/*" putExtra(Intent.EXTRA_MIME_TYPES, arrayOf( "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt )) }, REQUEST_CODE )
Java
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "application/pdf", // .pdf "application/vnd.oasis.opendocument.text", // .odt "text/plain" // .txt }); startActivityForResult(intent, REQUEST_CODE);
Écrire dans des fichiers stockés sur des volumes de stockage secondaires
Les volumes de stockage secondaires incluent les cartes SD. Pour accéder aux informations concernant un volume de stockage donné, utilisez la classe StorageVolume
.
Incorporez une logique basée sur la version d'Android sur laquelle votre application s'exécute.
Exécution sur Android 11
Adoptez cette approche :
- Utilisez le modèle d'espace de stockage cloisonné.
- Ciblez Android 10 (niveau d'API 29) ou version antérieure.
- Déclarez l'autorisation
WRITE_EXTERNAL_STORAGE
. - Définissez l'un des types d'accès suivants :
- Accès aux fichiers via l'API
MediaStore
- Accès via le chemin d'accès direct aux fichiers à l'aide d'API telles que
File
oufopen()
- Accès aux fichiers via l'API
Exécution sur des versions plus anciennes
Utilisez le framework d'accès au stockage, qui permet aux utilisateurs de sélectionner l'emplacement d'un volume de stockage secondaire dans lequel votre application peut enregistrer le fichier.
Migrer des fichiers existants depuis un ancien emplacement de stockage
Un répertoire est considéré comme un ancien emplacement de stockage s'il ne s'agit pas d'un répertoire spécifique à l'application ni d'un répertoire partagé public. Si votre application crée ou consomme des fichiers dans un ancien emplacement de stockage, nous vous recommandons de migrer ses fichiers vers des emplacements accessibles avec un espace de stockage cloisonné et d'apporter les modifications nécessaires à l'application pour qu'elle fonctionne avec les fichiers inclus dans cet espace de stockage.
Conserver l'accès à l'ancien emplacement de stockage pour la migration des données
Pour pouvoir migrer les fichiers de l'application vers les emplacements accessibles via un espace de stockage cloisonné, votre application doit conserver l'accès à l'ancien emplacement de stockage. L'approche à utiliser dépend du niveau d'API cible de votre application.
Si votre application cible Android 11
Définissez l'indicateur
preserveLegacyExternalStorage
surtrue
pour conserver l'ancien modèle de stockage afin que votre application puisse migrer les données d'un utilisateur lorsqu'il passe à la nouvelle version de votre application qui cible Android 11.Continuez à désactiver l'espace de stockage cloisonné pour que votre application puisse continuer à accéder à vos fichiers dans l'ancien emplacement de stockage sur les appareils Android 10.
Si votre application cible Android 10
Désactivez l'espace de stockage cloisonné pour que le comportement de votre application sur toutes les versions d'Android soit harmonieux.
Migrer les données de l'application
Lorsque votre application est prête pour la migration, adoptez l'approche suivante :
- Ciblez Android 10 ou version antérieure.
- Désactivez l'espace de stockage cloisonné afin que votre application ait accès aux fichiers que vous devez migrer.
-
Déployez le code qui utilise l'API
File
pour déplacer les fichiers de leur emplacement actuel sous/sdcard/
vers un emplacement accessible via un espace de stockage cloisonné :- Déplacez tous les fichiers d'application privés vers le répertoire renvoyé par la méthode
getExternalFilesDir()
. - Déplacez tous les fichiers non multimédias partagés vers un sous-répertoire dédié du répertoire
Downloads/
.
- Déplacez tous les fichiers d'application privés vers le répertoire renvoyé par la méthode
- Supprimez les anciens répertoires de stockage de votre application du répertoire
/sdcard/
.
Une fois que les utilisateurs auront installé la nouvelle version de votre application, ils effectueront le processus de migration des données sur leurs appareils. Vous pouvez créer un événement d'analyse afin de surveiller ce processus pour votre base d'utilisateurs.
Une fois que les utilisateurs ont migré leurs données, publiez une autre mise à jour dans votre application, qui cible Android 11.
Partager du contenu avec d'autres applications
Pour partager les fichiers de votre application avec une seule autre application, utilisez un fichier FileProvider
. Pour les applications qui doivent partager des fichiers entre elles, nous vous recommandons de recourir à un fournisseur de contenu pour chaque application, puis de synchroniser les données à mesure que les applications sont ajoutées à la collection.
Mettre en cache les fichiers non multimédias
L'approche à adopter dépend du type de fichier à mettre en cache.
- Fichiers de petite taille ou fichiers contenant des informations sensibles : utilisez
Context#getCacheDir()
. - Fichiers volumineux ou fichiers ne contenant pas d'informations sensibles : utilisez
Context#getExternalCacheDir()
.
Exporter des fichiers non multimédias vers un appareil
Définissez un emplacement par défaut approprié pour stocker les fichiers non multimédias. Donnez aux utilisateurs la possibilité d'exporter des fichiers depuis des répertoires spécifiques à l'application vers un emplacement plus accessible. Utilisez les téléchargements ou collections de documents de MediaStore pour exporter les fichiers non multimédias vers l'appareil.
Gérer les fichiers spécifiques à une application
Si votre application crée des fichiers auxquels d'autres applications n'ont pas besoin d'accéder ou ne doivent pas accéder, vous pouvez les stocker dans des emplacements de stockage spécifiques à l'application.
Répertoires de stockage interne
Le système empêche d'autres applications d'accéder à ces emplacements. Ils sont chiffrés sur Android 10 (niveau d'API 29) ou version ultérieure. Ces emplacements sont un bon endroit pour stocker des données sensibles auxquelles seule votre application peut accéder.
Répertoires de stockage externe
Si la mémoire de stockage interne est insuffisante pour stocker les fichiers spécifiques à l'application, envisagez d'utiliser un espace de stockage externe. Bien qu'une autre application puisse accéder à ces répertoires si elle dispose des autorisations appropriées, les fichiers stockés dans ces répertoires sont destinés à être utilisés uniquement par votre application.
Sous Android 4.4 (niveau d'API 19) ou version ultérieure, votre application n'a pas besoin de demander des autorisations liées au stockage pour accéder aux répertoires spécifiques à l'application dans un espace de stockage externe.
Lorsque l'utilisateur désinstalle votre application, les fichiers enregistrés dans l'espace de stockage spécifique à l'application sont supprimés. Par conséquent, vous ne devez pas utiliser cet espace de stockage pour enregistrer ce que l'utilisateur souhaite conserver indépendamment de votre application.
Désactiver temporairement l'espace de stockage cloisonné
Avant que votre application soit entièrement compatible avec l'espace de stockage cloisonné, vous pouvez le désactiver temporairement, à la fois dans vos tests et dans votre application de production.
Désactiver l'espace de stockage cloisonné dans vos tests
Sur Android 10 (niveau d'API 29) ou version ultérieure, les tests de votre application s'exécutent par défaut dans un bac à sable de stockage. Ce bac à sable empêche votre application d'accéder aux fichiers situés en dehors du répertoire spécifique à l'application et des répertoires partagés publiquement.
Si un test génère des fichiers pour l'hôte, tels que des captures d'écran, des données de débogage, des données de couverture ou des métriques de performances, vous pouvez écrire ces fichiers dans des répertoires globaux. Pour ce faire, ajoutez l'indicateur suivant à l'élément approprié qui appelle am instrument
:
-e no-isolated-storage 1
Cet indicateur s'applique au comportement entier du scénario de test instrumenté et à tout le code de test appelé. Par conséquent, lorsque vous l'utilisez, vous ne pouvez pas confirmer la compatibilité de votre application avec l'espace de stockage cloisonné. Pour les résultats de test, il est préférable d'écrire dans un espace de stockage spécifique à l'application que l'interface système peut comprendre. Vous pouvez ensuite extraire ce répertoire spécifique à l'application. Pour déterminer le répertoire à partir duquel effectuer l'extraction, appelez getExternalMediaDirs()
.
Désactiver l'espace de stockage cloisonné dans l'application de production
Si votre application cible Android 10 (niveau d'API 29) ou version antérieure, vous pouvez désactiver temporairement l'espace de stockage cloisonné dans votre application de production. Toutefois, si vous ciblez Android 10, vous devez définir la valeur de requestLegacyExternalStorage
sur true
dans le fichier manifeste de votre application :
<manifest ... > <!-- This attribute is "false" by default on apps targeting Android 10. --> <application android:requestLegacyExternalStorage="true" ... > ... </application> </manifest>
Pour tester le comportement d'une application ciblant Android 10 ou version antérieure lors de l'utilisation de l'espace de stockage cloisonné, définissez la valeur de requestLegacyExternalStorage
sur false
afin d'activer ce comportement. Si vous effectuez le test sur un appareil exécutant Android 11, vous pouvez également utiliser des indicateurs de compatibilité pour tester le comportement de votre application avec ou sans espace de stockage cloisonné.
Ressources supplémentaires
Pour en savoir plus sur l'espace de stockage Android, consultez les ressources suivantes :