Stockage et accès aux fichiers avec Xamarin.Android

Une exigence courante pour les applications Android est de manipuler des fichiers , en enregistrant des images, en téléchargeant des documents ou en exportant des données à partager avec d’autres programmes. Android (qui est basé sur Linux) prend en charge cela en fournissant de l’espace pour le stockage de fichiers. Android regroupe le système de fichiers en deux types de stockage différents :

  • Stockage interne : il s’agit d’une partie du système de fichiers accessible uniquement par l’application ou le système d’exploitation.
  • Stockage externe : il s’agit d’une partition pour le stockage de fichiers accessible par toutes les applications, l’utilisateur et éventuellement d’autres appareils. Sur certains appareils, le stockage externe peut être amovible (par exemple, un carte SD).

Ces regroupements sont uniquement conceptuels et ne font pas nécessairement référence à une seule partition ou répertoire sur l’appareil. Un appareil Android fournit toujours une partition pour le stockage interne et le stockage externe. Il est possible que certains appareils aient plusieurs partitions considérées comme du stockage externe. Quelle que soit la partition, les API de lecture, d’écriture ou de création de fichiers sont identiques. Il existe deux ensembles d’API qu’une application Xamarin.Android peut utiliser pour l’accès aux fichiers :

  1. API .NET (fournies par Mono et encapsulées par Xamarin.Android) : elles incluent les assistances de système de fichiers fournies par Xamarin.Essentials. Les API .NET offrent la meilleure compatibilité multiplateforme et, par conséquent, ce guide se concentrera sur ces API.
  2. API d’accès aux fichiers Java natives (fournies par Java et encapsulées par Xamarin.Android) : Java fournit ses propres API pour la lecture et l’écriture de fichiers. Il s’agit d’une alternative tout à fait acceptable aux API .NET, mais elles sont spécifiques à Android et ne conviennent pas aux applications destinées à être multiplateformes.

La lecture et l’écriture dans des fichiers sont presque identiques dans Xamarin.Android comme dans n’importe quelle autre application .NET. L’application Xamarin.Android détermine le chemin d’accès au fichier qui sera manipulé, puis utilise les idiomes .NET standard pour l’accès aux fichiers. Étant donné que les chemins d’accès réels au stockage interne et externe peuvent varier d’un appareil à l’autre ou d’une version Android à une version Android, il n’est pas recommandé de coder en dur le chemin d’accès aux fichiers. Utilisez plutôt les API Xamarin.Android pour déterminer le chemin d’accès aux fichiers. De cette façon, les API .NET pour la lecture et l’écriture de fichiers exposent les API Android natives qui vous aideront à déterminer le chemin d’accès aux fichiers sur le stockage interne et externe.

Avant de discuter des API impliquées dans l’accès aux fichiers, il est important de comprendre certains détails concernant le stockage interne et externe. Cela sera abordé dans la section suivante.

Stockage interne ou externe

D’un point de vue conceptuel, le stockage interne et le stockage externe sont très similaires : il s’agit des deux emplacements où une application Xamarin.Android peut enregistrer des fichiers. Cette similarité peut prêter à confusion pour les développeurs qui ne sont pas familiarisés avec Android, car il n’est pas clair quand une application doit utiliser le stockage interne et le stockage externe.

Le stockage interne fait référence à la mémoire non volatile qu’Android alloue au système d’exploitation, aux APIK et pour les applications individuelles. Cet espace n’est accessible que par le système d’exploitation ou les applications. Android allouera un répertoire dans la partition de stockage interne pour chaque application. Lorsque l’application est désinstallée, tous les fichiers qui sont conservés dans le stockage interne dans ce répertoire sont également supprimés. Le stockage interne convient mieux aux fichiers qui sont uniquement accessibles à l’application et qui ne seront pas partagés avec d’autres applications ou auront très peu de valeur une fois l’application désinstallée. Sur Android 6.0 ou version ultérieure, les fichiers sur le stockage interne peuvent être automatiquement sauvegardés par Google à l’aide de la fonctionnalité de sauvegarde automatique dans Android 6.0. Le stockage interne présente les inconvénients suivants :

  • Les fichiers ne peuvent pas être partagés.
  • Les fichiers sont supprimés lorsque l’application est désinstallée.
  • L’espace disponible sur le stockage interne peut être limité.

Le stockage externe fait référence au stockage de fichiers qui n’est pas un stockage interne et qui n’est pas exclusivement accessible à une application. L’objectif principal du stockage externe est de fournir un emplacement pour placer des fichiers qui sont destinés à être partagés entre les applications ou qui sont trop volumineux pour s’adapter au stockage interne. L’avantage du stockage externe est qu’il a généralement beaucoup plus d’espace pour les fichiers que le stockage interne. Toutefois, la présence du stockage externe sur un appareil n’est pas toujours garantie et peut nécessiter une autorisation spéciale de la part de l’utilisateur pour y accéder.

Notes

Pour les appareils qui prennent en charge plusieurs utilisateurs, Android fournit à chaque utilisateur son propre répertoire sur le stockage interne et externe. Ce répertoire est inaccessible aux autres utilisateurs sur l’appareil. Cette séparation est invisible pour les applications tant qu’elles ne codent pas en dur les chemins d’accès aux fichiers sur un stockage interne ou externe.

