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

Android 10, kullanıcılara dosyaları üzerinde daha fazla kontrol sağlamak ve dosya dağınıklığını sınırlamak amacıyla kapsamlı depolama adlı uygulamalar için yeni bir depolama alanı paradigmasını kullanıma 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 açıklanan yaygın depolama alanı kullanım alanlarıyla ilgili en iyi uygulamaları takip edin. Kullanım alanları iki kategoriye ayrılır: medya dosyalarını işleme ve medya olmayan dosyaları işleme.

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

Medya dosyalarını işleme

Bu bölümde, medya dosyalarının (video, resim ve ses dosyaları) işlenmesiyle ilgili yaygın kullanım alanlarından bazıları açıklanmakta 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 her bir bölüme bağlantı 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 bir yaklaşım kullanın. Uygulamanız, kapsamlı depolamayı devre dışı bırakırsa farklı bir yaklaşım kullanın.
Yeni indirilenler için depolama konumu tanımlama Uygulamanız kapsamlı depolama alanı kullanıyorsa bir yaklaşım kullanın. Uygulamanız, kapsamlı depolamayı devre dışı bırakırsa farklı bir yaklaşım kullanın.
Kullanıcı medya dosyalarını bir 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 için kapsamlı depolamayı devre dışı bırakıp bunun yerine Android 9 ve önceki sürümler için olan yaklaşımı kullanın.
Mevcut tek bir resmi içe aktarma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Tek bir resim çekin 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.
Belirli bir uygulamayla medya dosyaları paylaşma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Dosyalara doğrudan dosya yollarını kullanan kod veya kitaplıklardan erişme Android 11 için tek bir yaklaşım kullanın. Android 10 için kapsamlı depolamayı devre dışı bırakıp bunun yerine Android 9 ve önceki sürümler için olan yaklaşımı kullanın.

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

query() API'sini kullanarak bir medya koleksiyonunu sorgulama. 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österme

Ş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ı MediaColumns.DATA değerine göre alın. Bu değer, diskteki medya öğesinin mutlak dosya sistemi yolunu içerir.

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ı ele almaya hazır olun.

Öte yandan, bir medya dosyasını 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 rehberinin 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 izni olması gerekir.

Yeni indirilenler için depolama konumu tanımla

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

Başka uygulamaların dosyalara erişmesi gerekiyorsa indirmeler veya doküman koleksiyonları için iyi tanımlanmış medya koleksiyonları kullanmayı düşünebilirsiniz.

Android 11 ve sonraki sürümlerde harici uygulamaya özgü dizininizin içindeki dosyalara, bu dosyaları getirmek için DownloadManager kullanıyor olsanız bile diğer uygulamalar erişemez.

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

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

Tek bir işlemde birden çok medya dosyasını değiştirme veya silme

Uygulamanızın üzerinde çalıştığı Android sürümlerini temel alan bir mantık ekleyin.

Android 11'de çalıştırma

Şu yaklaşımı kullanın:

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

    • İzin verildiyse değiştirme veya silme işlemiyle 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ı nasıl yöneteceğiniz hakkında daha fazla bilgi edinin.

Android 10'da çalışıyor

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

Android 9 veya önceki bir sürümde çalışma

Ş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.

Zaten var olan tek bir resmi içe aktarın

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

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

Ş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 kullanma

Kullanıcıdan içe aktarılacak bir resim seçmesini isteyen ACTION_GET_CONTENT amacını 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 kullanabilirsiniz.

Tek bir resim çekin

Uygulamanızda kullanmak üzere tek bir resim çekmek istediğinizde (örneğin, bir kullanıcı profilinin fotoğrafı olarak kullanmak için) kullanıcıdan cihazın kamerasını kullanarak bir fotoğraf çekmesini istemek için ACTION_IMAGE_CAPTURE amacından yararlanın. 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.

Belirli bir uygulamayla medya dosyaları paylaşma

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

Dosyalara, doğrudan dosya yollarını kullanan kod veya kitaplıklardan erişme

Uygulamanızın üzerinde çalıştığı Android sürümlerini temel alan bir mantık ekleyin.

Android 11'de çalıştırma

Ş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ı depolamayı devre dışı bırakın ve bu işlemi gerçekleştirmek için Android 9 ve önceki sürümler için yaklaşımı kullanmaya devam edin.

Android 9 veya önceki bir sürümde çalışma

Ş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ışındaki dosyaları işleme

Bu bölümde, medya harici 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 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şıyın Mümkün olduğunda dosyalarınızı kapsamlı depolama alanına taşıyın. Gerektiğinde Android 10 için kapsamlı depolamayı 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 dışı dosyaları önbelleğe alma Android'in tüm sürümleri için aynı yaklaşımı kullanın.
Medya dışındaki dosyaları bir cihaza aktarma Uygulamanız kapsamlı depolama alanı kullanıyorsa bir yaklaşım kullanın. Uygulamanız, kapsamlı depolamayı devre dışı bırakırsa farklı bir yaklaşım kullanın.

