Content Provider — ilovalar o'rtasida ma'lumotlarga kirish uchun yagona interfeysni ta'minlovchi Android komponentidir. U jismoniy saqlashni (SQLite, fayllar, tarmoq manbalari) abstraksiyalaydi va ContentResolver orqali xavfsiz ma'lumot almashinuvini ta'minlaydi. Android Developer Guide, 2026 ma'lumotlariga ko'ra, Content Provider Activity, Service va BroadcastReceiver bilan bir qatorda Android ilovasining to'rtta asosiy komponentidan biridir. Uning vazifasi — ma'lumotlarni boshqa ilovalarga o'qish va yozish ruxsatlarini nazorat qilish bilan taqdim etishdir.
Asosiy fikrlar
Content Provider — markazlashtirilgan ma'lumotlar omboriga kirishni boshqaruvchi va ularni boshqa ilovalarga yagona shartnoma interfeysi orqali taqdim etuvchi Android komponentidir. U saqlash tafsilotlarini yashiradi: ma'lumotlar SQLite, fayl tizimida, bulutda saqlanishi yoki tarmoq so'rovi natijasi bo'lishi mumkin.
Android tizim ma'lumotlari uchun o'rnatilgan Content Provider-larni o'z ichiga oladi — ContactsContract, MediaStore, CalendarContract, CallLog. Uchinchi tomon ilovalari ham xavfsiz ma'lumot almashinuvi uchun o'z provayderlarini yaratishi mumkin. Har bir provayder AndroidManifest.xml da authority — URI ning birinchi qismini tashkil etuvchi noyob satr ko'rsatilgan holda ro'yxatdan o'tkaziladi.
Content Provider mijoz-server modeli bo'yicha ishlaydi. Provayder oltita majburiy metodni amalga oshiruvchi server sifatida ishlaydi: query, insert, update, delete, getType va onCreate. Mijoz (boshqa ilova) provayderga ContentResolver orqali murojaat qiladi, u chaqiruvlarni Android IPC mexanizmi orqali provayderning tegishli metodlariga uzatadi.
Har bir Content Provider URI sxemasi content:// bilan identifikatsiyalanadi. Masalan, content://com.example.app.provider/items. Birinchi qism authority (com.example.app.provider) manifestda provayder sinfiga bog'lanadi. /items yo'li jadvalga, /items/5 esa ID=5 bo'lgan aniq yozuvga ishora qiladi.
Ilova ContentResolver.query(URI) ni chaqirganda, Android chaqiruvchi paketning ruxsatlarini tekshiradi, authority bo'yicha provayderni topadi va agar u hali ishga tushmagan bo'lsa, uning jarayonini boshlaydi. Provayder so'rovni bajaradi va Cursor — natijani o'z ichiga olgan va mijozga yozuvlar bo'ylab harakatlanish imkonini beruvchi obyektni qaytaradi.
ContentProvider sinfi oltita abstrakt metodni amalga oshirishni talab qiladi. Har bir metod URI ni qabul qiladi va operatsiya turiga mos natijani qaytaradi. Tizim bu metodlarni istalgan jarayondan chaqiradi, shuning uchun ular thread-safe bo'lishi va uzoq vaqt davomida bajarilishni bloklamasligi kerak.
query metodi URI, ustunlar massivi projection, argumentlar bilan selection satri va saralash tartibini qabul qiladi. Ma'lumotlar bilan Cursor qaytaradi. Amalga oshirishda URI ni UriMatcher yordamida tahlil qilish va ma'lumotlar bazasiga tegishli SQL so'rovini bajarish kerak.
Bu metodlar ombordagi ma'lumotlarni o'zgartiradi. insert ContentValues — kalit-qiymat juftliklarini qabul qiladi va yangi yozuvning URI sini qaytaradi. update va delete yozuvlarni filtrlash uchun selection qabul qiladi va ta'sirlangan qatorlar sonini qaytaradi. Ma'lumotlarni o'zgartirgandan so'ng, provayder bu haqda ContentResolver.notifyChange orqali xabardor qilishi kerak.
| Metod | Maqsad | Qaytarish |
|---|---|---|
| query | URI bo'yicha ma'lumotlarni olish | Cursor yoki null |
| insert | Yangi yozuvni qo'shish | Yangi yozuvning URI si |
| update | Mavjud yozuvlarni yangilash | int (qatorlar soni) |
| delete | Yozuvlarni o'chirish | int (qatorlar soni) |
| getType | URI uchun MIME turi | String |
| onCreate | Provayderni ishga tushirish | boolean |
ContentResolver — tizimdagi barcha Content Provider-lar bilan ishlash uchun yagona kirish nuqtasidir. Mijoz ilova hech qachon provayder metodlarini to'g'ridan-to'g'ri chaqirmaydi — faqat ContentResolver orqali, Android buni kontekstdan oladi. ContentResolver-dagi CRUD operatsiyalari provayderdagi kabi nomlarga ega, ammo to'g'ridan-to'g'ri havolalar o'rniga URI qabul qiladi.
Provayder ichida kiruvchi URI-larni tahlil qilish uchun UriMatcher ishlatiladi. U URI ni raqamli kod bilan moslashtirishga imkon beradi — masalan, content://authority/items URI si kod 1, content://authority/items/# esa kod 2 ni beradi. Bu har bir metodda URI satrini qo'lda tahlil qilish zaruratini bartaraf qiladi.
// Kontaktlarga kirish uchun ContentResolver dan foydalanish
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("Kontaktlar", "Ism: $name")
}
}
Cursor foydalanilgandan so'ng albatta yopilishi kerak — yuqoridagi misolda buni use (Kotlin kengaytma funksiyasi) amalga oshiradi. Agar Cursor yopilmasa, xotira sizib ketadi, chunki u Binder hovuzidagi ma'lumotlarga havolani ushlab turadi. UI stsenariylari uchun CursorLoader yoki Room ni LiveData/Flow bilan ishlating.
O'z Content Provider-ingizni yaratish ContentProvider sinfidan meros olish bilan boshlanadi. Provayder SQLiteOpenHelper orqali SQLite bazasi bilan ishlaydi va so'rov turini aniqlash uchun UriMatcher dan foydalanadi. Eslatmalar ro'yxatini boshqarish uchun minimal amalga oshirishni ko'rib chiqaylik.
Provayder AndroidManifest.xml da application tegi ichida ro'yxatdan o'tkaziladi. authorities atributi noyob identifikatorni belgilaydi, exported esa boshqa ilovalar provayderga murojaat qila olishini aniqlaydi. exported=true bo'lmasa, provayder faqat sizning ilovangiz ichida mavjud.
// Eslatmalar uchun Content Provider misoli
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 qisqalik uchun tushirib qoldirilgan
}
Sinf yaratilgandan so'ng, provayder android:authorities va android:exported (agar provayder ommaviy bo'lsa true) atributlari bilan manifestda ro'yxatdan o'tkazilishi kerak. Tizim provayderning nusxasini unga birinchi murojaatda yaratadi — bu UI oqimida sodir bo'ladi, shuning uchun onCreate tez bajarilishi kerak.
Content Provider ma'lumotlarga kirishni ikki darajada boshqarish imkonini beradi: o'qish ruxsatlari va yozish ruxsatlari. Ular manifestda android:readPermission va android:writePermission atributlari bilan belgilanadi. Agar mijoz ilova tegishli ruxsatga ega bo'lmasa, tizim chaqiruvni SecurityException bilan rad etadi.
Android FLAG_GRANT_READ_URI_PERMISSION va FLAG_GRANT_WRITE_URI_PERMISSION bayroqlari orqali vaqtinchalik ruxsatlarni qo'llab-quvvatlaydi. Bu ilova fayl URI sini Intent orqali boshqa ilovaga uzatganda foydalidir — qabul qiluvchi faqat ma'lum URI ga cheklangan vaqt davomida kirish huquqini oladi. Tizim vaqtinchalik ruxsatni qabul qiluvchi ilova tugagandan so'ng bekor qiladi.
Tizim provayderlari uchun Android ilova manifestida aniq ruxsatlarni ko'rsatishni talab qiladi. Masalan, kontaktlarga kirish uchun READ_CONTACTS, taqvim uchun READ_CALENDAR kerak. Android 6 dan boshlab, bu ruxsatlar o'rnatish vaqtida emas, balki bajarish vaqtida so'raladi.
Tez-tez beriladigan savollar
Content Provider — ContentResolver orqali ilovalar o'rtasida ma'lumot almashinuvi uchun standart interfeysni ta'minlovchi Android komponentidir. U saqlash usulini (SQLite, fayllar, tarmoq) abstraksiyalaydi va o'qish/yozish ruxsatlari nazorati bilan xavfsiz ma'lumot kirishini ta'minlaydi.
Authority — AndroidManifest.xml da ko'rsatilgan provayderning noyob identifikator satridir. U content://authority/path URI ning birinchi qismini tashkil qiladi va tizim tomonidan ContentResolver chaqiruvlarini tegishli provayderga yo'naltirish uchun ishlatiladi. Authority qurilmadagi barcha ilovalar orasida noyob bo'lishi kerak.
UriMatcher URI larni raqamli kodlar bilan moslashtiradi. Siz addURI orqali andozalar qo'shasiz, so'ngra kiruvchi URI uchun kod olish uchun match ni chaqirasiz. Bu query, insert, update, delete metodlarida qaysi jadval yoki yozuv so'ralganligini aniqlash va ma'lumotlar bazasida tegishli operatsiyani bajarish imkonini beradi.
Ha, Cursor foydalanilgandan so'ng albatta yopilishi kerak. Agar Cursor yopilmasa, xotira sizib ketadi, chunki u provayder ma'lumotlariga Binder havolasini ushlab turadi. Kotlin da avtomatik yopish uchun use funksiyasidan, Java da esa try-with-resources yoki finally blokida cursor.close() chaqiruvidan foydalaning.
Content Provider — ilovalararo ma'lumot kirishi uchun komponent, SQLiteDatabase esa bitta ilovaning ichki omboridir. Content Provider URI interfeysi va ruxsat nazoratini ta'minlaydi, SQLiteDatabase esa operatsion tizim darajasidagi xavfsizlik mexanizmlarisiz to'g'ridan-to'g'ri baza bilan ishlaydi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.