Przypadki użycia i sprawdzone metody dotyczące miejsca na dane na Androidzie

Aby zapewnić użytkownikom większą kontrolę nad plikami i ograniczyć ich nadmiar, w Androidzie 10 wprowadziliśmy nowy model przechowywania danych w aplikacjach o nazwie zakresowy dostęp do pamięci. Zmiany w zakresie pamięci masowej wpływają na sposób, w jaki aplikacje przechowują pliki w pamięci zewnętrznej urządzenia i uzyskują do nich dostęp. Aby ułatwić Ci migrację aplikacji do obsługi pamięci o ograniczonym zakresie, postępuj zgodnie ze sprawdzonymi metodami w przypadku typowych zastosowań pamięci, które zostały opisane w tym przewodniku. Przypadki użycia są podzielone na 2 kategorie: obsługa plików multimedialnychobsługa plików innych niż multimedialne.

W wielu przypadkach aplikacja tworzy pliki, do których inne aplikacje nie muszą mieć dostępu lub nie powinny go mieć. System udostępnia miejsca na dane przypisane do aplikacji, w których można zarządzać takimi plikami.

Więcej informacji o przechowywaniu plików na Androidzie i uzyskiwaniu do nich dostępu znajdziesz w przewodnikach szkoleniowych dotyczących pamięci.

Obsługa plików multimedialnych

W tej sekcji opisujemy niektóre typowe przypadki użycia związane z obsługą plików multimedialnych (wideo, obrazów i audio) oraz wyjaśniamy ogólne podejście, które może zastosować Twoja aplikacja. W tabeli poniżej znajdziesz podsumowanie każdego z tych przypadków użycia oraz linki do sekcji zawierających więcej szczegółów.

Przypadek użycia Podsumowanie
Wyświetlanie wszystkich plików z obrazami lub filmami Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Wyświetlanie zdjęć lub filmów z określonego folderu Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Dostęp do informacji o lokalizacji ze zdjęć Jeśli aplikacja korzysta z ograniczonego dostępu do miejsca na dane, zastosuj jedno z tych podejść. Jeśli Twoja aplikacja nie korzysta z ograniczonego dostępu do miejsca na dane, zastosuj inne podejście.
Określanie lokalizacji przechowywania nowych pobranych plików Jeśli aplikacja korzysta z ograniczonego dostępu do miejsca na dane, zastosuj jedno z tych podejść. Jeśli Twoja aplikacja nie korzysta z ograniczonego dostępu do miejsca na dane, zastosuj inne podejście.
Eksportowanie plików multimedialnych użytkownika na urządzenie Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Modyfikowanie lub usuwanie wielu plików multimedialnych w ramach jednej operacji W przypadku Androida 11 użyj jednego podejścia. W przypadku Androida 10 zrezygnuj z pamięci o ograniczonym zakresie i zastosuj podejście dla Androida 9 i starszych wersji.
Importowanie pojedynczego obrazu, który już istnieje Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Zrobienie pojedynczego zdjęcia Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Udostępnianie plików multimedialnych w innych aplikacjach Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Udostępnianie plików multimedialnych określonej aplikacji Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Uzyskiwanie dostępu do plików z kodu lub bibliotek, które używają bezpośrednich ścieżek do plików W przypadku Androida 11 użyj jednego podejścia. W przypadku Androida 10 zrezygnuj z pamięci o ograniczonym zakresie i zastosuj podejście dla Androida 9 i starszych wersji.

Wyświetlanie plików z obrazami lub filmami z wielu folderów

Wysyłanie zapytań dotyczących kolekcji multimediów za pomocą interfejsu query() API. Aby filtrować lub sortować pliki multimedialne, dostosuj parametry projection, selection, selectionArgssortOrder.

Wyświetlanie zdjęć lub filmów z określonego folderu

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Żądanie uprawnień aplikacji i poproś o uprawnienie READ_EXTERNAL_STORAGE.
  2. Pobieranie plików multimedialnych na podstawie wartości parametru MediaColumns.DATA, który zawiera bezwzględną ścieżkę do pliku multimedialnego na dysku.

