Content Provider: шта је то, архитектура компоненте и принцип рада

Аутор: IT Sectr Објављено: 2026-06-17 Време читања: 8 мин

Content Provider — је Android компонента која обезбеђује јединствени интерфејс за приступ подацима између апликација. Апстрахује физичко складиштење (SQLite, фајлови, мрежни извори) и обезбеђује сигурну размену информација путем ContentResolver-а. Према Android Developer Guide, 2026, Content Provider је једна од четири основне Android компоненте, уз Activity, Service и BroadcastReceiver. Његов задатак је да учини податке доступним другим апликацијама са контролом дозвола за читање и писање.

Главно

  • Content Provider — стандардна Android компонента за међуапликацијску размену података кроз ContentResolver интерфејс.
  • URI (content://) идентификује табелу или запис и користи се за све CRUD операције са провајдером.
  • UriMatcher — помоћна класа која парсира долазне URI-је и одређује која табела или ред је затражен.
  • Дозволе за читање и писање се постављају у манифесту и захтевају од корисника приликом инсталације.
  • CursorLoader или Room са Content Provider-ом обезбеђују асинхроно учитавање података из провајдера без блокирања UI нити.

Шта је Content Provider?

Content Provider — је Android компонента која управља приступом централизованом складишту података и обезбеђује их другим апликацијама кроз јединствени уговорни интерфејс. Сакрива детаље имплементације складиштења: подаци могу бити ускладиштени у SQLite, на фајл систему, у облаку или бити резултат мрежног захтева.

Android укључује уграђене Content Provider-е за системске податке — ContactsContract, MediaStore, CalendarContract, CallLog. Апликације трећих страна такође могу креирати сопствене провајдере за сигурну размену података. Сваки провајдер се региструје у AndroidManifest.xml са навођењем authority — јединственог низа који чини први део URI-ја.

Како ради Content Provider

Content Provider ради по моделу клијент-сервер. Провајдер делује као сервер који имплементира шест обавезних метода: query, insert, update, delete, getType и onCreate. Клијент (друга апликација) приступа провајдеру путем ContentResolver-а, који преусмерава позиве на одговарајуће методе провајдера кроз Android-ов IPC механизам.

URI и authority

Сваки Content Provider се идентификује URI схеме content://. На пример, content://com.example.app.provider/items. Први део authority (com.example.app.provider) се везује за класу провајдера у манифесту. Путања /items указује на табелу, а /items/5 — на одређени запис са ID=5.

Процес позивања

Када апликација позове ContentResolver.query(URI), Android проверава дозволе пакета који позива, проналази провајдера по authority и покреће његов процес, ако већ није покренут. Провајдер извршава упит и враћа Cursor — објекат који садржи резултат и омогућава клијенту да итерира кроз записе.

Основне методе Content Provider-а

Класа ContentProvider захтева имплементацију шест апстрактних метода. Свака метода прима URI и враћа резултат који одговара типу операције. Систем позива ове методе из било ког процеса, тако да оне морају бити thread-safe и не блокирати извршење на дуго време.

Метода query

Метода query прима URI, низ колона projection, низ selection са аргументима и редослед сортирања. Враћа Cursor са подацима. У имплементацији потребно је раздвојити URI помоћу UriMatcher-а и извршити одговарајући SQL упит према бази података.

Методе insert, update, delete

Ове методе мењају податке у складишту. insert прима ContentValues — парове кључ-вредност — и враћа URI новог записа. update и delete примају selection за филтрирање записа и враћају број погођених редова. Након измене података, провајдер мора обавестити о томе путем ContentResolver.notifyChange.

МетодаНаменаПовратна вредност
queryДобијање података по URI-јуCursor или null
insertДодавање новог записаURI новог записа
updateАжурирање постојећих записаint (број редова)
deleteБрисање записаint (број редова)
getTypeMIME тип за URIString
onCreateИницијализација провајдераboolean

ContentResolver и URI у Android-у

ContentResolver — је јединствена тачка приступа за рад са свим Content Provider-има у систему. Клијентска апликација никада не позива методе провајдера директно — само путем ContentResolver-а, који Android добија из контекста. CRUD операције у ContentResolver-у имају иста имена као у провајдеру, али примају URI уместо директних референци.

UriMatcher

За парсирање долазних URI-јева унутар провајдера користи се UriMatcher. Он омогућава повезивање URI-ја са нумеричким кодом — на пример, URI content://authority/items даје код 1, а content://authority/items/# — код 2. Ово елиминише потребу за ручним парсирањем низа URI-ја у свакој методи.

kotlin
// Коришћење ContentResolver-а за приступ контактима
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("Контакти", "Име: $name")
    }
}

Cursor након употребе обавезно треба затворити — у примеру изнад то ради use (Kotlin екстензиона функција). Ако Cursor није затворен, доћи ће до цурења меморије, јер држи референцу на податке у Binder-пулу. За UI сценарије користите CursorLoader или Room са LiveData/Flow.

