接下来是getType方法,此方法参数是URI,根据Uri返回不同的MimeType:
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case COLL_TYPE_URI_MATCHER: {
return Book.ContentType.COLL_TYPE;
}
case ITEM_TYPE_URI_MATCHER: {
return Book.ContentType.ITEM_TYPE;
}
default: {
throw new SQLException("Unknown URI:" + uri);
}
}
}
接下来是insert方法,参数是Uri及ContentValues,较为简单:
@Override
public Uri insert(Uri uri, ContentValues values) {
if (uriMatcher.match(uri) != COLL_TYPE_URI_MATCHER) {
throw new SQLException("Unknown URI:" + uri);
}
Long now = System.currentTimeMillis();
if (!values.containsKey(Book.Columns.NAME)) {
throw new SQLException(Book.Columns.NAME.concat(" 的值不得为空!"));
}
if (!values.containsKey(Book.Columns.AUTHOR)) {
values.put(Book.Columns.AUTHOR, "Unknown Author");
}
if (!values.containsKey(Book.Columns.CREATE_TIME)) {
values.put(Book.Columns.CREATE_TIME, now);
}
SQLiteDatabase db = dbHelper.getWritableDatabase();
Long rowId = db.insert(Book.TABLE_NAME, Book.Columns.NAME, values);
if (rowId > 0) {
Uri insertedBookUri = ContentUris.withAppendedId(Book.CONTENT_URI,
rowId);
getContext().getContentResolver().notifyChange(insertedBookUri,
null);
return insertedBookUri;
}
throw new SQLException("添加图书失败,URI:" + uri);
}
前文说过,最好都加上notifyChange。
delete和update也没什么特别的:
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case COLL_TYPE_URI_MATCHER: {
count = db.delete(Book.TABLE_NAME, selection, selectionArgs);
break;
}
case ITEM_TYPE_URI_MATCHER: {
selection = Book.Columns._ID
.concat("=")
.concat(uri.getPathSegments().get(1))
.concat(TextUtils.isEmpty(selection) ? "" : " AND ("
.concat(selection).concat(")"));
count = db.delete(Book.TABLE_NAME, selection, selectionArgs);
break;
}
default: {
throw new SQLException("Unknown URI:" + uri);
}
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int count = 0;
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case COLL_TYPE_URI_MATCHER: {
count = db
.update(Book.TABLE_NAME, values, selection, selectionArgs);
break;
}
case ITEM_TYPE_URI_MATCHER: {
selection = Book.Columns._ID
.concat("=")
.concat(uri.getPathSegments().get(1))
.concat(TextUtils.isEmpty(selection) ? "" : " AND ("
.concat(selection).concat(")"));
count = db
.update(Book.TABLE_NAME, values, selection, selectionArgs);
break;
}
default: {
throw new SQLException("Unknown URI:" + uri);
}
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
至此已实现BookProvider,全部代码如下所示:
/**
*
* Dec 22, 2014 3:43:47 PM
* @Geloin
*
*/
package com.geloin.baseopera.provider;
import java.util.HashMap;
import java.util.Map;
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.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
/**
*
* Dec 22, 2014 3:43:47 PM
*
* @Geloin
*
*/
public class BookProvider extends ContentProvider {
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, Book.DB_FILE_NAME, null, Book.DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
StringBuilder builder = new StringBuilder();
builder.append(" CREATE TABLE ");
builder.append(Book.TABLE_NAME);
builder.append(" ( ");
builder.append(Book.Columns._ID);
builder.append(" INTEGER PRIMARY KEY, ");
builder.append(Book.Columns.NAME);
builder.append(" TEXT, ");
builder.append(Book.Columns.AUTHOR);
builder.append(" TEXT, ");
builder.append(Book.Columns.CREATE_TIME);
builder.append(" INTEGER ");
builder.append(" ); ");
db.execSQL(builder.toString());
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS ".concat(Book.TABLE_NAME));
onCreate(db);
}
}
private DBHelper dbHelper;
private static UriMatcher uriMatcher;
private static final int COLL_TYPE_URI_MATCHER = 1;
private static final int ITEM_TYPE_URI_MATCHER = 2;
private static Map<String, String> columnMap;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(Book.AUTHORITY, "books", COLL_TYPE_URI_MATCHER);
uriMatcher.addURI(Book.AUTHORITY, "books/#", ITEM_TYPE_URI_MATCHER);
columnMap = new HashMap<String, String>();
columnMap.put(Book.Columns._ID, Book.Columns._ID);
columnMap.put(Book.Columns.NAME, Book.Columns.NAME);
columnMap.put(Book.Columns.AUTHOR, Book.Columns.AUTHOR);
columnMap.put(Book.Columns.CREATE_TIME, Book.Columns.CREATE_TIME);
}
@Override
public boolean onCreate() {
dbHelper = new DBHelper(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (uriMatcher.match(uri)) {
case COLL_TYPE_URI_MATCHER: {
qb.setTables(Book.TABLE_NAME);
qb.setProjectionMap(columnMap);
break;
}
case ITEM_TYPE_URI_MATCHER: {
qb.setTables(Book.TABLE_NAME);
qb.setProjectionMap(columnMap);
qb.appendWhere(Book.Columns._ID.concat("=").concat(
uri.getPathSegments().get(1)));
break;
}
default: {
throw new SQLException("Unknown URI:" + uri);
}
}
String orderBy = null;
if (TextUtils.isEmpty(sortOrder)) {
orderBy = Book.DEFAULT_ORDER;
} else {
orderBy = sortOrder;
}
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor c = db.query(Book.TABLE_NAME, projection, selection,
selectionArgs, null, null, orderBy);
// 通知数据库变化
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case COLL_TYPE_URI_MATCHER: {
return Book.ContentType.COLL_TYPE;
}
case ITEM_TYPE_URI_MATCHER: {
return Book.ContentType.ITEM_TYPE;
}
default: {
throw new SQLException("Unknown URI:" + uri);
}
}
}
@Override
public Uri insert(Uri uri, ContentValues values) {
if (uriMatcher.match(uri) != COLL_TYPE_URI_MATCHER) {
throw new SQLException("Unknown URI:" + uri);
}
Long now = System.currentTimeMillis();
if (!values.containsKey(Book.Columns.NAME)) {
throw new SQLException(Book.Columns.NAME.concat(" 的值不得为空!"));
}
if (!values.containsKey(Book.Columns.AUTHOR)) {
values.put(Book.Columns.AUTHOR, "Unknown Author");
}
if (!values.containsKey(Book.Columns.CREATE_TIME)) {
values.put(Book.Columns.CREATE_TIME, now);
}
SQLiteDatabase db = dbHelper.getWritableDatabase();
Long rowId = db.insert(Book.TABLE_NAME, Book.Columns.NAME, values);
if (rowId > 0) {
Uri insertedBookUri = ContentUris.withAppendedId(Book.CONTENT_URI,
rowId);
getContext().getContentResolver().notifyChange(insertedBookUri,
null);
return insertedBookUri;
}
throw new SQLException("添加图书失败,URI:" + uri);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case COLL_TYPE_URI_MATCHER: {
count = db.delete(Book.TABLE_NAME, selection, selectionArgs);
break;
}
case ITEM_TYPE_URI_MATCHER: {
selection = Book.Columns._ID
.concat("=")
.concat(uri.getPathSegments().get(1))
.concat(TextUtils.isEmpty(selection) ? "" : " AND ("
.concat(selection).concat(")"));
count = db.delete(Book.TABLE_NAME, selection, selectionArgs);
break;
}
default: {
throw new SQLException("Unknown URI:" + uri);
}
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int count = 0;
SQLiteDatabase db = dbHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case COLL_TYPE_URI_MATCHER: {
count = db
.update(Book.TABLE_NAME, values, selection, selectionArgs);
break;
}
case ITEM_TYPE_URI_MATCHER: {
selection = Book.Columns._ID
.concat("=")
.concat(uri.getPathSegments().get(1))
.concat(TextUtils.isEmpty(selection) ? "" : " AND ("
.concat(selection).concat(")"));
count = db
.update(Book.TABLE_NAME, values, selection, selectionArgs);
break;
}
default: {
throw new SQLException("Unknown URI:" + uri);
}
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
再把Book代码贴出来:
/**
*
* Dec 22, 2014 3:42:39 PM
* @Geloin
*
*/
package com.geloin.baseopera.provider;
import android.net.Uri;
import android.provider.BaseColumns;
/**
*
* Dec 22, 2014 3:42:39 PM
*
* @Geloin
*
*/
public class Book {
public static final String TABLE_NAME = "books";
public static final String DB_FILE_NAME = "books.db";
public static final Integer DB_VERSION = 1;
public static final String AUTHORITY = "com.geloin.baseopera.provider.BookProvider";
public static final String DEFAULT_ORDER = "createTime DESC";
public static final Uri CONTENT_URI = Uri.parse("content://".concat(
AUTHORITY).concat("/books"));
/**
* 列名
*
* Dec 22, 2014 3:52:25 PM
*
* @Geloin
*
*/
public class Columns implements BaseColumns {
public static final String NAME = "name";
public static final String AUTHOR = "author";
public static final String CREATE_TIME = "createTime";
}
/**
* ContentType
*
* Dec 22, 2014 3:53:40 PM
*
* @Geloin
*
*/
public class ContentType {
/**
* 集合
*/
public static final String COLL_TYPE = "vnd.android.cursor.dir/vnd.androidbook.book";
/**
* 单项
*/
public static final String ITEM_TYPE = "vnd.android.cursor.item/vnd.androidbook.book";
}
}
定义ContentProvider后,必须在AndroidManifest.xml中注册:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.geloin.baseopera"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="21" />
<permission
android:name="com.geloin.permission.SayHello"
android:protectionLevel="normal" >
</permission>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".activity.BooksActivity"
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=".provider.BookProvider"
android:authorities="com.geloin.baseopera.provider.BookProvider"
android:exported="false" >
</provider>
</application>
</manifest>
接下来会讲述如何使用自定义的ContentProvider。