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 nowy model pamięci masowej dla aplikacji, który nazywa się ograniczonym dostępem do miejsca na dane. Wydzielony obszar pamięci zmienia 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 na potrzeby obsługi ograniczonego dostępu do miejsca na dane, w tym przewodniku opisaliśmy sprawdzone metody dotyczące typowych przypadków użycia pamięci. Przypadki użycia są podzielone na 2 kategorie: obsługa plików multimedialnych i obsługa plików innych niż multimedialne.

W wielu przypadkach aplikacja tworzy pliki, do których inne aplikacje nie muszą lub nie powinny mieć dostępu. System udostępnia lokalizacje pamięci masowej przeznaczone dla aplikacji, które umożliwiają zarządzanie takimi plikami.

Więcej informacji o przechowywaniu plików i uzyskiwaniu do nich dostępu na Androidzie znajdziesz w przewodnikach 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 (plików wideo, obrazów i plików audio) oraz ogólne podejście, które może zastosować Twoja aplikacja. Tabela poniżej zawiera podsumowanie każdego z tych przypadków użycia oraz linki do sekcji, w których znajdziesz więcej informacji.

Przypadek użycia Podsumowanie
Wyświetlanie wszystkich plików graficznych i wideo Takie samo podejście dotyczy wszystkich wersji Androida.
Wyświetlanie obrazów lub filmów z określonego folderu Takie samo podejście dotyczy wszystkich wersji Androida.
Uzyskiwanie dostępu do informacji o lokalizacji ze zdjęć Jeśli aplikacja korzysta z ograniczonego dostępu do miejsca na dane, użyj jednej metody. Jeśli Twoja aplikacja nie korzysta z ograniczonego dostępu do miejsca na dane, użyj innego podejścia.
Definiowanie lokalizacji przechowywania nowych pobranych plików Jeśli aplikacja korzysta z ograniczonego dostępu do miejsca na dane, użyj jednej metody. Jeśli Twoja aplikacja nie korzysta z ograniczonego dostępu do miejsca na dane, użyj innego podejścia.
Eksportowanie plików multimedialnych użytkownika na urządzenie Takie samo podejście dotyczy 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 wydzielonej pamięci i zastosuj podejście dla Androida 9 i starszych wersji.
Importowanie pojedynczego obrazu, który już istnieje Takie samo podejście dotyczy wszystkich wersji Androida.
Robienie pojedynczego zdjęcia Takie samo podejście dotyczy wszystkich wersji Androida.
Udostępnianie plików multimedialnych innym aplikacjom Takie samo podejście dotyczy wszystkich wersji Androida.
Udostępnianie plików multimedialnych określonej aplikacji Takie samo podejście dotyczy 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 wydzielonej pamięci i zastosuj podejście dla Androida 9 lub starszego.

Wyświetlanie plików graficznych lub wideo 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świetlać obrazy lub filmy z określonego folderu;

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Prośba o uprawnienia aplikacji i poproś o uprawnienie READ_EXTERNAL_STORAGE.
  2. Pobieraj pliki multimedialne na podstawie wartości MediaColumns.DATA, która zawiera bezwzględną ścieżkę systemu plików do elementu multimedialnego na dysku.

Uwaga: gdy uzyskujesz dostęp do istniejącego pliku multimedialnego, możesz użyć w logice wartości z kolumny DATA. 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ę wszelkich 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_NAME i RELATIVE_PATH.

Dostęp do informacji o lokalizacji ze zdjęć

Jeśli Twoja aplikacja korzysta z ograniczonego dostępu do miejsca na dane, wykonaj czynności opisane w sekcji Informacje o lokalizacji na zdjęciach w przewodniku po pamięci multimediów.

Definiowanie lokalizacji zapisu nowych pobranych plików

Jeśli Twoja aplikacja korzysta z ograniczonego dostępu do miejsca na dane, zwróć uwagę na lokalizację, 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.

Na Androidzie 11 i nowszych pliki w zewnętrznym katalogu aplikacji nie są dostępne dla innych aplikacji, nawet jeśli do ich pobrania używasz DownloadManager.

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

Zdefiniuj 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.

z Androidem 11,

Zastosuj to podejście:

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

    • Jeśli uprawnienie zostało przyznane, przejdź do operacji modyfikacji lub usunięcia.
    • Jeśli uprawnienie nie zostało przyznane, wyjaśnij użytkownikowi, dlaczego funkcja w aplikacji go wymaga.

Dowiedz się więcej o zarządzaniu grupami plików multimedialnych za pomocą tych metod, które są dostępne na urządzeniach z Androidem 11 lub nowszym.

działa na Androidzie 10,

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom API 29), zrezygnuj z wydzielonej pamięci i nadal używaj metody dla Androida 9 i starszych wersji, aby wykonać tę operację.