Пример Content Provider-а у Kotlin-у

Креирање сопственог Content Provider-а почиње наслеђивањем од класе ContentProvider. Провајдер ради са SQLite базом путем SQLiteOpenHelper-а и користи UriMatcher за одређивање типа упита. Размотримо минималну имплементацију за управљање списком белешки.

Регистрација у манифесту

Провајдер се региструје у AndroidManifest.xml унутар application тага. Атрибут authorities поставља јединствени идентификатор, а exported одређује да ли друге апликације могу приступити провајдеру. Без exported=true провајдер је доступан само унутар ваше апликације.

kotlin
// Пример Content Provider-а за белешке
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 изостављени ради краткоће
}

Након креирања класе, провајдер треба регистровати у манифесту са атрибутима android:authorities и android:exported (true ако је провајдер јаван). Систем креира инстанцу провајдера при првом приступу — то се дешава у UI нити, тако да onCreate треба да се изврши брзо.

Заштита података кроз дозволе

Content Provider омогућава управљање приступом подацима на два нивоа: дозволе за читање и дозволе за писање. Оне се постављају у манифесту атрибутима android:readPermission и android:writePermission. Ако клијентска апликација нема одговарајућу дозволу, систем ће одбити позив са SecurityException.

Дозвола на нивоу URI-ја

Android подржава привремене дозволе кроз заставице FLAG_GRANT_READ_URI_PERMISSION и FLAG_GRANT_WRITE_URI_PERMISSION. Ово је корисно када апликација прослеђује URI фајла другој апликацији путем Intent-а — прималац добија приступ само одређеном URI-ју на ограничено време. Систем опозива привремену дозволу након завршетка апликације примаоца.

За системске провајдере, Android захтева навођење конкретних дозвола у манифесту апликације. На пример, за приступ контактима потребно је READ_CONTACTS, за календар — READ_CALENDAR. Почев од Android 6, ове дозволе се захтевају током извршавања, а не приликом инсталације.

Често постављана питања

Шта је Content Provider у Android-у?

Content Provider — је Android компонента која обезбеђује стандардни интерфејс за размену података између апликација путем ContentResolver-а. Апстрахује начин складиштења (SQLite, фајлови, мрежа) и обезбеђује сигуран приступ подацима са контролом дозвола за читање и писање.

Шта је authority у Content Provider-у?

Authority — је јединствени низ идентификатор провајдера који се наводи у AndroidManifest.xml. Он чини први део URI content://authority/path и користи се од стране система за усмеравање позива ContentResolver-а ка одговарајућем провајдеру. Authority мора бити јединствена међу свим апликацијама на уређају.

Како ради UriMatcher у Content Provider-у?

UriMatcher повезује URI-је са нумеричким кодовима. Додајете шаблоне путем addURI, а затим позивате match да бисте добили код за долазни URI. Ово омогућава у методама query, insert, update, delete да одредите која табела или запис је затражен и извршите одговарајућу операцију са базом података.

Да ли треба затворити Cursor након рада са ContentResolver-ом?

Да, Cursor обавезно треба затворити након употребе. Ако Cursor није затворен, доћи ће до цурења меморије, јер држи Binder референцу на податке провајдера. У Kotlin-у користите функцију use за аутоматско затварање, а у Java-и — try-with-resources или позив cursor.close() у finally блоку.

По чему се Content Provider разликује од SQLiteDatabase?

Content Provider — је компонента за међуапликацијски приступ подацима, док је SQLiteDatabase интерно складиште једне апликације. Content Provider пружа URI интерфејс и контролу дозвола, а SQLiteDatabase ради директно са базом без безбедносних механизама на нивоу оперативног система.

Закључак

  • Content Provider — је стандардна Android компонента за сигурну размену података између апликација кроз јединствени ContentResolver интерфејс.
  • URI схеме content://authority/path/id идентификује провајдера, табелу и конкретан запис — сваки сегмент има строго одређену намену.
  • UriMatcher поједностављује парсирање долазних URI-јева унутар провајдера, елиминишући ручно парсирање низова у свакој CRUD методи.
  • Провајдер се региструје у AndroidManifest.xml са атрибутима authorities и exported — ово је системски механизам без кога провајдер неће радити.
  • ContentValues се прослеђују у insert и update као скуп парова кључ-вредност, а Cursor се враћа из query за итерацију кроз резултате.
  • Дозволе readPermission и writePermission у манифесту контролишу приступ подацима, а FLAG_GRANT_URI_PERMISSION даје привремени приступ одређеном URI-ју.
  • За асинхроно учитавање података из Content Provider-а користите CursorLoader, Room са ContentProvider-ом или LoaderManager — ово спречава блокирање UI нити.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође