一,介绍
1.底层实现也是Binder
2.其6个方法除了onCreate方法运行于主线程,其他4个方法由外界回调并运行于Binder线程池。
3.注册ContentProvider需要一个属性android:authorities=“XXXXX” 唯一标识ContentProvider,外部应用即可通过它进行访问
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.contentprovider">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
...
<provider
android:name=".views.MyContentProvider"
android:authorities="com.example.contentprovider.views.provider"
android:enabled="true"
android:exported="true"
android:process=":provider" />
</application>
</manifest>
指定访问ContentProvider的Uri为authorities+数据库名
public static final String DB_TABLE = "contacts";
public static final String AUTHORITIES = "com.example.contentprovider.views.provider";
public static final Uri CONTACTS_URI = Uri.parse("content://" + AUTHORITIES + "/" + DB_TABLE);
二,创建ContentProvider
1.创建一个帮助类用于创建和更新数据库
public class DBHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "contact.db";
private static final String DB_TABLE = "contacts";
private static final int DB_VERSION = 1;
public DBHelper(Context context) {
super(context, DB_NAME,null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table contacts(" +
"id integer primary key autoincrement," +
"name text," +
"phone text," +
"email text," +
"address text)");
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS tb_words");
onCreate(sqLiteDatabase);
}
}
}
2.创建ContentProvider的子类,重写它的6个方法
(一)UriMatcher 类主要用于匹配Uri。使用方法如下
第1步,初始化:
UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
第2步注册需要的Uri:
mUriMatcher.addURI(AUTHORITIES, DB_TABLE, URI_CODE_ONE);
mUriMatcher.addURI(AUTHORITIES, DB_TABLE + "/#", URI_CODE_TWO);
第3部,与已经注册的Uri进行匹配:mUriMatcher.match(uri)返回注册ID
switch (mUriMatcher.match(uri)) {
case URI_CODE_ONE:
cursor = db.query(DB_TABLE, projection, selection, selectionArgs,null,null,null);
break;
case URI_CODE_TWO:
String id = uri.getPathSegments().get(1);
cursor = db.query(DB_TABLE, projection, ContactsColumns.CONTACTS_ID + "= ?",
new String[]{id + (!TextUtils.isEmpty(selection) ? "AND" + selection : "")},
null, null, null);
break;
}
(二)ContentUris 类用于获取Uri路径后面的ID部分
1、为路径加上ID: withAppendedId(uri, id)
public static final Uri CONTACTS_URI = Uri.parse("content://" + AUTHORITIES + "/" + DB_TABLE);
通过withAppendedId方法,为该Uri加上ID
Uri resultUri = ContentUris.withAppendedId(uri, 10);
最后resultUri为: content://com.example.contentprovider.views.provider/contacts/10
2、从路径中获取ID: parseId(uri)
Uri uri = Uri.parse("content://com.example.contentprovider.views.provider/contacts/10")
long resultId = ContentUris.parseId(uri);
结果为10
还可用过String id = uri.getPathSegments().get(1);得到id
ContentProvider代码:
public class MyContentProvider extends ContentProvider {
private static UriMatcher mUriMatcher;
public static final String DB_TABLE = "contacts";
public static final String AUTHORITIES = "com.example.contentprovider.views.provider";
public static final Uri CONTACTS_URI = Uri.parse("content://" + AUTHORITIES + "/" + DB_TABLE);
public static final int URI_CODE_ONE = 1;
public static final int URI_CODE_TWO = 2;
private DBHelper mDBHelper;
private Context mContext;
private SQLiteDatabase db;
//程序首先执行静态块,UriMatcher专门用于为ContentProvider添加待匹配Uri
static {
mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
mUriMatcher.addURI(AUTHORITIES, DB_TABLE, URI_CODE_ONE);
mUriMatcher.addURI(AUTHORITIES, DB_TABLE + "/#", URI_CODE_TWO);
}
@Override
public boolean onCreate() {
mContext = getContext();
mDBHelper = new DBHelper(mContext);
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs, @Nullable String sortOrder) {
Cursor cursor;
//实例化数据库
db = mDBHelper.getReadableDatabase();
//依据前台查询的Uri进行判定是要访问那个Uri
switch (mUriMatcher.match(uri)) {
case URI_CODE_ONE:
cursor = db.query(DB_TABLE, projection, selection, selectionArgs,null,null,null);
break;
case URI_CODE_TWO:
String id = uri.getPathSegments().get(1);
cursor = db.query(DB_TABLE, projection, ContactsColumns.CONTACTS_ID +
"= ?",
new String[]{id + (!TextUtils.isEmpty(selection) ? "AND" + selection : "")},
null, null, null);
break;
default:
throw new IllegalArgumentException("unknown uri :" + uri);
}
return cursor;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
switch (mUriMatcher.match(uri)) {
case URI_CODE_ONE:
return "vnd.android.cursor.dir/vnd.contacts";
case URI_CODE_TWO:
return "vnd.android.cursor.item/vnd.contacts";
default:throw new IllegalArgumentException("unknown uri" + uri);
}
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
db = mDBHelper.getWritableDatabase();
long newId;
if (mUriMatcher.match(uri) != URI_CODE_ONE) {
throw new IllegalArgumentException("unknown uri" + uri);
}
Uri newUri = null;
newId = db.insert(DB_TABLE, null, contentValues);
if (newId > 0) {
newUri = ContentUris.withAppendedId(CONTACTS_URI, newId);
try {
getContext().getContentResolver().notifyChange(newUri, null);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
return newUri;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String whereCause, @Nullable String[] whereArgs) {
db = mDBHelper.getWritableDatabase();
int count;
switch (mUriMatcher.match(uri)) {
case URI_CODE_ONE:
count = db.delete(DB_TABLE,whereCause,whereArgs);
break;
case URI_CODE_TWO:
String id = uri.getPathSegments().get(1);
count = db.delete(DB_TABLE,ContactsColumns.CONTACTS_ID
+"=" + "?",new String[]{id + (!TextUtils.isEmpty(whereCause) ?
"AND" + whereCause : "")});
break;
default:throw new IllegalArgumentException("unknown uri" + uri);
}
getContext().getContentResolver().notifyChange(uri,null);
return count;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues contentValues,
@Nullable String whereCouse, @Nullable String[] whereArgs) {
db = mDBHelper.getWritableDatabase();
int count;
switch (mUriMatcher.match(uri)) {
case URI_CODE_ONE:
count = db.update(DB_TABLE,contentValues,whereCouse,whereArgs);
break;
case URI_CODE_TWO:
long id = ContentUris.parseId(uri);
count = db.update(DB_TABLE,contentValues,ContactsColumns.CONTACTS_ID
+"= ?",new String[]{id + (!TextUtils.isEmpty(whereCouse) ?
"AND" + whereCouse : "")});
break;
default:throw new IllegalArgumentException("unknown uri" + uri);
}
getContext().getContentResolver().notifyChange(uri,null);
return count;
}
}