Przyznawanie częściowego dostępu do zdjęć i filmów

Android 14 wprowadza dostęp do wybranych zdjęć, który umożliwia użytkownikom przyznawanie aplikacji dostępu do określonych obrazów i filmów w bibliotece, zamiast przyznawać do wszystkich multimediów danego typu.

Ta zmiana zostanie wprowadzona tylko wtedy, gdy aplikacja jest kierowana na Androida 14 (poziom interfejsu API 34) lub wyżej. Jeśli nie korzystasz jeszcze z selektora zdjęć, zalecamy wdrożenie go w Twojej aplikacji, aby umożliwić Ci spójny wybór obrazów i filmów która zwiększa prywatność użytkowników bez konieczności wysyłania próśb o dostęp do miejsca na dane. uprawnień.

Jeśli masz własny selektor galerii za pomocą uprawnień do przechowywania danych i konieczne jest zachować pełną kontrolę nad implementacją, dostosować ją aby korzystać z nowych uprawnień READ_MEDIA_VISUAL_USER_SELECTED. Jeśli Twoja aplikacja nie będzie używać nowych uprawnień, system uruchomi aplikację ze zgodnością .

Docelowy pakiet SDK Zadeklarowano READ_MEDIA_VISUAL_USER_SELECTED Dostęp do wybranych zdjęć włączony Zachowanie UX
Pakiet SDK 33 Nie Nie Nie dotyczy
Tak Tak Kontrolowane przez aplikację
Pakiet SDK 34 Nie Tak Kontrolowane przez system (działanie zgodne)
Tak Tak Kontrolowane przez aplikację

Tworzenie własnego selektora galerii wymaga pracochłonnego rozwijania i utrzymywania, , a aplikacja musi poprosić o zgodę na przechowywanie danych, aby uzyskać wyraźną zgodę użytkownika. Użytkownicy mogą odrzucać te prośby. Jeśli aplikacja działa na urządzeniu z Android 14 i Twoja aplikacja jest kierowana na Androida 14 (poziom interfejsu API 34) lub nowszego, limit dostęp do wybranych multimediów. Ilustracja poniżej przedstawia przykład żądania i wyborze multimediów za pomocą nowych opcji.

Format
Rysunek 1. Nowe okno pozwala użytkownikowi wybrać zdjęcia i filmy, które użytkownicy chcą udostępnić aplikacji, do standardowych opcji przyznawania pełnego dostępu lub odmowy dostępu.

W tej sekcji przedstawiamy zalecane metody tworzenia własnej galerii za pomocą funkcji MediaStore. Jeśli masz już selektor galerii dla swojej aplikacji i chcesz zachować pełną kontrolę, możesz wykorzystać te przykłady, aby dostosować implementacji. Jeśli nie zaktualizujesz implementacji, aby obsługiwała wybrane dostęp do Zdjęć, system uruchamia Twoją aplikację w trybie zgodności.

Poproś 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 działania aplikacji w zależności 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 wymagają uprawnień

Od Androida 10 (poziom interfejsu API 29) aplikacje nie muszą już mieć uprawnień do dodawania pamięci pliki w pamięci współdzielonej. Oznacza to, że aplikacje mogą dodawać obrazy do galerii, nagrywać filmy i zapisywać je w pamięci współdzielonej albo pobierać faktury w formacie PDF bez i prosić o pozwolenie na przechowywanie danych. Jeśli Twoja aplikacja dodaje pliki tylko do i nie wysyła zapytań o zdjęcia ani filmy, nie wysyłaj próśb o miejsce na dane. uprawnień i ustaw maxSdkVersion interfejsu API 28 w 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" />

Ponowne wybieranie multimediów

Dzięki funkcji dostępu do wybranych zdjęć na Androidzie 14 aplikacja powinna przyjąć: nowe uprawnienie READ_MEDIA_VISUAL_USER_SELECTED do sterowania multimediami ponownego wyboru aplikacji i zaktualizuj jej interfejs, aby umożliwić użytkownikom przyznawanie jej dostępu. z innym zestawem zdjęć i filmów. Poniższa grafika przedstawia przykładową prośba o uprawnienia i ponowne wybranie multimediów:

Format
Rysunek 2. Nowe okno umożliwia też użytkownikowi ponowne wybranie zdjęcia i filmy, które użytkownicy chcą udostępnić Twojej aplikacji.
.

Po otwarciu okna wyboru wyświetlane są zdjęcia, filmy lub oba te elementy w zależności od tego, o wymaganych uprawnieniach. Na przykład jeśli prosisz o Uprawnienia READ_MEDIA_VIDEO bez uprawnienia READ_MEDIA_IMAGES (tylko) filmów pojawią się w interfejsie, aby użytkownicy mogli wybierać pliki.

