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 columns private 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" + ");"; @Override public void onCreate(SQLiteDatabase db) { db.execSQL(SQL_QUERY_CREATE); } private static final String SQL_QUERY_DROP = "DROP TABLE IF EXISTS " + NotesMetaData.NotesTable.TABLE_NAME + ";"; @Override public void onUpgrade(SQLiteDatabase db, int oldVer, int newVer) { db.execSQL(SQL_QUERY_DROP); onCreate(db); } } // create a db helper object private NotesDBHelper mDbHelper; @Override public boolean onCreate() { mDbHelper = new NotesDBHelper(getContext()); return false; } @Override public 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; } @Override public 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); } } @Override public Uri insert(Uri uri, ContentValues values) { // you cannot insert a bunch of values at once so throw exception if (sUriMatcher.match(uri) != NOTES_ALL) { throw new IllegalArgumentException(" Unknown URI: " + uri); } // Insert once row SQLiteDatabase 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 @Override public 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; } @Override public 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-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android: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> <provider android: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; @Override protected 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 Listners add = (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"); } } @Override public void onClick(View arg0) { if (arg0 == add) { addNote(); } if (arg0 == update) { // update note with Id updateNote(delete_id.getText().toString()); } if (arg0 == delete) { // delete note with Id deleteNote(delete_id.getText().toString()); } if (arg0 == showNotes) { // show all getNotes(); } } private void makeToast(String text) { Toast.makeText(this, text, Toast.LENGTH_LONG).show(); } }
You can download the complete source code from this demo here.