Sdílet prostřednictvím


Úložiště souborů a přístup s Xamarin.Androidem

Běžným požadavkem pro aplikace pro Android je manipulace se soubory – ukládání obrázků, stahování dokumentů nebo export dat pro sdílení s jinými programy. Android (který je založený na Linuxu) to podporuje tím, že poskytuje prostor pro úložiště souborů. Android seskupí systém souborů do dvou různých typů úložiště:

  • Interní úložiště – to je část systému souborů, ke které má přístup jenom aplikace nebo operační systém.
  • Externí úložiště – toto je oddíl pro ukládání souborů, které jsou přístupné všemi aplikacemi, uživatelem a případně dalšími zařízeními. Na některých zařízeních může být externí úložiště vyměnitelné (například SD karta).

Tyto seskupení jsou pouze koncepční a nemusí nutně odkazovat na jeden oddíl nebo adresář v zařízení. Zařízení s Androidem bude vždy poskytovat oddíl pro interní úložiště a externí úložiště. Je možné, že některá zařízení můžou mít více oddílů, které se považují za externí úložiště. Bez ohledu na oddíl rozhraní API pro čtení, zápis nebo vytváření souborů je stejné. Existují dvě sady rozhraní API, která může aplikace Xamarin.Android používat pro přístup k souborům:

  1. Rozhraní .NET API (poskytovaná mono a zabalená Xamarin.Androidem) – patří mezi ně pomocné rutiny systému souborů, které poskytuje Xamarin.Essentials. Rozhraní .NET API poskytují nejlepší kompatibilitu mezi platformami a jako takový se zaměří na tato rozhraní API.
  2. Nativní rozhraní API pro přístup k souborům v Javě (poskytovaná jazykem Java a zabalená Xamarin.Android) – Java poskytuje vlastní rozhraní API pro čtení a zápis souborů. Jedná se o zcela přijatelnou alternativu k rozhraním .NET API, ale jsou specifické pro Android a nejsou vhodné pro aplikace, které mají být multiplatformní.

Čtení a zápis do souborů je v Xamarin.Androidu téměř stejné jako u jakékoli jiné aplikace .NET. Aplikace Xamarin.Android určuje cestu k souboru, který bude manipulován, a pak pro přístup k souborům používá standardní idiomy .NET. Vzhledem k tomu, že skutečné cesty k internímu a externímu úložišti se můžou lišit od zařízení po zařízení nebo verze Androidu na verzi Androidu, nedoporučuje se pevně kódovat cestu k souborům. Místo toho použijte rozhraní API Xamarin.Android k určení cesty k souborům. Díky tomu rozhraní .NET API pro čtení a zápis souborů zpřístupňuje nativní rozhraní API androidu, která vám pomůžou určit cestu k souborům v interním a externím úložišti.

Než probereme rozhraní API, která se týkají přístupu k souborům, je důležité pochopit některé podrobnosti týkající se interního a externího úložiště. O tom se budeme zabývat v další části.

Interní a externí úložiště

Interní úložiště a externí úložiště jsou koncepčně velmi podobné – obě místa mohou ukládat soubory aplikace Xamarin.Android. Tato podobnost může být matoucí pro vývojáře, kteří nejsou obeznámeni s Androidem, protože není jasné, když by aplikace měla používat interní úložiště a externí úložiště.

Interní úložiště označuje nevolatilní paměť, kterou Android přiděluje operačnímu systému, sadám AKS a jednotlivým aplikacím. Tento prostor není přístupný s výjimkou operačního systému nebo aplikací. Android přidělí adresář v interním oddílu úložiště pro každou aplikaci. Po odinstalaci aplikace se odstraní také všechny soubory, které jsou uložené v interním úložišti v daném adresáři. Interní úložiště je nejvhodnější pro soubory, které jsou přístupné jenom pro aplikaci a které nebudou sdíleny s jinými aplikacemi nebo budou mít po odinstalaci aplikace velmi malou hodnotu. Na Androidu 6.0 nebo novějším se soubory v interním úložišti můžou automaticky zálohovat pomocí funkce Automatické zálohování v Androidu 6.0. Interní úložiště má následující nevýhody:

  • Soubory nelze sdílet.
  • Soubory se odstraní při odinstalaci aplikace.
  • Místo dostupné v interním úložišti může být omezené.

Externí úložiště odkazuje na úložiště souborů, které není interním úložištěm a není výhradně přístupné pro aplikaci. Primárním účelem externího úložiště je poskytnout místo pro umístění souborů, které mají být sdíleny mezi aplikacemi nebo které jsou příliš velké, aby se vešly do interního úložiště. Výhodou externího úložiště je, že má obvykle mnohem více místa pro soubory než interní úložiště. Externí úložiště ale není vždy zaručeno, že je na zařízení přítomno a může vyžadovat zvláštní oprávnění od uživatele, aby k němu mohl přistupovat.

Poznámka:

Zařízení, která podporují více uživatelů, poskytne Android každému uživateli svůj vlastní adresář v interním i externím úložišti. Tento adresář je pro ostatní uživatele v zařízení nepřístupný. Toto oddělení je pro aplikace neviditelné, pokud nejsou pevně zakódovat cesty k souborům v interním nebo externím úložišti.