// Allow the user to select only videos
requestPermissions.launch(arrayOf(READ_MEDIA_VIDEO, READ_MEDIA_VISUAL_USER_SELECTED))

Możesz sprawdzić, czy aplikacja ma pełny, częściowy lub zabroniony dostęp i odpowiednio zaktualizuj interfejs. Poproś o te uprawnienia gdy aplikacja potrzebuje dostępu do pamięci, a nie podczas uruchamiania. Pamiętaj, że parametr uprawnienia można zmieniać między aplikacją onStart a onResume wywołań zwrotnych cyklu życia, ponieważ użytkownik może zmienić dostęp w ustawieniach bez zamknij aplikację.

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ń

Gdy potwierdzisz, że masz odpowiednie uprawnienia dostępu do pamięci, możesz: użyj polecenia MediaStore, aby przesłać zapytanie do biblioteki urządzenia (to samo podejście działa 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 aplikacji gotowej do wdrożenia wersji produkcyjnej użyj podziału na strony, np. Paging , która zapewnia wysoką wydajność.

Zapytanie dotyczące ostatniego wyboru

Aplikacje na urządzeniach z Androidem 15 lub nowszym oraz Androidem 14 i aktualizacjami systemowymi Google Play mogą zapytanie dotyczące ostatniego wyboru obrazów i filmów zrobionych przez użytkownika w przypadku częściowego dostępu po włączeniu 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)
}

Po uaktualnieniu urządzenia dostęp do zdjęć i filmów zostanie zachowany

W przypadkach, gdy aplikacja znajduje się na urządzeniu z wcześniejszym Androidem. na Androida 14, system zachowa pełny dostęp do zdjęć filmów i automatycznie przyzna niektóre uprawnienia aplikacji. Dokładny zależy od zestawu uprawnień przyznanych aplikacji przed urządzenie zostanie zaktualizowane do Androida 14.

Uprawnienia Androida 13

