Content Provider: ce este, arhitectura componentului și principiul de funcționare

Autor: IT Sectr Publicat: 2026-06-17 Timp de citire: 8 min

Content Provider — este o componentă Android care oferă o interfață unificată pentru accesul la date între aplicații. Abstrage stocarea fizică (SQLite, fișiere, surse de rețea) și asigură schimbul securizat de informații prin ContentResolver. Conform Android Developer Guide, 2026, Content Provider este una dintre cele patru componente principale ale unei aplicații Android, alături de Activity, Service și BroadcastReceiver. Sarcina sa este de a face datele disponibile altor aplicații cu controlul permisiunilor de citire și scriere.

Principalele puncte

  • Content Provider — componenta standard Android pentru schimbul de date între aplicații prin interfața ContentResolver.
  • URI (content://) identifică tabela sau înregistrarea și este utilizat pentru toate operațiile CRUD cu furnizorul.
  • UriMatcher — o clasă de serviciu care parsează URI-urile primite și determină ce tabelă sau rând a fost solicitat.
  • Permisiunile de citire și scriere sunt stabilite în manifest și solicitate de la utilizator la instalare.
  • CursorLoader sau Room cu Content Provider asigură încărcarea asincronă a datelor de la furnizor fără blocarea firului UI.

Ce este Content Provider?

Content Provider — este o componentă Android care gestionează accesul la un depozit centralizat de date și le oferă altor aplicații printr-o interfață contractuală unificată. Ascunde detaliile de implementare a stocării: datele pot fi stocate în SQLite, pe sistemul de fișiere, în nor sau pot fi rezultatul unei cereri de rețea.

Android include Content Provider încorporați pentru date de sistem — ContactsContract, MediaStore, CalendarContract, CallLog. Aplicațiile terțe pot, de asemenea, să își creeze proprii furnizori pentru schimbul securizat de date. Fiecare furnizor este înregistrat în AndroidManifest.xml cu specificarea authority — un șir unic care formează prima parte a URI.

Cum funcționează Content Provider

Content Provider funcționează după modelul client-server. Furnizorul acționează ca un server care implementează șase metode obligatorii: query, insert, update, delete, getType și onCreate. Clientul (o altă aplicație) accesează furnizorul prin ContentResolver, care transmite apelurile către metodele corespunzătoare ale furnizorului prin mecanismul IPC al Android.

URI și authority

Fiecare Content Provider este identificat printr-un URI al schemei content://. De exemplu, content://com.example.app.provider/items. Prima parte authority (com.example.app.provider) este legată de clasa furnizorului în manifest. Calea /items indică tabela, iar /items/5 — o înregistrare specifică cu ID=5.

Procesul de apelare

Când o aplicație apelează ContentResolver.query(URI), Android verifică permisiunile pachetului apelant, găsește furnizorul după authority și pornește procesul acestuia, dacă nu este deja pornit. Furnizorul execută interogarea și returnează un Cursor — un obiect care conține rezultatul și permite clientului să itereze prin înregistrări.

Metodele principale ale Content Provider

Clasa ContentProvider necesită implementarea a șase metode abstracte. Fiecare metodă primește un URI și returnează un rezultat corespunzător tipului de operație. Sistemul apelează aceste metode din orice proces, deci ele trebuie să fie thread-safe și să nu blocheze execuția pentru mult timp.

Metoda query

Metoda query primește URI, un tablou de coloane projection, un șir selection cu argumente și ordinea de sortare. Returnează un Cursor cu date. În implementare trebuie să parseze URI cu ajutorul UriMatcher și să execute interogarea SQL corespunzătoare în baza de date.

Metodele insert, update, delete

Aceste metode modifică datele în depozit. insert primește ContentValues — perechi cheie-valoare — și returnează URI-ul noii înregistrări. update și delete primesc selection pentru filtrarea înregistrărilor și returnează numărul de rânduri afectate. După modificarea datelor, furnizorul trebuie să notifice prin ContentResolver.notifyChange.

MetodăScopReturnează
queryObținerea datelor după URICursor sau null
insertAdăugarea unei noi înregistrăriURI-ul noii înregistrări
updateActualizarea înregistrărilor existenteint (număr de rânduri)
deleteȘtergerea înregistrărilorint (număr de rânduri)
getTypeTipul MIME pentru URIString
onCreateInițializarea furnizoruluiboolean

ContentResolver și URI în Android

ContentResolver — este un punct unic de acces pentru lucrul cu toți Content Provider din sistem. Aplicația client nu apelează niciodată metodele furnizorului direct — doar prin ContentResolver, pe care Android îl obține din context. Operațiile CRUD în ContentResolver au aceleași nume ca în furnizor, dar primesc URI în loc de referințe directe.

UriMatcher

Pentru parsarea URI-urilor primite în interiorul furnizorului se utilizează UriMatcher. Acesta permite asocierea URI cu un cod numeric — de exemplu, URI content://authority/items dă codul 1, iar content://authority/items/# — codul 2. Acest lucru elimină necesitatea parsării manuale a șirului URI în fiecare metodă.

kotlin
// Utilizarea ContentResolver pentru accesarea contactelor
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("Contacte", "Nume: $name")
    }
}

