How To Create Android Custom Content Provider Example

This article will show you examples about how to create you own custom android content provider.

1. Custom Android Content Provider Example Overview.

From below program diagram. We can see that generally there are two parts in a custom content provider example.

  1. Custom content provider part. This part use SQLite database to store and manipulate user account data.
  2. Content provider consumer part. This part use ContentResolver to invoke method that custom content provider provided.

create and call custom content provider diagram

2. Custom Content Provider Part Source Code.

To learn how to create custom content provider in theory, please read article Android Custom Content Provider Introduction.

To create a custom content provider, you need create below two java files and update AndroidManifest.xml file.

account custom content provider java class file

2.1 Custom Content Provider Class.

This class must extends android.content.ContentProvider.

To learn how to create it, please follow Android Custom Content Provider Introduction‘s How To Create Custom Content Provider Class In Android Studio part.

AccountContentProvider.java

package com.dev2qa.example.datasharing.custom.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;

public class AccountContentProvider extends ContentProvider {

    private static String TAG_ACCOUNT_CONTENT_PROVIDER = "CONTENT_PROVIDER";

    private AccountDBHelper accountDBHelper;

    private final String accountDBFile = "Account.db";

    private int dbVersion = 1;

    // Represent account table.
    public static final int ACCOUNT_DIR = 1;

    // Represent one row in account table.
    public static final int ACCOUNT_ITEM = 2;

    // The authority of account content provider.
    public static final String AUTHORITY = "com.dev2qa.account.provider";

    private static final String accountPath = "account";

    // Declare UriMatcher object.
    private static UriMatcher uriMatcher;

    // if content data mimetype is a table then use this prefix.
    private static final String mimeTypeDirPrefix = "vnd.android.cursor.dir/";

    // if content data mimetype is table rows then use this prefix.
    private static final String mimeTypeItemPrefix = "vnd.android.cursor.item/";

    // Base uri for this content provider.
    public static final String BASE_CONTENT_URI = "content://" + AUTHORITY + "/" + accountPath;

    // Initialize uriMatcher, add matched uri.
    static{
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        // Match uri to account table.
        uriMatcher.addURI(AUTHORITY, accountPath, ACCOUNT_DIR);
        // Match uri to account table row.
        uriMatcher.addURI(AUTHORITY, accountPath+"/#", ACCOUNT_ITEM);
    }


    public AccountContentProvider() {
    }

    /* Delete data in account content provider. */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.

        // Return deleted rows count.
        int ret = 0;

        // Get account db object. Below code will create a SQLite database. 
        SQLiteDatabase accountDb = accountDBHelper.getWritableDatabase();

        // Get uri match code.
        int matchCode = uriMatcher.match(uri);

        if(matchCode==ACCOUNT_DIR)
        {
            // Delete all rows in account table.
            ret = accountDb.delete(AccountDBHelper.TABLE_NAME_ACCOUNT, selection, selectionArgs);
        }else if(matchCode==ACCOUNT_ITEM)
        {
            // Delete row with request row id.
            String accountId = uri.getPathSegments().get(1);
            String whereClause = " _id = ? ";
            String whereArgsArr[] = {accountId};
            ret = accountDb.delete(AccountDBHelper.TABLE_NAME_ACCOUNT, whereClause, whereArgsArr);
        }

        Log.d(TAG_ACCOUNT_CONTENT_PROVIDER, "Account content provider delete method is called.");

