Android depolama alanı kullanım alanları ve en iyi uygulamalar

Android 10, kullanıcılara dosyaları üzerinde daha fazla kontrol sağlamak ve dosya karmaşıklığını azaltmak amacıyla, kapsamlı depolama adı verilen uygulamalar için yeni bir depolama paradigması sundu. Kapsamlı depolama, uygulamaların bir cihazın harici depolama alanındaki dosyaları depolama ve dosyalara erişme biçimini değiştirir. Uygulamanızı kapsamlı depolamayı destekleyecek şekilde taşımanıza yardımcı olması için bu kılavuzda özetlenen yaygın depolama alanı kullanım alanlarına yönelik en iyi uygulamaları izleyin. Kullanım alanları iki kategoriye ayrılır: medya dosyalarının işlenmesi ve medya dışı dosyaların işlenmesi.

Android'de dosyaları depolama ve dosyalara erişme hakkında daha fazla bilgi edinmek için depolama alanı eğitim kılavuzlarını inceleyin.

Medya dosyalarını işleme

Bu bölümde medya dosyalarını (video, resim ve ses dosyaları) işlemek için yaygın kullanım alanlarından bazıları ve uygulamanızın kullanabileceği üst düzey yaklaşım açıklanmaktadır. Aşağıdaki tabloda bu kullanım alanlarının her biri özetlenmiş ve daha fazla ayrıntı içeren bölümlerin her birine bağlantılar verilmiştir.

Kullanım alanı Özet
Tüm resim veya video dosyalarını gösterme Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Belirli bir klasördeki resimleri veya videoları gösterme Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Fotoğraflardan konum bilgilerine erişme Uygulamanız kapsamlı depolama alanı kullanıyorsa şu yaklaşımlardan birini kullanın. Uygulamanız kapsamlı depolama alanını devre dışı bırakırsa farklı bir yaklaşım kullanın.
Yeni indirilenler için depolama konumunu tanımlama Uygulamanız kapsamlı depolama alanı kullanıyorsa şu yaklaşımlardan birini kullanın. Uygulamanız kapsamlı depolama alanını devre dışı bırakırsa farklı bir yaklaşım kullanın.
Kullanıcı medya dosyalarını cihaza aktarma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Tek bir işlemde birden çok medya dosyasını değiştirme veya silme Android 11 için tek bir yaklaşım kullanın. Android 10'da kapsamlı depolama alanını devre dışı bırakın ve bunun yerine Android 9 ve önceki sürümlerde yaklaşımı kullanın.
Mevcut tek bir resmi içe aktarın Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Tek bir resim çekme Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Medya dosyalarını diğer uygulamalarla paylaşma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Medya dosyalarını belirli bir uygulamayla paylaşma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Dosyalara doğrudan dosya yolları kullanan koddan veya kitaplıklardan erişme Android 11 için tek bir yaklaşım kullanın. Android 10'da kapsamlı depolama alanını devre dışı bırakın ve bunun yerine Android 9 ve önceki sürümlerde yaklaşımı kullanın.

Birden fazla klasördeki resim veya video dosyalarını gösterme

query() API'sini kullanarak bir medya koleksiyonunu sorgulayın. Medya dosyalarını filtrelemek veya sıralamak için projection, selection, selectionArgs ve sortOrder parametrelerini ayarlayın.

Belirli bir klasördeki resimleri veya videoları gösterin

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde açıklanan en iyi uygulamaları izleyerek READ_EXTERNAL_STORAGE iznini isteyin.
  2. Medya dosyalarını, diskteki medya öğesinin mutlak dosya sistemi yolunu içeren MediaColumns.DATA değerine göre alın.

Not: Mevcut bir medya dosyasına eriştiğinizde mantığınızda DATA sütununun değerini kullanabilirsiniz. Bunun nedeni, bu değerin geçerli bir dosya yoluna sahip olmasıdır. Ancak, dosyanın her zaman kullanılabilir olduğunu varsaymayın. Oluşabilecek dosya tabanlı G/Ç hatalarını işlemeye hazır olun.

