安卓ContentProvider詳解
阿新 • • 發佈:2019-02-18
如有轉載,請申明:
ContentProvider是安卓四大元件之一,但與其他三種元件相比,並不是很常用,但同樣重要。
ContentProvider可以讓應用之間相互共享資源,比通過公開的檔案的共享方式更加安全和高效。一般來說,我們很少需要自己去編寫一個ContentProvider,除非你是一個著名應用的開發者。但這並不意味著我們不應該學習如何編寫。下面簡單介紹一下ContentProvider的編寫流程。
編寫ContentProvider
首先這個類需要繼承ContentProvider,然後在AndroidManifest.xml中配置
<provider android:name="com.ittianyu.contentprovider.StudentContentProvider" android:authorities="com.ittianyu.contentprovider.student" android:enabled="true" android:exported="true"></provider>
Name 為對應的ContentProvider類,authorities為訪問ContentProvider的路徑。
下面我把一個簡單的ContentProvider實現類程式碼貼出來
package com.ittianyu.contentprovider; import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.net.Uri; /** * 學生內容提供者 */ public class StudentContentProvider extends ContentProvider { private static final int MATCH_SUCCESS = 1; private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); static { matcher.addURI("com.ittianyu.contentprovider.student", "insert", MATCH_SUCCESS); } public StudentContentProvider() { } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // Implement this to handle requests to delete one or more rows. throw new UnsupportedOperationException("Not yet implemented"); } @Override public String getType(Uri uri) { // TODO: Implement this to handle requests for the MIME type of the data // at the given URI. throw new UnsupportedOperationException("Not yet implemented"); } @Override public Uri insert(Uri uri, ContentValues values) { if(MATCH_SUCCESS != matcher.match(uri)) { throw new RuntimeException("路徑錯誤....."); } System.out.println("資料插入成功"); return null; } @Override public boolean onCreate() { // TODO: Implement this to initialize your content provider on startup. return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO: Implement this to handle query requests from clients. throw new UnsupportedOperationException("Not yet implemented"); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO: Implement this to handle requests to update one or more rows. throw new UnsupportedOperationException("Not yet implemented"); } }
上面的程式碼中,除了insert方法,其他方法都是自動生成,沒有改動過。
細心的你會發現裡面還有一個自己手動寫的UriMatcher matcher,這個物件是用來匹配uri的,因此你可以新增自定義路徑來限制一些非法的請求。
比如上面的程式碼中在static程式碼塊中
matcher.addURI("com.ittianyu.contentprovider.student", "insert", MATCH_SUCCESS);
就添加了路徑”insert”。所以在請求這個ContentProvider是,傳遞的Uri中需要加上路徑insert,具體的完整Uri看後面的呼叫類。
我們可以看到自動生成的方法insert、delete、update、query 對應的是資料的增刪改查,熟悉資料庫操作的肯定一看就明白了,這裡不多囉嗦。
除了對資料操作的方法,還有一個getType,意如其名,這個方法是用來返回指定URI的MIME資料型別。若URI是單條資料,則返回的MIME資料型別以vnd.android.cursor.item開頭;若URI是多條資料,則返回的MIME資料型別以vnd.android.cursor.dir/開頭。
編寫ContentProvider呼叫方法
/**
* 通過content provider 新增資料
*/
private void add() {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.ittianyu.contentprovider.student/insert");
ContentValues values = new ContentValues();
resolver.insert(uri, values);
}
要和ContentProvider通訊,我們就需要ContentResolver。
通過getContentResolver就可以獲得ContentResolver物件。
有了物件,我們還需要先準備好Uri 和ContentValues。
uri 有固定的格式,以”content://”開頭,然後加上要通訊的地址,如果有路徑,則在後面追加,比如這裡通訊路徑為”com.ittianyu.contentprovider.student”,路徑為”insert”,所以完整的uri文字為"content://com.ittianyu.contentprovider.student/insert"。
由於我們這裡沒有要插入的資料,所以直接傳了一個沒有資料的values。
然後呼叫insert(uri, values);方法就實現了呼叫方法。
常見應用場景
讀取簡訊自動填寫驗證碼、簡訊備份還原、讀取聯絡人、聯絡人備份還原。