Custom Content Provider In Android

I’ve been searching over internet to find out one good example for Custom Content Provider but found very little help in trying to run examples rightaway from web. Lots of examples are 1/2 done or 1/2 written. I wanted to come out with a runnign example and here is the example. Again as before i’ve compiled and modified this example from code i have found over web so that some UI is added to it.

Content providers store and retrieve data and make it accessible to all applications. They’re the only way to share data across applications; there’s no common storage area that all Android packages can access.
Each content provider exposes a public URI (wrapped as a Uri object) that uniquely identifies its data set. A content provider that controls multiple data sets (multiple tables) exposes a separate URI for each one. All URIs for providers begin with the string “content://”. The content: scheme identifies the data as being controlled by a content provider

Querying a Content Provider

You need three pieces of information to query a content provider:

The URI that identifies the provider
The names of the data fields you want to receive
The data types for those fields
If you’re querying a particular record, you also need the ID for that record.

Below is the code that creates content provider (Here content provider acts like a wrapper to sqllite database)

package com.linkwithweb.providers;

import android.net.Uri;
import android.provider.BaseColumns;

/**
 * @author Ashwin Kumar
 *
 */
public class MyUsers {

	public static final String AUTHORITY = "com.linkwithweb.providers.MyContentProvider";

	// BaseColumn contains _id.
	public static final class User implements BaseColumns {

		public static final Uri CONTENT_URI = Uri
				.parse("content://com.linkwithweb.providers.MyContentProvider");

		// Table column
		public static final String USER_NAME = "USER_NAME";
	}
}
package com.linkwithweb.providers;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;

/**
 * @author Ashwin Kumar
 *
 */
public class MyContentProvider extends ContentProvider {

	private SQLiteDatabase sqlDB;

	private DatabaseHelper dbHelper;

	private static final String DATABASE_NAME = "Users.db";

	private static final int DATABASE_VERSION = 1;

	private static final String TABLE_NAME = "User";

	private static final String TAG = "MyContentProvider";

	private static class DatabaseHelper extends SQLiteOpenHelper {

		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			// create table to store user names
			db.execSQL("Create table "
					+ TABLE_NAME
					+ "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);");
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
			onCreate(db);
		}
	}

	@Override
	public int delete(Uri uri, String s, String[] as) {
		return 0;
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues contentvalues) {
		// get database to insert records
		sqlDB = dbHelper.getWritableDatabase();
		// insert record in user table and get the row number of recently inserted record
		long rowId = sqlDB.insert(TABLE_NAME, "", contentvalues);
		if (rowId > 0) {
			Uri rowUri = ContentUris.appendId(
					MyUsers.User.CONTENT_URI.buildUpon(), rowId).build();
			getContext().getContentResolver().notifyChange(rowUri, null);
			return rowUri;
		}
		throw new SQLException("Failed to insert row into " + uri);
	}

	@Override
	public boolean onCreate() {
		dbHelper = new DatabaseHelper(getContext());
		return (dbHelper == null) ? false : true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		SQLiteDatabase db = dbHelper.getReadableDatabase();
		qb.setTables(TABLE_NAME);
		Cursor c = qb.query(db, projection, selection, null, null, null,
				sortOrder);
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	@Override
	public int update(Uri uri, ContentValues contentvalues, String s,
			String[] as) {
		return 0;
	}
}

Now lets create an Activity and Corresponding view to display this in GUI

/**
 * 
 */
package com.linkwithweb;

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.linkwithweb.providers.MyUsers;

/**
 * @author Ashwin Kumar
 * 
 */
public class CustomProviderDemo extends Activity {
	private EditText mContactNameEditText;
	private TextView mContactsText;
	private Button mContactSaveButton;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.custom_provider);

		// Obtain handles to UI objects
		mContactNameEditText = (EditText) findViewById(R.id.contactNameEditText);
		mContactSaveButton = (Button) findViewById(R.id.contactSaveButton);
		mContactsText = (TextView) findViewById(R.id.contactEntryText);

		
		mContactSaveButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
            	String name = mContactNameEditText.getText().toString();
            	insertRecord(name);
            	mContactsText.append("\n"+name);
            }
        });
		
		//insertRecord("MyUser");
		displayRecords();
	}

	private void insertRecord(String userName) {
		ContentValues values = new ContentValues();
		values.put(MyUsers.User.USER_NAME, userName);
		getContentResolver().insert(MyUsers.User.CONTENT_URI, values);
	}

	private void displayRecords() {
		// An array specifying which columns to return.
		String columns[] = new String[] { MyUsers.User._ID,
				MyUsers.User.USER_NAME };
		Uri myUri = MyUsers.User.CONTENT_URI;
		Cursor cur = managedQuery(myUri, columns, // Which columns to return
				null, // WHERE clause; which rows to return(all rows)
				null, // WHERE clause selection arguments (none)
				null // Order-by clause (ascending by name)
		);
		if (cur.moveToFirst()) {
			String id = null;
			String userName = null;
			do {
				// Get the field values
				id = cur.getString(cur.getColumnIndex(MyUsers.User._ID));
				userName = cur.getString(cur
						.getColumnIndex(MyUsers.User.USER_NAME));
				Toast.makeText(this, id + " " + userName, Toast.LENGTH_LONG)
						.show();
			} while (cur.moveToNext());
		}
	}
}

Below is the view code

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    <TableLayout android:layout_width="match_parent"
                 android:layout_height="match_parent">

        <TableRow>
            <TextView android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:text="@string/contactNameLabel"/>
        </TableRow>
        <TableRow>
            <EditText android:id="@+id/contactNameEditText"
                      android:layout_height="wrap_content"
                      android:layout_width="wrap_content"
                      android:layout_weight="1"/>
        </TableRow>
        <TableRow>
            <Button android:layout_height="wrap_content"
                    android:text="@string/save"
                    android:id="@+id/contactSaveButton"
                    android:layout_width="match_parent"
                    android:layout_weight="1"/>
        </TableRow>
        <TableRow>
	        <TextView android:text="@+id/contactEntryText"
	              android:id="@+id/contactEntryText"
	              android:layout_width="match_parent"
	              android:layout_height="wrap_content"/>
   		 </TableRow>
        
    </TableLayout>
</ScrollView>

Below is the configuration you can define in Manifest file

		<activity android:name=".CustomProviderDemo" android:label="CustomProviderDemo">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.SAMPLE_CODE" />
			</intent-filter>
		</activity>	
		
		
		<provider android:name="com.linkwithweb.providers.MyContentProvider" android:authorities="com.linkwithweb.providers.MyContentProvider" />		

Code has been checked in to below url. You can checkout from the below svn url for workign code of whole project with all other lessons
https://linkwithweb.googlecode.com/svn/trunk/Android/AndroidLessons

12 thoughts on “Custom Content Provider In Android

  1. Thank you for this tutorial. Unfortunately it is not working for me. I cannot get rid of “Failed to find provider info for MyContentProvider . It seems to be a simple issue, but all I found on google could not solve this problem. Do you have a solution for it / know, what could be wrong?
    Thx in advance!!!

  2. I just wanted to just take a couple of seconds and let you know that I
    appreciated the write-up. I honestly don’t think many people know how many hours of labor that gets put into having a post. I’m sure this is kind of random however it bugs me sometimes.
    Anyhow good site.

  3. nice tutorial.. works perfectly.. but how to use this in another application.. means how to work with same database in another application ???

Leave a comment