        return ret;
    }

    /* Get request uri data mimetype string. */
    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data at the given URI.

        // Data mimetype string format. vndPrefix/vnd.<authority>.<path>
        StringBuffer retBuf = new StringBuffer();

        // Parse request code.
        int requestCode = uriMatcher.match(uri);

        if(requestCode == ACCOUNT_DIR)
        {
            // If request table.
            retBuf.append(mimeTypeDirPrefix);
            retBuf.append("vnd.");
            retBuf.append(AUTHORITY);
            retBuf.append(".");
            retBuf.append(accountPath);
        }else if(requestCode == ACCOUNT_ITEM)
        {
            // If request table rows.
            retBuf.append(mimeTypeItemPrefix);
            retBuf.append("vnd.");
            retBuf.append(AUTHORITY);
            retBuf.append(".");
            retBuf.append(accountPath);
        }

        Log.d(TAG_ACCOUNT_CONTENT_PROVIDER, "Account content provider getType method is called.");

        return retBuf.toString();
    }

    /* Insert data into account content provider. */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.

        // Return newly inserted uri object..
        Uri ret = null;

        // Get account db object.
        SQLiteDatabase accountDb = accountDBHelper.getWritableDatabase();

        // Get uri match code.
        int matchCode = uriMatcher.match(uri);

        // Both match code means insert data into account table.
        if(matchCode==ACCOUNT_DIR || matchCode==ACCOUNT_ITEM)
        {
            // Insert user data into SQLite database account table and get newly added account id..
            long newAccountId = accountDb.insert(AccountDBHelper.TABLE_NAME_ACCOUNT, null, values);

            // Create new account uri. Uri string format : "content://<authority>/path/id".
            String newAccountUriStr = "content://" + AUTHORITY + "/" + accountPath + "/" + newAccountId;
            ret = Uri.parse(newAccountUriStr);
        }

        Log.d(TAG_ACCOUNT_CONTENT_PROVIDER, "Account content provider insert method is called.");

        return ret;
    }

    @Override
    public boolean onCreate() {
        boolean ret = true;
        // Get Account database helper instance.
        accountDBHelper = new AccountDBHelper(getContext(), accountDBFile, null, dbVersion);

        Log.d(TAG_ACCOUNT_CONTENT_PROVIDER, "Account content provider onCreate method is called.");

        return ret;
    }

    /* Query content provider, return result Cursor object.*/
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.

        Cursor ret = null;

        // Get account db object.
        SQLiteDatabase accountDb = accountDBHelper.getWritableDatabase();

        // Get uri match code.
        int matchCode = uriMatcher.match(uri);

        if(matchCode==ACCOUNT_DIR)
        {
            // Return all rows that match query condition in account table.
            ret = accountDb.query(AccountDBHelper.TABLE_NAME_ACCOUNT, projection, selection, selectionArgs, null, null, sortOrder);
        }else if(matchCode==ACCOUNT_ITEM)
        {
            // Update rows with request row id.
            String accountId = uri.getPathSegments().get(1);
            String whereClause = " _id = ? ";
            String whereArgsArr[] = {accountId};
            ret = accountDb.query(AccountDBHelper.TABLE_NAME_ACCOUNT, projection, whereClause, whereArgsArr, null, null, sortOrder);
        }

        Log.d(TAG_ACCOUNT_CONTENT_PROVIDER, "Account content provider query method is called.");

        return ret;

    }

    /* Update content provider data. */
    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.

        // Return updated rows count.
        int ret = 0;

        // Get account db object.
        SQLiteDatabase accountDb = accountDBHelper.getWritableDatabase();

        // Get uri match code.
        int matchCode = uriMatcher.match(uri);

        if(matchCode==ACCOUNT_DIR)
        {
            // Update all rows in account table.
            ret = accountDb.update(AccountDBHelper.TABLE_NAME_ACCOUNT, values, selection, selectionArgs);
        }else if(matchCode==ACCOUNT_ITEM)
        {
            // Update rows with request row id.
            String accountId = uri.getPathSegments().get(1);
            String whereClause = " _id = ? ";
            String whereArgsArr[] = {accountId};
            ret = accountDb.update(AccountDBHelper.TABLE_NAME_ACCOUNT, values, whereClause, whereArgsArr);
        }

        Log.d(TAG_ACCOUNT_CONTENT_PROVIDER, "Account content provider update method is called.");

        return ret;
    }
}

2.2 Account SQLite Database Helper Class.

This custom content provider will use below SQLite database helper class to create and store user account info.

READ :   Android Change Screen Brightness Programmatically Example

The database file is saved in android emulator /data/data/com.dev2qa.example/databases/Account.db file. You can open android device monitor to browse it.

If you can not open data folder in android device monitor by click it. You can run below shell command in a dos window. Then you can get root permission to operate the folder.

adb root

custom android content provider database file save location

AccountDBHelper.java

package com.dev2qa.example.datasharing.custom.provider;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by Jerry on 2/5/2018.
 */

public class AccountDBHelper extends SQLiteOpenHelper {

    private Context ctx;

    public static final String TABLE_NAME_ACCOUNT = "account";

    public AccountDBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        this.ctx = ctx;
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        StringBuffer createAccountTableSqlBuf = new StringBuffer();
        createAccountTableSqlBuf.append("create table ");
        createAccountTableSqlBuf.append(TABLE_NAME_ACCOUNT);
        createAccountTableSqlBuf.append("( _id integer primary key autoincrement,");
        createAccountTableSqlBuf.append(" user_name text,");
        createAccountTableSqlBuf.append(" password text,");
        createAccountTableSqlBuf.append(" email text,");
        createAccountTableSqlBuf.append(" title text )");

        sqLiteDatabase.execSQL(createAccountTableSqlBuf.toString());
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        if(newVersion > oldVersion) {
            sqLiteDatabase.execSQL("drop table " + TABLE_NAME_ACCOUNT);
            this.onCreate(sqLiteDatabase);
        }
    }
}

2.3 Register Custom Content Provider In Android Manifest Xml File.

AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <provider
        android:name=".datasharing.custom.provider.AccountContentProvider"
        android:authorities="com.dev2qa.account.provider"
        android:enabled="true"
        android:exported="true"></provider>
</application>

If you want to know how to invoke this custom content provider’s method to manipulate user account data, you can read next article How To Invoke Custom Content Provider In Other Apps Examples.

(Visited 529 times, 8 visits today)

1 Comment


  1. Is there a way to hide groups when users are looking for contacts on contacts app? thanks!

    Reply

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.