Doküman dosyası aç

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

Örneğin, aşağıdaki kodu kullanarak tüm PDF, ODT ve TXT dosyalarını 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 birimleri SD kartları içerir. Belirli bir depolama hacmiyle ilgili bilgilere StorageVolume sınıfını kullanarak erişebilirsiniz.

Uygulamanızın üzerinde çalıştığı Android sürümünü temel alan bir mantık ekleyin.

Android 11'de çalıştırma

Ş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'ler kullanarak doğrudan dosya yolu erişimi.

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

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

Eski bir depolama konumundaki mevcut dosyaları taşıyın

Bir dizin, uygulamaya özel bir dizin veya herkese açık bir paylaşılan dizin değilse eski depolama konumu olarak kabul edilir. Uygulamanız eski bir depolama konumunda dosya oluşturuyor veya kullanıyorsa uygulamanızın dosyalarını kapsamlı depolama ile erişilebilen konumlara taşımanızı ve kapsamlı depolama alanındaki dosyalarla çalışmak için gerekli uygulama değişikliklerini yapmanızı öneririz.

Veri taşıma için eski depolama konumuna erişimi koruma

Uygulama dosyalarını kapsamlı depolamayla erişilebilen konumlara taşıyabilmesi için uygulamanızın eski depolama konumuna erişimini koruması gerekir. Kullanmanız gereken yaklaşım, uygulamanızın hedef API seviyesine 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, uygulamanızın Android 11'i hedefleyen yeni sürümüne geçtiğinde kullanıcıların verilerini taşıyabilir.

  2. Uygulamanızın Android 10 cihazlarda eski depolama alanındaki dosyalarınıza erişmeye devam edebilmesi için kapsamlı depolama alanını devre dışı bırakmaya devam edin.

Uygulamanız Android 10'u hedefliyorsa

Uygulamanızın Android sürümlerindeki 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 bir sürümü hedefleyin.
  2. Uygulamanızın, taşımanız gereken dosyalara erişebilmesi için kapsamlı depolamayı devre dışı bırakın.
  3. Dosyaları /sdcard/ altındaki mevcut konumlarından kapsamlı depolama ile erişilebilen bir konuma taşımak için File API'yi kullanan kodu dağıtın:

    1. Tüm gizli uygulama dosyalarını, getExternalFilesDir() yöntemi tarafından döndürülen dizine taşıyın.
    2. Medya dışındaki paylaşılan tüm 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 tamamlar. Bir analiz etkinliği oluşturarak kullanıcı tabanınız genelinde taşıma sürecini 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. Tüm uygulamalar arasında dosya paylaşması gereken uygulamalar söz konusu olduğunda her uygulama için bir içerik sağlayıcı kullanmanızı ve koleksiyona eklenen uygulamalar eklendikçe verileri senkronize etmenizi öneririz.

Medya olmayan 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ışındaki dosyaları bir cihaza aktarın

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

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

Uygulamanız, kapsamlı depolamayla tam olarak uyumlu hale gelmeden önce, hem testlerinizde hem de üretim uygulamanızda geçici olarak kapsam dışında kalmayı seçebilirsiniz.

Testlerinizde devre dışı bırakma

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

Bir test ana makine için dosyalar (ör. ekran görüntüleri, hata ayıklama verileri, kapsam verileri veya performans metrikleri) oluşturursa bu dosyaları global dizinlere yazabilirsiniz. Bunu yapmak için am instrument yöntemini çağıran ilgili bant genişliğine aşağıdaki işareti ekleyin:

-e no-isolated-storage 1

Bu işaret, donatılmış test durumunun tüm davranışını etkiler ve çağrılan tüm test kodunu 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ı depolama alanına yazmak daha iyidir. Daha sonra, bu uygulama kapsamlı dizini alabilirsiniz. Hangi dizinden veri çekileceğini 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ı depolamayı 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ı depolamayı kullanırken nasıl davranacağını test etmek için requestLegacyExternalStorage değerini false olarak ayarlayarak davranışı etkinleştirebilirsiniz. Testinizi Android 11 çalıştıran bir cihazda yapıyorsanız uygulama uyumluluğu işaretlerini kullanarak uygulamanızın davranışını kapsamlı depolama ile veya kapsamlı depolama olmadan test edebilirsiniz.

Ek kaynaklar

Android depolama alanı hakkında daha fazla bilgi için aşağıdaki materyalleri inceleyin:

Blog yayınları