Öte yandan, bir medya dosyası oluşturmak veya güncellemek için DATA sütununu kullanmayın. Bunun yerine DISPLAY_NAME ve RELATIVE_PATH sütunlarını kullanın.

Fotoğraflardan konum bilgilerine erişme

Uygulamanız kapsamlı depolama alanı kullanıyorsa medya depolama kılavuzunun Fotoğraflardaki konum bilgileri bölümündeki adımları uygulayın.

kullanılarak erişilen resimlerdeki çıkartılmamış konum bilgilerini okumak için ACCESS_MEDIA_LOCATION iznine ihtiyaç duyar.

Yeni indirilenler için depolama konumunu tanımlayın

Uygulamanız, kapsamlı depolama alanı kullanıyorsa indirdiğiniz medya dosyalarını depolamayı seçtiğiniz konuma dikkat edin.

Diğer uygulamaların dosyalara erişmesi gerekiyorsa indirme veya belge koleksiyonları için iyi tanımlanmış medya koleksiyonları kullanabilirsiniz.

Android 11 ve sonraki sürümlerde, bu dosyaları getirmek için DownloadManager uygulamasını kullansanız bile harici uygulamaya özel dizininizdeki dosyalara diğer uygulamalar erişemez.

Kullanıcının medya dosyalarını cihaza aktarın

Kullanıcı medya dosyalarını depolamak için uygun bir varsayılan konum tanımlayın:

Tek bir işlemde birden fazla medya dosyasını değiştirin veya silin

Uygulamanızın çalıştığı Android sürümlerine göre mantığı dahil edin.

Android 11'de yüklü olmalıdır.

Şu yaklaşımı kullanın:

  1. MediaStore.createWriteRequest() veya MediaStore.createTrashRequest() kullanarak uygulamanızın yazma veya silme isteği için bekleyen bir intent oluşturun ve ardından bu niyeti çağırarak kullanıcıdan bir dosya grubunu düzenleme izni isteyin.
  2. Kullanıcının yanıtını değerlendirin:

    • İzin verildiyse değiştirme veya silme işlemine devam edin.
    • İzin verilmediyse kullanıcıya uygulamanızdaki özelliğin neden bu izne ihtiyaç duyduğunu açıklayın.

Android 11 ve sonraki sürümlerde kullanılabilen bu yöntemleri kullanarak medya dosyası gruplarını yönetme hakkında daha fazla bilgi edinin.

Android 10'da çalışıyor

Uygulamanız Android 10'u (API düzeyi 29) hedefliyorsa kapsamlı depolama alanını devre dışı bırakın ve bu işlemi gerçekleştirmek için Android 9 ve önceki sürümlerde yaklaşımı kullanmaya devam edin.

Android 9 veya önceki sürümlerde çalışan

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde açıklanan en iyi uygulamaları izleyerek WRITE_EXTERNAL_STORAGE iznini isteyin.
  2. Medya dosyalarını değiştirmek veya silmek için MediaStore API'yi kullanın.

Mevcut tek bir resmi içe aktarın

Zaten var olan tek bir resmi içe aktarmak istediğinizde (örneğin, bir kullanıcının profilinin fotoğrafı olarak kullanmak için) uygulamanız işlem için kendi kullanıcı arayüzünü veya sistem seçiciyi kullanabilir.

Kendi kullanıcı arayüzünüzü sunma

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde açıklanan en iyi uygulamaları izleyerek READ_EXTERNAL_STORAGE iznini isteyin.
  2. Bir medya koleksiyonunu sorgulamak için query() API'sini kullanın.
  3. Sonuçları uygulamanızın özel kullanıcı arayüzünde görüntüleyin.

Sistem seçiciyi kullanın

Kullanıcıdan içe aktarmak üzere bir resim seçmesini isteyen ACTION_GET_CONTENT niyetini kullanın.

Sistem seçicinin, aralarından seçim yapması için kullanıcıya sunduğu resim türlerini filtrelemek istiyorsanız setType() veya EXTRA_MIME_TYPES aracını kullanabilirsiniz.

Tek bir resim çek

