Что такое ContentProvider

ContentProvider в Android - это компонент, который предоставляет единый интерфейс для управления набором данных вашего приложения. Этот компонент позволяет вашему приложению совместно использовать данные с другими приложениями в рамках вашего приложения.

В качестве примера, допустим, у вас есть приложение заметок, которое хранит заметки пользователя. Вы можете использовать ContentProvider, чтобы разрешить другим приложениям получать доступ к этим заметкам (например, для отображения заметок в виде виджета на домашнем экране).

  1. Создание ContentProvider: Начнем с создания простого ContentProvider, который предоставляет доступ к списку пользователей.
import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri

class UserContentProvider : ContentProvider() {

    private lateinit var userDbHelper: UserDbHelper

    override fun onCreate(): Boolean {
        userDbHelper = UserDbHelper(context!!)
        return true
    }

    override fun query(
        uri: Uri,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor? {
        val db = userDbHelper.readableDatabase
        return db.query(
            UserContract.UserEntry.TABLE_NAME,
            projection,
            selection,
            selectionArgs,
            null,
            null,
            sortOrder
        )
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        val db = userDbHelper.writableDatabase
        val id = db.insert(UserContract.UserEntry.TABLE_NAME, null, values)
        return Uri.parse("${UserContract.CONTENT_URI}/$id")
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        val db = userDbHelper.writableDatabase
        return db.delete(UserContract.UserEntry.TABLE_NAME, selection, selectionArgs)
    }

    override fun update(
        uri: Uri,
        values: ContentValues?,
        selection: String?,
        selectionArgs: Array<out String>?
    ): Int {
        val db = userDbHelper.writableDatabase
        return db.update(UserContract.UserEntry.TABLE_NAME, values, selection, selectionArgs)
    }

    override fun getType(uri: Uri): String? {
        return "vnd.android.cursor.dir/vnd.${UserContract.CONTENT_AUTHORITY}.${UserContract.PATH_USERS}"
    }
}
  1. Определение контракта ContentProvider: В этом примере мы определим контракт для нашего ContentProvider, включая имя таблицы и URI.
import android.net.Uri
import android.provider.BaseColumns

object UserContract {
    const val CONTENT_AUTHORITY = "com.example.myapp"
    const val PATH_USERS = "users"
    val CONTENT_URI: Uri = Uri.parse("content://$CONTENT_AUTHORITY/$PATH_USERS")

    object UserEntry : BaseColumns {
        const val TABLE_NAME = "users"
        const val COLUMN_NAME = "name"
        const val COLUMN_AGE = "age"
    }
}
  1. Использование ContentProvider: Теперь мы можем использовать наш ContentProvider в других частях приложения, например, для чтения и записи данных.
val newUser = ContentValues().apply {
    put(UserContract.UserEntry.COLUMN_NAME, "John")
    put(UserContract.UserEntry.COLUMN_AGE, 30)
}
val uri = contentResolver.insert(UserContract.CONTENT_URI, newUser)

// Чтение данных
val cursor = contentResolver.query(UserContract.CONTENT_URI, null, null, null, null)
cursor?.use {
    while (it.moveToNext()) {
        val name = it.getString(it.getColumnIndexOrThrow(UserContract.UserEntry.COLUMN_NAME))
        val age = it.getInt(it.getColumnIndexOrThrow(UserContract.UserEntry.COLUMN_AGE))
        // Делаем что-то с данными
    }
}

Другие приложения могут использовать ваш ContentProvider, чтобы получить доступ к данным, которые ваше приложение предоставляет. Для этого они могут использовать URI вашего ContentProvider для выполнения операций чтения и записи данных.

Давайте рассмотрим пример использования вашего ContentProvider из другого приложения:

  1. Объявление разрешений доступа: Ваше приложение должно объявить разрешение доступа к вашему ContentProvider в манифесте.
<provider
    android:name=".UserContentProvider"
    android:authorities="com.example.myapp"
    android:exported="true"/>
  1. Чтение данных: Другое приложение может использовать ContentResolver для запроса данных у вашего ContentProvider.
val cursor = contentResolver.query(Uri.parse("content://com.example.myapp/users"), 
                null, null, null, null)
cursor?.use {
    while (it.moveToNext()) {
        val name = it.getString(it.getColumnIndexOrThrow("name"))
        val age = it.getInt(it.getColumnIndexOrThrow("age"))
        // Делаем что-то с данными
    }
}
  1. Запись данных: Другое приложение также может использовать ContentResolver для вставки новых данных через ваш ContentProvider.
val newUser = ContentValues().apply {
    put("name", "Alice")
    put("age", 25)
}
val uri = contentResolver.insert(Uri.parse("content://com.example.myapp/users"), newUser)