Android 14 wprowadza dostęp do wybranych zdjęć, który pozwala użytkownikom przyznawać aplikacjom dostęp do konkretnych obrazów i filmów w bibliotece, zamiast przyznawać dostęp do wszystkich multimediów danego typu.
Ta zmiana jest dostępna tylko wtedy, gdy Twoja aplikacja jest kierowana na Androida 14 (poziom API 34) lub nowszego. Jeśli nie korzystasz jeszcze z selektora zdjęć, zalecamy wdrożenie go w aplikacji, aby zapewnić spójne działanie funkcji wybierania obrazów i filmów, a także zwiększyć prywatność użytkowników bez konieczności uzyskiwania uprawnień do przechowywania.
Jeśli masz własną aplikację do wybierania zdjęć, która korzysta z uprawnień dostępu do pamięci, i chcesz zachować pełną kontrolę nad jej implementacją, zmodyfikuj implementację, aby używała nowego uprawnienia READ_MEDIA_VISUAL_USER_SELECTED
. Jeśli aplikacja nie korzysta z nowych uprawnień, system uruchamia ją w trybie zgodności.
Docelowy pakiet SDK | Zadeklarowane READ_MEDIA_VISUAL_USER_SELECTED |
Dostęp do wybranych zdjęć włączony | Zachowanie związane z UX |
---|---|---|---|
Pakiet SDK 33 | Nie | Nie | Nie dotyczy |
Tak | Tak | Kontrolowane przez aplikację | |
Pakiet SDK 34 | Nie | Tak | Kontrolowane przez system (zachowanie zgodności) |
Tak | Tak | Kontrolowane przez aplikację |
Tworzenie lub dostosowywanie własnego selektora galerii
Tworzenie własnego selektora galerii wymaga zaawansowanych działań deweloperskich i konserwacji, a aplikacja musi poprosić o uprawnienia dostępu do pamięci, aby uzyskać wyraźną zgodę użytkownika. Użytkownicy mogą odmówić udzielenia dostępu do tych mediów. Jeśli Twoja aplikacja działa na urządzeniu z Androidem 14 i jest kierowana na Androida 14 (poziom interfejsu API 34) lub nowszego, możesz ograniczyć dostęp do wybranych mediów. Poniższy obraz przedstawia przykład żądania uprawnień i wybierania multimediów za pomocą nowych opcji.

W tej sekcji pokazujemy zalecany sposób tworzenia własnego selektora galerii za pomocą MediaStore
. Jeśli masz już w swojej aplikacji selektor galerii i chcesz zachować pełną kontrolę, możesz dostosować implementację, korzystając z tych przykładów. Jeśli nie zaktualizujesz implementacji, aby obsługiwać dostęp do wybranych zdjęć, system uruchomi aplikację w trybie zgodności.
Prośba o uprawnienia
Najpierw poproś o odpowiednie uprawnienia dostępu do pamięci w pliku manifestu Androida (w zależności od wersji systemu operacyjnego):
<!-- Devices running Android 12L (API level 32) or lower -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Devices running Android 13 (API level 33) or higher -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- To handle the reselection within the app on devices running Android 14
or higher if your app targets Android 14 (API level 34) or higher. -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
Następnie poproś o odpowiednie uprawnienia w czasie wykonywania, które zależą też od wersji systemu operacyjnego:
// Register ActivityResult handler
val requestPermissions = registerForActivityResult(RequestMultiplePermissions()) { results ->
// Handle permission requests results
// See the permission example in the Android platform samples: https://github.com/android/platform-samples
}
// Permission request logic
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissions.launch(arrayOf(READ_MEDIA_IMAGES, READ_MEDIA_VIDEO))
} else {
requestPermissions.launch(arrayOf(READ_EXTERNAL_STORAGE))
}
Niektóre aplikacje nie potrzebują uprawnień
Od Androida 10 (poziom API 29) aplikacje nie potrzebują już uprawnień do przechowywania, aby dodawać pliki do pamięci współdzielonej. Oznacza to, że aplikacje mogą dodawać obrazy do galerii, nagrywać filmy i zapisywać je w pamięci współdzielonej lub pobierać faktury w formacie PDF bez prośby o zgodę na przechowywanie danych. Jeśli Twoja aplikacja tylko dodaje pliki do współdzielonej pamięci i nie wysyła zapytań o obrazy ani filmy, nie proś o uprawnienia dostępu do pamięci i ustaw maxSdkVersion
interfejsu API 28 w swoim AndroidManifest.xml
:
<!-- No permission is needed to add files to shared storage on Android 10 (API level 29) or higher -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
Obsługa ponownego wyboru multimediów
W Androidzie 14 funkcja dostępu do wybranych zdjęć wymaga od aplikacji obsługi nowego uprawnienia READ_MEDIA_VISUAL_USER_SELECTED
, które umożliwia kontrolowanie ponownego wyboru multimediów. Aplikacja powinna też zaktualizować interfejs, aby umożliwić użytkownikom przyznawanie dostępu do innego zestawu obrazów i filmów. Na ilustracji poniżej pokazano przykład żądania uprawnień i ponownie wybrania multimediów:

