Fotoğraflara ve videolara kısmi erişim izni verme

Android 14, kullanıcıların belirli bir türdeki tüm medyalara erişim vermek yerine uygulamalara kitaplarındaki belirli resimlere ve videolara erişim izni vermesine olanak tanıyan Seçili Fotoğraflara Erişim özelliğini kullanıma sunar.

Bu değişiklik yalnızca uygulamanız Android 14'ü (API düzeyi 34) veya sonraki sürümleri hedefliyorsa etkinleştirilir. Fotoğraf seçiciyi henüz kullanmıyorsanız depolama alanı izni istemek zorunda kalmadan resim ve video seçmek için tutarlı bir deneyim sunmak ve kullanıcı gizliliğini artırmak amacıyla uygulamanıza uygulamanızı öneririz.

Depolama alanı izinlerini kullanarak kendi galeri seçicinizi kullanıyorsanız ve uygulamanız üzerinde tam kontrol sahibi olmanız gerekiyorsa yeni READ_MEDIA_VISUAL_USER_SELECTED iznini kullanmak için uygulamanızı uyarlayın. Uygulamanız yeni izni kullanmıyorsa sistem, uygulamanızı uyumluluk modunda çalıştırır.

Hedef SDK READ_MEDIA_VISUAL_USER_SELECTED beyan edildi Seçili fotoğraflara erişim etkinleştirildi Kullanıcı deneyimi davranışı
SDK 33 Hayır Hayır Yok
Evet Evet Uygulama tarafından kontrol ediliyor
SDK 34 Hayır Evet Sistem tarafından kontrol edilir (uyumlu davranış)
Evet Evet Uygulama tarafından kontrol ediliyor

Kendi galeri seçicinizi oluşturmak için kapsamlı geliştirme ve bakım yapmanız gerekir. Ayrıca, uygulamanızın kullanıcılardan açık izin almak için depolama alanı izinleri istemesi gerekir. Kullanıcılar bu istekleri reddedebilir veya uygulamanız Android 14 yüklü bir cihazda çalışıyorsa ve Android 14'ü (API düzeyi 34) veya sonraki sürümleri hedefliyorsa seçili medyaya erişimi sınırlayabilir. Aşağıdaki resimde, izin isteme ve yeni seçenekleri kullanarak medya seçme örneği gösterilmektedir.

(
Şekil 1. Yeni iletişim kutusu, kullanıcıların tam erişim verme veya tüm erişimi reddetme gibi genel seçeneklere ek olarak, uygulamanıza sunmak istedikleri belirli fotoğraf ve videoları seçmesine olanak tanır.

Bu bölümde, MediaStore'ü kullanarak kendi galeri seçicinizi oluşturmak için önerilen yaklaşım gösterilmektedir. Uygulamanız için zaten bir galeri seçici kullanıyorsanız ve tam kontrole sahip olmanız gerekiyorsa uygulamanızı bu örneklere göre uyarlayabilirsiniz. Uygulamanızı, Seçili Fotoğraflara Erişim'i işleyecek şekilde güncellemezseniz sistem uygulamanızı uyumluluk modunda çalıştırır.

İzin isteme

Öncelikle, işletim sistemi sürümüne bağlı olarak Android manifest dosyasında doğru depolama izinlerini isteyin:

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

Ardından, OS sürümüne bağlı olarak doğru çalışma zamanı izinlerini isteyin:

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

Bazı uygulamaların izinlere ihtiyacı yoktur

Android 10 (API düzeyi 29) itibarıyla, uygulamaların paylaşılan depolama alanına dosya eklemek için depolama alanı izinlerine ihtiyacı yoktur. Bu sayede uygulamalar, depolama alanı izni istemek zorunda kalmadan galeriye resim ekleyebilir, video kaydedip paylaşılan depolama alanına kaydedebilir veya PDF faturaları indirebilir. Uygulamanız yalnızca paylaşılan depolama alanına dosya ekliyor ve resim ya da video sorgulaması yapmıyorsa depolama alanı izinleri istemeyi bırakmalı ve AndroidManifest.xml dosyanızda API 28 için maxSdkVersion ayarını yapmalısınız:

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

Medya yeniden seçimini yönetme

Android 14'teki Seçili Fotoğraflara Erişim özelliğiyle uygulamanız, medya yeniden seçimini kontrol etmek için yeni READ_MEDIA_VISUAL_USER_SELECTED iznini benimsemeli ve kullanıcıların uygulamanıza farklı bir resim ve video grubuna erişim izni vermesine olanak tanımak için uygulamanızın arayüzünü güncellemelidir. Aşağıdaki resimde, izin isteme ve medyayı yeniden seçme örneği gösterilmektedir:

(
Şekil 2. Yeni iletişim kutusu, kullanıcıların uygulamanıza hangi fotoğraf ve videoları sunmak istediklerini yeniden seçmesine de olanak tanır.

Seçim iletişim kutusu açıldığında, istenen izinlere bağlı olarak fotoğraflar, videolar veya her ikisi de gösterilir. Örneğin, READ_MEDIA_IMAGES izni olmadan READ_MEDIA_VIDEO iznini istiyorsanız kullanıcıların dosya seçmesi için kullanıcı arayüzünde yalnızca videolar gösterilir.

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

Uygulamanızın cihazın fotoğraf kitaplığına tam, kısmi veya reddedilmiş erişimi olup olmadığını kontrol edebilir ve arayüzünüzü buna göre güncelleyebilirsiniz. Bu izinleri, uygulamanın depolama alanına erişmesi gerektiğinde isteyin. Kullanıcı, uygulamanızı kapatmadan ayarlardan erişimi değiştirebileceğinden izin verme işleminin onStart ve onResume uygulama yaşam döngüsü geri çağırma çağrıları arasında değiştirilebileceğini unutmayın.

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
}

Cihaz kitaplığını sorgulayın

Doğru depolama izinlerine erişiminizin olduğunu doğruladıktan sonra cihaz kitaplığını sorgulamak için MediaStore ile etkileşimde bulunabilirsiniz (izin verilen erişim kısmi veya tam olsun da aynı yaklaşım geçerlidir):

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
}

