Memberikan akses sebagian ke foto dan video

Android 14 memperkenalkan Akses Foto yang Dipilih, yang memungkinkan pengguna memberi aplikasi akses ke gambar dan video tertentu di galeri foto mereka, bukan memberikan akses ke semua media dari jenis tertentu.

Perubahan ini hanya diaktifkan jika aplikasi Anda menargetkan Android 14 (level API 34) atau yang lebih baru. Jika Anda belum menggunakan pemilih foto, sebaiknya terapkan di aplikasi Anda untuk memberikan pengalaman yang konsisten dalam memilih gambar dan video yang juga meningkatkan privasi pengguna tanpa harus meminta izin penyimpanan apa pun.

Jika Anda mengelola pemilih galeri Anda sendiri menggunakan izin penyimpanan dan perlu mempertahankan kontrol penuh atas implementasi Anda, sesuaikan implementasi Anda untuk menggunakan izin READ_MEDIA_VISUAL_USER_SELECTED baru. Jika aplikasi Anda tidak menggunakan izin baru, sistem akan menjalankan aplikasi Anda dalam mode kompatibilitas.

SDK Target READ_MEDIA_VISUAL_USER_SELECTED dideklarasikan Akses Foto yang Dipilih diaktifkan Perilaku UX
SDK 33 Tidak Tidak T/A
Ya Ya Dikontrol oleh aplikasi
SDK 34 Tidak Ya Dikontrol oleh sistem (perilaku kompatibilitas)
Ya Ya Dikontrol oleh aplikasi

Membuat pemilih galeri Anda sendiri memerlukan pengembangan dan pemeliharaan yang ekstensif, dan aplikasi Anda perlu meminta izin penyimpanan untuk mendapatkan izin pengguna yang eksplisit. Pengguna dapat menolak permintaan ini atau, jika aplikasi Anda berjalan di perangkat dengan Android 14 dan aplikasi Anda menargetkan Android 14 (level API 34) atau yang lebih tinggi, batasi akses ke media yang dipilih. Gambar berikut menunjukkan contoh permintaan izin dan memilih media menggunakan opsi baru.

Ekstensi .
Gambar 1. Dialog baru ini memungkinkan pengguna memilih foto dan video tertentu yang ingin mereka sediakan untuk aplikasi Anda, selain opsi biasa untuk memberikan akses penuh atau menolak semua akses.

Bagian ini menunjukkan pendekatan yang direkomendasikan untuk membuat pemilih galeri Anda sendiri menggunakan MediaStore. Jika sudah mengelola pemilih galeri untuk aplikasi dan perlu mempertahankan kontrol penuh, Anda dapat menggunakan contoh ini untuk menyesuaikan penerapan. Jika Anda tidak mengupdate penerapan untuk menangani Akses Foto yang Dipilih, sistem akan menjalankan aplikasi Anda dalam mode kompatibilitas.

Meminta izin

Pertama, minta izin penyimpanan yang benar dalam manifes Android, bergantung pada versi OS:

<!-- 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" />

Kemudian, minta izin runtime yang benar, yang juga bergantung pada versi OS:

// 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))
}

Beberapa aplikasi tidak memerlukan izin

Mulai Android 10 (level API 29), aplikasi tidak lagi memerlukan izin penyimpanan untuk menambahkan file ke penyimpanan bersama. Artinya, aplikasi dapat menambahkan gambar ke galeri, merekam video dan menyimpannya ke penyimpanan bersama, atau mendownload invoice PDF tanpa harus meminta izin penyimpanan. Jika aplikasi Anda hanya menambahkan file ke penyimpanan bersama dan tidak membuat kueri gambar atau video, Anda harus berhenti meminta izin penyimpanan dan menetapkan maxSdkVersion API 28 di 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" />

Menangani pemilihan ulang media

Dengan fitur Akses Foto yang Dipilih di Android 14, aplikasi Anda harus mengadopsi izin READ_MEDIA_VISUAL_USER_SELECTED baru untuk mengontrol pemilihan ulang media, dan mengupdate antarmuka aplikasi agar pengguna dapat memberikan akses ke kumpulan gambar dan video yang berbeda ke aplikasi Anda. Gambar berikut menunjukkan contoh permintaan izin dan pemilihan ulang media:

Ekstensi .
Gambar 2. Dialog baru ini juga memungkinkan pengguna memilih ulang foto dan video yang ingin mereka sediakan untuk aplikasi Anda.

Saat membuka dialog pilihan, foto, video, atau keduanya akan ditampilkan bergantung pada izin yang diminta. Misalnya, jika Anda meminta izin READ_MEDIA_VIDEO tanpa izin READ_MEDIA_IMAGES, hanya video yang akan muncul di UI agar pengguna dapat memilih file.

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

