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;
    }
}

你可能感兴趣的:(IPC)