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 bałagan, w Androidzie 10 wprowadziliśmy nową metodę przechowywania danych w aplikacjach, zwaną storage wydzielonym. Ograniczony dostęp do pamięci zmienia sposób, w jaki aplikacje przechowują pliki i do nich uzyskują dostęp na zewnętrznej pamięci urządzenia. Aby ułatwić sobie migrację aplikacji na obsługę ograniczonego miejsca na dane, stosuj sprawdzone metody dotyczące typowych przypadków użycia miejsca na dane opisane w tym przewodniku. Przypadki użycia są podzielone na 2 kategorie: obsługa plików multimedialnychobsługa plików niemultimedialnych.

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

Więcej informacji o przechowywaniu plików i dostępie do nich na urządzeniach z Androidem znajdziesz w przewodnikach dotyczących miejsca na dane.

Obsługa plików multimedialnych

W tej sekcji opisaliśmy kilka typowych przypadków użycia dotyczących obsługi plików multimedialnych (plików wideo, obrazów i dźwięku) oraz ogólne podejście, którego może używać Twoja aplikacja. Tabela poniżej zawiera podsumowanie tych przypadków użycia oraz linki do sekcji, w których znajdziesz więcej informacji.

Przypadek użycia Podsumowanie
Pokaż wszystkie pliki z obrazami lub filmami Stosuj to samo podejście we wszystkich wersjach Androida.
Wyświetlanie obrazów lub filmów z określonego folderu Stosuj to samo podejście we wszystkich wersjach Androida.
Dostęp do informacji o lokalizacji ze zdjęć Jeśli Twoja 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.
Definiowanie lokalizacji przechowywania nowych pobranych plików Jeśli Twoja 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 multimediów użytkownika na urządzenie Stosuj to samo podejście we wszystkich wersjach Androida.
Modyfikowanie lub usuwanie wielu plików multimedialnych za pomocą jednej operacji Użyj jednego podejścia w przypadku Androida 11. W przypadku Androida 10 zrezygnuj z ograniczonego miejsca na dane i zamiast tego zastosuj podejście stosowane w przypadku Androida 9 i starszych wersji.
Importowanie pojedynczego obrazu, który już istnieje Stosuj to samo podejście we wszystkich wersjach Androida.
Zapisywanie pojedynczego zdjęcia Stosuj to samo podejście we wszystkich wersjach Androida.
Udostępnianie plików multimedialnych za pomocą innych aplikacji Stosuj to samo podejście we wszystkich wersjach Androida.
Udostępnianie plików multimedialnych określonej aplikacji Stosuj to samo podejście we wszystkich wersjach Androida.
Uzyskiwanie dostępu do plików z kodu lub bibliotek, które używają bezpośrednich ścieżek plików Użyj jednego podejścia w przypadku Androida 11. W przypadku Androida 10 zrezygnuj z ograniczonego miejsca na dane i zamiast tego zastosuj podejście stosowane w przypadku Androida 9 i starszych wersji.

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

Wysyłanie zapytania do kolekcji multimediów za pomocą interfejsu API query(). Aby filtrować lub sortować pliki multimedialne, dostosuj parametry projection, selection, selectionArgs i sortOrder.

Wyświetlanie obrazów lub filmów z określonego folderu

Skorzystaj z tego podejścia:

  1. Zgodnie ze sprawdzonymi metodami opisanymi w artykule o uzyskiwaniu uprawnień do aplikacji poproś o uprawnienia READ_EXTERNAL_STORAGE.
  2. Pobierz pliki multimedialne 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 w kolumnie DATA w swojej logice. Dzieje się tak, ponieważ ta wartość ma prawidłową ścieżkę do pliku. Nie zakładaj jednak, że plik jest zawsze dostępny. Bądź przygotowany na ewentualne błędy we/wy związane z plikami.

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 z zdjęć

Jeśli Twoja aplikacja korzysta z ograniczonego miejsca na dane, wykonaj czynności opisane w sekcji Informacje o lokalizacji w zdjęciach w przewodniku dotyczącym przechowywania multimediów.

Definiowanie lokalizacji zapisu nowych plików do pobrania

Jeśli Twoja aplikacja korzysta z ograniczonego miejsca na dane, pamiętaj o tym, gdzie zapisujesz pobrane pliki multimedialne.

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

