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

Android 14'te, kullanıcıların belirli bir türdeki tüm medyalara erişim izni vermek yerine, kitaplıklarındaki belirli resim ve videolara erişim izni verebilmelerini sağlayan Seçili Fotoğraflar Erişimi kullanıma sunuldu.

Bu değişiklik yalnızca uygulamanız Android 14 (API düzeyi 34) veya sonraki sürümleri hedefliyorsa etkin olur. Fotoğraf seçiciyi henüz kullanmıyorsanız herhangi bir depolama izni istemek zorunda kalmadan kullanıcı gizliliğini iyileştiren resim ve video seçerken tutarlı bir deneyim sunmak için uygulamanızda bu özelliği uygulamanızı öneririz.

Depolama 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çilen 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 kapsamlı geliştirme ve bakım gerektirir. 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 uygulamanız Android 14 (API düzeyi 34) veya sonraki bir sürümü hedefliyorsa erişimi seçili medyayla sınırlandırabilir. Aşağıdaki resimde, izin isteme ve yeni seçenekleri kullanarak medya seçme ile ilgili bir örnek gösterilmektedir.

(
Şekil 1. Yeni iletişim kutusu, kullanıcıların tam erişim izni verme veya erişimi reddetme gibi normal seçeneklere ek olarak, uygulamanızda kullanılabilir olmasını istedikleri 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 tüm kontrolü elinizde tutmanız gerekiyorsa uygulamanızı uyarlamak için bu örnekleri kullanabilirsiniz. Uygulamanızı Seçili Fotoğraflara Erişim'i işleyecek şekilde güncellemezseniz sistem, uygulamanızı uyumluluk modunda çalıştırır.

İzin iste

İlk olarak, 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, işletim sistemi 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 izin gerektirmez

Android 10'dan (API düzeyi 29) itibaren, uygulamaların paylaşılan depolama alanına dosya eklemek için artık depolama izinlerine ihtiyacı yoktur. Yani uygulamalar, depolama 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 görüntü veya videoları sorgulamıyorsa depolama izni istemeyi bırakmalı ve AndroidManifest.xml öğenizde API 28 için maxSdkVersion ayarlamalı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önetin

Android 14'teki Seçili Fotoğraflara Erişim özelliği sayesinde uygulamanız, medya yeniden seçimini kontrol etmek için yeni READ_MEDIA_VISUAL_USER_SELECTED iznini kullanmalı ve uygulamanızın arayüzünü, kullanıcıların farklı resim ve videolara erişmesine izin verecek şekilde güncellemelidir. Aşağıdaki resimde izin isteme ve medyayı yeniden seçme ile ilgili bir örnek gösterilmektedir:

(
Şekil 2. Yeni iletişim kutusu sayesinde kullanıcılar, uygulamanızda kullanmak istedikleri fotoğraf ve videoları yeniden seçebilirler.

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ı arayüzünde kullanıcıların dosyaları seçebilmesi için 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 kısmi erişim sahibi olduğunu kontrol edebilir ve arayüzünüzü buna göre güncelleyebilirsiniz. Bu izinleri, uygulama başlangıçta değil, depolama alanına erişmesi gerektiğinde isteyin. Kullanıcı, uygulamanızı kapatmadan ayarlar bölümünden erişimi değiştirebileceği için izin vermenin, onStart ve onResume uygulama yaşam döngüsü geri çağırmaları 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ı sorgulama

Doğru depolama izinlerine erişiminiz olduğunu doğruladıktan sonra cihaz kitaplığını sorgulamak için MediaStore ile etkileşim kurabilirsiniz (izin verilen erişimin kısmi veya tam olması fark etmeksizin aynı yaklaşım işe yarar):

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şimde bulunacağınızı göstermek için basitleştirilmiştir. Üretime hazır bir uygulamada, iyi bir performans sağlamak için sayfalara ayırma işlemini Çağrı kitaplığı gibi bir şekilde kullanın.

Cihaz yeni sürüme geçirildiğinde fotoğraf ve video erişimi korunur

Uygulamanızın önceki bir Android sürümünden Android 14'e yükseltilmiş bir cihazda bulunduğu durumlarda sistem, kullanıcının fotoğraflarına ve videolarına tam erişim sahibi olmaya devam eder ve uygulamanıza otomatik olarak bazı izinler verir. Kesin davranış, cihaz Android 14'e yükseltilmeden önce uygulamanıza verilen izin grubuna bağlıdır.

Android 13'teki izinler

Aşağıdaki durumu göz önünde bulundurun:

  1. Uygulamanız Android 13 çalıştıran bir cihazda yüklü olmalıdır.
  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şlıyor.

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

Android 12 ve önceki sürümlerden izinler

Aşağıdaki durumu göz önünde bulundurun:

  1. Uygulamanız Android 13 çalıştıran bir cihazda yüklü olmalıdır.
  2. Kullanıcı uygulamanıza READ_EXTERNAL_STORAGE veya WRITE_EXTERNAL_STORAGE 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şlıyor.

Bu durumda, uygulamanız kullanıcının fotoğraflarına ve videolarına tam erişim sahibi olmaya devam eder. Sistem ayrıca uygulamanıza READ_MEDIA_IMAGES ve READ_MEDIA_VIDEO iznini otomatik olarak verir.

En iyi uygulamalar

Bu bölümde, READ_MEDIA_VISUAL_USER_SELECTED izninin kullanımıyla ilgili 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 depolama

İzin durumunu, SharedPreferences veya DataStore dahil olmak üzere kalıcı bir şekilde saklamayın. Depolanma durumu, gerçek durumla senkronize olmayabilir. İzin durumu; izin sıfırlandıktan, uygulama hazırda bekletildikten, uygulamanızın ayarlarında kullanıcı tarafından başlatılan bir değişiklikten veya uygulamanız arka plana gittiğinde değişebilir. Bunun yerine, ContextCompat.checkSelfPermission() kullanarak depolama alanı izinlerini kontrol edin.

Fotoğraflara ve videolara tam erişim olduğunu varsaymayın

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

  • MediaStore öğesini, depolanan önbelleği kullanmak yerine her zaman ContentResolver kullanarak sorgulayın.
  • Uygulamanız ön plandayken sonuçları bellekte tutun.
  • Kullanıcı, izin ayarları üzerinden tam erişimden kısmi erişime geçiş yapabileceği için uygulamanız onResume uygulamasının yaşam döngüsünü tamamladığında sonuçları yenileyin.

URI erişimini geçici olarak değerlendir

Kullanıcı, sistem izinleri iletişim kutusunda Fotoğraf ve videoları seçin'i seçerse uygulamanızın seçilen fotoğraflara ve videolara erişimi sonunda sona erer. Uygulamanız, yetkisi önemli olsa da hiçbir Uri öğesine erişememe durumunu ele almalıdır.

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

Seçim iletişim kutusu, istenen izin türü konusunda hassastır:

  • Yalnızca READ_MEDIA_IMAGES isteğinde bulunulduğunda yalnızca seçilebilecek resimler gösterilir.
  • Yalnızca READ_MEDIA_VIDEO isteğinde bulunulduğunda sadece seçilebilecek video gösteriliyor.
  • Hem READ_MEDIA_IMAGES hem de READ_MEDIA_VIDEO istendiğinde tüm fotoğraf kitaplığı seçilebilir olarak gösterilir.

Uygulamanızın kullanım alanlarına göre, 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 bulunduğunuzdan emin olun.

Tek bir işlemde izin isteme

Kullanıcıların birden fazla sistem çalışma zamanı iletişim kutusu görmesini engellemek 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 kendi seçimlerini yönetmesine izin verin

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

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

Uyumluluk modu

Depolama izinlerini kullanarak kendi galeri seçicinizi 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ı bir uyumluluk modunda çalıştırır.

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

İlk seçim sırasında kullanıcı "Fotoğraf ve video seç"i seçerse (Şekil 1'e bakın) uygulama oturumu sırasında READ_MEDIA_IMAGES ve READ_MEDIA_VIDEO izinleri verilir. Böylece, kullanıcı tarafından seçilen fotoğraf ve videolara geçici bir izin ve geçici erişim sağlanır. Uygulamanız arka plana geçtiğinde veya kullanıcı uygulamanızı etkin bir şekilde sonlandırdığında, sistem sonunda bu izinleri reddeder. Bu davranış, diğer tek seferlik izinler gibidir.

Medya yeniden seçimi sırasında davranış

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

Uygulamanız izinlerle ilgili en iyi uygulamaları izliyorsa bu değişiklik uygulamanızı bozmaz. Bu durum özellikle uygulamanız URI erişiminin korunduğunu varsaymıyorsa, sistem izin durumunu saklamıyorsa veya izin değişikliklerinden sonra görüntülenen görüntü grubunu yenilerse 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 fotoğraf seçiciyi uygulamanızı veya bu davranışı doğrudan READ_MEDIA_VISUAL_USER_SELECTED izniyle ele alacak şekilde uygulamanızın galeri seçicisini uyarlamanızı öneririz.