Wed. Jan 15th, 2025

Content Providers in Android

A Content Provider is a component in Android used to manage access to a central repository of data. It allows applications to share data with each other in a structured and secure way. Content providers enable CRUD (Create, Read, Update, Delete) operations on app data.


Key Features of Content Providers

  1. Data Sharing: Allows sharing of data between different applications securely.
  2. Structured Access: Provides a standardized way to query and manipulate data using URIs.
  3. Integration: Works with ContentResolver for data access and manipulation.

Content Provider Components

  1. URI (Uniform Resource Identifier): A unique identifier for the data (e.g., content://com.example.provider/users).
  2. ContentResolver: Used by client applications to interact with the content provider.
  3. Cursor: A pointer to the result set of a query.

Creating a Content Provider

To create a custom content provider:

  1. Extend the ContentProvider class.
  2. Implement its abstract methods:
  • onCreate(): Initialize resources.
  • query(): Retrieve data.
  • insert(): Insert new data.
  • update(): Update existing data.
  • delete(): Delete data.
  • getType(): Return the MIME type of data.

Example: Custom Content Provider

1. ContentProvider Class

class MyContentProvider : ContentProvider() {

    companion object {
        const val AUTHORITY = "com.example.provider"
        val CONTENT_URI: Uri = Uri.parse("content://$AUTHORITY/users")
        const val TABLE_NAME = "users"
    }

    private lateinit var database: SQLiteDatabase

    override fun onCreate(): Boolean {
        val dbHelper = MyDatabaseHelper(context!!)
        database = dbHelper.writableDatabase
        return true
    }

    override fun query(
        uri: Uri,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor? {
        return database.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder)
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        val id = database.insert(TABLE_NAME, null, values)
        context?.contentResolver?.notifyChange(uri, null)
        return ContentUris.withAppendedId(CONTENT_URI, id)
    }

    override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?): Int {
        val rowsUpdated = database.update(TABLE_NAME, values, selection, selectionArgs)
        context?.contentResolver?.notifyChange(uri, null)
        return rowsUpdated
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        val rowsDeleted = database.delete(TABLE_NAME, selection, selectionArgs)
        context?.contentResolver?.notifyChange(uri, null)
        return rowsDeleted
    }

    override fun getType(uri: Uri): String? {
        return "vnd.android.cursor.dir/$TABLE_NAME"
    }
}

2. Database Helper

class MyDatabaseHelper(context: Context) : SQLiteOpenHelper(context, "MyDatabase", null, 1) {

    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL("CREATE TABLE users (_id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        db.execSQL("DROP TABLE IF EXISTS users")
        onCreate(db)
    }
}

3. Manifest Declaration

Add the content provider in the AndroidManifest.xml file.

<provider
    android:name=".MyContentProvider"
    android:authorities="com.example.provider"
    android:exported="true"
    android:grantUriPermissions="true" />

Using a Content Provider

1. Insert Data

val values = ContentValues().apply {
    put("name", "John Doe")
    put("email", "john.doe@example.com")
}

val uri = contentResolver.insert(MyContentProvider.CONTENT_URI, values)
Log.d("ContentProvider", "Inserted URI: $uri")

2. Query Data

val cursor = contentResolver.query(
    MyContentProvider.CONTENT_URI,
    arrayOf("_id", "name", "email"), // Columns
    null, // Selection
    null, // Selection Args
    null  // Sort Order
)

cursor?.use {
    while (it.moveToNext()) {
        val id = it.getInt(it.getColumnIndex("_id"))
        val name = it.getString(it.getColumnIndex("name"))
        val email = it.getString(it.getColumnIndex("email"))
        Log.d("ContentProvider", "User: $id, $name, $email")
    }
}

3. Update Data

val values = ContentValues().apply {
    put("email", "new.email@example.com")
}

val rowsUpdated = contentResolver.update(
    MyContentProvider.CONTENT_URI,
    values,
    "name = ?", // Selection
    arrayOf("John Doe") // Selection Args
)

Log.d("ContentProvider", "Rows Updated: $rowsUpdated")

4. Delete Data

val rowsDeleted = contentResolver.delete(
    MyContentProvider.CONTENT_URI,
    "name = ?", // Selection
    arrayOf("John Doe") // Selection Args
)

Log.d("ContentProvider", "Rows Deleted: $rowsDeleted")

Built-in Content Providers

Android includes several built-in content providers for common data types:

  1. Contacts: ContactsContract
  2. Media Store: MediaStore
  3. Settings: Settings.System

Example: Querying contacts:

val cursor = contentResolver.query(
    ContactsContract.Contacts.CONTENT_URI,
    null, null, null, null
)

cursor?.use {
    while (it.moveToNext()) {
        val name = it.getString(it.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
        Log.d("Contacts", "Name: $name")
    }
}

Best Practices

  1. Secure Data Access: Use permissions or implement validation to prevent unauthorized access.
  2. Minimize Resource Usage: Optimize queries and limit the amount of data returned.
  3. Use URIs: Define consistent URI structures for easy data manipulation.

By Rajashekar

I’m (Rajashekar) a core Android developer with complimenting skills as a web developer from India. I cherish taking up complex problems and turning them into beautiful interfaces. My love for decrypting the logic and structure of coding keeps me pushing towards writing elegant and proficient code, whether it is Android, PHP, Flutter or any other platforms. You would find me involved in cuisines, reading, travelling during my leisure hours.

Leave a Reply

Your email address will not be published. Required fields are marked *