Content Provider, uygulamalar arasında veri erişimi için birleşik bir arayüz sağlayan bir Android bileşenidir. Fiziksel depolamayı (SQLite, dosyalar, ağ kaynakları) soyutlar ve ContentResolver aracılığıyla güvenli bilgi alışverişini sağlar. Android Developer Guide, 2026'ya göre, Content Provider, Activity, Service ve BroadcastReceiver ile birlikte Android uygulamasının dört ana bileşeninden biridir. Görevi, okuma ve yazma izin kontrolü ile verileri diğer uygulamalar için kullanılabilir hale getirmektir.
Önemli Noktalar
Content Provider, merkezi bir veri deposuna erişimi yöneten ve bunu birleşik bir sözleşme arayüzü aracılığıyla diğer uygulamalara sağlayan bir Android bileşenidir. Depolama uygulama ayrıntılarını gizler: veriler SQLite'da, dosya sisteminde, bulutta saklanabilir veya bir ağ isteğinin sonucu olabilir.
Android, sistem verileri için yerleşik Content Provider'lar içerir — ContactsContract, MediaStore, CalendarContract, CallLog. Üçüncü taraf uygulamalar da güvenli veri alışverişi için kendi sağlayıcılarını oluşturabilir. Her sağlayıcı, URI'nin ilk bölümünü oluşturan benzersiz bir dize olan authority ile AndroidManifest.xml'de kaydedilir.
Content Provider istemci-sunucu modelinde çalışır. Sağlayıcı, altı zorunlu metodu uygulayan bir sunucu görevi görür: query, insert, update, delete, getType ve onCreate. İstemci (başka bir uygulama), ContentResolver aracılığıyla sağlayıcıya erişir ve ContentResolver, Android'in IPC mekanizması aracılığıyla çağrıları sağlayıcının ilgili metotlarına çevirir.
Her Content Provider, content:// şemasının bir URI'si ile tanımlanır. Örneğin, content://com.example.app.provider/items. İlk bölüm authority (com.example.app.provider), manifestoda sağlayıcı sınıfına bağlanır. /items yolu bir tabloyu, /items/5 ise ID=5 olan belirli bir kaydı işaret eder.
Bir uygulama ContentResolver.query(URI) çağrısı yaptığında, Android çağrı yapan paketin izinlerini kontrol eder, authority ile sağlayıcıyı bulur ve henüz çalışmıyorsa sürecini başlatır. Sağlayıcı sorguyu yürütür ve sonucu içeren bir Cursor nesnesi döndürür, böylece istemci kayıtlar üzerinde dolaşabilir.
ContentProvider sınıfı, altı soyut metodun uygulanmasını gerektirir. Her metot bir URI alır ve işlem türüne karşılık gelen bir sonuç döndürür. Sistem bu metotları herhangi bir süreçten çağırır, bu nedenle iş parçacığı güvenli olmalı ve yürütmeyi uzun süre engellememelidir.
query metodu bir URI, sütunlardan oluşan bir projection dizisi, argümanlarla birlikte bir selection dizesi ve bir sıralama düzeni alır. Verilerle birlikte bir Cursor döndürür. Uygulamada, UriMatcher kullanarak URI'yi ayrıştırmanız ve veritabanında ilgili SQL sorgusunu yürütmeniz gerekir.
Bu metotlar depodaki verileri değiştirir. insert, ContentValues — anahtar-değer çiftleri — alır ve yeni kaydın URI'sini döndürür. update ve delete, kayıtları filtrelemek için bir selection alır ve etkilenen satır sayısını döndürür. Verileri değiştirdikten sonra sağlayıcı, ContentResolver.notifyChange aracılığıyla bunu bildirmelidir.
| Metot | Amaç | Dönüş |
|---|---|---|
| query | URI ile veri alma | Cursor veya null |
| insert | Yeni kayıt ekleme | Yeni kaydın URI'si |
| update | Mevcut kayıtları güncelleme | int (satır sayısı) |
| delete | Kayıtları silme | int (satır sayısı) |
| getType | URI için MIME türü | String |
| onCreate | Sağlayıcı başlatma | boolean |
ContentResolver, sistemdeki tüm Content Provider'larla çalışmak için tek bir erişim noktasıdır. İstemci uygulama, sağlayıcı metotlarını asla doğrudan çağırmaz — yalnızca Android'in bağlamdan aldığı ContentResolver aracılığıyla çağırır. ContentResolver'daki CRUD işlemleri, sağlayıcıdakiyle aynı adlara sahiptir ancak doğrudan referanslar yerine URI alır.
Sağlayıcı içinde gelen URI'leri ayrıştırmak için UriMatcher kullanılır. Bir URI'yi sayısal bir koda eşlemenizi sağlar — örneğin, content://authority/items URI'si kod 1'i, content://authority/items/# ise kod 2'yi verir. Bu, her metotta manuel URI dizesi ayrıştırma ihtiyacını ortadan kaldırır.
// Kişilere erişmek için ContentResolver kullanma
val uri = ContactsContract.Contacts.CONTENT_URI
val cursor = contentResolver.query(
uri,
arrayOf(ContactsContract.Contacts.DISPLAY_NAME),
null, null, null
)
cursor?.use {
while (it.moveToNext()) {
val name = it.getString(it.getColumnIndexOrThrow(
ContactsContract.Contacts.DISPLAY_NAME
))
Log.d("Kişiler", "Ad: $name")
}
}
Cursor kullanımdan sonra her zaman kapatılmalıdır — yukarıdaki örnekte use işlevi (Kotlin uzantısı) bunu yapar. Cursor kapatılmazsa, Binder havuzundaki verilere bir referans tuttuğu için bellek sızıntısı oluşur. UI senaryoları için LiveData/Flow ile CursorLoader veya Room kullanın.
Kendi Content Provider'ınızı oluşturmak, ContentProvider sınıfını genişletmekle başlar. Sağlayıcı, SQLiteOpenHelper aracılığıyla bir SQLite veritabanıyla çalışır ve sorgu türünü belirlemek için UriMatcher kullanır. Not listesini yönetmek için minimum bir uygulama düşünün.
Sağlayıcı, AndroidManifest.xml içinde application etiketinin içine kaydedilir. authorities özniteliği benzersiz bir tanımlayıcı belirler ve exported, diğer uygulamaların sağlayıcıya erişip erişemeyeceğini belirler. exported=true olmadan, sağlayıcı yalnızca uygulamanız içinde erişilebilir.
// Notlar için Content Provider örneği
class NotesProvider : ContentProvider() {
companion object {
const val AUTHORITY = "com.example.app.notes"
const val NOTES_PATH = "notes"
const val NOTES_URI = "content://$AUTHORITY/$NOTES_PATH"
const val NOTES_ID = "content://$AUTHORITY/$NOTES_PATH/#"
private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
addURI(AUTHORITY, NOTES_PATH, 1)
addURI(AUTHORITY, "$NOTES_PATH/#", 2)
}
}
override fun query(uri: Uri, projection: Array<String>?,
selection: String?, args: Array<String>?, sort: String?): Cursor? {
return when (uriMatcher.match(uri)) {
1 -> dbHelper.readableDatabase.query(TABLE_NOTES,
projection, selection, args, null, null, sort)
2 -> dbHelper.readableDatabase.query(TABLE_NOTES,
projection, "_id=?", arrayOf(uri.lastPathSegment), null, null, null)
else -> throw IllegalArgumentException("Unknown URI: $uri")
}
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
val id = dbHelper.writableDatabase.insert(TABLE_NOTES, null, values)
context?.contentResolver?.notifyChange(uri, null)
return ContentUris.withAppendedId(uri, id)
}
override fun delete(uri: Uri, selection: String?, args: Array<String>?): Int {
val count = dbHelper.writableDatabase.delete(TABLE_NOTES, selection, args)
context?.contentResolver?.notifyChange(uri, null)
return count
}
// getType, update, onCreate kısaltma amacıyla atlandı
}
Sağlayıcı sınıfını oluşturduktan sonra, android:authorities ve android:exported öznitelikleriyle (sağlayıcı herkese açıksa true) manifestoya kaydedilmelidir. Sistem, ilk erişimde bir sağlayıcı örneği oluşturur — bu UI iş parçacığında gerçekleşir, bu nedenle onCreate hızlı yürütülmelidir.
Content Provider, veri erişimini iki düzeyde yönetmeye olanak tanır: okuma izinleri ve yazma izinleri. Bunlar manifestoda android:readPermission ve android:writePermission öznitelikleriyle belirlenir. İstemci uygulamanın ilgili izni yoksa, sistem SecurityException ile çağrıyı reddeder.
Android, FLAG_GRANT_READ_URI_PERMISSION ve FLAG_GRANT_WRITE_URI_PERMISSION bayrakları aracılığıyla geçici izinleri destekler. Bu, bir uygulamanın Intent aracılığıyla başka bir uygulamaya bir dosya URI'si göndermesi durumunda kullanışlıdır — alıcı, sınırlı bir süre için yalnızca belirli URI'ye erişim sağlar. Sistem, alıcı uygulama sona erdikten sonra geçici izni iptal eder.
Sistem sağlayıcıları için Android, uygulama manifestosunda belirli izinlerin belirtilmesini gerektirir. Örneğin, kişilere erişmek READ_CONTACTS gerektirir ve takvime erişmek READ_CALENDAR gerektirir. Android 6'dan itibaren bu izinler kurulum sırasında değil, çalışma zamanında istenir.
Sıkça Sorulan Sorular
Content Provider, ContentResolver aracılığıyla uygulamalar arasında veri alışverişi için standart bir arayüz sağlayan Android bileşenidir. Depolama yöntemini (SQLite, dosyalar, ağ) soyutlar ve okuma ve yazma izin kontrolü ile güvenli veri erişimi sağlar.
Authority, AndroidManifest.xml'de belirtilen sağlayıcının benzersiz tanımlayıcı dizesidir. URI content://authority/path'in ilk bölümünü oluşturur ve sistem tarafından ContentResolver çağrılarını doğru sağlayıcıya yönlendirmek için kullanılır. Authority, cihazdaki tüm uygulamalar arasında benzersiz olmalıdır.
UriMatcher, URI'leri sayısal kodlara eşler. addURI ile desenler eklersiniz, ardından gelen bir URI için kodu almak üzere match'i çağırırsınız. Bu, query, insert, update, delete metotlarının hangi tablo veya kaydın istendiğini belirlemesine ve veritabanında ilgili işlemi gerçekleştirmesine olanak tanır.
Evet, Cursor kullanımdan sonra her zaman kapatılmalıdır. Cursor kapatılmazsa, sağlayıcının verilerine bir Binder referansı tuttuğu için bellek sızıntısı oluşur. Kotlin'de otomatik kapatma için use işlevini, Java'da ise try-with-resources veya finally bloğunda cursor.close() kullanın.
Content Provider uygulamalar arası veri erişimi için bir bileşendir, SQLiteDatabase ise tek bir uygulama için dahili depolama mekanizmasıdır. Content Provider URI arayüzü ve izin kontrolü sağlarken, SQLiteDatabase işletim sistemi düzeyinde güvenlik mekanizmaları olmadan doğrudan veritabanıyla çalışır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun