1. 程式人生 > >安卓ContentProvider詳解

安卓ContentProvider詳解

如有轉載,請申明:

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);方法就實現了呼叫方法。

常見應用場景

讀取簡訊自動填寫驗證碼、簡訊備份還原、讀取聯絡人、聯絡人備份還原。