W Androidzie 11 i nowszych pliki w zewnętrznym katalogu aplikacji są niedostępne dla innych aplikacji, nawet jeśli używasz do ich pobierania polecenia DownloadManager.

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

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

Uruchomienie na Androidzie 11

Skorzystaj z tego podejścia:

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

    • Jeśli uprawnienia zostały przyznane, kontynuuj operację modyfikacji lub usuwania.
    • Jeśli użytkownik nie przyznał uprawnień, wyjaśnij mu, dlaczego funkcja w aplikacji ich potrzebuje.

Dowiedz się więcej o zarządzaniu grupami plików multimedialnych za pomocą tych metod, które są dostępne w Androidzie 11 i nowszych.

działa w Androidzie 10,

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom interfejsu API 29), wyłącz ograniczone miejsce na dane i wykonaj tę operację w sposób odpowiedni dla Androida 9 i starszych wersji.

działać na Androidzie 9 lub starszym,

Skorzystaj z tego podejścia:

  1. Zgodnie ze sprawdzonymi metodami opisanymi w artykule o uzyskiwaniu uprawnień do aplikacji poproś o uprawnienia WRITE_EXTERNAL_STORAGE.
  2. Aby zmodyfikować lub usunąć pliki multimedialne, użyj interfejsu API MediaStore.

Importowanie pojedynczego obrazu, który już istnieje

Jeśli chcesz zaimportować istniejący obraz (np. do użycia jako zdjęcie profilowe użytkownika), aplikacja może użyć do tej operacji własnego interfejsu użytkownika lub selektora systemowego.

Prezentowanie własnego interfejsu

Skorzystaj z tego podejścia:

  1. Zgodnie ze sprawdzonymi metodami opisanymi w artykule o uzyskiwaniu uprawnień do aplikacji poproś o uprawnienia READ_EXTERNAL_STORAGE.
  2. Użyj interfejsu API query(), aby wysłać zapytanie do kolekcji multimediów.
  3. Wyświetlanie wyników w niestandardowym interfejsie aplikacji.

Używanie 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 systemowy selektor wyświetla użytkownikowi, możesz użyć setType() lub EXTRA_MIME_TYPES.

Robienie pojedynczego zdjęcia

Jeśli chcesz zarejestrować pojedynczy obraz, aby użyć go w aplikacji (np. jako zdjęcia do profilu użytkownika), użyj intencji ACTION_IMAGE_CAPTURE, aby poprosić użytkownika o zrobienie zdjęcia za pomocą aparatu urządzenia. System przechowuje zrobione zdjęcie w tabeli MediaStore.Images.

Udostępnianie plików multimedialnych za pomocą innych aplikacji

Aby dodać rekordy bezpośrednio do MediaStore, użyj metody insert(). Więcej informacji znajdziesz w sekcji Dodawanie elementów w przewodniku dotyczącym przechowywania multimediów.

Udostępnianie plików multimedialnych określonej aplikacji

Użyj komponentu FileProvider na urządzeniu z Androidem 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 plików

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

Uruchomienie na Androidzie 11

Skorzystaj z tego podejścia:

  1. Zgodnie ze sprawdzonymi metodami opisanymi w artykule o uzyskiwaniu uprawnień do aplikacji poproś o uprawnienia 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 o otwieraniu plików multimedialnych za pomocą bezpośrednich ścieżek do plików.

działa w Androidzie 10,

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom interfejsu API 29), wyłącz ograniczone miejsce na dane i wykonaj tę operację w sposób odpowiedni dla Androida 9 i starszych wersji.

działać na Androidzie 9 lub starszym,

Skorzystaj z tego podejścia:

  1. Zgodnie ze sprawdzonymi metodami opisanymi w artykule o uzyskiwaniu uprawnień do aplikacji poproś o uprawnienia WRITE_EXTERNAL_STORAGE.
  2. Uzyskaj dostęp do plików za pomocą bezpośrednich ścieżek do plików.

Obsługa plików niemultimediów

W tej sekcji opisano kilka typowych przypadków użycia dotyczących obsługi plików niebędących plikami multimedialnymi oraz ogólne podejście, którego może używać aplikacja. Tabela poniżej zawiera podsumowanie tych przypadków użycia oraz linki do sekcji, w których znajdziesz więcej informacji.

