Android'de Content Providers Nasıl Çalışır ve Onlarla Nasıl Çalışılır
Content Provider, uygulamanızın verilerine diğer uygulamalardan ve sistemin kendisinden erişim sağlamak için standartlaştırılmış bir API (URI ve CRUD işlemleri aracılığıyla) sunan bir Android bileşenidir. Kısacası: Verileri dışa doğru güvenli bir şekilde yayınlamanız, sistem seçicileriyle entegre olmanız veya uygulamalarınız arasında ortak bir API düzenlemeniz gerektiğinde Content Provider kullanın.
İçindekiler {{TOC_AUTOMATIC}}
Content Provider Nedir ve Ne Zaman Gereklidir
Content Provider, bir veri kaynağını (SQLite/Room, dosyalar, bellek veya ağ) kapsüller ve content:// URI ile query/insert/update/delete yöntemleri üzerinden erişim sağlar. Şu durumlarda kullanışlıdır:
- verilerin diğer uygulamalar tarafından erişilebilir olması gerekiyorsa (widget'lar, dışa aktarmalar, eklentiler);
- sistem bileşenleriyle entegrasyon gerekiyorsa (MediaStore, Contacts, DocumentPicker);
- ContentObserver aracılığıyla değişiklikler hakkında reaktif bildirim gerekiyorsa;
- birçok istemci için tek bir arayüz istiyorsanız.
Provider ne zaman gerekli değildir: Veriler yalnızca tek bir uygulama içinde kullanılıyorsa ve repository/DAO katmanları yeterliyse — Content Provider mimariyi yalnızca karmaşıklaştırır.
Content Provider Oluşturma ve Kaydetme — Kısa Özet
- Sözleşme (URI sabitleri, sütun adları). Örnek:
object NotesContract {
const val AUTHORITY = "com.example.notes.provider"
val BASE_URI = Uri.parse("content://$AUTHORITY")
object Notes {
val CONTENT_URI = BASE_URI.buildUpon().appendPath("notes").build()
const val _ID = "_id"; const val TITLE = "title"; const val BODY = "body"
}
}
- Provider uygulaması (minimum yöntemler):
class NotesProvider: ContentProvider() {
private lateinit var dbHelper: NotesDbHelper
override fun onCreate() = run { dbHelper = NotesDbHelper(context!!); true }
override fun query(uri: Uri, proj: Array<String>?, sel: String?, selArgs: Array<String>?, sort: String?) =
dbHelper.readableDatabase.query("notes", proj, sel, selArgs, null, null, sort).also {
it.setNotificationUri(context!!.contentResolver, uri)
}
override fun insert(uri: Uri, values: ContentValues?) = /* ekleme + notifyChange */
override fun update(...) = /* güncelleme + notifyChange */
override fun delete(...) = /* silme + notifyChange */
override fun getType(uri: Uri) = null
}
- AndroidManifest.xml içinde kayıt:
<provider
android:name=".data.NotesProvider"
android:authorities="com.example.notes.provider"
android:exported="true"
android:readPermission="com.example.notes.permission.READ"
android:writePermission="com.example.notes.permission.WRITE"/>
- İstemci ContentResolver kullanır: CONTENT_URI üzerinden query/insert/update/delete.
Güvenlik ve En İyi Uygulamalar
- Gereksiz yere provider'ı dışa açmayın: Veriler yalnızca uygulama içindeyse android:exported="false" kullanın.
- Okuma ve yazma izinlerini ayırın (readPermission / writePermission).
- Geçici paylaşım için grantUriPermission + FLAG_GRANT_* kullanın (dosyalar için FileProvider).
- Giriş parametrelerinin doğrulaması: URI'yi, selection/selectionArgs'ı kontrol edin, hazırlama olmadan SQL'e dizeleri doğrudan yerleştirmeyin.
- Minimum veri kümesini sunun, dahili ayrıntıları (tablo adları, SQL şeması) ortaya çıkarmayın.
- ContentObserver/Loader/LiveData'nın çalışması için her zaman notifyChange çağırın ve imleçte setNotificationUri ayarlayın.
Sık yapılan bir hata — uygun izinler ve kontroller olmadan android:exported="true" bırakmaktır: Bu, herhangi bir uygulamanın verilerinizi okumasına/yazmasına olanak tanır.
Yalnızca dosyaları güvenli bir şekilde paylaşmanız gerekiyorsa — AndroidX'teki FileProvider'ı kullanın: Yol yapılandırmasını ve Intent aracılığıyla geçici izin vermeyi basitleştirir.
Sık Yapılan Hatalar
- Yanlış authority (benzersiz olmalı, genellikle paket adıyla aynıdır).
- cursor.setNotificationUri çağrısını unutmak → UI değişikliklerde güncellenmez.
- getType()'ı göz ardı etmek — sistem istemcileri doğru MIME türünü bekleyebilir.
- Harici API'yi SQLite uygulamasına sıkıca bağlamak — migrasyonlarda istemcileri bozar.
SSS
- Room için Content Provider gerekli mi? Hayır, Room yerel sorguları karşılar. Provider yalnızca diğer uygulamalarla veri alışverişi veya sistem entegrasyonu için gereklidir.
- Tek bir dosya nasıl doğru şekilde paylaşılır? FileProvider ve FLAG_GRANT_READ_URI_PERMISSION bayrağı içeren Intent kullanın.
- Authority çakışması nasıl hata ayıklanır? Yüklü tüm uygulamaların manifest dosyasını kontrol edin ve benzersiz bir ad kullanın (genellikle paket + ".provider").
Bu kurallar ve örnekler seti, Content Provider'ın ne zaman haklı çıkarıldığını, nasıl uygulanacağını ve verileri dışa yayınlarken tipik hatalardan nasıl kaçınılacağını hızlıca anlamınızı sağlayacaktır.