Bu kod snippet'i, MediaStore ile nasıl etkileşim kurulacağını göstermek amacıyla basitleştirilmiştir. Üretime hazır bir uygulamada, iyi performans sağlamak için çağrı kitaplığı gibi bir sayfayla numaralandırmayı kullanın.

Son seçimi sorgulayın

Android 15 ve sonraki sürümlerde ve Google Play sistem güncellemeleri desteğine sahip Android 14'te çalışan uygulamalar, QUERY_ARG_LATEST_SELECTION_ONLY iznini etkinleştirerek kullanıcının kısmi erişimde yaptığı son resim ve video seçimini sorgulayabilir:

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

Cihaz yükseltme işleminde fotoğraf ve videolara erişim korunur

Uygulamanızın, daha eski bir Android sürümünden Android 14'e yükseltilen bir cihazda olduğu durumlarda sistem, kullanıcının fotoğraflarına ve videolarına tam erişim sağlar ve uygulamanıza otomatik olarak bazı izinler verir. Kesin davranış, cihaz Android 14'e geçmeden önce uygulamanıza verilen izin grubuna bağlıdır.

Android 13'teki izinler

Aşağıdaki durumu ele alalım:

  1. Uygulamanız Android 13 çalıştıran bir cihaza yüklü.
  2. Kullanıcı, uygulamanıza READ_MEDIA_IMAGES ve READ_MEDIA_VIDEO iznini verdi.
  3. Ardından, uygulamanız hâlâ yüklüyken cihaz Android 14'e yükseltilir.
  4. Uygulamanız Android 14 (API düzeyi 34) veya sonraki sürümleri hedeflemeye başlar.

Bu durumda, uygulamanız kullanıcının fotoğraf ve videolarına tam erişmeye devam eder. Sistem, uygulamanıza otomatik olarak verilen READ_MEDIA_IMAGES ve READ_MEDIA_VIDEO izinlerini de korur.

Android 12 ve önceki sürümlerdeki izinler

Aşağıdaki durumu ele alalım:

  1. Uygulamanız Android 13 çalıştıran bir cihaza yüklü.
  2. Kullanıcı, uygulamanıza READ_EXTERNAL_STORAGE veya WRITE_EXTERNAL_STORAGE iznini verdi.
  3. Ardından cihaz, uygulamanız yüklüyken Android 14'e geçer.
  4. Uygulamanız Android 14 (API düzeyi 34) veya sonraki sürümleri hedeflemeye başlar.

Bu durumda, uygulamanız kullanıcının fotoğraf ve videolarına tam erişmeye devam eder. Sistem, uygulamanıza READ_MEDIA_IMAGES ve READ_MEDIA_VIDEO izinlerini de otomatik olarak verir.

En iyi uygulamalar

Bu bölümde, READ_MEDIA_VISUAL_USER_SELECTED izninin kullanımıyla ilgili bazı en iyi uygulamalar yer almaktadır. Daha fazla bilgi için izinlerle ilgili en iyi uygulamalarımıza göz atın.

İzin durumunu kalıcı olarak saklamayın

İzin durumunu SharedPreferences veya DataStore dahil olmak üzere kalıcı bir şekilde saklamayın. Depolanan durum, gerçek durumla senkronize olmayabilir. İzin durumu, izin sıfırlandıktan, uygulama uyku moduna girdikten, uygulamanızın ayarlarında kullanıcı tarafından başlatılan bir değişiklik yapıldıktan veya uygulamanız arka plana geçtikten sonra değişebilir. Bunun yerine ContextCompat.checkSelfPermission() kullanarak depolama izinlerini kontrol edin.

Fotoğraflara ve videolara tam erişim elde ettiğinizi varsaymayın

