Context, ContentProvider ve content:// ile Nasıl Çalışılır (Java/Kotlin)
Kısa cevap: Çevreye ve sistem servislerine erişim için Context'i kullanın; verilerin birleşik ve güvenli şekilde paylaşımı için ContentProvider + content:// URI'sini kullanın; bu URI'leri açmak ve paylaşmak için Intent.data/scheme kullanın; dosya alışverişinde her zaman applicationContext ve FileProvider'a öncelik verin.
İçindekiler {{TOC_AUTOMATIC}}
Context: Roller, Türler ve Doğru Kullanım
Context, uygulamanın "çevresi"dir: kaynaklar, dosya sistemi, ContentResolver ve sistem servisleri. Temel pratik tavsiye, uzun ömürlü nesnelere (repository'ler, singleton'lar) applicationContext'i aktarmak ve Activity context'ini yalnızca kısa ömürlü UI işlemleri için kullanmaktır.
Hangi Context'in Ne Zaman Kullanılacağı:
- applicationContext — repository'ler, veritabanı, UI içermeyen servis başlatmaları için.
- Activity/Fragment context — Inflater, UI oluşturma, startActivity() için.
- BroadcastReceiver (onReceive) — context, onReceive yürütme süresiyle sınırlıdır.
Örnekler: Kotlin — repository applicationContext alır:
class MyRepository(private val context: Context) {
fun getAppVersion(): String =
context.packageManager.getPackageInfo(context.packageName, 0).versionName ?: "unknown"
}
Sık yapılan bir hata, Activity veya View referansını singleton'da tutmaktır → bellek sızıntıları. Uzun ömürlü nesneler için applicationContext kullanın.
ContentProvider ve content://: Yapı, Uygulama ve Kullanım
ContentProvider, veri alışverişi ve kapsülleme için bir soyutlamadır: erişimi ContentResolver ve content:// şemalı URI üzerinden standartlaştırır. URI'ler genellikle şu şekildedir: content://authority/path/.../[id]
Örnekler:
- content://com.android.contacts/contacts
- content://com.example.notes.provider/notes/42
ContentResolver'ın temel metodları:
- query(uri, projection, selection, selectionArgs, sort)
- insert(uri, values)
- update(uri, values, selection, args)
- delete(uri, selection, args)
- openInputStream(uri) / openOutputStream(uri)
Minimal provider yapısı (önemli noktalar):
- ContentProvider'dan türetin ve onCreate, query, insert, update, delete, getType metodlarını geçersiz kılın;
- AndroidManifest'te provider'ı kaydedin, authorities ve exported/permissions değerlerini belirtin;
- Değişikliklerde context?.contentResolver?.notifyChange(uri, null) çağrısını yapın.
Güvenliğin anahtarı: Hassas verileri içeren provider'ı, URI ve işlemler üzerinde hak kontrolü ve kısıtlamalar olmadan dışa açmayın.
Intent, data ve scheme: İçeriği Aktarma ve Açma
Intent, data alanında URI ve type alanında MIME türü içerebilir. Bu, diğer bileşenlerin/uygulamaların bir kaynağı açma/işleme isteğinde bulunmasını sağlar:
Kotlin — URI ile kişi açma:
fun openContact(context: Context, contactUri: Uri) {
val intent = Intent(Intent.ACTION_VIEW, contactUri)
context.startActivity(intent)
}
scheme — iki nokta üst üste işaretinden önceki URI kısmı: content, file, https, tel. intent-filter içinde android:scheme, android:host ve android:pathPrefix belirterek Activity'nin belirli URI'leri kabul etmesini sağlayabilirsiniz.
Uygulamalar arası dosya paylaşımı için:
- file:// yerine content:// URI veren FileProvider kullanın;
- Intent.FLAG_GRANT_READ_URI_PERMISSION bayrağını aktarın.
Java — FileProvider ile PDF açma:
Uri uri = FileProvider.getUriForFile(context, "com.example.app.fileprovider", pdfFile);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(intent);
Uygulamalar arası dosya paylaşımında her zaman FileProvider ve content:// URI kullanın — bu güvenlidir ve modern Android sürümlerindeki dosya erişim politikasına uygundur.
Pratik Senaryolar: Kısa ve Uygulanabilir
- Galeriden görüntü alma:
- ActivityResultContracts.GetContent() başlatın → content:// URI alırsınız.
- contentResolver.openInputStream(uri) ile Bitmap'i kod çözün.
- Dosya paylaşma:
- FileProvider.getUriForFile(...) ile URI alın.
- Intent.ACTION_SEND oluşturun, EXTRA_STREAM ekleyin ve FLAG_GRANT_READ_URI_PERMISSION ayarlayın.
- Verilere genel erişim:
- Net URI şeması ve izinlerle ContentProvider uygulayın.
- Diğer uygulamaların belirli bir kaynağı açabilmesi için VIEW intent-filter'lı Activity ekleyin.
Mimari Önerileri ve En İyi Uygulamalar
- ContentResolver erişimini repository/data-source içinde kapsülleyin; sahte nesnelerle (mock ContentResolver) test edin.
- URI dizelerini sabit kodlamayın — URI'leri merkezi olarak oluşturan bir yardımcı program yazın.
- Provider işlemlerini IO thread'inde gerçekleştirin (coroutine'ler, Executors).
- Verileri dışa açarken izinleri, çağıranın doğrulamasını (örneğin UID bağlama) düşünün ve harici istemciler için erişilebilir işlemleri en aza indirin.
Sık Yapılan Hatalar
- Activity-context'i uzun ömürlü nesnelerde tutmak → bellek sızıntıları.
- content:// (FileProvider) yerine file:// kullanmak → yeni Android sürümlerinde erişim hataları.
- URI'yi başka bir uygulamaya aktarırken FLAG_GRANT_READ_URI_PERMISSION belirtmemek.
- Hassas verileri içeren ContentProvider'ı kısıtlama veya izinler olmadan dışa açmak.
Hassas verileri içeren ContentProvider'ı hiçbir zaman net izinler ve çağıran uygulama doğrulaması olmadan dışa açmayın. Aksi takdirde verilerinizi herhangi bir üçüncü taraf uygulaması okuyabilir/değiştirebilir.
SSS
S: Dahili veriler için her zaman ContentProvider uygulamak gerekir mi? C: Hayır. Veriler yalnızca uygulama içinde kullanılıyorsa provider oluşturmanız gerekmez. ContentProvider, erişimi standartlaştırmak ve harici uygulamalarla veri alışverişi yapmak veya soyutlamaları kullanmak (örneğin modüler mimaride Room + ContentProvider) için gereklidir.
S: Başka bir uygulamaya dosya erişimini nasıl güvenli şekilde verebilirim?
C: FileProvider aracılığıyla ve FLAG_GRANT_READ_URI_PERMISSION bayrağıyla content:// URI vererek; manifest'te
S: URI ve authority nerede saklanmalı? C: Tek bir yerde — veri modülü içindeki sabitler/yardımcı programlarda; dizeleri uygulama geneline sabit kodlamayın.
Artık hazır bir pratik resminiz var: Context — çevreye erişim, ContentProvider ve content:// — verilere birleşik erişim noktası, Intent.data/scheme — açma ve paylaşım mekanizması. Context kısıtlamalarına uyun, FileProvider kullanın ve iyi düşünülmüş bir izin sistemi kurun — verileriniz hem erişilebilir hem de güvenli olacaktır.