Uygulamanızda kullanmak üzere tek bir resim çekmek istediğinizde (örneğin, bir kullanıcının profilinin fotoğrafı için) ACTION_IMAGE_CAPTURE amacından yararlanarak kullanıcıdan cihazın kamerasını kullanarak fotoğraf çekmesini isteyin. Sistem, çekilen fotoğrafı MediaStore.Images tablosunda depolar.

Medya dosyalarını diğer uygulamalarla paylaşma

Kayıtları doğrudan MediaStore'a eklemek için insert() yöntemini kullanın. Daha fazla bilgi için medya depolama rehberinin Öğe ekleme bölümüne bakın.

Medya dosyalarını belirli bir uygulamayla paylaşma

Android FileProvider bileşenini, Dosya paylaşımını ayarlama kılavuzunda açıklandığı şekilde kullanın.

Doğrudan dosya yollarını kullanan kod veya kitaplıklardan dosyalara erişme

Uygulamanızın çalıştığı Android sürümlerine göre mantığı dahil edin.

Android 11'de yüklü olmalıdır.

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde açıklanan en iyi uygulamaları izleyerek READ_EXTERNAL_STORAGE iznini isteyin.
  2. Dosyalara doğrudan dosya yollarını kullanarak erişin.

Daha fazla bilgi için doğrudan dosya yollarını kullanarak medya dosyalarını açma ile ilgili bölüme bakın.

Android 10'da çalışıyor

Uygulamanız Android 10'u (API düzeyi 29) hedefliyorsa kapsamlı depolama alanını devre dışı bırakın ve bu işlemi gerçekleştirmek için Android 9 ve önceki sürümlerde yaklaşımı kullanmaya devam edin.

Android 9 veya önceki sürümlerde çalışan

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde açıklanan en iyi uygulamaları izleyerek WRITE_EXTERNAL_STORAGE iznini isteyin.
  2. Dosyalara doğrudan dosya yollarını kullanarak erişin.

Medya dışı dosyaları işleme

Bu bölümde, medya dışı dosyaların işlenmesiyle ilgili yaygın kullanım alanlarından bazıları ve uygulamanızın kullanabileceği üst düzey yaklaşım açıklanmaktadır. Aşağıdaki tabloda, bu kullanım alanlarının her biri özetlenmiş ve daha fazla ayrıntı içeren bölümlerin her birine bağlantılar verilmiştir.

Kullanım alanı Özet
Doküman dosyası açma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
İkincil depolama birimlerindeki dosyalara yazma Android 11 için tek bir yaklaşım kullanın. Android'in önceki sürümleri için farklı bir yaklaşım kullanın.
Eski depolama konumundaki mevcut dosyaları taşıma Mümkün olduğunda dosyalarınızı kapsamlı depolama alanına taşıyın. Gerektiğinde Android 10 için kapsamlı depolama alanını devre dışı bırakın.
Diğer uygulamalarla içerik paylaşma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Medya olmayan dosyaları önbelleğe alma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Medya olmayan dosyaları bir cihaza dışa aktarma Uygulamanız kapsamlı depolama alanı kullanıyorsa şu yaklaşımlardan birini kullanın. Uygulamanız kapsamlı depolama alanını devre dışı bırakırsa farklı bir yaklaşım kullanın.

Doküman dosyası açma

Kullanıcıdan sistem seçiciyi kullanarak açılacak bir dosyayı seçmesini istemek için ACTION_OPEN_DOCUMENT amacını kullanın. Sistem seçicinin kullanıcıya seçim yapması için sunacağı dosya türlerini filtrelemek istiyorsanız setType() veya EXTRA_MIME_TYPES aracını kullanabilirsiniz.

Örneğin, tüm PDF, ODT ve TXT dosyalarını aşağıdaki kodu kullanarak bulabilirsiniz:

Kotlin

startActivityForResult(
        Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
            addCategory(Intent.CATEGORY_OPENABLE)
            type = "*/*"
            putExtra(Intent.EXTRA_MIME_TYPES, arrayOf(
                    "application/pdf", // .pdf
                    "application/vnd.oasis.opendocument.text", // .odt
                    "text/plain" // .txt
            ))
        },
        REQUEST_CODE
      )