Gdy otworzysz okno wyboru, wyświetlą się zdjęcia, filmy lub oba te elementy, w zależności od wymaganych uprawnień. Jeśli na przykład żądasz uprawnienia READ_MEDIA_VIDEO
bez uprawnienia READ_MEDIA_IMAGES
, w interfejsie będą wyświetlane tylko filmy, które użytkownicy mogą wybrać.
// Allow the user to select only videos
requestPermissions.launch(arrayOf(READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))
Możesz sprawdzić, czy Twoja aplikacja ma pełny, częściowy czy odmówiony dostęp do biblioteki zdjęć na urządzeniu i odpowiednio zaktualizować interfejs. Proś o te uprawnienia, gdy aplikacja potrzebuje dostępu do pamięci, a nie podczas uruchamiania. Pamiętaj, że uprawnienia dostępu można zmienić między wywołaniami zwrotnymi cyklu życia aplikacji onStart
i onResume
, ponieważ użytkownik może zmienić dostęp w ustawieniach bez zamykania aplikacji.
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
(
ContextCompat.checkSelfPermission(context, READ_MEDIA_IMAGES) == PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(context, READ_MEDIA_VIDEO) == PERMISSION_GRANTED
)
) {
// Full access on Android 13 (API level 33) or higher
} else if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE &&
ContextCompat.checkSelfPermission(context, READ_MEDIA_VISUAL_USER_SELECTED) == PERMISSION_GRANTED
) {
// Partial access on Android 14 (API level 34) or higher
} else if (ContextCompat.checkSelfPermission(context, READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED) {
// Full access up to Android 12 (API level 32)
} else {
// Access denied
}
Wysyłanie zapytania do biblioteki urządzeń
Po sprawdzeniu, czy masz dostęp do odpowiednich uprawnień do przechowywania danych, możesz korzystać z funkcji MediaStore
, aby wysyłać zapytania do biblioteki urządzenia (to samo podejście działa niezależnie od tego, czy przyznany dostęp jest częściowy czy pełny):
data class Media(
val uri: Uri,
val name: String,
val size: Long,
val mimeType: String,
)
// Run the querying logic in a coroutine outside of the main thread to keep the app responsive.
// Keep in mind that this code snippet is querying only images of the shared storage.
suspend fun getImages(contentResolver: ContentResolver): List<Media> = withContext(Dispatchers.IO) {
val projection = arrayOf(
Images.Media._ID,
Images.Media.DISPLAY_NAME,
Images.Media.SIZE,
Images.Media.MIME_TYPE,
)
val collectionUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Query all the device storage volumes instead of the primary only
Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
Images.Media.EXTERNAL_CONTENT_URI
}
val images = mutableListOf<Media>()
contentResolver.query(
collectionUri,
projection,
null,
null,
"${Images.Media.DATE_ADDED} DESC"
)?.use { cursor ->
val idColumn = cursor.getColumnIndexOrThrow(Images.Media._ID)
val displayNameColumn = cursor.getColumnIndexOrThrow(Images.Media.DISPLAY_NAME)
val sizeColumn = cursor.getColumnIndexOrThrow(Images.Media.SIZE)
val mimeTypeColumn = cursor.getColumnIndexOrThrow(Images.Media.MIME_TYPE)
while (cursor.moveToNext()) {
val uri = ContentUris.withAppendedId(collectionUri, cursor.getLong(idColumn))
val name = cursor.getString(displayNameColumn)
val size = cursor.getLong(sizeColumn)
val mimeType = cursor.getString(mimeTypeColumn)
val image = Media(uri, name, size, mimeType)
images.add(image)
}
}
return@withContext images
}
Ten fragment kodu został uproszczony i pokazuje, jak korzystać z narzędzia MediaStore
.
W wersji aplikacji przeznaczonej do wdrożenia użyj podziału na strony, np. za pomocą biblioteki Paging, aby zapewnić dobrą wydajność.
Zapytanie o ostatni wybór
Aplikacje na Androidzie w wersji 15 lub nowszej oraz na Androidzie 14 z aktualizacjami systemowymi Google Play mogą zapytać o ostatni wybór obrazów i filmów dokonany przez użytkownika z częściowym dostępem. Aby to zrobić, muszą mieć włączoną opcję QUERY_ARG_LATEST_SELECTION_ONLY
:
if (getExtensionVersion(Build.VERSION_CODES.U) >= 12) {
val queryArgs = bundleOf(
QUERY_ARG_SQL_SORT_ORDER to "${Images.Media.DATE_ADDED} DESC"
QUERY_ARG_LATEST_SELECTION_ONLY to true
)
contentResolver.query(collectionUri, projection, queryArgs, null)
}
Dostęp do zdjęć i filmów jest zachowany podczas aktualizacji urządzenia
Jeśli Twoja aplikacja jest zainstalowana na urządzeniu, którego wersja Androida zostanie uaktualniona z wcześniejszej wersji do Androida 14, system zachowa pełny dostęp do zdjęć i filmów użytkownika, a także automatycznie przyzna Twojej aplikacji niektóre uprawnienia. Dokładne działanie zależy od zestawu uprawnień, które aplikacja otrzymała przed aktualizacją do Androida 14.
Uprawnienia w Androidzie 13
Rozważ tę sytuację:
- Aplikacja jest zainstalowana na urządzeniu z Androidem 13.
- Użytkownik przyznał aplikacji uprawnienia
READ_MEDIA_IMAGES
iREAD_MEDIA_VIDEO
. - Następnie urządzenie zostanie zaktualizowane do Androida w wersji 14, gdy aplikacja jest nadal zainstalowana.
- Twoja aplikacja jest kierowana na Androida 14 (poziom API 34) lub nowszego.
W takim przypadku aplikacja nadal będzie miała pełny dostęp do zdjęć i filmów użytkownika.
System automatycznie zachowuje też uprawnienia READ_MEDIA_IMAGES
i READ_MEDIA_VIDEO
przyznawane Twojej aplikacji.
Uprawnienia Androida 12 i starszych
Rozważ tę sytuację:
- Aplikacja jest zainstalowana na urządzeniu z Androidem 13.
- Użytkownik przyznał aplikacji uprawnienia
READ_EXTERNAL_STORAGE
lubWRITE_EXTERNAL_STORAGE
. - Następnie urządzenie zostanie zaktualizowane do Androida w wersji 14, gdy aplikacja jest nadal zainstalowana.
- Twoja aplikacja jest kierowana na Androida 14 (poziom API 34) lub nowszego.
W takim przypadku aplikacja nadal będzie miała pełny dostęp do zdjęć i filmów użytkownika.
System automatycznie przyznaje też aplikacji uprawnienia READ_MEDIA_IMAGES
i READ_MEDIA_VIDEO
.
Sprawdzone metody
W tej sekcji znajdziesz kilka sprawdzonych metod korzystania z uprawnienia READ_MEDIA_VISUAL_USER_SELECTED
. Więcej informacji znajdziesz w artykule Sprawdzone metody dotyczące uprawnień.
Nie zapisuj na stałe stanu uprawnień
Nie zapisuj stanu uprawnień na stałe, np. SharedPreferences
czy DataStore
. Zapisany stan może nie być zsynchronizowany z rzeczywistym stanem. Stan uprawnień może się zmienić po zresetowaniu uprawnień, hibernacji aplikacji, zmianie ustawień aplikacji przez użytkownika lub gdy aplikacja przechodzi do trybu uśpienia. Zamiast tego sprawdź uprawnienia dostępu do pamięci za pomocą ContextCompat.checkSelfPermission()
.
Nie zakładaj, że masz pełny dostęp do zdjęć i filmów
Ze względu na zmiany wprowadzone w Androidzie 14 Twoja aplikacja może mieć tylko częściowy dostęp do biblioteki zdjęć na urządzeniu. Jeśli aplikacja przechowuje w pamięci podręcznej dane MediaStore
, gdy jest zapytanie wysyłane za pomocą ContentResolver
, pamięć podręczna może nie być aktualna.
- Zawsze wysyłaj zapytanie do
MediaStore
, używając parametruContentResolver
, zamiast polegać na przechowywanej pamięci podręcznej. - przechowywać wyniki w pamięci, gdy aplikacja działa na pierwszym planie.
- Odświeżaj wyniki, gdy aplikacja przechodzi przez cykl życia
onResume
, ponieważ użytkownik może w ustawieniach uprawnień przełączyć się z pełnego na częściowy dostęp.
Traktowanie dostępu do identyfikatora URI jako tymczasowego
Jeśli użytkownik w oknie uprawnień systemowych wybierze Wybierz zdjęcia i filmy, dostęp aplikacji do wybranych zdjęć i filmów wygaśnie.
Aplikacja powinna zawsze obsługiwać przypadek braku dostępu do Uri
, niezależnie od autorytetu.
Filtrowanie dostępnych typów multimediów według uprawnień
Okno wyboru zależy od żądanego typu uprawnienia:
- Przesyłanie tylko
READ_MEDIA_IMAGES
powoduje wyświetlenie tylko obrazów, które można wybrać. - Wybranie tylko opcji
READ_MEDIA_VIDEO
powoduje, że można wybrać tylko film. - Żądanie
READ_MEDIA_IMAGES
iREAD_MEDIA_VIDEO
pokazuje całą bibliotekę zdjęć do wyboru.
W zależności od przypadków użycia aplikacji należy poprosić o odpowiednie uprawnienia, aby nie pogarszać wrażeń użytkowników. Jeśli funkcja oczekuje,
że tylko filmy zostaną wybrane, poproś o to jedynie READ_MEDIA_VIDEO
.
Poproś o uprawnienia w jednej operacji
Aby zapobiec wyświetlaniu użytkownikom wielu okien dialogowych systemu w czasie działania, poproś o uprawnienia READ_MEDIA_VISUAL_USER_SELECTED
, ACCESS_MEDIA_LOCATION
oraz „Czytaj media” (READ_MEDIA_IMAGES
, READ_MEDIA_VIDEO
lub oba te uprawnienia) w ramach jednej operacji.
Zezwalaj użytkownikom na zarządzanie swoim wyborem
Gdy użytkownik wybierze tryb częściowego dostępu, aplikacja nie powinna zakładać, że biblioteka zdjęć na urządzeniu jest pusta. Powinna umożliwić użytkownikowi przyznanie dostępu do większej liczby plików.
Użytkownik może zmienić pełny dostęp na częściowy w ustawieniach uprawnień, nie przyznając dostępu do niektórych plików multimediów.
Tryb zgodności
Jeśli korzystasz z własnego selektora galerii za pomocą uprawnień do przechowywania, ale nie dostosowujesz aplikacji do nowego uprawnienia READ_MEDIA_VISUAL_USER_SELECTED
, system uruchomi ją w trybie zgodności za każdym razem, gdy użytkownik będzie musiał wybrać multimedia.
Zachowanie podczas początkowego wyboru multimediów
Jeśli podczas początkowego wyboru użytkownik wybierze opcję „Wybierz zdjęcia i filmy” (zobacz ilustrację 1), w trakcie sesji aplikacji zostaną przyznane uprawnienia READ_MEDIA_IMAGES
i READ_MEDIA_VIDEO
, czyli tymczasowe i tymczasowy dostęp do zdjęć i filmów wybranych przez użytkownika. Gdy aplikacja przejdzie do działania w tle lub użytkownik ją zamknie, system ostatecznie odmówi udzielenia tych uprawnień. Działania te są takie same jak w przypadku innych jednorazowych uprawnień.
Działanie podczas ponownego wyboru multimediów
Jeśli Twoja aplikacja później będzie potrzebować dostępu do dodatkowych zdjęć i filmów, musisz ręcznie poprosić o uprawnienie READ_MEDIA_IMAGES
lub READ_MEDIA_VIDEO
. System postępuje tak samo jak w przypadku początkowego żądania uprawnień, prosząc użytkowników o wybranie zdjęć i filmów (patrz rycina 2).
Jeśli aplikacja jest zgodna ze sprawdzonymi metodami dotyczącymi uprawnień, ta zmiana nie powinna zepsuć aplikacji. Zwłaszcza wtedy, gdy aplikacja nie zakłada, że dostęp za pomocą identyfikatora URI jest zachowywany, nie przechowuje stanu uprawnień systemu ani nie odświeża zestawu wyświetlanych obrazów po zmianie uprawnień. W zależności od zastosowania aplikacji takie działanie może jednak nie być optymalne. Aby zapewnić użytkownikom jak najlepsze wrażenia, zalecamy wdrożenie selektora zdjęć lub dostosowanie selektora galerii aplikacji, aby obsługiwać to zachowanie bezpośrednio za pomocą uprawnienia READ_MEDIA_VISUAL_USER_SELECTED
.