Uwaga: gdy uzyskujesz dostęp do istniejącego pliku multimedialnego, możesz użyć wartości z kolumny DATA w logice. Dzieje się tak, ponieważ ta wartość ma prawidłową ścieżkę do pliku. Nie zakładaj jednak, że plik jest zawsze dostępny. Przygotuj się na obsługę błędów wejścia/wyjścia związanych z plikami, które mogą wystąpić.

Aby utworzyć lub zaktualizować plik multimedialny, nie używaj kolumny DATA. Zamiast tego użyj kolumn DISPLAY_NAMERELATIVE_PATH.

Dostęp do informacji o lokalizacji ze zdjęć

Jeśli Twoja aplikacja korzysta z pamięci o ograniczonym zakresie, wykonaj czynności opisane w sekcji Informacje o lokalizacji na zdjęciach w przewodniku po pamięci multimediów.

Określanie lokalizacji zapisu nowych pobranych plików

Jeśli Twoja aplikacja korzysta z pamięci o ograniczonym zakresie, pamiętaj o lokalizacji, w której chcesz przechowywać pobrane pliki multimedialne.

Jeśli inne aplikacje wymagają dostępu do plików, rozważ użycie dobrze zdefiniowanych kolekcji multimediów do pobierania lub kolekcji dokumentów.

W Androidzie 11 i nowszych pliki w zewnętrznym katalogu specyficznym dla aplikacji nie są dostępne dla innych aplikacji, nawet jeśli używasz DownloadManager do pobierania tych plików.

Eksportowanie plików multimedialnych użytkownika na urządzenie

Określ odpowiednią domyślną lokalizację do przechowywania plików multimedialnych użytkownika:

Modyfikowanie lub usuwanie wielu plików multimedialnych w ramach jednej operacji

Zastosuj logikę opartą na wersjach Androida, na których działa Twoja aplikacja.

Android 11

Zastosuj to podejście:

  1. Utwórz oczekujący zamiar dla żądania zapisu lub usunięcia w aplikacji, używając MediaStore.createWriteRequest() lub MediaStore.createTrashRequest(), a następnie poproś użytkownika o zezwolenie na edytowanie zestawu plików, wywołując ten zamiar.
  2. Oceń odpowiedź użytkownika:

    • Jeśli uprawnienia zostały przyznane, kontynuuj operację modyfikowania lub usuwania.
    • Jeśli uprawnienie nie zostało przyznane, wyjaśnij użytkownikowi, dlaczego funkcja w aplikacji wymaga tego uprawnienia.

Dowiedz się więcej o zarządzaniu grupami plików multimedialnych za pomocą tych metod dostępnych na urządzeniach z Androidem 11 i nowszym.

działa w systemie Android 10,

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom API 29), zrezygnuj z zakresu pamięci i nadal używaj podejścia stosowanego w przypadku Androida 9 i starszych wersji, aby wykonać tę operację.

Android 9 lub starszy

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Żądanie uprawnień aplikacji i poproś o uprawnienie WRITE_EXTERNAL_STORAGE.
  2. Do modyfikowania lub usuwania plików multimedialnych użyj interfejsu API MediaStore.

Importowanie pojedynczego obrazu, który już istnieje

Jeśli chcesz zaimportować pojedynczy obraz, który już istnieje (np. aby użyć go jako zdjęcia profilowego użytkownika), aplikacja może użyć własnego interfejsu do tej operacji lub selektora systemowego.

Wyświetlanie własnego interfejsu

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Żądanie uprawnień aplikacji i poproś o uprawnienie READ_EXTERNAL_STORAGE.
  2. Użyj interfejsu query() API, aby wysłać zapytanie do kolekcji multimediów.
  3. Wyświetl wyniki w interfejsie niestandardowym aplikacji.

Użyj selektora systemowego

Użyj intencji ACTION_GET_CONTENT, która prosi użytkownika o wybranie obrazu do zaimportowania.

Jeśli chcesz odfiltrować typy obrazów, które selektor systemowy wyświetla użytkownikowi do wyboru, możesz użyć setType() lub EXTRA_MIME_TYPES.

Zrobienie pojedynczego zdjęcia

Jeśli chcesz zrobić jedno zdjęcie do wykorzystania w aplikacji (np. jako zdjęcie profilowe użytkownika), użyj intencji ACTION_IMAGE_CAPTURE, aby poprosić użytkownika o zrobienie zdjęcia za pomocą aparatu urządzenia. System zapisuje zrobione zdjęcie w tabeli MediaStore.Images.