Java

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {
                "application/pdf", // .pdf
                "application/vnd.oasis.opendocument.text", // .odt
                "text/plain" // .txt
        });
        startActivityForResult(intent, REQUEST_CODE);

İkincil depolama birimlerindeki dosyalara yazma

İkincil depolama birimlerine SD kartlar dahildir. StorageVolume sınıfını kullanarak belirli bir depolama birimi hakkındaki bilgilere erişebilirsiniz.

Uygulamanızın çalıştığı Android sürümüne dayalı mantığı dahil edin.

Android 11'de çalışır

Şu yaklaşımı kullanın:

  1. Kapsamlı depolama modelini kullanın.
  2. Android 10 (API düzeyi 29) veya önceki sürümleri hedefleyin.
  3. WRITE_EXTERNAL_STORAGE iznini beyan edin.
  4. Aşağıdaki erişim türlerinden birini gerçekleştirin:
    • MediaStore API'yi kullanarak dosya erişimi.
    • File veya fopen() gibi API'leri kullanarak doğrudan dosya yolu erişimi.

Eski sürümlerde çalışıyor

Kullanıcıların ikincil depolama biriminde, uygulamanızın dosyayı yazabileceği konumu seçmelerine olanak tanıyan Depolama Erişim Çerçevesi'ni kullanın.

Eski depolama konumundaki mevcut dosyaları taşıma

Uygulamaya özel bir dizin veya herkese açık bir paylaşılan dizin değilse dizinler eski depolama konumu olarak kabul edilir. Uygulamanız eski bir depolama konumunda dosya oluşturuyor veya tüketiyorsa uygulamanızın dosyalarını kapsamlı depolama alanıyla erişilebilen konumlara taşımanızı ve kapsama dahil olan dosyalarla çalışmak için gerekli uygulama değişikliklerinizi yapmanızı öneririz.

Veri taşıma için eski depolama konumuna erişimi sürdür

Uygulama dosyalarını, kapsamlı depolama alanıyla erişilebilen konumlara taşımak için uygulamanızın eski depolama konumuna erişimini koruması gerekir. Kullanmanız gereken yaklaşım, uygulamanızın hedef API düzeyine bağlıdır.

Uygulamanız Android 11'i hedefliyorsa
  1. Eski depolama modelini korumak için preserveLegacyExternalStorage işaretini true olarak ayarlayın. Böylece uygulamanız, Android 11'i hedefleyen yeni sürüme geçen kullanıcıların verilerini taşıyabilir.

  2. Uygulamanızın Android 10 cihazlarda eski depolama konumundaki dosyalarınıza erişmeye devam edebilmesi için kapsamlı depolama alanının kapsamı dışında kalmayı seçme işlemine devam edin.

Uygulamanız Android 10'u hedefliyorsa

Android sürümleri genelinde uygulamanızın davranışını sürdürmeyi kolaylaştırmak için kapsamlı depolamayı devre dışı bırakın.

Uygulama verilerini taşı

Uygulamanız taşınmaya hazır olduğunda aşağıdaki yaklaşımı kullanın:

  1. Android 10 veya önceki sürümleri hedefleyin.
  2. Uygulamanızın taşımanız gereken dosyalara erişebilmesi için kapsamlı depolama alanını devre dışı bırakın.
  3. Dosyaları /sdcard/ altındaki mevcut konumundan kapsamlı depolama alanıyla erişilebilen bir konuma taşımak için File API'yi kullanan bir kod dağıtın:

    1. Tüm gizli uygulama dosyalarını getExternalFilesDir() yöntemi tarafından döndürülen dizine taşıyın.
    2. Paylaşılan tüm medya dışı dosyaları Downloads/ dizininin uygulamaya özel bir alt dizinine taşıyın.
  4. Uygulamanızın eski depolama dizinlerini /sdcard/ dizininden kaldırın.

