如果想公開自己的數(shù)據(jù),那么可有兩種辦法:
1.創(chuàng)建自己的ContentProvider,需要繼承ContentProvider類
2.如果你的數(shù)據(jù)和已存在的ContentProvider數(shù)據(jù)結(jié)構(gòu)一致,可以將數(shù)據(jù)寫到已存在的ContentProvider中
當(dāng)然前提是獲取寫該ContentProvider的權(quán)限.比如把OA中的成員通訊信息加入到系統(tǒng)的聯(lián)系人ContentProvider中
ContentProvider基礎(chǔ)
所有ContentProvider都需要實(shí)現(xiàn)相同的接口,用于查詢ContentProvider并返回?cái)?shù)據(jù).也包括增加、修改和刪除數(shù)據(jù).
步驟:
1.獲得一個(gè)ContentResolver的實(shí)例,可通過(guò)Activity的成員方法getContentResovler()方法:
ContentResolver cr = this.getContentResolver();
ContentResolver實(shí)例帶的方法可實(shí)現(xiàn)找到指定的ContentProvider并獲取到ContentProvider的數(shù)據(jù)
ContentResolver的查詢過(guò)程開始,Android系統(tǒng)將確定查詢所需的具體ContentProvider,確認(rèn)它是否啟動(dòng)并運(yùn)行它.
android系統(tǒng)負(fù)責(zé)初始化所有的ContentProvider,不需要用戶自己去創(chuàng)建.實(shí)際上,ContentProvider的用戶都不可能直接訪問(wèn)到ContentProvider實(shí)例,只能通過(guò)ContentResolver在中間代理.
2.數(shù)據(jù)模型
ContentProvider展示數(shù)據(jù)類似一個(gè)單個(gè)數(shù)據(jù)庫(kù)表.
其中:
每行有個(gè)帶唯一值的數(shù)字字段,名為_ID,可用于對(duì)表中指定記錄的定位.
ContentProvider返回的數(shù)據(jù)結(jié)構(gòu),是類似JDBC的ResultSet,在android中,是Cursor對(duì)象.
URI,每個(gè)ContentProvider定義一個(gè)唯一的公開的URI,用于指定到它的數(shù)據(jù)集.
一個(gè)ContentProvider可以包含多個(gè)數(shù)據(jù)集(可以看作多張表),這樣,就需要有多個(gè)URI與每個(gè)數(shù)據(jù)集對(duì)應(yīng).
這些URI要以這樣的格式開頭:
content://
表示這個(gè)URI指定一個(gè)ContentProvider.
如果你想創(chuàng)建自己的ContentProvider,最好把自定義的URI設(shè)置為類的常量,這樣簡(jiǎn)化別人的調(diào)用,并且以后如果更新URI也很容易.
android定義了CONTENT_URI常量用于URI,如:android.provider.Contacts.Phones.CONTENT_URI
2.查詢ContentProvider
要想使用一個(gè)ContentProvider,需要以下信息:
定義這個(gè)ContentProvider的URI,返回結(jié)果的字段名稱,這些字段的數(shù)據(jù)類型
如果需要查詢ContentProvider數(shù)據(jù)集的特定記錄(行),還需要知道該記錄的ID的值.
構(gòu)建查詢
查詢就是輸入U(xiǎn)RI等參數(shù),其中URI是必須的,其他是可選的,如果系統(tǒng)能找到URI對(duì)應(yīng)的ContentProvider將返回一個(gè)Cursor對(duì)象.
可以通過(guò)ContentResolver.query()或者Activity.managedQuery()方法.
兩者的方法參數(shù)完全一樣,查詢過(guò)程和返回值也是相同的.
區(qū)別是,通過(guò)Activity.managedQuery()方法,不但獲取到Cursor對(duì)象,而且能夠管理Cursor對(duì)象的生命周期.
比如當(dāng)Activity暫停(pause)的時(shí)候,卸載該Cursor對(duì)象,當(dāng)ActivityRestart的時(shí)候重新查詢.另外,也可以對(duì)一個(gè)沒有處于Activity管理的Cursor對(duì)象做成被Activity管理的,通過(guò)調(diào)用Activity.startManaginCursor()方法.
類似這樣:
Cursor cur = managedQuery(myPerson,null,null,null,null);
其中第一個(gè)參數(shù)myPerson是Uri類型實(shí)例.
如果需要查詢的是指定行的記錄,需要用_ID值,比如ID值為23,URI將是類似:
content://....../23
android提供了方便的方法,讓開發(fā)者不需要自己拼接上面這樣的URI,比如類似:
Uri myPerson =ContentUris.withAppendedId(People.CONTENT_URI,23);
或者:
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI,"23");
二者的區(qū)別是一個(gè)接收整數(shù)類型的ID值,一個(gè)接收字符串類型.
其他幾個(gè)參數(shù):
names,可以為null,表示取數(shù)據(jù)集的全部列,或者聲明一個(gè)String數(shù)組,數(shù)組中存放列名稱,比如:People._ID.一般列名都在該ContentProvider中有常量對(duì)應(yīng);
針對(duì)返回結(jié)果的過(guò)濾器,格式類似于SQL中的WHERE子句,區(qū)別是不帶WHERE關(guān)鍵字,如果返回null表示不過(guò)濾,比如name=?;
前面過(guò)濾器的參數(shù),是String數(shù)組,是針對(duì)前面條件中?占位符的值;
排序參數(shù),類似SQL的ORDER BY字句,不過(guò)不需要寫ORDER BY部分,比如namedesc,如果不排序,可輸入null.
返回值是Cursor對(duì)象,游標(biāo)位置在第一條記錄之前.
下面實(shí)例適用于android 2.0及以上版本,從android通訊錄中得到姓名字段:
java代碼:
Cursor cursor =getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
讀取返回的數(shù)據(jù)
如果在查詢的時(shí)候使用到ID,那么返回的數(shù)據(jù)只有一條記錄.在其他情況下,一般會(huì)有多條記錄.和JDBC的ResultSet類似,需要操作游標(biāo)遍歷結(jié)果集,在每行,再通過(guò)列名獲取到列的值,可以通過(guò)getString()、getInt()、getFloat()等方法獲取值.
比如類似下面:
java代碼:
while(cursor.moveToNext()) {
builder.append(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))).append("-");
}
和JDBC中不同,沒有直接通過(guò)列名獲取列值的方法,只能先列名獲取到列的整型索引值,然后再通過(guò)該索引值定位獲取列的值.
編輯數(shù)據(jù)
可以通過(guò)ContentProvider實(shí)現(xiàn)以下編輯功能:
增加新的記錄:
在已經(jīng)存在的記錄中增加新的值、批量更新已經(jīng)存在的多個(gè)記錄、刪除記錄.
所有的編輯功能都是通過(guò)ContentResolver的方法實(shí)現(xiàn).一些ContentProvider對(duì)權(quán)限要求更嚴(yán)格一些,需要寫的權(quán)限,如果沒有會(huì)報(bào)錯(cuò).
增加記錄
要想增加記錄到ContentProvider,首先,要在ContentValues對(duì)象中設(shè)置類似map的鍵值對(duì),在這里,鍵的值對(duì)應(yīng)ContentProvider中的列的名字,鍵值對(duì)的值,是對(duì)應(yīng)列希望的類型.
然后,調(diào)用ContentResolver.insert()方法,傳入這個(gè)ContentValues對(duì)象,和對(duì)應(yīng)ContentProvider的URI即可.返回值是這個(gè)新記錄的URI對(duì)象.這樣你可以通過(guò)這個(gè)URI獲得包含這條記錄的Cursor對(duì)象.
比如:
java代碼:
ContentValues values = new ContentValues();
values.put(People.NAME,"Abraham Lincoln");
Uri uri = getContentResolver().insert(People.CONTENT_URI,values);
在原有記錄上增加值
如果記錄已經(jīng)存在,可在記錄上增加新的值,或者編輯已經(jīng)存在的值.
首先要找到原來(lái)的值對(duì)象,然后要清除原有的值,然后像上面增加記錄一樣即可:
java代碼:
Uri uri = Uri.withAppendedPath(People.CONTENT_URI, "23");
Uri phoneUri = Uri.withAppendedPath(uri,People.Phones.CONTENT_DIRECTORY);
values.clear();
values.put(People.Phones.TYPE, People.Phones.TYPE_MOBILE);
values.put(People.Phones.NUMBER, "1233214567");
getContentResolver().insert(phoneUri, values);
批量更新值
批量更新一組記錄的值,比如NY改名為Eew York.可調(diào)用ContentResolver.update()方法.
刪除記錄
如果是刪除單個(gè)記錄,調(diào)用ContentResolver.delete()方法,URI參數(shù),指定到具體行即可.
如果是刪除多個(gè)記錄,調(diào)用ContentResolver.delete()方法,URI參數(shù)指定Contentprovider即可,并帶一個(gè)類似SQL的WHERE子句條件.這里和上面類似,不帶WHERE關(guān)鍵字.
創(chuàng)建自己的ContentProvider
創(chuàng)建contentprovider,需要設(shè)置存儲(chǔ)系統(tǒng).大多數(shù)ContentProvider使用文件或者SQLite數(shù)據(jù)庫(kù),不過(guò)你可以用任何方式存儲(chǔ)數(shù)據(jù).android提供SQLiteOpenHelper幫助開發(fā)者創(chuàng)建和管理SQLiteDatabase.
繼承ContentProvider,提供對(duì)數(shù)據(jù)的訪問(wèn).在manifest文件中聲明ContentProvider.繼承ContentProvider類
必須定義ContentProvider類的子類,需要實(shí)現(xiàn)如下方法:
java代碼:
query()
insert()
update()
delete()
getType()
onCreate()
在實(shí)現(xiàn)子類的時(shí)候,還有一些步驟可以簡(jiǎn)化ContentProvider客戶端的使用:
定義public static final Uri常量,名稱為CONTENT_URI:
java代碼:
public static final Uri CONTENT_URI =Uri.parse("content://com.example.codelab.transportationprovider");
如果有多個(gè)表,它們也是使用相同的CONTENT_URI,只是它們的路徑部分不同.
聲明ContentProvider
創(chuàng)建ContentProvider后,需要在manifest文件中聲明,android系統(tǒng)才能知道它,當(dāng)其他應(yīng)用需要調(diào)用該ContentProvider時(shí)才能創(chuàng)建或者調(diào)用它.
語(yǔ)法類似:
<providerandroid:name="com.easymorse.cp.MyContentProvider"
android:authorities="com.easymorse.cp.mycp">
</provider>
android:name要寫ContentProvider繼承類的全名.
android:authorities要寫和CONTENT_URI常量的B部分
愛華網(wǎng)