urządzenie z Androidem 9 lub starszym,

Zastosuj to podejście:

  1. Postępując zgodnie ze sprawdzonymi metodami opisanymi w artykule Prośba o uprawnienia aplikacji, poproś o uprawnienie 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ć 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 lub selektora systemowego.

Wyświetlanie własnego interfejsu

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Prośba o uprawnienia aplikacji i poproś o uprawnienie READ_EXTERNAL_STORAGE.
  2. Użyj interfejsu API query(), aby wysłać zapytanie do kolekcji multimediów.
  3. Wyświetl wyniki 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 filtrować typy obrazów, które selektor systemowy prezentuje użytkownikowi do wyboru, możesz użyć setType() lub EXTRA_MIME_TYPES.

Zrób jedno zdjęcie

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

Udostępnianie plików multimedialnych innym aplikacjom

Aby dodawać rekordy bezpośrednio do MediaStore, użyj metody insert(). Więcej informacji znajdziesz w sekcji Dodawanie elementu w przewodniku po pamięci multimediów.

Udostępnianie plików multimedialnych określonej aplikacji

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

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

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

z Androidem 11,

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Prośba o uprawnienia aplikacji i poproś o uprawnienie READ_EXTERNAL_STORAGE.
  2. Uzyskiwać dostęp do plików za pomocą bezpośrednich ścieżek.

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

działa na Androidzie 10,

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom API 29), zrezygnuj z wydzielonej pamięci i nadal używaj metody dla Androida 9 i starszych wersji, aby wykonać tę operację.

urządzenie z Androidem 9 lub starszym,

Zastosuj to podejście:

  1. Postępuj zgodnie ze sprawdzonymi metodami opisanymi w artykule Prośba o uprawnienia aplikacji i poproś o uprawnienie WRITE_EXTERNAL_STORAGE.
  2. Uzyskaj dostęp do plików, korzystając z bezpośrednich ścieżek do nich.

Obsługa plików innych niż multimedialne

W tej sekcji opisano niektóre typowe przypadki użycia związane z obsługą plików innych niż multimedialne oraz ogólne podejście, które może zastosować aplikacja. Tabela poniżej zawiera podsumowanie każdego z tych przypadków użycia oraz linki do sekcji, w których znajdziesz więcej informacji.

Przypadek użycia Podsumowanie
Otwieranie pliku dokumentu Takie samo podejście dotyczy wszystkich wersji Androida.
Zapisywanie plików na dodatkowych woluminach pamięci W przypadku Androida 11 użyj jednego podejścia. W przypadku wcześniejszych wersji Androida użyj innego podejścia.
Przenoszenie istniejących plików ze starszej lokalizacji przechowywania Jeśli to możliwe, przenieś pliki do pamięci wydzielonej. W razie potrzeby zrezygnuj z wydzielonego miejsca na dane na Androidzie 10.
Udostępnianie treści innym aplikacjom Takie samo podejście dotyczy wszystkich wersji Androida.
Zapisywanie w pamięci podręcznej plików innych niż multimedialne Takie samo podejście dotyczy wszystkich wersji Androida.
Eksportowanie plików innych niż multimedialne na urządzenie Jeśli aplikacja korzysta z ograniczonego dostępu do miejsca na dane, użyj jednej metody. Jeśli Twoja aplikacja nie korzysta z ograniczonego dostępu do miejsca na dane, użyj innego podejścia.

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 prezentować 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 dodatkowych woluminach pamięci masowej

Dodatkowe woluminy pamięci masowej obejmują karty SD. Informacje o danym woluminie pamięci masowej możesz uzyskać za pomocą klasy StorageVolume.

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

Android 11

Zastosuj to podejście:

  1. Używaj modelu ograniczonego dostępu do miejsca na dane.
  2. być kierowane na Androida 10 (poziom interfejsu API 29) lub starszego;
  3. Zadeklaruj uprawnienie WRITE_EXTERNAL_STORAGE.
  4. Wykonaj jedną z tych czynności:
    • Dostęp do plików za pomocą interfejsu API MediaStore.
    • Bezpośredni dostęp do ścieżki pliku za pomocą interfejsów API, takich jak File lub fopen().

Starsze wersje

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 zapisać plik.

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

Katalog jest uznawany za starszą lokalizację miejsca na dane, jeśli nie jest katalogiem aplikacji ani publicznym katalogiem udostępnionym. Jeśli aplikacja tworzy lub wykorzystuje pliki w starszej lokalizacji, zalecamy przeniesienie plików aplikacji do lokalizacji dostępnych w ramach wydzielonej pamięci i wprowadzenie niezbędnych zmian w aplikacji, aby mogła ona działać z plikami w wydzielonej pamięci.

