20170104第一行程式碼第七章Content Provider

weixin_34087301發表於2017-01-04

一、簡介

Content Provider用法有兩種:

1、使用現有的CP來讀取和操作相應程式中的資料;比如系統電話本。

2、建立自己的CP給我們的程式資料提供外部訪問的介面。

二、訪問已有的CP

當一個APP通過CP對其資料提供了外部的訪問介面,則其他任何程式都可以通過這個介面對資料進行訪問和操作。

1、ContentResolver用法

任何程式如果想訪問其他程式通過CP共享的資料,都要使用ContentResolver,通過Context的getContentResolver()方法獲取。

CR不接受表名,只接收內容URI。

URI:給CP中的資料建立了一個唯一的識別符號,通過URI就可以訪問該資料。

URI包含兩個部分:許可權authority+路徑path。

許可權authority:為了區分不同的程式,一般用該程式的包名做許可權,com.example.app.provider

路徑path:為了區分同一個APP中不同的表名。

URI標準格式為:content://com.example.app.provider/table1

其中,com.example.app為提供CP的程式包名;table1為資料所在表名。

使用方法:

ContentResolver cr=getContentResolver();

//查詢資料

Cursor cursor=cr.query(uri, column1, “column1=? and column2=?”, new String[] {“ ”,” ”});

分別填入URI,查詢的列名,查詢的約束條件,佔位符的值,最後還可以加上排序方式。

//增加資料

ContentValues values=new ContentValues();

values.put(“column1”,”hello”);

values.put(“column2”,”hujun”);

cr.insert(uri, values);

利用ContentValues將資料插入表。

//修改資料

ContentValues values=new ContentValues();

values.put(“column1”,”data_changed”);

cr.update(uri, values, “column1=? and column2=?”, new String[] {“ ”,” ”});

分別填入URI,values,以及約束條件和佔位符的值。

//刪除資料

cr.delete(uri, “column1=?” , new String[] {“data”});

刪除列1中值為data的行。

2、讀取系統聯絡人

手機聯絡人URI為:

ContactsContract.CommonDataKinds.Phone.CONTENT_URI

該資料中包括聯絡人姓名、號碼,所在列名分別為:

ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME

ContactsContract.CommonDataKinds.Phone.NUMBER

讀取聯絡人資訊,還需要獲取許可權

android.permission.READ_CONTACTS

讀取程式碼為:

public void init()

{

ContentResolver cr=getContentResolver();

Cursor cursor=cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);

if(cursor!=null)

{

while(cursor.moveToNext())

{

String name=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));

String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

contacts.add(name+"\n"+number);

}}

if(cursor!=null)cursor.close();

}

三、建立自己的ContentProvider

1、建立CP步驟5部曲

(1)首先,新建MyContentProvider類去繼承ContentProvider,需要重寫6個方法:

onCreate():當存在ContentResolver嘗試訪問該CP時,自動呼叫onCreate()方法來初始化CP,通常在此完成資料庫建立、升級等操作。

insert()、query()、update()、delete()就是操作CP提供的資料時使用的方法。

getType():根據傳入的URI來返回相應的MIME型別?

(2)然後,如何解析URI?

UIR包括兩種格式:

content://com.example.app.provider/table1

content://com.example.app.provider/table1/1

第一種格式,以路徑table1結尾,訪問表table1中所有資料;

第二種格式,在最後加上了id,即訪問表table1中id為1的資料。

以萬用字元形式表示:

*:代表任意長度任意字元;

#:代表任意長度任意數字。

content://com.example.app.provider/*代表任意一個表

content://com.example.app.provider/table1/#代表表table1中任意一行

採用UriMatcher解析URI,

首先,配置UriMatcher,利用addURI()方法,將許可權,路徑和自定義程式碼傳入;

然後,解析URI,利用match(uri)方法,如果該uri和之前addURI()寫入的許可權和路徑相同時,返回自定義程式碼。

最後,通過這個自定義程式碼,即可採取不同的操作。

(3)重寫query()等

public class MyContentProvider extends ContentProvider{

public static final int TABLE1_DIR=0;

public static final int TABLE1_ITEM=1;

public static final int TABLE2_DIR=2;

public static final int TABLE2_ITEM=3;

private static UriMatcher uriMatcher;

static

{

uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI("com.example.contentprovider", "Book", TABLE1_DIR);

uriMatcher.addURI("com.example.contentprovider", "Book/#", TABLE1_ITEM);

uriMatcher.addURI("com.example.contentprovider", "Category", TABLE2_DIR);

uriMatcher.addURI("com.example.contentprovider", "Category/#", TABLE2_ITEM);

}

public Cursor query(Uri uri, String[] projection, String selection,

String[] selectionArgs, String sortOrder) {

switch (uriMatcher.match(uri)) {

case TABLE1_DIR:

//查詢Book中所有資料

break;

case TABLE1_ITEM:

//查詢Book中單條資料,根據id

break;

case TABLE2_DIR:

//查詢Category中單條資料

break;

case TABLE2_ITEM:

//查詢Book中單條資料,根據id

break;

default:

break;

}

return null;

}

(4)重寫getType()

獲取URI物件所對應的MIME型別。

一個內容URI對應的MIME字串包含3個部分:

1、必須以vnd開頭;

2、如果內容URI以路徑結尾,則後接android.cursor.dir/

如果內容URI以id結尾,則後接android.cursor.item/

3、最後接vnd..

例如:

URI:content://com.example.app.provider/table1

MIMIE:vnd.android.cursor.dir/vnd.com.example.app.provider.table1

URI:  content://com.example.app.provider/table1/1

MIMIE:  vnd.android.cursor.item/vnd.com.example.app.provider.table1

(5)在AndroidManifest.xml中註冊

android:name="com.example.contentprovider.MyContentProvider"

android:authorities="com.example.contentprovider.provider"

android:exported="true" >

android:exported="true"表示該provider可以被其他程式訪問。

四、跨程式資料共享實踐

資料傳送方,需要構建ContentProvider,將資料共享;共享的資料在CP類中onCreate()封裝到資料庫中。

資料接收方,利用ContentResolver獲取資料。

附錄:

當URI中包含id,如何獲取呢?

String id=uri.getPathSegments().get(1);

由此可見,路徑獲取方式為:String path=uri.getPathSegments().get(0);

相關文章