Anda dapat memeriksa apakah aplikasi memiliki akses penuh, sebagian, atau ditolak ke galeri foto perangkat dan mengupdate antarmuka. Minta izin ini saat aplikasi memerlukan akses penyimpanan, bukan saat dimulai. Perhatikan bahwa pemberian izin dapat diubah di antara callback siklus proses aplikasi onStart dan onResume, karena pengguna dapat mengubah akses di setelan tanpa menutup aplikasi Anda.

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
}

Membuat kueri library perangkat

Setelah memverifikasi bahwa Anda memiliki akses ke izin penyimpanan yang tepat, Anda dapat berinteraksi dengan MediaStore untuk membuat kueri library perangkat (pendekatan yang sama berlaku baik akses yang diberikan bersifat sebagian maupun penuh):

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
}

Cuplikan kode ini disederhanakan untuk menggambarkan cara berinteraksi dengan MediaStore. Dalam aplikasi yang siap produksi, gunakan penomoran halaman dengan sesuatu seperti library Paging untuk membantu memastikan performa yang baik.

Buat kueri pilihan terakhir

Aplikasi di Android 15+ dan Android 14 dengan dukungan update sistem Google Play dapat mengkueri pilihan terakhir gambar dan video yang dibuat oleh pengguna pada akses parsial dengan mengaktifkan 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)
}

Akses foto dan video tetap dipertahankan saat perangkat diupgrade

Jika aplikasi Anda berada di perangkat yang diupgrade dari versi Android sebelumnya ke Android 14, sistem akan memiliki akses penuh ke foto dan video pengguna, serta memberikan beberapa izin ke aplikasi Anda secara otomatis. Perilaku yang tepat bergantung pada sekumpulan izin yang diberikan ke aplikasi Anda sebelum perangkat diupgrade ke Android 14.

Izin dari Android 13

Pertimbangkan situasi berikut:

  1. Aplikasi Anda diinstal di perangkat yang menjalankan Android 13.
  2. Pengguna telah memberikan izin READ_MEDIA_IMAGES dan izin READ_MEDIA_VIDEO ke aplikasi Anda.
  3. Perangkat kemudian diupgrade ke Android 14 saat aplikasi Anda masih terinstal.
  4. Aplikasi Anda mulai menargetkan Android 14 (API level 34) atau yang lebih tinggi.

Dalam hal ini, aplikasi Anda masih memiliki akses penuh ke foto dan video pengguna. Sistem juga mempertahankan izin READ_MEDIA_IMAGES dan READ_MEDIA_VIDEO yang diberikan ke aplikasi Anda secara otomatis.

Izin dari Android 12 dan yang lebih rendah

Pertimbangkan situasi berikut:

  1. Aplikasi Anda diinstal di perangkat yang menjalankan Android 13.
  2. Pengguna telah memberikan izin READ_EXTERNAL_STORAGE atau izin WRITE_EXTERNAL_STORAGE ke aplikasi Anda.
  3. Perangkat kemudian diupgrade ke Android 14 saat aplikasi Anda masih terinstal.
  4. Aplikasi Anda mulai menargetkan Android 14 (API level 34) atau yang lebih tinggi.

Dalam hal ini, aplikasi Anda masih memiliki akses penuh ke foto dan video pengguna. Sistem juga memberikan izin READ_MEDIA_IMAGES dan izin READ_MEDIA_VIDEO ke aplikasi Anda secara otomatis.

Praktik terbaik

Bagian ini berisi beberapa praktik terbaik untuk menggunakan izin READ_MEDIA_VISUAL_USER_SELECTED. Untuk informasi selengkapnya, lihat praktik terbaik izin kami.

Jangan simpan status izin secara permanen

Jangan simpan status izin secara permanen, termasuk SharedPreferences atau DataStore. Status yang disimpan mungkin tidak disinkronkan dengan status sebenarnya. Status izin dapat berubah setelah reset izin, hibernasi aplikasi, perubahan yang dimulai pengguna di setelan aplikasi Anda, atau ketika aplikasi beralih ke latar belakang. Sebagai gantinya, periksa izin penyimpanan menggunakan ContextCompat.checkSelfPermission().

Jangan berasumsi memiliki akses penuh ke foto dan video

