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

Android 10, kullanıcılara dosyaları üzerinde daha fazla kontrol olanağı sağlamak ve dosya yığınını sınırlandırmak amacıyla kapsamlı depolama adı verilen 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 şeklini 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ğitim 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 örneklerinden 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
Tüm resim veya video dosyalarını göster Tüm Android sürümleri için aynı yaklaşımı kullanın.
Belirli bir klasördeki resimleri veya videoları gösterme Tüm Android sürümleri için aynı yaklaşımı kullanın.
Fotoğraflardan konum bilgilerine erişme Uygulamanız kapsamlı depolama alanı kullanıyorsa tek 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 tek 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 Tüm Android 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 Android 9 ve önceki sürümler için olan yaklaşımı kullanın.
Mevcut tek bir resmi içe aktarma Tüm Android sürümleri için aynı yaklaşımı kullanın.
Tek bir resim çekin Tüm Android sürümleri için aynı yaklaşımı kullanın.
Medya dosyalarını diğer uygulamalarla paylaşma Tüm Android sürümleri için aynı yaklaşımı kullanın.
Medya dosyalarını belirli bir uygulamayla paylaşma Tüm Android sürümleri için aynı yaklaşımı kullanın.
Doğrudan dosya yollarını kullanan kod veya kitaplıklardan dosyalara erişme Android 11 için tek bir yaklaşım kullanın. Android 10 için kapsamlı depolamayı devre dışı bırakıp 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 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österme

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde özetlenen en iyi uygulamaları izleyerek READ_EXTERNAL_STORAGE izni 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. Bununla birlikte, dosyanın her zaman kullanılabilir olduğunu varsaymayın. Oluşabilecek dosya tabanlı G/Ç hatalarını işlemeye hazır olun.

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 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 iznine ihtiyacı vardır.

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

Uygulamanız kapsamlı depolama alanı 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ı kullanabilirsiniz.

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ışıyor

Şu yaklaşımı kullanın:

  1. MediaStore.createWriteRequest() veya MediaStore.createTrashRequest() kullanarak uygulamanızın yazma ya da silme isteği için beklemedeki bir intent oluşturun ve ardından bu amacı çağırarak kullanıcıdan bir grup dosyayı 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 ihtiyacı olduğ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ümlerdeki yaklaşımı kullanmaya devam edin.

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

Şu yaklaşımı kullanın:

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

Mevcut tek bir resmi içe aktarma

Mevcut tek bir resmi içe aktarmak istediğinizde (örneğin, bir kullanıcı 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 özetlenen en iyi uygulamaları izleyerek READ_EXTERNAL_STORAGE izni 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 öğesini 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 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.

Medya dosyalarını belirli bir uygulamayla paylaşma

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

Dosyalara doğrudan dosya yolları 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ışıyor

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde özetlenen en iyi uygulamaları izleyerek READ_EXTERNAL_STORAGE izni isteyin.
  2. Doğrudan dosya yollarını kullanarak dosyalara erişin.

Daha fazla bilgi için doğrudan dosya yollarını kullanarak medya dosyalarını açma bölümüne 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ümlerdeki yaklaşımı kullanmaya devam edin.

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

Şu yaklaşımı kullanın:

  1. Uygulama İzinleri İsteme bölümünde özetlenen en iyi uygulamaları izleyerek WRITE_EXTERNAL_STORAGE izni isteyin.
  2. Doğrudan dosya yollarını kullanarak dosyalara erişin.

Medya dışı dosyaları işleme

Bu bölümde, medya dışı dosyaların ele alınmasına dair 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ı verilmiştir.

Kullanım alanı Özet
Doküman dosyası açma Tüm Android 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 konumundan 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ı depolamayı devre dışı bırakın.
Diğer uygulamalarla içerik paylaşma Tüm Android sürümleri için aynı yaklaşımı kullanın.
Medya dışı dosyaları önbelleğe alma Tüm Android sürümleri için aynı yaklaşımı kullanın.
Medya harici dosyaları cihaza aktarma Uygulamanız kapsamlı depolama alanı kullanıyorsa tek 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ını kullanın. Sistem seçicinin, seçim yapması için kullanıcıya sunacağı dosya türlerini filtrelemek istiyorsanız setType() veya EXTRA_MIME_TYPES öğesini 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ışıyor

Ş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 yapın:
    • 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şıma

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ı depolamayla 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şilebilir olan 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, uygulamanızın Android 11'i hedefleyen yeni sürümüne geçtikten sonra 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

Android sürümlerinde uygulamanızın davranışını daha kolay korumak 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ı uygulayı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ı depolama alanını devre dışı bırakın.
  3. Dosyaları /sdcard/ altındaki geçerli konumlarından kapsamlı depolamayla 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önteminin döndürdüğü dizine taşıyın.
    2. Medya harici paylaşılan 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 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. Tüm uygulamalar arasında dosya paylaşması gereken uygulamalarda her uygulama için bir içerik sağlayıcı kullanmanızı ve daha sonra uygulamalar koleksiyona eklendikçe verileri senkronize etmenizi öneririz.

Medya harici dosyaları önbelleğe alın

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

Medya dışı dosyaları cihaza aktarma

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

Kapsamlı depolamayı geçici olarak devre dışı bırakma

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

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 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ı genel dizinlere yazabilirsiniz. Bunu yapmak için am instrument çağıran ilgili araca 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ı depolamayla 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. Android 11 çalıştıran bir cihazda test yapıyorsanız uygulamanızın davranışını kapsamlı depolama alanı ile veya bu depolama alanı olmadan test etmek için uygulama uyumluluk işaretlerini de kullanabilirsiniz.

Ek kaynaklar

Android depolama alanı hakkında daha fazla bilgi edinmek için aşağıdaki materyallere göz atın:

Blog yayınları