Przypadek użycia Podsumowanie
Otwieranie pliku dokumentu Stosuj to samo podejście we wszystkich wersjach Androida.
Zapisywanie danych w plikach na woluminach pamięci pomocniczej Użyj jednego podejścia w przypadku Androida 11. W przypadku starszych wersji Androida należy zastosować inne podejście.
Przenoszenie istniejących plików ze starego miejsca na dane Tam, gdzie to możliwe, przenieś pliki do ograniczonego miejsca na dane. W razie potrzeby zrezygnuj z ograniczonego miejsca na dane w Androidzie 10.
Udostępnianie treści innym aplikacjom Stosuj to samo podejście we wszystkich wersjach Androida.
Pamięć podręczna plików niemedialnych Stosuj to samo podejście we wszystkich wersjach Androida.
Eksportowanie plików niemultimediów na urządzenie Jeśli Twoja 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 filtrować typy plików, które selektor systemowy ma wyświetlać użytkownikowi, możesz użyć setType() lub EXTRA_MIME_TYPES.

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

KotlinJava
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
      )
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 danych do plików na woluminach pamięci dodatkowej

Do pamięci dodatkowej należą karty SD. Informacje o danym woluminie pamięci masowej można uzyskać, korzystając z klasy StorageVolume.

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

Uruchomienie na Androidzie 11

Skorzystaj z tego podejścia:

  1. Użyj modelu ograniczonego miejsca na dane.
  2. kierować aplikację na Androida 10 (poziom API 29) lub niższego.
  3. Zadeklaruj uprawnienie WRITE_EXTERNAL_STORAGE.
  4. Wybierz jeden z tych typów dostępu:
    • Dostęp do plików za pomocą interfejsu MediaStore API.
    • bezpośredni dostęp do ścieżki pliku za pomocą interfejsów API, takich jak File lub fopen().

Uruchamianie w starszych wersjach

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

Przenoszenie istniejących plików z starszego miejsca na dane

Katalog jest uważany za starszą lokalizację pamięci masowej, jeśli nie jest katalogiem specyficznym dla aplikacji ani publicznym katalogiem współdzielonym. Jeśli aplikacja tworzy lub zużywa pliki w starszej lokalizacji pamięci, zalecamy przeniesienie plików aplikacji do lokalizacji dostępnych za pomocą ograniczonej pamięci i wprowadzenie niezbędnych zmian w aplikacji, aby mogła pracować z plikami w ograniczonej pamięci.

Utrzymanie dostępu do starszego miejsca na dane na potrzeby migracji danych

Aplikacja musi zachować dostęp do starszego miejsca na dane, aby przenieść pliki aplikacji do lokalizacji dostępnych za pomocą ograniczonego miejsca na dane. Sposób, w jaki należy to zrobić, zależy od docelowego poziomu interfejsu API aplikacji.

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

  2. Kontynuuj wycofywanie ograniczonego dostępu do pamięci, aby Twoja aplikacja nadal miała 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 ograniczonego miejsca na dane, aby ułatwić zachowanie zachowania aplikacji w różnych wersjach Androida.

Migracja danych aplikacji

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

  1. kierować aplikację na Androida 10 lub starszego;
  2. Wycofanie zgody na ograniczoną pamięć, aby aplikacja miała dostęp do plików, które są potrzebne do przeprowadzenia migracji.
  3. Wdróż kod, który używa interfejsu API File do przenoszenia plików z bieżącej lokalizacji w ramach /sdcard/ do lokalizacji dostępnej za pomocą ograniczonego miejsca na dane:

    1. Przenieś wszystkie pliki aplikacji prywatnej do katalogu zwróconego przez metodę getExternalFilesDir().
    2. Przenoś wszystkie udostępnione pliki niemultimedialne do podkatalogu Downloads/ przeznaczonego dla aplikacji.
  4. Usuń starsze katalogi pamięci aplikacji z katalogu /sdcard/.

Po zainstalowaniu nowej wersji aplikacji użytkownicy przeprowadzają na swoich urządzeniach proces migracji danych. Możesz monitorować proces migracji wśród całej grupy użytkowników, tworząc zdarzenie Analytics.

Gdy użytkownicy przeniosą swoje dane, opublikuj kolejną aktualizację aplikacji, w której kierujesz ją na Androida 11.

Udostępnianie treści innym aplikacjom