Cursorul trebuie închis după utilizare — în exemplul de mai sus, use (funcția de extensie Kotlin) face acest lucru. Dacă Cursor nu este închis, va apărea o scurgere de memorie, deoarece menține o referință la date în pool-ul Binder. Pentru scenariile UI, utilizați CursorLoader sau Room cu LiveData/Flow.

Exemplu de Content Provider în Kotlin

Crearea propriului Content Provider începe cu moștenirea clasei ContentProvider. Furnizorul lucrează cu baza de date SQLite prin SQLiteOpenHelper și utilizează UriMatcher pentru a determina tipul de interogare. Să analizăm o implementare minimală pentru gestionarea listei de note.

Înregistrarea în manifest

Furnizorul se înregistrează în AndroidManifest.xml în interiorul tagului application. Atributul authorities stabilește un identificator unic, iar exported determină dacă alte aplicații pot accesa furnizorul. Fără exported=true, furnizorul este accesibil doar în interiorul aplicației dvs.

kotlin
// Exemplu de Content Provider pentru note
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 omise pentru concizie
}

După crearea clasei, furnizorul trebuie înregistrat în manifest cu atributele android:authorities și android:exported (true dacă furnizorul este public). Sistemul creează o instanță a furnizorului la prima accesare — aceasta are loc în firul UI, deci onCreate trebuie să se execute rapid.

Protejarea datelor prin permisiuni

Content Provider permite gestionarea accesului la date pe două niveluri: permisiuni de citire și permisiuni de scriere. Acestea sunt stabilite în manifest prin atributele android:readPermission și android:writePermission. Dacă aplicația client nu are permisiunea corespunzătoare, sistemul va respinge apelul cu SecurityException.

Permisiune la nivel de URI

Android acceptă permisiuni temporare prin flagurile FLAG_GRANT_READ_URI_PERMISSION și FLAG_GRANT_WRITE_URI_PERMISSION. Acest lucru este util atunci când o aplicație transmite URI-ul unui fișier altei aplicații prin Intent — destinatarul primește acces doar la URI-ul specific pentru un timp limitat. Sistemul revocă permisiunea temporară după finalizarea aplicației destinatare.

Pentru furnizorii de sistem, Android necesită specificarea permisiunilor concrete în manifestul aplicației. De exemplu, pentru accesul la contacte este necesar READ_CONTACTS, pentru calendar — READ_CALENDAR. Începând cu Android 6, aceste permisiuni sunt solicitate în timpul execuției, nu la instalare.

Întrebări frecvente

Ce este Content Provider în Android?

Content Provider — este o componentă Android care oferă o interfață standard pentru schimbul de date între aplicații prin ContentResolver. Abstrage modul de stocare (SQLite, fișiere, rețea) și asigură acces securizat la date cu controlul permisiunilor de citire și scriere.

Ce este authority în Content Provider?

Authority — este un șir unic de identificare a furnizorului, specificat în AndroidManifest.xml. Acesta formează prima parte a URI content://authority/path și este utilizat de sistem pentru rutarea apelurilor ContentResolver către furnizorul corespunzător. Authority trebuie să fie unică printre toate aplicațiile de pe dispozitiv.

Cum funcționează UriMatcher în Content Provider?

UriMatcher asociază URI-urile cu coduri numerice. Adăugați șabloane prin addURI, apoi apelați match pentru a obține codul pentru URI-ul primit. Acest lucru permite în metodele query, insert, update, delete să determinați ce tabelă sau înregistrare a fost solicitată și să executați operația corespunzătoare în baza de date.

Trebuie închis Cursor după lucrul cu ContentResolver?

Da, Cursor trebuie închis după utilizare. Dacă Cursor nu este închis, va apărea o scurgere de memorie, deoarece menține o referință Binder la datele furnizorului. În Kotlin, utilizați funcția use pentru închiderea automată, iar în Java — try-with-resources sau apelul cursor.close() în finally.

Cu ce se deosebește Content Provider de SQLiteDatabase?

Content Provider — este o componentă pentru accesul între aplicații la date, în timp ce SQLiteDatabase este un depozit intern al unei singure aplicații. Content Provider oferă interfață URI și control al permisiunilor, iar SQLiteDatabase lucrează direct cu baza de date fără mecanisme de securitate la nivel de sistem de operare.

Concluzii

  • Content Provider — este componenta standard Android pentru schimbul securizat de date între aplicații printr-o interfață unificată ContentResolver.
  • URI-ul schemei content://authority/path/id identifică furnizorul, tabela și înregistrarea specifică — fiecare segment are o destinație strictă.
  • UriMatcher simplifică parsarea URI-urilor primite în interiorul furnizorului, eliminând parsarea manuală a șirurilor în fiecare metodă CRUD.
  • Furnizorul se înregistrează în AndroidManifest.xml cu atributele authorities și exported — acesta este mecanismul de sistem fără de care furnizorul nu va funcționa.
  • ContentValues sunt transmise în insert și update ca un set de perechi cheie-valoare, iar Cursor este returnat din query pentru iterarea prin rezultate.
  • Permisiunile readPermission și writePermission în manifest controlează accesul la date, iar FLAG_GRANT_URI_PERMISSION oferă acces temporar la un URI specific.
  • Pentru încărcarea asincronă a datelor din Content Provider, utilizați CursorLoader, Room cu ContentProvider sau LoaderManager — acest lucru previne blocarea firului UI.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și