1. Define a Database Contract.
It contains the following information about a Database.
(1) Authority
(2) Table names
(3) column names of each Table
(4) content Uri
import android.net.Uri; import android.provider.BaseColumns; import static com.example.viki_hung.imageforumviewer.Constant.PACKAGE_NAME; /** * The contract holds database setting for forum content provider. */ public final class ForumDBContract { /** * the authority of Content Provider */ static final String AUTHORITY = PACKAGE_NAME; /** * To prevent someone from accidentally instantiating the contract class, * give it an empty constructor. */ private ForumDBContract() { } /** * Inner class that defines the Forum table contents */ public static final class ForumEntry implements BaseColumns { public static final String FORUM_TABLE_NAME = "ForumList"; public static final String FORUM_ID = "fid"; public static final String FORUM_TITLE = "title"; } /** * Inner class that defines the Topic table contents */ public static final class TopicEntry implements BaseColumns { public static final String TOPIC_TABLE_NAME = "TopicList"; public static final String TOPIC_ID = "tid"; public static final String TOPIC_FORUM_ID = "fid"; public static final String TOPIC_TITLE = "title"; public static final String TOPIC_IMAGE = "image"; public static final String TOPIC_IMAGE_LIST = "imagelist"; } /** * Uri of Forum list content */ static final Uri CONTENT_URI_FORUM_LIST = Uri.parse("content://" + AUTHORITY + "/" + ForumEntry.FORUM_TABLE_NAME); /** * Uri of Topic list content */ static final Uri CONTENT_URI_TOPIC_LIST = Uri.parse("content://" + AUTHORITY + "/" + TopicEntry.TOPIC_TABLE_NAME); }
2. Create a class extends SQLiteOpenHelper
It contains the following information.
(1) Database name
(2) Database version
(3) SQL command to create a database
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import static android.provider.BaseColumns._ID; import static com.example.viki_hung.imageforumviewer.ForumDBContract.ForumEntry.FORUM_ID; import static com.example.viki_hung.imageforumviewer.ForumDBContract.ForumEntry.FORUM_TABLE_NAME; import static com.example.viki_hung.imageforumviewer.ForumDBContract.ForumEntry.FORUM_TITLE; import static com.example.viki_hung.imageforumviewer.ForumDBContract.TopicEntry.TOPIC_FORUM_ID; import static com.example.viki_hung.imageforumviewer.ForumDBContract.TopicEntry.TOPIC_ID; import static com.example.viki_hung.imageforumviewer.ForumDBContract.TopicEntry.TOPIC_IMAGE; import static com.example.viki_hung.imageforumviewer.ForumDBContract.TopicEntry.TOPIC_IMAGE_LIST; import static com.example.viki_hung.imageforumviewer.ForumDBContract.TopicEntry.TOPIC_TABLE_NAME; import static com.example.viki_hung.imageforumviewer.ForumDBContract.TopicEntry.TOPIC_TITLE; /** * Database create Helper of forum database */ class ForumDBHelper extends SQLiteOpenHelper { private static final String DEBUG_TAG = ForumDBHelper.class.getSimpleName(); private static final String DATABASE_NAME = "ForumList"; private static final int VERSION_INITIAL = 1; private static final String DATABASE_CREATE_FORUM_LIST = "CREATE TABLE if not exists " + FORUM_TABLE_NAME + " (" + _ID + " integer PRIMARY KEY autoincrement," + FORUM_ID + " TEXT, " + FORUM_TITLE + " TEXT );"; private static final String DATABASE_CREATE_TOPIC_LIST = "CREATE TABLE if not exists " + TOPIC_TABLE_NAME + " (" + _ID + " integer PRIMARY KEY autoincrement," + TOPIC_ID + " TEXT, " + TOPIC_FORUM_ID + " TEXT, " + TOPIC_TITLE + " TEXT, " + TOPIC_IMAGE + " TEXT, " + TOPIC_IMAGE_LIST + " TEXT );"; ForumDBHelper(Context context) { super(context, DATABASE_NAME, null, VERSION_INITIAL); } @Override public void onCreate(SQLiteDatabase db) { Log.d(DEBUG_TAG, "DB onCreate"); db.execSQL(DATABASE_CREATE_FORUM_LIST); db.execSQL(DATABASE_CREATE_TOPIC_LIST); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
3. Create a ContentProvider which uses SQLiteOpenHelper and UriMatcher
package com.example.viki_hung.imageforumviewer; 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; import static com.example.viki_hung.imageforumviewer.ForumDBContract.AUTHORITY; import static com.example.viki_hung.imageforumviewer.ForumDBContract.CONTENT_URI_FORUM_LIST; import static com.example.viki_hung.imageforumviewer.ForumDBContract.CONTENT_URI_TOPIC_LIST; import static com.example.viki_hung.imageforumviewer.ForumDBContract.ForumEntry.FORUM_TABLE_NAME; import static com.example.viki_hung.imageforumviewer.ForumDBContract.TopicEntry.TOPIC_TABLE_NAME; /** * The Content Provider of the image forum */ public class ForumContentProvider extends ContentProvider { private static final String DEBUG_TAG = ForumContentProvider.class.getSimpleName(); /** * UriMatcher to match URI to a code */ private static final UriMatcher sUriMatcher; private static final int URI_MATCH_FORUM_LIST = 1; private static final int URI_MATCH_TOPIC_LIST = 2; /** * match URI to a code using UriMatcher */ static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(AUTHORITY, FORUM_TABLE_NAME, URI_MATCH_FORUM_LIST); sUriMatcher.addURI(AUTHORITY, TOPIC_TABLE_NAME, URI_MATCH_TOPIC_LIST); } private ForumDBHelper mDbHelper; @Override public boolean onCreate() { Log.d(DEBUG_TAG, "CP onCreate"); mDbHelper = new ForumDBHelper(getContext()); return true; } @Override public String getType(Uri uri) { switch (sUriMatcher.match(uri)) { case URI_MATCH_FORUM_LIST: { return "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + FORUM_TABLE_NAME; } case URI_MATCH_TOPIC_LIST: { return "vnd.android.cursor.dir/vnd." + AUTHORITY + "." + TOPIC_TABLE_NAME; } default: { return null; } } } @Override public Uri insert(Uri uri, ContentValues values) { Uri returnUri = null; if (values == null || values.size() == 0) { return null; } try { SQLiteDatabase db = mDbHelper.getWritableDatabase(); if (db == null) { return null; } long id; switch (sUriMatcher.match(uri)) { case URI_MATCH_FORUM_LIST: { // insert value to forum list id = db.insert(FORUM_TABLE_NAME, null, values); returnUri = Uri.withAppendedPath(CONTENT_URI_FORUM_LIST, String.valueOf(id)); Log.d(DEBUG_TAG, "CP insert, uri=" + returnUri); break; } case URI_MATCH_TOPIC_LIST: { // insert value to topic list id = db.insert(TOPIC_TABLE_NAME, null, values); returnUri = Uri.withAppendedPath(CONTENT_URI_TOPIC_LIST, String.valueOf(id)); Log.d(DEBUG_TAG, "CP insert, uri=" + returnUri); break; } default: { return null; } } getContext().getContentResolver().notifyChange(returnUri, null); } catch (Exception ignored) { Log.e(DEBUG_TAG, ignored.getMessage(), ignored); } return returnUri; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = null; try { SQLiteDatabase db = mDbHelper.getReadableDatabase(); if (db == null) { return null; } switch (sUriMatcher.match(uri)) { case URI_MATCH_FORUM_LIST: { Log.d(DEBUG_TAG, "CP query forum list."); cursor = db.query(FORUM_TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); break; } case URI_MATCH_TOPIC_LIST: { Log.d(DEBUG_TAG, "CP query topic list."); cursor = db.query(TOPIC_TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); break; } default: { return null; } } Log.d(DEBUG_TAG, "CP query result cursor_count=" + cursor.getCount()); } catch (Exception ignored) { Log.e(DEBUG_TAG, ignored.getMessage(), ignored); } return cursor; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int deleteCount = -1; SQLiteDatabase db = mDbHelper.getWritableDatabase(); if (db == null) { return -1; } try { switch (sUriMatcher.match(uri)) { case URI_MATCH_FORUM_LIST: { Log.d(DEBUG_TAG, "CP delete forum list."); deleteCount = db.delete(FORUM_TABLE_NAME, selection, selectionArgs); break; } case URI_MATCH_TOPIC_LIST: { Log.d(DEBUG_TAG, "CP delete topic list."); deleteCount = db.delete(TOPIC_TABLE_NAME, selection, selectionArgs); break; } default: { return -1; } } getContext().getContentResolver().notifyChange(uri, null); } catch (Exception ignored) { Log.e(DEBUG_TAG, ignored.getMessage(), ignored); } return deleteCount; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int updateCount = -1; try { SQLiteDatabase db = mDbHelper.getWritableDatabase(); if (db == null) { return -1; } switch (sUriMatcher.match(uri)) { case URI_MATCH_FORUM_LIST: { Log.d(DEBUG_TAG, "CP update forum list."); updateCount = db.update(FORUM_TABLE_NAME, values, selection, selectionArgs); break; } case URI_MATCH_TOPIC_LIST: { Log.d(DEBUG_TAG, "CP update topic list."); updateCount = db.update(TOPIC_TABLE_NAME, values, selection, selectionArgs); break; } default: { return -1; } } getContext().getContentResolver().notifyChange(uri, null); } catch (Exception ignored) { Log.e(DEBUG_TAG, ignored.getMessage(), ignored); } return updateCount; } }
4. Usage of the ContentProvider
Insert:
// new item ContentValues values = new ContentValues(); values.put(FORUM_ID, forumId); values.put(FORUM_TITLE, forumTitle); // insert a record to DB Uri uri = getContentResolver().insert(CONTENT_URI_FORUM_LIST, values);
delete:
// if parse json OK, clear topic list in DB int dCount = getContentResolver().delete( CONTENT_URI_TOPIC_LIST, TOPIC_FORUM_ID + " = ?", new String[]{fid});