En règle générale, les applications Xamarin.Android doivent préférer enregistrer leurs fichiers sur le stockage interne lorsque cela est raisonnable et s’appuyer sur un stockage externe lorsque les fichiers doivent être partagés avec d’autres applications, sont très volumineux ou doivent être conservés même si l’application est désinstallée. Par exemple, un fichier de configuration convient mieux pour un stockage interne, car il n’a aucune importance, sauf pour l’application qui le crée. En revanche, les photos sont un bon candidat pour le stockage externe. Ils peuvent être très volumineux et, dans de nombreux cas, l’utilisateur peut vouloir les partager ou y accéder même si l’application est désinstallée.

Ce guide se concentre sur le stockage interne. Consultez le guide Stockage externe pour plus d’informations sur l’utilisation du stockage externe dans une application Xamarin.Android.

Utilisation du stockage interne

Le répertoire de stockage interne d’une application est déterminé par le système d’exploitation et est exposé aux applications Android par la Android.Content.Context.FilesDir propriété . Cela retourne un Java.IO.File objet représentant le répertoire qu’Android a dédié exclusivement à l’application. Par exemple, une application avec le nom de package com.companyname du répertoire de stockage interne peut être :

/data/user/0/com.companyname/files

Ce document fait référence au répertoire de stockage interne en tant que INTERNAL_STORAGE.

Important

Le chemin exact du répertoire de stockage interne peut varier d’un appareil à l’autre et d’une version d’Android à l’autre. Pour cette raison, les applications ne doivent pas coder en dur le chemin d’accès au répertoire de stockage des fichiers internes et utiliser plutôt les API Xamarin.Android, telles que System.Environment.GetFolderPath().

Pour optimiser le partage de code, les applications Xamarin.Android (ou les applications Xamarin.Forms ciblant Xamarin.Android) doivent utiliser la System.Environment.GetFolderPath() méthode . Dans Xamarin.Android, cette méthode retourne une chaîne pour un répertoire qui se trouve au même emplacement que Android.Content.Context.FilesDir. Cette méthode prend une énumération, System.Environment.SpecialFolder, qui est utilisée pour identifier un ensemble de constantes énumérées qui représentent les chemins d’accès des dossiers spéciaux utilisés par le système d’exploitation. Toutes les System.Environment.SpecialFolder valeurs ne sont pas mappées à un répertoire valide sur Xamarin.Android. Le tableau suivant décrit le chemin d’accès attendu pour une valeur donnée de System.Environment.SpecialFolder:

System.Environment.SpecialFolder Path
ApplicationData INTERNAL_STORAGE/.config
Desktop INTERNAL_STORAGE/Desktop
LocalApplicationData INTERNAL_STORAGE/.local/share
MyDocuments INTERNAL_STORAGE
MyMusic INTERNAL_STORAGE/Musique
MyPictures INTERNAL_STORAGE/Images
MyVideos INTERNAL_STORAGE/Vidéos
Personal INTERNAL_STORAGE
Fonts INTERNAL_STORAGE/.fonts
Templates INTERNAL_STORAGE/Modèles
CommonApplicationData /usr/share
CommonApplicationData /usr/share

Lecture ou écriture dans des fichiers sur le stockage interne

Toutes les API C# pour l’écriture dans un fichier sont suffisantes ; tout ce qui est nécessaire est d’obtenir le chemin du fichier qui se trouve dans le répertoire alloué à l’application. Il est vivement recommandé d’utiliser les versions asynchrones des API .NET pour réduire les problèmes qui peuvent être associés à l’accès aux fichiers bloquant le thread main.

Cet extrait de code est un exemple d’écriture d’un entier dans un fichier texte UTF-8 dans le répertoire de stockage interne d’une application :

public async Task SaveCountAsync(int count)
{
    var backingFile = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "count.txt");
    using (var writer = File.CreateText(backingFile))
    {
        await writer.WriteLineAsync(count.ToString());
    }
}

L’extrait de code suivant fournit un moyen de lire une valeur entière stockée dans un fichier texte :

public async Task<int> ReadCountAsync()
{
    var backingFile = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "count.txt");

    if (backingFile == null || !File.Exists(backingFile))
    {
        return 0;
    }

    var count = 0;
    using (var reader = new StreamReader(backingFile, true))
    {
        string line;
        while ((line = await reader.ReadLineAsync()) != null)
        {
            if (int.TryParse(line, out var newcount))
            {
                count = newcount;
            }
        }
    }

    return count;
}

Utilisation de Xamarin.Essentials – Helpers du système de fichiers

Xamarin.Essentials est un ensemble d’API permettant d’écrire du code compatible multiplateforme. Les helpers du système de fichiers sont une classe qui contient une série d’assistances pour simplifier la localisation des répertoires de cache et de données de l’application. Cet extrait de code fournit un exemple de recherche du répertoire de stockage interne et du répertoire de cache d’une application :

// Get the path to a file on internal storage
var backingFile = Path.Combine(Xamarin.Essentials.FileSystem.AppDataDirectory, "count.txt");

// Get the path to a file in the cache directory
var cacheFile = Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, "count.txt");

Masquage de fichiers à partir du MediaStore

Le MediaStore est un composant Android qui collecte des métadonnées sur les fichiers multimédias (vidéos, musique, images) sur un appareil Android. Son objectif est de simplifier le partage de ces fichiers entre toutes les applications Android sur l’appareil.

Les fichiers privés ne s’affichent pas en tant que média partageable. Par exemple, si une application enregistre une image dans son stockage externe privé, ce fichier n’est pas récupéré par le scanneur multimédia (MediaStore).

Les fichiers publics seront récupérés par MediaStore. Répertoires qui ont un nom de fichier d’octet zéro . NOMEDIA ne sera pas analysé par MediaStore.