一 爲什麼需要內容提供者
(1)android平臺提供了Content Provider使一個應用程序的指定數據集提供給其他應用程序。其他應用可以通過ContentResolver類從該內容提供者中獲取或存入數據。
(2)只有需要在多個應用程序間共享數據是才需要內容提供者。例如,通訊錄數據被多個應用程序使用,且必須存儲在一個內容提供者中。它的好處是統一數據訪問方式。
(3)ContentProvider實現數據共享。ContentProvider用於保存和獲取數據,並使其對所有應用程序可見。這是不同應用程序間共享數據的唯一方式,因爲android沒有提供所有應用共同訪問的公共存儲區。
(4)開發人員不會直接使用ContentProvider類的對象,大多數是通過ContentResolver對象實現對ContentProvider的操作。
(5)ContentProvider使用URI來唯一標識其數據集,這裏的URI以content://作爲前綴,表示該數據由ContentProvider來管理。
二內容提供者實現原理
三 實現內容提供者使用步驟
[1]定義內容提供者 定義一個類繼承contentProvider
[2]在清單文件裏面配置一下, 定義一些規則 a呀 d
[3] 定義一個urimatcher
[4]寫一個靜態代碼塊 添加匹配規則
[5]按照我們添加的匹配規則 暴露想暴露的方法
[6]如果你發現如下log日誌 就說明內容提供者寫的沒有問題
[7]只要是通過內容提供者暴露出來的數據 其他應用訪問的方式都是一樣的 就是通過內容解析者
四.內容解析器ContextResolver
想要獲取到其他應用所暴露出來的數據則必須使用,內容提供者裏面的內容解析器ContextResolver
1.首先獲取到內容解析器
通過context中的getContentResolver(),來獲得一個內容解析器
ContentResolver resolver = getContentResolver();
2.進行數據操作
拿到了內容解析器對象就可以進行相關的ASUQ(增刪改查)操作,以讀取手機聯繫人爲例。
讀取聯繫人信息只是用到了查詢操作,通過query操作去查詢
通過 resolver.query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)這個方法查詢系統聯繫人數據庫。
參數的含義:
① Uri uri:要查詢那個數據庫中的那個表
一般是Uri.parse(content://要查詢的數據庫/表名);
② String[] projection:查詢哪一列(表中數據的列名)
③ String selection:查詢的條件 such as:”id = ?”
④ String[] selectionArgs:查詢條件的值,和查詢條件相匹配
當查詢條件是”id = ?”時,這裏是”id = 5”
如果查詢條件是一組數,如”id = ?and name = ?”
則此處應該也是一組數,new String[]{5,”Tom”};
⑤ String sortOrder:排序方式
實現結果:
點擊按鈕跳轉到手機聯繫人界面,去選擇手機聯繫人
此時可以看到手機聯繫人,因爲系統手機聯繫人這個應用就已經給我們通過內容提供者提供了一個可以讀取數據的接口,我們只需要在代碼中實現內容解析器,並且知道聯繫人的表結構,就可以去讀取自己想要的數據
當選擇一個條目,那麼就會到這這個數據對象回到我們之前的那個界面,將phoneNum讀取出來,設置在EditText上面,實現聯繫人的讀取。
//代碼操作:(如果聯繫人多了,讀取聯繫人屬於耗時操作,需要放在子線程中執行)
new Thread(){
@Override
public void run() {
//獲取廣播解析器
ContentResolver resolver = getContentResolver();
//查詢系統聯繫人數據庫的raw_contacts表
Cursor cursor = resolver.query(Uri.parse("content://com.android.contacts/raw_contacts"),
new String[]{"contact_id"},null,null,null);
//每次查詢都將之前的List清空一下
mList.clear();
//循環查找(cursor中有多少個id,就查詢具體內容多少次)
while (cursor.moveToNext()){
//查找到的數據第一個是聯繫人唯一標示id
String id = cursor.getString(0);
//根據用戶唯一id查找data和mimetype合成的視圖,找到data1和mimetype字段
Cursor indexCursor = resolver.query(Uri.parse("content://com.android.contacts/data"),
new String[]{"data1", "mimetype"}, "raw_contact_id = ?", new String[]{ id }, null);
//創建一個map集合用來存每次遍歷得到的姓名和電話號碼的鍵值對
HashMap<String,String> map = new HashMap<String, String>();
//循環遍歷(次數是查詢到數據的組數),查找每個聯繫人的姓名和電話
while (indexCursor.moveToNext()){
//每組數據的具體數據,包括聯繫人姓名和電話號碼
String data = indexCursor.getString(0);
//獲取該組中數據的類型
String type = indexCursor.getString(1);
//如果是匹配到"vnd.android.cursor.item/phone_v2",則是電話號碼
if (type.equals("vnd.android.cursor.item/phone_v2")){
if (!TextUtils.isEmpty(data)){
//拿到電話號碼
map.put("phone",data);
}
}
//如果匹配到"vnd.android.cursor.item/name",則是聯繫人姓名
if (type.equals("vnd.android.cursor.item/name")){
if (!TextUtils.isEmpty(data)){
//拿到姓名
map.put("name",data);
}
}
}
indexCursor.close();
mList.add(map);
}
cursor.close();
//用消息發送機制發送一個空消息,爲了提醒主線程數據獲取完畢,
mhandler.sendEmptyMessage(0);
}
}.start();