Aby udostępnić pliki aplikacji innej aplikacji, użyj FileProvider. W przypadku aplikacji, które muszą udostępniać sobie nawzajem pliki, zalecamy użycie dostawcy treści dla każdej aplikacji, a następnie zsynchronizowanie danych po dodaniu aplikacji do kolekcji.

Pamięć podręczna plików niemultimediów

Sposób, którego należy użyć, zależy od typu plików, które chcesz zapisać w pamięci podręcznej.

Eksportowanie plików niemultimediów na urządzenie

Określ odpowiednią domyślną lokalizację do przechowywania plików niemultimedialnych. Zezwalanie użytkownikom na eksportowanie plików z katalogów aplikacji do bardziej ogólnie dostępnej lokalizacji. Aby wyeksportować na urządzenie pliki inne niż multimedialne, użyj pobieranych plików lub kolekcji dokumentów w MediaStore.

Obsługa plików związanych z aplikacją

Jeśli Twoja aplikacja tworzy pliki, do których inne aplikacje nie muszą mieć dostępu lub nie powinny do nich mieć dostępu, możesz je przechowywać w miejscach przechowywania danych aplikacji.

Katalogi pamięci wewnętrznej

System uniemożliwia innym aplikacjom dostęp do tych lokalizacji, a w Androidzie 10 (poziom interfejsu API 29) i nowszych są one szyfrowane. Te lokalizacje to dobre miejsce na przechowywanie danych poufnych, do których dostęp ma tylko Twoja aplikacja.

Katalogi pamięci zewnętrznej

Jeśli w pamięci wewnętrznej jest za mało miejsca na pliki związane z aplikacją, rozważ użycie pamięci zewnętrznej. Chociaż inna aplikacja może dostępować do tych katalogów, jeśli ma odpowiednie uprawnienia, pliki zapisane w tych katalogach są przeznaczone tylko do użytku Twojej aplikacji.

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

Gdy użytkownik odinstaluje aplikację, pliki zapisane w pamięci konkretnej aplikacji zostaną usunięte. Nie należy więc używać tej pamięci do zapisywania treści, które użytkownik chce zachować niezależnie od aplikacji.

Tymczasowe wyłączenie ograniczonego miejsca na dane

Zanim Twoja aplikacja będzie w pełni zgodna z ograniczonym dostępem do pamięci, możesz tymczasowo zrezygnować z tej funkcji zarówno w testach, jak i w wersji produkcyjnej aplikacji.

Wycofanie zgody na udział w testach

W Androidzie 10 (poziom interfejsu API 29) i nowszych testy aplikacji są domyślnie wykonywane w sandboxie pamięci. Ten piaskownicy uniemożliwia aplikacji dostęp do plików spoza katalogu aplikacji i publicznie udostępnionych katalogów.

Jeśli test wygeneruje pliki dla hosta, takie jak zrzuty ekranu, dane debugowania, dane pokrycia czy dane o wydajności, możesz zapisać te pliki w katalogach globalnych. Aby to zrobić, dodaj ten parametr do odpowiedniego gniazda, które wywołuje am instrument:

-e no-isolated-storage 1

Ten parametr wpływa na całe zachowanie testowanego przypadku, a także na cały wywoływany kod testu. Dlatego, gdy używasz tego parametru, nie możesz sprawdzić zgodności aplikacji z ograniczonym miejscem na dane. W przypadku danych testowych lepiej jest zapisywać je w pamięci dostępnej dla aplikacji, która jest czytelna dla powłoki. Następnie możesz pobrać ten katalog ograniczony do aplikacji. Aby określić, z którego katalogu pobrać dane, wywołaj funkcję getExternalMediaDirs().

Rezygnacja z usługi w wersji produkcyjnej aplikacji

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom interfejsu API 29) lub starszego, możesz tymczasowo zrezygnować z ograniczonego miejsca w wersji produkcyjnej aplikacji. Jeśli jednak kierujesz ją na Androida 10, musisz w pliku manifestu aplikacji ustawić wartość requestLegacyExternalStorage na true:

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

Aby przetestować, jak aplikacja kierowana na Androida 10 lub niższą wersję działa z użyciem ograniczonego miejsca na dane, 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ć jej działanie z ograniczonym lub bez ograniczonego miejsca na dane.

Dodatkowe materiały

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

Posty na blogu