1. 程式人生 > >Androi IPC程序間通訊(五)ContentProvider

Androi IPC程序間通訊(五)ContentProvider

程序間通訊之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;
    }
}