Kullanıcılar uygulamanızın yeni sürümünü yükledikten sonra cihazlarında veri taşıma işlemini tamamlarlar. Bir analiz etkinliği oluşturarak taşıma sürecini kullanıcı tabanınız genelinde izleyebilirsiniz.

Kullanıcılar verilerini taşıdıktan sonra, Android 11'i hedeflediğiniz uygulamanızda başka bir güncelleme yayınlayın.

Diğer uygulamalarla içerik paylaşma

Uygulamanızın dosyalarını tek bir uygulamayla paylaşmak için FileProvider kullanın. Birbiriyle dosya paylaşması gereken uygulamalar için her uygulama için bir içerik sağlayıcı kullanmanızı ve daha sonra uygulamalar koleksiyona eklendikçe verileri senkronize etmenizi öneririz.

Medya dışı dosyaları önbelleğe al

Kullanmanız gereken yaklaşım, önbelleğe almanız gereken dosyaların türüne bağlıdır.

Medya dışı dosyaları bir cihaza aktarın

Medya dışı dosyaları depolamak için uygun bir varsayılan konum tanımlayın. Kullanıcıların uygulamaya özel dizinlerden daha genel erişilebilir bir konuma dosya aktarmasına izin verin. Medya dışı dosyaları cihaza aktarmak için MediaStore'un indirme veya doküman koleksiyonlarını kullanın.

Kapsamlı depolama alanını geçici olarak devre dışı bırak

Uygulamanız, kapsamlı depolama alanıyla tam uyumlu hale gelmeden önce hem testlerinizde hem de üretim uygulamanızda geçici olarak bu özelliği geçici olarak devre dışı bırakabilirsiniz.

Testlerinize katılma

Android 10 (API düzeyi 29) ve sonraki sürümlerde uygulamanızın testleri varsayılan olarak bir depolama korumalı alanında çalışır. Bu korumalı alan, uygulamanızın uygulamaya özel dizin ve herkese açık olarak paylaşılan dizinlerin dışındaki dosyalara erişmesini önler.

Bir test, ana makine için dosyalar (ör. ekran görüntüleri, hata ayıklama verileri, kapsam verileri veya performans metrikleri) veriyorsa bu dosyaları global dizinlere yazabilirsiniz. Bunu yapmak için am instrument öğesini çağıran ilgili donanıma aşağıdaki işareti ekleyin:

-e no-isolated-storage 1

Bu işaret, kullanılan test durumunun tüm davranışlarını etkiler ve çağrılan tüm test kodlarını etkiler. Bu nedenle, bu işareti kullandığınızda uygulamanızın kapsamlı depolama ile uyumluluğunu doğrulayamazsınız. Test çıkışı için bunun yerine, kabuk tarafından okunabilen uygulama kapsamlı bir depolama alanına yazmak daha iyidir. Ardından bu uygulama kapsamlı dizini alabilirsiniz. Hangi dizinden veri alınacağını belirlemek için getExternalMediaDirs() çağrısı yapın.

Üretim uygulamanızda devre dışı bırakma

Uygulamanız Android 10 (API düzeyi 29) veya önceki sürümleri hedefliyorsa üretim uygulamanızda kapsamlı depolama alanını geçici olarak devre dışı bırakabilirsiniz. Ancak Android 10'u hedeflerseniz uygulamanızın manifest dosyasında requestLegacyExternalStorage değerini true olarak ayarlamanız gerekir:

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting
       Android 10. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

Android 10 veya önceki sürümleri hedefleyen bir uygulamanın, kapsamlı depolama kullanırken nasıl davranacağını test etmek için requestLegacyExternalStorage değerini false olarak ayarlayarak bu davranışı etkinleştirebilirsiniz. Android 11'i çalıştıran bir cihazda test yapıyorsanız uygulamanızın, kapsama dahil olan veya olmayan davranışını test etmek için uygulama uyumluluğu işaretlerini de kullanabilirsiniz.

Ek kaynaklar

Android depolama alanı hakkında daha fazla bilgi edinmek için aşağıdaki materyalleri görüntüleyin:

Blog yayınları