Udostępnianie plików multimedialnych w innych aplikacjach

Użyj metody insert() , aby dodać rekordy bezpośrednio do MediaStore. Więcej informacji znajdziesz w sekcji Dodawanie elementu w przewodniku po przechowywaniu multimediów.

Udostępnianie plików multimedialnych w określonej aplikacji

Użyj komponentu Androida FileProvider zgodnie z opisem w przewodniku Konfigurowanie udostępniania plików.

Dostęp do plików z kodu lub bibliotek, które używają bezpośrednich ścieżek do plików

Zastosuj logikę opartą na wersjach Androida, na których działa Twoja aplikacja.

Android 11

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Żądanie uprawnień aplikacji i poproś o uprawnienie READ_EXTERNAL_STORAGE.
  2. Uzyskaj dostęp do plików za pomocą bezpośrednich ścieżek do plików.

Więcej informacji znajdziesz w sekcji dotyczącej otwierania plików multimedialnych za pomocą bezpośrednich ścieżek do plików.

działa w systemie Android 10,

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom API 29), zrezygnuj z zakresu pamięci i nadal używaj podejścia stosowanego w przypadku Androida 9 i starszych wersji, aby wykonać tę operację.

Android 9 lub starszy

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Żądanie uprawnień aplikacji i poproś o uprawnienie WRITE_EXTERNAL_STORAGE.
  2. Uzyskaj dostęp do plików za pomocą bezpośrednich ścieżek do plików.

Obsługa plików innych niż multimedia

W tej sekcji opisujemy niektóre typowe przypadki użycia związane z obsługą plików innych niż multimedia i wyjaśniamy ogólne podejście, które może zastosować Twoja aplikacja. W tabeli poniżej znajdziesz podsumowanie każdego z tych przypadków użycia oraz linki do sekcji zawierających więcej szczegółów.

Przypadek użycia Podsumowanie
Otwieranie pliku dokumentu Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Zapisywanie plików na dodatkowych woluminach pamięci W przypadku Androida 11 użyj jednego podejścia. W przypadku starszych wersji Androida zastosuj inne podejście.
Przenoszenie istniejących plików z starszej lokalizacji pamięci W miarę możliwości przenieś pliki do pamięci o ograniczonym zakresie. W razie potrzeby zrezygnuj z pamięci o ograniczonym zakresie na urządzeniach z Androidem 10.
Udostępnianie treści w innych aplikacjach Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Buforowanie plików multimedialnych Stosuj to samo podejście w przypadku wszystkich wersji Androida.
Eksportowanie plików innych niż multimedia na urządzenie Jeśli aplikacja korzysta z ograniczonego dostępu do miejsca na dane, zastosuj jedno z tych podejść. Jeśli Twoja aplikacja nie korzysta z ograniczonego dostępu do miejsca na dane, zastosuj inne podejście.

Otwieranie pliku dokumentu

Użyj intencji ACTION_OPEN_DOCUMENT, aby poprosić użytkownika o wybranie pliku do otwarcia za pomocą selektora systemowego. Jeśli chcesz przefiltrować typy plików, które selektor systemowy będzie wyświetlać użytkownikowi do wyboru, możesz użyć setType() lub EXTRA_MIME_TYPES.

Możesz na przykład znaleźć wszystkie pliki PDF, ODT i TXT, używając tego kodu:

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

Zapisywanie plików na woluminach pamięci dodatkowej

Woluminy pamięci dodatkowej obejmują karty SD. Dostęp do informacji o danym woluminie pamięci masowej można uzyskać za pomocą klasy StorageVolume.

Zastosuj logikę opartą na wersji Androida, na której działa Twoja aplikacja.

Android 11

Zastosuj to podejście:

  1. Używaj modelu pamięci o ograniczonym zakresie.
  2. kierować aplikację na Androida 10 (interfejs API na poziomie 29) lub starszego;
  3. Zadeklaruj uprawnienie WRITE_EXTERNAL_STORAGE.
  4. Wykonaj jedną z tych czynności:
    • Dostęp do pliku za pomocą interfejsu API MediaStore.
    • Bezpośredni dostęp do ścieżki pliku za pomocą interfejsów API, takich jak File lub fopen().

