CoderzHeaven

September 22, 2013

How to write a custom content provider in android? with a sample application using our own custom content provider.

Hello all

we all know what are content providers right?
Those who are unaware of content providers please visit this link http://developer.android.com/guide/topics/providers/content-providers.html

In a breif content Providers are

Content providers manage access to a structured set of data. They encapsulate the data, and provide mechanisms for defining data security. Content providers are the standard interface that connects data in one process with code running in another process.

When you want to access data in a content provider, you use the ContentResolver object in your application’s Context to communicate with the provider as a client. The ContentResolver object communicates with the provider object, an instance of a class that implements ContentProvider. The provider object receives data requests from clients, performs the requested action, and returns the results.

This sample Demo is creating custom content provider using SQLite Database.

Now we will see how we can create our own custom content provider.

Tn this example I have three classes.
1. MainActivity.java
2. NotesContentProvider.java
3. NotesMetaData.java

At first we will look at “NotesMetaData.java”.

package com.coderzheaven.custom_contentproviderdemo;import android.net.Uri;import android.provider.BaseColumns;public class NotesMetaData {public NotesMetaData() {}// A content URI is a URI that identifies data in a provider. Content URIs// include the symbolic name of the entire provider (its authority)public static final String AUTHORITY = "com.coderzheaven.custom_contentproviderdemo.Notes";public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY+ "/notes");public static final String DATABASE_NAME = "notes.db";public static final int DATABASE_VERSION = 1;public static final String CONTENT_TYPE_NOTES_ALL = "vnd.android.cursor.dir/vnd.coderz.notes";public static final String CONTENT_TYPE_NOTES_ONE = "vnd.android.cursor.item/vnd.coderz.notes";public class NotesTable implements BaseColumns {private NotesTable() {}public static final String TABLE_NAME = "tbl_notes";public static final String ID = "_id";public static final String TITLE = "title";public static final String CONTENT = "content";}}

NotesMetaData class defines some required constant values to use:

+ AUTHORITY: this is the name of your content provider

+ CONTENT_URI: is your content provider URI for other applications to access data from it.

Let’s say if you want to get all notes, it would be like:

content://”com.coderzheaven.custom_contentproviderdemo.Notes/notes”

To retrieve a specific note:

content://com.coderzheaven.custom_contentproviderdemo.Notes/notes/5″

Now the “NotesContentProvider.java”

package com.coderzheaven.custom_contentproviderdemo;import java.util.HashMap;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.Context;import android.content.UriMatcher;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.database.sqlite.SQLiteQueryBuilder;import android.net.Uri;import android.text.TextUtils;public class NotesContentProvider extends ContentProvider {private static final UriMatcher sUriMatcher;private static final int NOTES_ALL = 1;private static final int NOTES_ONE = 2;static {sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);sUriMatcher.addURI(NotesMetaData.AUTHORITY, "notes", NOTES_ALL);sUriMatcher.addURI(NotesMetaData.AUTHORITY, "notes/#", NOTES_ONE);}// Map table columnsprivate static final HashMap<String, String> sNotesColumnProjectionMap;static {sNotesColumnProjectionMap = new HashMap<String, String>();sNotesColumnProjectionMap.put(NotesMetaData.NotesTable.ID,NotesMetaData.NotesTable.ID);sNotesColumnProjectionMap.put(NotesMetaData.NotesTable.TITLE,NotesMetaData.NotesTable.TITLE);sNotesColumnProjectionMap.put(NotesMetaData.NotesTable.CONTENT,NotesMetaData.NotesTable.CONTENT);}private static class NotesDBHelper extends SQLiteOpenHelper {public NotesDBHelper(Context c) {super(c, NotesMetaData.DATABASE_NAME, null,NotesMetaData.DATABASE_VERSION);}private static final String SQL_QUERY_CREATE = "CREATE TABLE "+ NotesMetaData.NotesTable.TABLE_NAME + " ("+ NotesMetaData.NotesTable.ID+ " INTEGER PRIMARY KEY AUTOINCREMENT, "+ NotesMetaData.NotesTable.TITLE + " TEXT NOT NULL, "+ NotesMetaData.NotesTable.CONTENT + " TEXT NOT NULL" + ");";@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL(SQL_QUERY_CREATE);}private static final String SQL_QUERY_DROP = "DROP TABLE IF EXISTS "+ NotesMetaData.NotesTable.TABLE_NAME + ";";@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVer, int newVer) {db.execSQL(SQL_QUERY_DROP);onCreate(db);}}// create a db helper objectprivate NotesDBHelper mDbHelper;@Overridepublic boolean onCreate() {mDbHelper = new NotesDBHelper(getContext());return false;}@Overridepublic int delete(Uri uri, String where, String[] whereArgs) {SQLiteDatabase db = mDbHelper.getWritableDatabase();int count = 0;switch (sUriMatcher.match(uri)) {case NOTES_ALL:count = db.delete(NotesMetaData.NotesTable.TABLE_NAME, where,whereArgs);break;case NOTES_ONE:String rowId = uri.getPathSegments().get(1);count = db.delete(NotesMetaData.NotesTable.TABLE_NAME,NotesMetaData.NotesTable.ID+ " = "+ rowId+ (!TextUtils.isEmpty(where) ? " AND (" + where+ ")" : ""), whereArgs);break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}@Overridepublic String getType(Uri uri) {switch (sUriMatcher.match(uri)) {case NOTES_ALL:return NotesMetaData.CONTENT_TYPE_NOTES_ALL;case NOTES_ONE:return NotesMetaData.CONTENT_TYPE_NOTES_ONE;default:throw new IllegalArgumentException("Unknown URI: " + uri);}}@Overridepublic Uri insert(Uri uri, ContentValues values) {// you cannot insert a bunch of values at once so throw exceptionif (sUriMatcher.match(uri) != NOTES_ALL) {throw new IllegalArgumentException(" Unknown URI: " + uri);}// Insert once rowSQLiteDatabase db = mDbHelper.getWritableDatabase();long rowId = db.insert(NotesMetaData.NotesTable.TABLE_NAME, null,values);if (rowId > 0) {Uri notesUri = ContentUris.withAppendedId(NotesMetaData.CONTENT_URI, rowId);getContext().getContentResolver().notifyChange(notesUri, null);return notesUri;}throw new IllegalArgumentException("<Illegal>Unknown URI: " + uri);}// Get values from Content Provider@Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {SQLiteQueryBuilder builder = new SQLiteQueryBuilder();switch (sUriMatcher.match(uri)) {case NOTES_ALL:builder.setTables(NotesMetaData.NotesTable.TABLE_NAME);builder.setProjectionMap(sNotesColumnProjectionMap);break;case NOTES_ONE:builder.setTables(NotesMetaData.NotesTable.TABLE_NAME);builder.setProjectionMap(sNotesColumnProjectionMap);builder.appendWhere(NotesMetaData.NotesTable.ID + " = "+ uri.getLastPathSegment());break;default:throw new IllegalArgumentException("Unknown URI: " + uri);}SQLiteDatabase db = mDbHelper.getReadableDatabase();Cursor queryCursor = builder.query(db, projection, selection,selectionArgs, null, null, null);queryCursor.setNotificationUri(getContext().getContentResolver(), uri);return queryCursor;}@Overridepublic int update(Uri uri, ContentValues values, String where,String[] whereArgs) {SQLiteDatabase db = mDbHelper.getWritableDatabase();int count = 0;switch (sUriMatcher.match(uri)) {case NOTES_ALL:count = db.update(NotesMetaData.NotesTable.TABLE_NAME, values,where, whereArgs);break;case NOTES_ONE:String rowId = uri.getLastPathSegment();count = db.update(NotesMetaData.NotesTable.TABLE_NAME, values,NotesMetaData.NotesTable.ID	+ " = "	+ rowId	+ (!TextUtils.isEmpty(where) ? " AND ("	+ ")" : ""), whereArgs);default:throw new IllegalArgumentException("Unknown URI: " + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}}

When you insert/update/delete, always remember to call “notifyChange()” to the URI that has been used.

When you query values, always remember to to call “setNotificationUri()” for Cursor.

That’s done for creating your custom content provider. In order to use, you need to register it to AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.coderzheaven.custom_contentproviderdemo"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="17" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name="com.coderzheaven.custom_contentproviderdemo.MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><providerandroid:name="com.coderzheaven.custom_contentproviderdemo.NotesContentProvider"android:authorities="com.coderzheaven.custom_contentproviderdemo.Notes" ></provider></application></manifest>

Now we look how we can use it in an activity

MainActivity.java

package com.coderzheaven.custom_contentproviderdemo;import android.app.Activity;import android.content.ContentValues;import android.database.Cursor;import android.os.Bundle;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;import com.coderzheaven.custom_contentproviderdemo.NotesMetaData.NotesTable;public class MainActivity extends Activity implements OnClickListener {private final static String TAG = "CustomContentProvider";EditText title, content, delete_id;Button add, update, delete, showNotes;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);title = (EditText) findViewById(R.id.title);content = (EditText) findViewById(R.id.content);delete_id = (EditText) findViewById(R.id.delete_id);// add Click Listnersadd = (Button) findViewById(R.id.button_add);add.setOnClickListener(this);update = (Button) findViewById(R.id.button_update);update.setOnClickListener(this);delete = (Button) findViewById(R.id.button_delete);delete.setOnClickListener(this);showNotes = (Button) findViewById(R.id.show_notes);showNotes.setOnClickListener(this);getNotes();}void addNote() {if (title.getText().toString().length() > 0&& content.getText().toString().length() > 0) {ContentValues values = new ContentValues();values.put(NotesTable.TITLE, title.getText().toString());values.put(NotesTable.CONTENT, content.getText().toString());getContentResolver().insert(NotesMetaData.CONTENT_URI, values);Log.i(TAG, "Inserted");makeToast("Note Added");} else {makeToast("Empty Field");}}void deleteNote(String str_id) {try {int id = Integer.parseInt(str_id);Log.i(TAG, "Deleting with id = " + id);getContentResolver().delete(NotesMetaData.CONTENT_URI,NotesMetaData.NotesTable.ID + " = " + id, null);Log.i(TAG, "Deleted");makeToast("Note Deleted");} catch (Exception e) {e.printStackTrace();}}void updateNote(String str_id) {try {int id = Integer.parseInt(str_id);Log.i(TAG, "Updating with id = " + id);ContentValues values = new ContentValues();values.put(NotesTable.TITLE, title.getText().toString());values.put(NotesTable.CONTENT, content.getText().toString());getContentResolver().update(NotesMetaData.CONTENT_URI, values,NotesMetaData.NotesTable.ID + " = " + id, null);makeToast("Note Updated");} catch (Exception e) {e.printStackTrace();}}void getNotes() {Cursor cur = getContentResolver().query(NotesMetaData.CONTENT_URI,null, null, null, null);if (cur.getCount() > 0) {Log.i(TAG, "Showing values.....");while (cur.moveToNext()) {String Id = cur.getString(cur.getColumnIndex(NotesTable.ID));String title = cur.getString(cur.getColumnIndex(NotesTable.TITLE));System.out.println("Id = " + Id + ", Note Title : " + title);}makeToast("Check the LogCat for Notes");} else {Log.i(TAG, "No Notes added");makeToast("No Notes added");}}@Overridepublic void onClick(View arg0) {if (arg0 == add) {addNote();}if (arg0 == update) {// update note with IdupdateNote(delete_id.getText().toString());}if (arg0 == delete) {// delete note with IddeleteNote(delete_id.getText().toString());}if (arg0 == showNotes) {// show allgetNotes();}}private void makeToast(String text) {Toast.makeText(this, text, Toast.LENGTH_LONG).show();}}

You can download the complete source code from this demo here.

Website PinFacebook TwitterMyspaceFriendfeedTechnoratidel.icio.usDiggGoogleStumbleUponPremium Responsive

Leave a Reply Cancel reply