IPC進程間通信的使用(四)——ContentProvider

Android四大組件之一CotentProvider相信做Android開發的人都知道。ContentProvider是Android中提供的專門用於不同應用間進行數據共享的方式。和Messenger一樣,CotentProvider的底層實現也是Binder。這裏也簡單記錄一下。
系統中預置了許多CotentProvider,如通訊錄,日曆,短信等等。要跨進程訪問這些信息,只需要通過使用CotentProvider的queryupdateinsertdelete方法即可。
這裏自定義一個ContentProvider。
CotentProvider主要以表格形式來組織數據,並且可以包含多個表,對每個表格來說,它們都具有行和列的層次性,行往往對應一條記錄,而列對應一條記錄中的一個字段,這點和數據庫很類似。除了表格在形式,ContentProvider還支持文件數據,比如圖片,視頻等。
話不多說,上代碼。
先上數據庫,創建Book和User兩個表。

/**
 * Created by Kevin on 2019/4/10<br/>
 * Blog:https://blog.csdn.net/student9128<br/>
 * Describe:<br/>
 */
public class DbOpenHelper extends SQLiteOpenHelper {
    public static final String DB_NAME = "book_provider.db";
    public static final String BOOK_TABLE_NAME = "book";
    public static final String USER_TABLE_NAME = "user";

    public static final int DB_VERSION = 1;

    private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS " + BOOK_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT)";

    private String CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS " + USER_TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT,gender INT)";

    public DbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK_TABLE);
        db.execSQL(CREATE_USER_TABLE);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists " + BOOK_TABLE_NAME);
        db.execSQL("drop table if exists " + USER_TABLE_NAME);
        onCreate(db);
    }
}

自定義ContentProvider,名爲BookProvider。

ContentProvider通過Uri來區分外界要訪問的數據集合,本例子中支持對BookProvider中的book和user的訪問,爲了知道要訪問的是哪個表,需要爲它們定義單獨的Uri和UriCode。通過UriMatcher中的addURI將Uri和UriCode關聯起來。這樣就可以通過UriCode來找到Uril知道外界要訪問的那個表格了。

/**
 * Created by Kevin on 2019/4/10<br/>
 * Blog:https://blog.csdn.net/student9128<br/>
 * Describe:<br/>
 */
public class BookProvider extends ContentProvider {
    private static final String TAG = "BookProvider";
    public static final String AUTHORITY = "com.kevin.server.provider";
    public static final Uri BOOK_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/book");
    public static final Uri USER_CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/user");
    public static final int BOOK_URI_CODE = 0;
    public static final int USER_URI_CODE = 1;
    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    private Context mContext;
    private SQLiteDatabase mDb;

    static {
        sUriMatcher.addURI(AUTHORITY, "book", BOOK_URI_CODE);
        sUriMatcher.addURI(AUTHORITY, "user", USER_URI_CODE);
    }

    @Override
    public boolean onCreate() {
        Log.d(TAG, "onCreate, current thread: " + Thread.currentThread().getName());
        mContext = getContext();
        initProviderData();
        return true;
    }

    private void initProviderData() {
        mDb = new DbOpenHelper(mContext, DbOpenHelper.DB_NAME, null, DbOpenHelper.DB_VERSION).getWritableDatabase();
        mDb.execSQL("delete from " + DbOpenHelper.BOOK_TABLE_NAME);
        mDb.execSQL("delete from " + DbOpenHelper.USER_TABLE_NAME);
        mDb.execSQL("insert into book values(3,'Android');");
        mDb.execSQL("insert into book values(4,'iOS');");
        mDb.execSQL("insert into book values(5,'Html5');");
        mDb.execSQL("insert into user values(1,'Jack', 1);");
        mDb.execSQL("insert into user values(2,'LiLy',0);");

    }


    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Log.d(TAG, "query,current thread:" + Thread.currentThread().getName());
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        return mDb.query(tableName, projection, selection, selectionArgs, null, null, sortOrder, null);
    }

    @Override
    public String getType(Uri uri) {
        Log.d(TAG, "getType");
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Log.d(TAG, "insert");
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri + " for insert.");
        }
        mDb.insert(tableName, null, values);
        mContext.getContentResolver().notifyChange(uri, null);
        return uri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        Log.d(TAG, "delete");
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri + " for delete.");
        }
        int count = mDb.delete(tableName, selection, selectionArgs);
        if (count > 0) {
            mContext.getContentResolver().notifyChange(uri, null);
        }
        return count;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        Log.d(TAG, "update");
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported Uri: " + uri + " for update.");
        }
        int row = mDb.update(tableName, values, selection, selectionArgs);
        if (row > 0) {
            mContext.getContentResolver().notifyChange(uri, null);
        }
        return row;
    }

    private String getTableName(Uri uri) {
        switch (sUriMatcher.match(uri)) {
            case BOOK_URI_CODE:
                return DbOpenHelper.BOOK_TABLE_NAME;
            case USER_URI_CODE:
                return DbOpenHelper.USER_TABLE_NAME;
        }
        return null;
    }
}

AndroidMainfest清單文件配置:

<permission
        android:name="com.kevin.server.ACCESS_PROVIDER"
        android:protectionLevel="normal" />
        <provider
            android:name=".BookProvider"
            android:authorities="com.kevin.server.provider"
            android:enabled="true"
            android:exported="true"
            android:permission="com.kevin.server.ACCESS_PROVIDER" />

其中android:authorities="com.kevin.server.provider"是ContentProvider的唯一標識,通過這個屬性外部應用就可以訪問BookProvider,因此android:authorities必須是唯一的。因爲是進程間通信,這裏爲BookProvider添加了權限。註冊以後,外部應用就可以訪問BookProvider了。

/**
 * Created by Kevin on 2019/4/10<br/>
 * Blog:https://blog.csdn.net/student9128<br/>
 * Describe:<br/>
 */
public class ProviderActivity extends AppCompatActivity {
    private static final String TAG = "ProviderActivity";
    private ContentResolver contentResolver;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Uri bookUri = Uri.parse("content://com.kevin.server.provider/book");
        ContentValues contentValues = new ContentValues();
        contentValues.put("_id", 6);
        contentValues.put("name", "程序設計的藝術");
        contentResolver = getContentResolver();
        contentResolver.insert(bookUri, contentValues);
        Cursor bookCursor = contentResolver.query(bookUri, new String[]{"_id", "name"}, null, null, null);
        while (bookCursor.moveToNext()) {
            Book book = new Book();
            book.id = bookCursor.getInt(0);
            book.name = bookCursor.getString(1);
            Log.d(TAG, "query book: " + book.toString());
        }
        bookCursor.close();
        Uri userUri = Uri.parse("content://com.kevin.server.provider/user");
        Cursor userCursor = contentResolver.query(userUri, new String[]{"_id", "name", "gender"}, null, null, null);
        while (userCursor.moveToNext()) {
            User user = new User();
            user.userId = userCursor.getInt(0);
            user.userName = userCursor.getString(1);
            user.isMale = userCursor.getInt(2) == 1;
            Log.d(TAG, "query user: " + user.userId + "=" + user.userName + "=" + user.isMale);
        }
        userCursor.close();

    }
}

查詢結果如下圖所示
在這裏插入圖片描述
注:本文章知識點來自學習《Android開發藝術探索》一書

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章