Działanie na starszych wersjach

Użyj platformy Storage Access Framework, która umożliwia użytkownikom wybranie lokalizacji na dodatkowym woluminie pamięci, w której aplikacja może zapisywać plik.

Przenoszenie istniejących plików z starszej lokalizacji pamięci

Katalog jest uważany za starszą lokalizację pamięci, jeśli nie jest katalogiem specyficznym dla aplikacji ani publicznym katalogiem udostępnionym. Jeśli Twoja aplikacja tworzy lub wykorzystuje pliki w starszej lokalizacji pamięci, zalecamy przeniesienie plików aplikacji do lokalizacji dostępnych w pamięci o ograniczonym zakresie i wprowadzenie niezbędnych zmian w aplikacji, aby działała z plikami w pamięci o ograniczonym zakresie.

Zachowaj dostęp do starszej lokalizacji pamięci na potrzeby migracji danych

Aplikacja musi mieć dostęp do starszej lokalizacji pamięci, aby przenieść pliki aplikacji do lokalizacji dostępnych w ramach pamięci o ograniczonym zakresie. Podejście, którego należy użyć, zależy od docelowego poziomu interfejsu API aplikacji.

Jeśli Twoja aplikacja jest kierowana na Androida 11
  1. Ustaw flagę preserveLegacyExternalStorage na true, aby zachować starszy model przechowywania danych. Dzięki temu aplikacja będzie mogła przenieść dane użytkownika, gdy przejdzie on na nową wersję aplikacji kierowaną na Androida 11.

  2. Zrezygnuj z pamięci o ograniczonym zakresie, aby aplikacja mogła nadal uzyskiwać dostęp do plików w starszej lokalizacji pamięci na urządzeniach z Androidem 10.

Jeśli Twoja aplikacja jest kierowana na Androida 10

Zrezygnuj z pamięci o ograniczonym zakresie, aby łatwiej było zachować spójne działanie aplikacji w różnych wersjach Androida.

Przenoszenie danych aplikacji

Gdy aplikacja będzie gotowa do migracji, wykonaj te czynności:

  1. kierować aplikację na Androida 10 lub starszego;
  2. Zrezygnuj z pamięci o ograniczonym zakresie, aby aplikacja miała dostęp do plików, które chcesz przenieść.
  3. Wdróż kod, który korzysta z interfejsu File API, aby przenieść pliki z bieżącej lokalizacji w /sdcard/ do lokalizacji dostępnej w ramach pamięci o ograniczonym zakresie:

    1. Przenieś wszystkie pliki aplikacji prywatnej do katalogu zwróconego przez metodę getExternalFilesDir().
    2. Przenoszenie dowolnych udostępnionych plików innych niż multimedia do podkatalogu Downloads/ dedykowanego aplikacji.
  4. Usuń starsze katalogi pamięci aplikacji z katalogu /sdcard/.

Po zainstalowaniu nowej wersji aplikacji użytkownicy przechodzą na swoich urządzeniach proces migracji danych. Możesz monitorować proces migracji w przypadku wszystkich użytkowników, tworząc zdarzenie analityczne.

Po przeniesieniu danych przez użytkowników opublikuj kolejną aktualizację aplikacji, w której kierujesz ją na Androida 11.

Udostępnianie treści w innych aplikacjach

Aby udostępnić pliki aplikacji jednej innej aplikacji, użyjFileProvider. W przypadku aplikacji, które muszą udostępniać sobie pliki, zalecamy używanie dostawcy treści w każdej z nich, a następnie synchronizowanie danych w miarę dodawania aplikacji do kolekcji.

Buforowanie plików innych niż multimedia

Podejście, którego należy użyć, zależy od typu plików, które chcesz buforować.

Eksportowanie plików niemultimedialnych na urządzenie

Określ odpowiednią domyślną lokalizację do przechowywania plików innych niż multimedialne. Zezwalaj użytkownikom na eksportowanie plików z katalogów specyficznych dla aplikacji do bardziej ogólnie dostępnej lokalizacji. Użyj pobrań lub kolekcji dokumentów w MediaStore, aby wyeksportować na urządzenie pliki inne niż multimedia.