Utrzymywanie dostępu do starszej lokalizacji przechowywania na potrzeby migracji danych

Aplikacja musi zachować dostęp do starszej lokalizacji pamięci, aby móc przenieść pliki do lokalizacji dostępnych w ramach pamięci ograniczonej. Metoda, której należy użyć, zależy od docelowego poziomu interfejsu API aplikacji.

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

  2. Nadal rezygnuj z wydzielonego miejsca na dane, aby aplikacja mogła nadal uzyskiwać dostęp do plików w starszej lokalizacji na urządzeniach z Androidem 10.

Jeśli aplikacja jest kierowana na Androida 10

Zrezygnuj z ograniczonego dostępu do miejsca na dane, aby łatwiej zachować działanie aplikacji na różnych wersjach Androida.

Migracja danych aplikacji

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

  1. być kierowane na Androida 10 lub starszego;
  2. Zrezygnuj z ograniczonego dostępu do miejsca na dane, aby aplikacja miała dostęp do plików, które chcesz przenieść.
  3. Wdróż kod, który używa interfejsu API File do przenoszenia plików z ich bieżącej lokalizacji w /sdcard/ do lokalizacji dostępnej w ramach ograniczonego dostępu do miejsca na dane:

    1. Przenieś wszystkie prywatne pliki aplikacji do katalogu zwracanego przez metodę getExternalFilesDir().
    2. Przenieś wszystkie udostępnione pliki inne niż multimedia do podkatalogu katalogu Downloads/ przeznaczonego dla aplikacji.
  4. Usuń starsze katalogi pamięci aplikacji z katalogu /sdcard/.

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

Gdy użytkownicy przeniosą swoje dane, opublikuj kolejną aktualizację aplikacji, w której kierujesz 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 mechanizmu dostarczania treści dla każdej aplikacji, a następnie synchronizowanie danych w miarę dodawania aplikacji do kolekcji.

Zapisywanie w pamięci podręcznej plików innych niż multimedialne

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

Eksportowanie plików niemultimedialnych na urządzenie

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

Obsługa plików aplikacji

Jeśli aplikacja tworzy pliki, do których inne aplikacje nie potrzebują lub nie powinny mieć dostępu, możesz przechowywać te pliki w miejscach przeznaczonych dla aplikacji.

Katalogi w pamięci wewnętrznej

System uniemożliwia innym aplikacjom dostęp do tych lokalizacji, a na Androidzie 10 (API na poziomie 29) i nowszych wersjach te lokalizacje są szyfrowane. Te lokalizacje są dobrym miejscem do przechowywania danych poufnych, 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. Inna aplikacja może uzyskać dostęp do tych katalogów, jeśli ma odpowiednie uprawnienia, ale pliki przechowywane w tych katalogach są przeznaczone do użytku tylko przez Twoją aplikację.

Na Androidzie 4.4 (interfejs API na poziomie 19) lub nowszym 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 aplikacji zostaną usunięte, dlatego nie należy używać tej pamięci do zapisywania niczego, co użytkownik chciałby zachować niezależnie od aplikacji.

Tymczasowa rezygnacja z ograniczonego dostępu do miejsca na dane

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

Rezygnacja z testów

Na Androidzie 10 (API na poziomie 29) i nowszych testy aplikacji są domyślnie uruchamiane w piaskownicy pamięci masowej. To środowisko uniemożliwia aplikacji dostęp do plików spoza katalogu aplikacji i katalogów udostępnianych publicznie.

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

-e no-isolated-storage 1

Ta flaga wpływa na wszystkie zachowania elementu testowania z instrumentacją i na cały wywołany kod testowy. Dlatego gdy używasz tej flagi, nie możesz sprawdzić zgodności aplikacji z ograniczonym dostępem do miejsca na dane. W przypadku danych wyjściowych testu lepiej jest zapisywać je w pamięci masowej o ograniczonym dostępie do miejsca na dane, która jest możliwa do odczytu przez powłokę. Następnie możesz pobrać ten katalog na poziomie aplikacji. Aby określić, z którego katalogu chcesz pobrać dane, wywołaj getExternalMediaDirs().

Rezygnacja w aplikacji produkcyjnej

Jeśli Twoja aplikacja jest kierowana na Androida 10 (poziom interfejsu API 29) lub starszego, możesz tymczasowo zrezygnować z ograniczonego dostępu do miejsca na dane w aplikacji produkcyjnej. Jeśli jednak kierujesz aplikację 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 ograniczonego dostępu do miejsca na dane, możesz wyrazić zgodę na 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 dostępem do miejsca na dane i bez niego.

Dodatkowe materiały

Więcej informacji o miejscu na dane na urządzeniach z Androidem znajdziesz w tych materiałach:

Posty na blogu