Przyjrzyjmy się takiej sytuacji:

  1. Aplikacja jest zainstalowana na urządzeniu z Androidem 13.
  2. Użytkownik przyznał uprawnienie READ_MEDIA_IMAGES oraz uprawnienia READ_MEDIA_VIDEO Twojej aplikacji.
  3. Gdy aplikacja będzie nadal zainstalowana, urządzenie zostanie zaktualizowane do Androida 14.
  4. Twoja aplikacja zaczyna być kierowana na Androida 14 (poziom interfejsu 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 zachowuje też uprawnienia READ_MEDIA_IMAGES i READ_MEDIA_VIDEO automatycznie przyznawane aplikacji.

Uprawnienia Androida 12 i starszych

Przyjrzyjmy się takiej sytuacji:

  1. Aplikacja jest zainstalowana na urządzeniu z Androidem 13.
  2. Użytkownik przyznał uprawnienie READ_EXTERNAL_STORAGE lub uprawnienia WRITE_EXTERNAL_STORAGE Twojej aplikacji.
  3. Gdy aplikacja będzie nadal zainstalowana, urządzenie zostanie zaktualizowane do Androida 14.
  4. Twoja aplikacja zaczyna być kierowana na Androida 14 (poziom interfejsu 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 przyznaje też uprawnienia READ_MEDIA_IMAGES oraz READ_MEDIA_VIDEO automatycznie.

Sprawdzone metody

Ta sekcja zawiera kilka sprawdzonych metod korzystania z Uprawnienie READ_MEDIA_VISUAL_USER_SELECTED. Aby dowiedzieć się więcej, zapoznaj się z nasze sprawdzone metody uzyskiwania zgody.

Nie zapisuj na stałe stanu uprawnień

Nie zapisuj stanu uprawnień na stałe, w tym: SharedPreferences lub DataStore. Stan zapisanego stanu może nie być zsynchronizowany z usługą do rzeczywistego stanu. Stan uprawnień może się zmienić po zresetowaniu uprawnień, hibernacji aplikacji, zainicjowanej przez użytkownika zmiany w ustawieniach aplikacji lub gdy aplikacja działa w tle. Zamiast tego sprawdź uprawnienia dostępu do pamięci za pomocą ContextCompat.checkSelfPermission()

Nie zakładaj pełnego dostępu do zdjęć i filmów.

Ze względu na zmiany wprowadzone w Androidzie 14 Twoja aplikacja może mieć tylko częściowe dostępu do biblioteki zdjęć na urządzeniu. Jeśli aplikacja zapisuje w pamięci podręcznej dane MediaStore w przypadku wysyłania zapytania z użyciem ContentResolver, pamięć podręczna może być nieaktualna.

  • Zawsze wysyłaj zapytania do usługi MediaStore za pomocą parametru ContentResolver, zamiast polegać na pamięci podręcznej.
  • Zachowuj wyniki w pamięci, gdy aplikacja działa na pierwszym planie.
  • Odśwież wyniki, gdy aplikacja przejdzie przez cykl życia aplikacji onResume ponieważ użytkownik może przejść z pełnego dostępu na częściowy dostęp za pomocą ustawienia uprawnień.

Traktuj dostęp do identyfikatora URI jako tymczasowy

Jeśli użytkownik wybierze Wybierz zdjęcia i filmy w uprawnieniach systemowych dostęp aplikacji do wybranych zdjęć i filmów po pewnym czasie wygaśnie. Aplikacja powinna zawsze reagować na brak dostępu do żadnego z Uri, nie mają znaczenie dla ich kompetencji.

Filtruj do wyboru typy mediów według uprawnień

Okno wyboru jest wrażliwe na żądany typ uprawnień:

  • Żądanie tylko elementu READ_MEDIA_IMAGES powoduje wyświetlenie tylko obrazów do wyboru.
  • Żądanie tylko READ_MEDIA_VIDEO powoduje wyświetlenie tylko filmu, który można wybrać.
  • Żądanie READ_MEDIA_IMAGES i READ_MEDIA_VIDEO powoduje wyświetlenie całego zbioru danych biblioteki zdjęć.

Na podstawie przypadków użycia Twojej aplikacji upewnij się, że wysyłasz prośbę o odpowiednią uprawnienia, by zadbać o wygodę użytkowników. Jeśli funkcja oczekuje tylko filmy, które chcesz wybrać, pamiętaj, aby poprosić o ich tylko READ_MEDIA_VIDEO.

Poproś o uprawnienia w jednej operacji

Aby uniemożliwić użytkownikom wyświetlanie kilku okien dialogowych systemu wykonawczego, poproś o READ_MEDIA_VISUAL_USER_SELECTED, ACCESS_MEDIA_LOCATION i funkcja „Odczyt multimediów” uprawnienia (READ_MEDIA_IMAGES, READ_MEDIA_VIDEO lub oba) w jednym .

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ęć urządzenia jest pusta i użytkownik powinien mieć możliwość przyznania większej liczby .

Użytkownik może przejść z pełnego dostępu na częściowy dostęp za pomocą ustawień uprawnień bez przyznawania dostępu do niektórych wizualnych plików multimedialnych.

Tryb zgodności

Jeśli korzystasz z własnego selektora galerii za pomocą uprawnień do przechowywania danych, ale nie używasz dostosował(a) Twoją aplikację, aby używała nowej wersji READ_MEDIA_VISUAL_USER_SELECTED system uruchamia aplikację w trybie zgodności zawsze, gdy użytkownik musi 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), uprawnienia READ_MEDIA_IMAGES i READ_MEDIA_VIDEO są przyznanych podczas sesji aplikacji, przyznając tymczasowe uprawnienia tymczasowy dostęp do zdjęć i filmów wybranych przez użytkownika. Po przeniesieniu aplikacji do w tle lub po wyłączeniu aplikacji przez użytkownika, odmawia przyznania tych uprawnień. Działa to tak samo jak w przypadku innych jednorazowych uprawnień.

Zachowanie podczas ponownego wyboru mediów

Jeśli aplikacja będzie potrzebować później dostępu do dodatkowych zdjęć i filmów, musi ręcznie poprosić o uprawnienie READ_MEDIA_IMAGES lub READ_MEDIA_VIDEO ponownie. Procedura jest taka sama jak w przypadku prośbę o przyznanie uprawnień, zawierającą prośbę o wybranie zdjęć i filmów (zobacz ilustrację 2).

Jeśli Twoja aplikacja jest zgodna ze sprawdzonymi metodami dotyczącymi uprawnień, ta zmiana nie powinna zepsuć Twoją aplikację. Jest to szczególnie istotne, jeśli aplikacja nie zakłada, że identyfikator URI dostęp jest zachowywany, zapisuje stan uprawnień systemu lub odświeża zestaw wyświetla obrazy po zmianie uprawnień. Takie działanie może jednak nie które będą idealnie dobrane do konkretnego przypadku użycia. Chcemy zapewnić Ci jak najlepsze wrażenia użytkowników, zalecamy zaimplementowanie selektora zdjęć lub dostosowanie z selektorem galerii aplikacji, aby obsługiwał to zachowanie bezpośrednio za pomocą Uprawnienia: READ_MEDIA_VISUAL_USER_SELECTED.