Androi IPC程序間通訊(五)ContentProvider
阿新 • • 發佈:2018-11-11
程序間通訊之ContentProvider
一,介紹
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;
}
}