Berdasarkan perubahan yang diperkenalkan di Android 14, aplikasi Anda mungkin hanya memiliki akses sebagian ke galeri foto perangkat. Jika aplikasi meng-cache data MediaStore saat dikueri menggunakan ContentResolver, cache tersebut mungkin tidak diperbarui.

  • Selalu buat kueri MediaStore menggunakan ContentResolver, bukan mengandalkan cache yang disimpan.
  • Simpan hasilnya di memori saat aplikasi Anda berada di latar depan.
  • Muat ulang hasil saat aplikasi Anda melalui siklus proses aplikasi onResume karena pengguna mungkin beralih dari akses penuh ke akses sebagian melalui setelan izin.

Perlakukan akses URI sebagai sementara

Jika pengguna memilih Pilih foto dan video dalam dialog izin sistem, akses aplikasi Anda ke foto dan video yang dipilih tidak akan berlaku lagi pada akhirnya. Aplikasi Anda harus selalu menangani kasus ketika tidak memiliki akses ke Uri apa pun, terlepas dari otoritasnya.

Memfilter jenis media yang dapat dipilih menurut izin

Dialog pilihan sensitif dengan jenis izin yang diminta:

  • Meminta hanya READ_MEDIA_IMAGES hanya akan menampilkan gambar yang dapat dipilih.
  • Meminta hanya READ_MEDIA_VIDEO akan menampilkan hanya video yang dapat dipilih.
  • Meminta READ_MEDIA_IMAGES dan READ_MEDIA_VIDEO akan menampilkan seluruh galeri foto yang dapat dipilih.

Berdasarkan kasus penggunaan aplikasi, Anda harus memastikan untuk meminta izin yang tepat untuk menghindari pengalaman pengguna yang buruk. Jika fitur hanya mengharapkan video dipilih, pastikan untuk hanya meminta READ_MEDIA_VIDEO.

Meminta izin dalam satu operasi

Untuk mencegah pengguna melihat beberapa kotak dialog runtime sistem, minta izin READ_MEDIA_VISUAL_USER_SELECTED, ACCESS_MEDIA_LOCATION, dan "baca media" (READ_MEDIA_IMAGES, READ_MEDIA_VIDEO, atau keduanya) dalam sebuah operasi.

Mengizinkan pengguna mengelola pilihan mereka

Saat pengguna memilih mode akses sebagian, aplikasi Anda tidak boleh mengasumsikan bahwa library foto perangkat kosong, dan harus mengizinkan pengguna memberikan lebih banyak file.

Pengguna dapat memutuskan untuk beralih dari akses penuh ke akses sebagian melalui setelan izin tanpa memberikan akses ke beberapa file media visual.

Mode kompatibilitas

Jika Anda mengelola pemilih galeri Anda sendiri menggunakan izin penyimpanan, tetapi belum menyesuaikan aplikasi untuk menggunakan izin READ_MEDIA_VISUAL_USER_SELECTED baru, sistem akan menjalankan aplikasi dalam mode kompatibilitas setiap kali pengguna perlu memilih atau memilih ulang media.

Perilaku selama pemilihan media awal

Selama pemilihan awal, jika pengguna memilih "Pilih foto dan video" (lihat gambar 1), izin READ_MEDIA_IMAGES dan READ_MEDIA_VIDEO akan diberikan selama sesi aplikasi, yang memberikan pemberian izin sementara dan akses sementara ke foto dan video yang dipilih pengguna. Saat aplikasi Anda berpindah ke latar belakang, atau saat pengguna secara aktif menghentikan aplikasi Anda, sistem pada akhirnya akan menolak izin ini. Perilaku ini seperti izin satu kali lainnya.

Perilaku selama pemilihan ulang media

Jika aplikasi Anda memerlukan akses ke foto dan video tambahan di lain waktu, Anda harus meminta izin READ_MEDIA_IMAGES atau izin READ_MEDIA_VIDEO lagi secara manual. Sistem mengikuti alur yang sama seperti permintaan izin awal, yang meminta pengguna untuk memilih foto dan video (lihat gambar 2).

Jika aplikasi Anda mengikuti praktik terbaik izin, perubahan ini tidak akan merusak aplikasi Anda. Hal ini terutama berlaku jika aplikasi Anda tidak berasumsi bahwa akses URI dipertahankan, menyimpan status izin sistem, atau memuat ulang kumpulan gambar yang ditampilkan setelah izin berubah. Namun, perilaku ini mungkin tidak ideal, bergantung pada kasus penggunaan aplikasi Anda. Untuk membantu memberikan pengalaman terbaik bagi pengguna, sebaiknya terapkan pemilih foto atau sesuaikan pemilih galeri aplikasi Anda untuk menangani perilaku ini secara langsung menggunakan izin READ_MEDIA_VISUAL_USER_SELECTED.