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 multimedialnych i obsługa plików niemultimedialnych.
W wielu przypadkach Twoja 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 opisano kilka typowych przypadków użycia dotyczących obsługi plików multimedialnych (wideo, obrazów i dźwięku) 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 |
---|---|
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 ze skanowania ograniczonego zakresem 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 obrazu | 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 ze skanowania ograniczonego zakresem 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:
- Zgodnie ze sprawdzonymi metodami opisanymi w artykule na temat żądania uprawnień aplikacji poproś o uprawnienie
READ_EXTERNAL_STORAGE
. - 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_NAME
i RELATIVE_PATH
.
Dostęp do informacji o lokalizacji z zdjęć
Jeśli Twoja aplikacja korzysta z ograniczonego magazynu, wykonaj czynności opisane w sekcji Informacje o lokalizacji w zdjęciach w przewodniku dotyczącym magazynowania 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ętrznej 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:
- Umożliw użytkownikom wybranie, czy ich pliki multimedialne mają być czytelne dla innych aplikacji, korzystając z miejsca na dane aplikacji lub miejsca na dane współdzielonego.
- Zezwalanie użytkownikom na eksportowanie plików z katalogów aplikacji do bardziej ogólnie dostępnej lokalizacji. Użyj kolekcji obrazów, filmów i plików audio MediaStore, aby eksportować pliki multimedialne do galerii urządzenia.
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:
- Utwórz oczekujący zamiar dla żądania zapisu lub usunięcia w aplikacji za pomocą
MediaStore.createWriteRequest()
lubMediaStore.createTrashRequest()
, a następnie poproś użytkownika o zezwolenie na edycję zbioru plików, wywołując ten zamiar. 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 wersjach.
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.
Android 9 lub starszy
Skorzystaj z tego podejścia:
- Zgodnie ze sprawdzonymi metodami opisanymi w artykule na temat żądania uprawnień aplikacji poproś o uprawnienie
WRITE_EXTERNAL_STORAGE
. - Aby modyfikować lub usuwać 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.
prezentować własny interfejs użytkownika;
Skorzystaj z tego podejścia:
- Zgodnie ze sprawdzonymi metodami opisanymi w artykule na temat żądania uprawnień aplikacji poproś o uprawnienie
READ_EXTERNAL_STORAGE
. - Użyj interfejsu API
query()
, aby wysłać zapytanie do kolekcji multimediów. - 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 system udostępnia użytkownikowi, możesz użyć setType()
lub EXTRA_MIME_TYPES
.
Robienie pojedynczego zdjęcia
Jeśli chcesz wykonać pojedyncze zdjęcie do wykorzystania w aplikacji (np. jako zdjęcie 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ącego 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:
- Zgodnie ze sprawdzonymi metodami opisanymi w artykule na temat żądania uprawnień aplikacji poproś o uprawnienie
READ_EXTERNAL_STORAGE
. - Uzyskiwać 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.
Android 9 lub starszy
Skorzystaj z tego podejścia:
- Zgodnie ze sprawdzonymi metodami opisanymi w artykule na temat żądania uprawnień aplikacji poproś o uprawnienie
WRITE_EXTERNAL_STORAGE
. - Uzyskiwać dostęp do plików za pomocą bezpośrednich ścieżek do plików.
Obsługa plików niemultimediów
W tej sekcji opisaliśmy 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 niemultimedialnych | 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:
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 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:
- Użyj modelu ograniczonego miejsca na dane.
- Kieruj aplikację na Androida 10 (poziom API 29) lub niższego.
- Zadeklaruj uprawnienie
WRITE_EXTERNAL_STORAGE
. - 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
lubfopen()
.
- Dostęp do plików za pomocą interfejsu
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.
Migracja istniejących plików z uprzednio używanego 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.
Zachowanie 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
Ustaw flagę
preserveLegacyExternalStorage
natrue
, 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.Kontynuuj wycofywanie zgody na ograniczoną pamięć, aby Twoja 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 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:
- kierować aplikację na Androida 10 lub starszego;
- Wyłącz ograniczoną pamięć, aby aplikacja miała dostęp do plików, które są potrzebne do przeniesienia.
-
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:- Przenieś wszystkie pliki prywatnych aplikacji do katalogu zwróconego przez metodę
getExternalFilesDir()
. - Przenoś wszystkie udostępnione pliki niemultimedialne do podkatalogu dedykowanego aplikacji w katalogu
Downloads/
.
- Przenieś wszystkie pliki prywatnych aplikacji do katalogu zwróconego przez metodę
- 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ć pliki między sobą, 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.
- Małe pliki lub pliki zawierające informacje poufne: użyj
Context#getCacheDir()
. - Duże pliki lub pliki, które nie zawierają informacji poufnych: użyj
Context#getExternalCacheDir()
.
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 potrzebują dostępu lub do których nie powinny mieć dostępu, możesz je przechowywać w miejscach przechowywania danych dla aplikacji.
Katalogi pamięci wewnętrznej
System uniemożliwia innym aplikacjom dostęp do tych lokalizacji, a na Androidzie 10 (poziom interfejsu API 29) i nowszych te lokalizacje są 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. Inna aplikacja może dostępować do tych katalogów, jeśli ma odpowiednie uprawnienia, ale pliki przechowywane 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 czegokolwiek, co użytkownik chce zachować niezależnie od aplikacji.
Tymczasowe wyłączenie ograniczonego miejsca na dane
Zanim 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. Piaskownica 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 o zasięgu lub 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łany 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 miejscu przeznaczonym na dane aplikacji, które jest czytelne 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 przetestować jej działanie z dostępem do ograniczonego miejsca na dane lub bez niego.
Dodatkowe materiały
Więcej informacji o miejscu na dane w Androidzie znajdziesz w tych materiałach: