Android'de content://, ContentProvider ve dosyalarla çalışma
Kısaca: content://, bir ContentProvider tarafından yönetilen verilere erişim için kullanılan URI şemasıdır; okuma/yazma işlemleri için ContentResolver'ı, basit dosya paylaşımı için FileProvider'ı ve harici belgeleri seçmek/erişmek için Storage Access Framework (SAF) kullanın. Aşağıda projenizde hemen uygulayabileceğiniz pratik örnekler ve öneriler yer almaktadır.
ContentProvider nedir ve ne zaman gereklidir
ContentProvider, verilere (tablo tabanlı ve dosya tabanlı) erişimi kapsüller ve ContentResolver aracılığıyla tek tip bir API sunar. Şu durumlarda kullanın:
- verileri diğer uygulamalara açmak (widget'lar, senkronizasyon, üçüncü taraf istemciler);
- hak kontrolü olan tek tip bir CRUD arayüzü uygulamak. Veriler yalnızca uygulama içinde kullanılıyorsa ContentProvider oluşturmanıza gerek yoktur (Room/dosyalar yeterli olacaktır).
Dosyaları basitçe paylaşmak için (bir fotoğrafı veya PDF'i Intent üzerinden paylaşmak) kendi ContentProvider'ınızı yazmak yerine androidx.core'dan FileProvider'ı yapılandırmak genellikle daha hızlı ve güvenlidir.
Temel işlemler: content:// URI'lerini okuma ve yazma
Kotlin örnekleri — minimal ve güvenilir.
InputStream olarak okuma:
context.contentResolver.openInputStream(uri)?.use { input ->
val bytes = input.readBytes()
// bytes'ı işle
}
OutputStream ile yazma:
context.contentResolver.openOutputStream(uri)?.use { out ->
out.write(data)
}
Seek/descriptor gerekiyorsa:
context.contentResolver.openFileDescriptor(uri, "r")?.use { pfd ->
FileInputStream(pfd.fileDescriptor).use { fis ->
// seek desteğiyle oku
}
}
ACTION_OPEN_DOCUMENT'dan uri alıyorsanız ve uzun vadeli erişim istiyorsanız:
val flags = intent.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
context.contentResolver.takePersistableUriPermission(uri, flags)
FileProvider, SAF ve çözüm tasarımı
FileProvider
- Manifest'te ve res/xml/file_paths.xml içinde yapılandırılır.
- Yerel dosyalar için content:// URI döndürür ve FLAG_GRANT_READ_URI_PERMISSION aracılığıyla geçici izinler vermeye olanak tanır. URI oluşturma ve gönderme örneği:
val uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.fileprovider", file)
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_STREAM, uri)
type = "image/jpeg"
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
context.startActivity(Intent.createChooser(intent, "Paylaş"))
Storage Access Framework (DocumentsProvider)
- Kullanıcının uygulama dışında dosya/klasör seçmesine veya bulut sağlayıcılarıyla çalışmasına ihtiyaç olduğunda kullanın.
- Android 11+ üzerindeki Scoped Storage için uygundur.
Uygulamalar arasında file:// URI'lerini aktarmayın — bu özel duruma yol açar. Gereksiz yere provider için android:exported="true" ayarlamayın.
Sık yapılan hatalar
- Intent gönderirken FLAG_GRANT_READ_URI_PERMISSION eksik → alıcı URI'yi açamaz.
- Manifest'te yanlış authority → getUriForFile/ContentResolver provider'ı bulamaz.
- Kapatılmayan akışlar/ParcelFileDescriptor → kaynak sızıntıları.
- content:// yerine file:// kullanımı → modern sürümlerde SecurityException.
SSS
- Veritabanı için her zaman ContentProvider yapmak gerekir mi? Yalnızca veriler diğer uygulamalar veya sistem bileşenleri tarafından kullanılacaksa.
- FileProvider yerine SAF'i ne zaman seçmeliyim? Kullanıcının dosya/klasör seçmesi gerekiyorsa veya bulut depolamaya erişim gerekiyorsa.
- Seçiciden gelen uri'ye uzun vadeli erişim nasıl verilir? Sonucu aldıktan sonra takePersistableUriPermission çağırın.
Yayınlama öncesi kontrol listesi:
- FileProvider için doğru authority ve android:grantUriPermissions.
- Paylaşım sırasında addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION).
- Tüm akışların ve tanımlayıcıların kapatılmış olması.
- Provider için minimum izinler/haklar, harici akışları işlemeden önce MIME/tür boyutu kontrolü.
İsterseniz hazırlayabilirim:
- UI içeren hazır ContentProvider + Room (Kotlin) örneği;
- yapınıza uygun res/xml/file_paths.xml dosyası;
- Scoped Storage'a geçiş talimatları.