Obsługa plików specyficznych dla aplikacji

Jeśli aplikacja tworzy pliki, do których inne aplikacje nie muszą mieć dostępu lub nie powinny go mieć, możesz je przechowywać w lokalizacjach pamięci specyficznych dla aplikacji.

Katalogi pamięci wewnętrznej

System uniemożliwia innym aplikacjom dostęp do tych lokalizacji, a na Androidzie 10 (API na poziomie 29) i nowszym są one szyfrowane. Te lokalizacje są dobrym miejscem do przechowywania danych wrażliwych, do których dostęp ma tylko Twoja aplikacja.

Katalogi pamięci zewnętrznej

Jeśli pamięć wewnętrzna nie zapewnia wystarczającej ilości miejsca na pliki aplikacji, rozważ użycie pamięci zewnętrznej. Chociaż inna aplikacja może uzyskać dostęp do tych katalogów, jeśli ma odpowiednie uprawnienia, pliki w nich przechowywane są przeznaczone do użytku tylko przez Twoją aplikację.

Na Androidzie 4.4 (poziom API 19) lub nowszym aplikacja nie musi prosić o żadne uprawnienia związane z pamięcią, aby uzyskać dostęp do katalogów specyficznych dla aplikacji w pamięci zewnętrznej.

Gdy użytkownik odinstaluje aplikację, pliki zapisane w pamięci specyficznej dla aplikacji zostaną usunięte. Dlatego nie należy używać tej pamięci do zapisywania niczego, co użytkownik chce zachować niezależnie od aplikacji.

Tymczasowa rezygnacja z pamięci o ograniczonym zakresie

Zanim Twoja aplikacja stanie się w pełni zgodna z zakresem pamięci, możesz tymczasowo zrezygnować z tej funkcji zarówno w testach, jak i w wersji produkcyjnej aplikacji.

Rezygnacja z udziału w testach

Na Androidzie 10 (API na poziomie 29) i nowszych testy aplikacji są domyślnie przeprowadzane w piaskownicy pamięci. Ta piaskownica uniemożliwia aplikacji dostęp do plików poza katalogiem aplikacji i katalogami udostępnionymi publicznie.

Jeśli test generuje pliki dla hosta, takie jak zrzuty ekranu, dane debugowania, dane o pokryciu lub dane o wydajności, możesz zapisać te pliki w globalnych katalogach. Aby to zrobić, dodaj do odpowiedniego narzędzia, które wywołuje am instrument, ten flag:

-e no-isolated-storage 1

Ta flaga wpływa na wszystkie działania testu z instrumentacją i na cały wywoływany kod testu. Dlatego, gdy używasz tego flagi, nie możesz sprawdzić zgodności aplikacji z pamięcią o ograniczonym zakresie. W przypadku danych wyjściowych testu lepiej jest zapisywać dane w pamięci o zakresie aplikacji, która jest czytelna dla powłoki. Następnie możesz pobrać ten katalog w zakresie aplikacji. Aby określić, z którego katalogu pobrać dane, wywołaj funkcję getExternalMediaDirs().

Rezygnacja w wersji produkcyjnej aplikacji

Jeśli Twoja aplikacja jest przeznaczona na Androida 10 (poziom interfejsu API 29) lub starszego, możesz tymczasowo zrezygnować z pamięci o ograniczonym zakresie w aplikacji produkcyjnej. Jeśli jednak Twoja aplikacja jest przeznaczona na Androida 10, musisz ustawić wartość requestLegacyExternalStorage na true w pliku manifestu aplikacji:

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting
       Android 10. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Aby sprawdzić, jak aplikacja kierowana na Androida 10 lub starszego zachowuje się podczas korzystania z pamięci o ograniczonym zakresie, możesz włączyć to zachowanie, ustawiając wartość requestLegacyExternalStorage na false. Jeśli testujesz aplikację na urządzeniu z Androidem 11, możesz też użyć flag zgodności aplikacji, aby sprawdzić, jak aplikacja działa z zakresem pamięci lub bez niego.

Dodatkowe materiały

Więcej informacji o miejscu na dane na Androidzie znajdziesz w tych materiałach:

Posty na blogu