Android 14'te yapılan değişikliklere bağlı olarak uygulamanız, cihazın fotoğraf kitaplığına yalnızca kısmi erişime sahip olabilir. Uygulama, ContentResolver kullanılarak sorgulandığında MediaStore verilerini önbelleğe alıyorsa önbellek güncel olmayabilir.

  • Depolanan bir önbelleğe güvenmek yerine MediaStore'ü her zaman ContentResolver kullanarak sorgulayın.
  • Uygulamanız ön plandayken sonuçları bellekte tutun.
  • Kullanıcı, izin ayarlarını kullanarak tam erişimden kısmi erişime geçebileceğinden, uygulamanız onResume uygulamasının yaşam döngüsü boyunca ilerlediğinde sonuçları yenileyin.

URI erişimini geçici olarak kabul etme

Kullanıcı, sistem izinleri iletişim kutusunda Fotoğraf ve video seç'i seçerse uygulamanızın seçili fotoğraf ve videolara erişimi zaman içinde sona erer. Uygulamanız, yetkileri ne olursa olsun hiçbir Uri'ye erişememe durumunu her zaman ele almalıdır.

Seçilebilir medya türünü izne göre filtrele

Seçim iletişim kutusu, istenen izin türüne duyarlıdır:

  • Yalnızca READ_MEDIA_IMAGES isteğinde bulunmak, yalnızca resimlerin seçilebilir olduğunu gösterir.
  • Yalnızca READ_MEDIA_VIDEO isteğinde bulunursanız yalnızca video seçilebilir olarak gösterilir.
  • Hem READ_MEDIA_IMAGES hem de READ_MEDIA_VIDEO isteğinde bulunmak, fotoğraf kitaplığının tamamının seçilebilir olduğunu gösterir.

Uygulamanızın kullanım alanlarına bağlı olarak, kötü bir kullanıcı deneyimini önlemek için doğru izinleri istediğinizden emin olmalısınız. Bir özellik yalnızca videoların seçilmesini bekliyorsa yalnızca READ_MEDIA_VIDEO isteğinde bulunun.

Tek bir işlemde izin isteme

Kullanıcıların birden fazla sistem çalışma zamanı iletişim kutusu görmesini önlemek için tek bir işlemde READ_MEDIA_VISUAL_USER_SELECTED, ACCESS_MEDIA_LOCATION ve "medya okuma" izinlerini (READ_MEDIA_IMAGES, READ_MEDIA_VIDEO veya her ikisi) isteyin.

Kullanıcıların seçimlerini yönetmelerine izin verin

Kullanıcı kısmi erişim modunu seçtiğinde uygulamanız, cihazın fotoğraf kitaplığının boş olduğunu varsaymaz ve kullanıcının daha fazla dosya vermesine izin verir.

Kullanıcı, bazı görsel medya dosyalarına erişim izni vermeden izin ayarlarından tam erişimden kısmi erişime geçmeye karar verebilir.

Uyumluluk modu

Depolama izinlerini kullanarak kendi galeri seçiciyi kullanıyor ancak uygulamanızı yeni READ_MEDIA_VISUAL_USER_SELECTED iznini kullanacak şekilde uyarlamadıysanız sistem, kullanıcının medya seçmesi veya yeniden seçmesi gerektiğinde uygulamanızı uyumluluk modunda çalıştırır.

İlk medya seçimi sırasındaki davranış

İlk seçim sırasında kullanıcı "Fotoğraf ve video seçin"i seçerse (şekil 1'e bakın) READ_MEDIA_IMAGES ve READ_MEDIA_VIDEO izinleri uygulama oturumu sırasında verilir. Bu sayede geçici izin verilir ve kullanıcının seçtiği fotoğraf ve videolara geçici erişim sağlanır. Uygulamanız arka plana geçtiğinde veya kullanıcı uygulamanızı aktif olarak öldürdüğünde, sistem nihayetinde bu izinleri reddeder. Bu davranış diğer tek seferlik izinlerle aynıdır.

Medya yeniden seçim sırasındaki davranış

Uygulamanızın daha sonra ek fotoğraf ve videolara erişmesi gerekiyorsa READ_MEDIA_IMAGES iznini veya READ_MEDIA_VIDEO iznini manuel olarak tekrar istemeniz gerekir. Sistem, ilk izin isteğiyle aynı akışı uygulayarak kullanıcılardan fotoğraf ve video seçmesini ister (Şekil 2'ye bakın).

Uygulamanız, izinlerle ilgili en iyi uygulamaları takip ediyorsa bu değişiklik uygulamanızı bozmamalıdır. Bu durum, özellikle uygulamanız URI erişiminin korunduğunu varsaymıyorsa, sistem izin durumunu sakladığında veya izin değiştikten sonra görüntülenen resim grubunu yeniliyorsa geçerlidir. Ancak bu davranış, uygulamanızın kullanım alanına bağlı olarak ideal olmayabilir. Kullanıcılarınıza en iyi deneyimi sunmak için READ_MEDIA_VISUAL_USER_SELECTED iznini kullanarak doğrudan bu davranışı işleyecek fotoğraf seçiciyi uygulamanızı veya uygulamanızın galeri seçiciyi uyarlamanızı öneririz.