Aplikace Xamarin.Android by obecně měly preferovat ukládání souborů do interního úložiště, pokud je to rozumné, a spoléhat se na externí úložiště, když je potřeba soubory sdílet s jinými aplikacemi, jsou velmi velké nebo by měly být zachovány i v případě, že je aplikace odinstalovaná. Konfigurační soubor je například nejvhodnější pro interní úložiště, protože nemá žádnou důležitost s výjimkou aplikace, která ho vytvoří. Naproti tomu fotky jsou vhodným kandidátem pro externí úložiště. Můžou být velmi velké a v mnoha případech ho uživatel může chtít sdílet nebo k nim přistupovat, i když je aplikace odinstalovaná.

Tato příručka se zaměří na interní úložiště. Podrobnosti o použití externího úložiště v aplikaci Xamarin.Android najdete v příručce Externí úložiště .

Práce s interním úložištěm

Interní adresář úložiště pro aplikaci je určen operačním systémem a je vystavený aplikacím pro Android vlastností Android.Content.Context.FilesDir . Tím se vrátí Java.IO.File objekt představující adresář, který má Android vyhrazený výhradně pro aplikaci. Například aplikace s názvem balíčku com.companyname může být interní adresář úložiště:

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

Tento dokument bude odkazovat na interní adresář úložiště jako INTERNAL_STORAGE.

Důležité

Přesná cesta k internímu adresáři úložiště se může lišit od zařízení po zařízení a mezi verzemi Androidu. Z tohoto důvodu nesmí aplikace pevně kódovat cestu k internímu adresáři úložiště souborů a místo toho používat rozhraní API Xamarin.Android, například System.Environment.GetFolderPath().

Pokud chcete maximalizovat sdílení kódu, aplikace Xamarin.Android (nebo aplikace Xamarin.Forms, které cílí na Xamarin.Android) by měly tuto metodu System.Environment.GetFolderPath() používat. V Xamarin.Android tato metoda vrátí řetězec pro adresář, který je stejné umístění jako Android.Content.Context.FilesDir. Tato metoda přebírá výčet, System.Environment.SpecialFolderkterý se používá k identifikaci sady výčtových konstant, které představují cesty speciálních složek používaných operačním systémem. Ne všechny System.Environment.SpecialFolder hodnoty se mapuje na platný adresář v Xamarin.Androidu. Následující tabulka popisuje, jakou cestu lze pro danou hodnotu System.Environment.SpecialFolderočekávat:

System.Environment.SpecialFolder Cesta
ApplicationData INTERNAL_STORAGE/.config
Desktop INTERNAL_STORAGE/Desktop
LocalApplicationData INTERNAL_STORAGE/.local/share
MyDocuments INTERNAL_STORAGE
MyMusic INTERNAL_STORAGE/Hudba
MyPictures INTERNAL_STORAGE/obrázky
MyVideos INTERNAL_STORAGE/videa
Personal INTERNAL_STORAGE
Fonts INTERNAL_STORAGE/.fonts
Templates INTERNAL_STORAGE/šablony
CommonApplicationData /usr/share
CommonApplicationData /usr/share

Čtení nebo zápis do souborů v interním úložišti

Všechna rozhraní API jazyka C# pro zápis do souboru jsou dostatečná. Stačí získat cestu k souboru, který je v adresáři přiděleném aplikaci. Důrazně doporučujeme používat asynchronní verze rozhraní .NET API k minimalizaci problémů, které mohou být přidruženy k přístupu k souborům blokující hlavní vlákno.

Tento fragment kódu je jedním z příkladů zápisu celého čísla do textového souboru UTF-8 do interního adresáře úložiště aplikace:

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());
    }
}

Další fragment kódu poskytuje jeden způsob, jak číst celočíselnou hodnotu uloženou v textovém souboru:

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;
}

Použití Xamarin.Essentials – pomocné rutiny systému souborů

Xamarin.Essentials je sada rozhraní API pro psaní kódu kompatibilního s více platformami. Pomocné rutiny systému souborů jsou třída, která obsahuje řadu pomocných rutin pro zjednodušení vyhledání mezipaměti a datových adresářů aplikace. Tento fragment kódu poskytuje příklad vyhledání interního adresáře úložiště a adresáře mezipaměti pro aplikaci:

// 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");

Skrytí souborů z MediaStore

Jedná se MediaStore o komponentu androidu, která shromažďuje meta data o mediálních souborech (videa, hudbě, obrázcích) na zařízení s Androidem. Jeho účelem je zjednodušit sdílení těchto souborů ve všech aplikacích pro Android na zařízení.

Soukromé soubory se nezobrazí jako sdílená média. Pokud například aplikace uloží obrázek do svého privátního externího úložiště, nebude tento soubor vyzvednut skenerem médií (MediaStore).

Veřejné soubory budou vyzvednuty MediaStore. Adresáře, které mají nulový název souboru bajtu . FUNKCE NOMEDIA nebude prohledávána MediaStore.