《Android第一行代碼》
內容提供器簡介
內容提供器(Content Provider)主要用于在不同的應用程序之間實現(xiàn)數(shù)據(jù)共享的功能,它提供了一套完整的機制,允許一個程序訪問另一個程序中的數(shù)據(jù),同時還能夠保證被訪問數(shù)據(jù)的安全性。目前,使用內容提供器是Android實現(xiàn)擴平臺共享數(shù)據(jù)的標準方式。
不同文件儲存和SharedPreferences儲存中的兩種全局可讀寫操作模式,內容提供器可以選擇只對哪一部分數(shù)據(jù)進行共享,從而保證我們數(shù)據(jù)的安全性。
內容提供器主要有兩種操作,一種是利用現(xiàn)有的內容提供器來讀取和操作相應程序的數(shù)據(jù),另一種是創(chuàng)建自己的內容提供器提供給其他程序使用。接下來我讓我們學習這兩種操作,本次我們先學習利用現(xiàn)有的內容提供器來讀取和操作相應程序的數(shù)據(jù)的相應操作。
訪問其他程序中的數(shù)據(jù)
當一個程序通過內容提供器對其數(shù)據(jù)提供了外部訪問接口,任何其他程序就都可以對這部分數(shù)據(jù)進行訪問。Android系統(tǒng)自帶的電話簿、短信、媒體播放器等程序都提供了類似的訪問接口,這就使得第三方程序可以允許充分利用這部分的數(shù)據(jù)來實現(xiàn)更好的功能。接下來我們就來看看怎么使用這部分數(shù)據(jù)。
ContentResolver 的基本用法
要使用其他程序提供的數(shù)據(jù),就需要借助ContentResolver類,可以通過Context中的getContentResolver()方法獲取到該類實例。ContentResolver中提供了一系列方法用于對數(shù)據(jù)的CRUD(增刪改查)操作,其中insert()方法用于添加數(shù)據(jù),update()方法用于更新數(shù)據(jù),delete()方法用于刪除數(shù)據(jù),query()方法用于查詢數(shù)據(jù)。這種操作類似于SQLiteDataBase的操作,但不同于SQLiteDataBase的是,ContentResolver中的增刪改查操作不接收表明參數(shù),而是接收一個Uri參數(shù)。這個參數(shù)被稱為內容ERI。內容URI給內容提供器中的數(shù)據(jù)建立了唯一的標識,他主要是由兩部分組成,權限(authority)和路徑(path)。權限適用于對不同的應用程序作區(qū)分的,一般為了避免沖突,都會采用程序包名方式來進行命名。比如摸個程序的包名是com.example.app,那么該程序對應的權限就可以命名為 com.example.app.provider。路徑則是用于對同一個應用程序中不同的表作區(qū)分的。比如你的應用程序有兩張表table1、table2,那么內容URI就可以寫成com.example.app.provider/table1和com.example.app.provider/table2。不過這樣還不算是完整的內容URI,還需要加上我們的協(xié)議聲明:
content://com.example.app.provider/table1
content://com.example.app.provider/table2
這樣我們就表明了我們想訪問哪個程序里面的哪一個表。有了內容URI之后我們還需要把它解析成Uri對象,這樣我們就可以把Uri對象傳入。
解析的方法非常簡單,代碼如下:
Uri uri = Uri.parse("content://com.example.app.provider/table1");
現(xiàn)在我們就可以使用這個Uri對象來查詢table1中的數(shù)據(jù)了,代碼如下:
Cursor cursor = getContentResolver().qurey(
uri,
projection,
selection,
selectionArgs,
sortOrder);
參數(shù)說明:
uri 指定查詢某個應用的某張表
projection 指定查詢的列名
selection 指定 where 的約束條件
selectionArgs 為 where 中的占位符提供具體的值
sortOrder 指定查詢的排列方式
查詢完成后返回一個Cursor對象,我們就可以將數(shù)據(jù)從Cursor對象中逐個讀取出來。讀取方式是通過移動游標的位置來遍歷Cursor的所有行,然后在取出每一行相應的數(shù)據(jù),代碼如下:
if(cursor!=null){
while(cursor.moveToNext()){
String colum1 = corsor.getString(cursor.getColumnIndex("column1"));
int colum2 = corsor.getInt(cursor.getColumnIndex("column2"));
}
cursor.close();
}
掌握了最難的查詢,我們再來看看怎么在表內添加一條數(shù)據(jù):
ContentValues v = new ContentValues();
v.put("column1","newText");
v.put("column2",1);
getContentResolver().insert(uri,v);
可以看到,跟數(shù)據(jù)庫的操作一樣,我們依然是把數(shù)據(jù)封裝在 ContentVakues 中,然后調用ContentResolver的insert()方法,將 Uri 和 ContentVakues 作為參數(shù)傳入即可。
讓我們再來看看數(shù)據(jù)的更新:
ContentValues v = new ContentValues();
v.put("column1","newText2");
v.put("column2",111);
getContentResolver().update(uri, "column1 = ? and column2 = ?", new String[]{"newText","1"});
然后是刪除:
getContentResolver().delete(uri,"column2 = ?", new String[]{"1"});
以上就是ContentResolver對數(shù)據(jù)的增刪改查,看到這里相信好多人會期待最后會有一個具體的示例來鞏固剛才學到的知識,接下來我們就利用學到的知識來讀取手機電話簿的聯(lián)系人信系。
讀取手機聯(lián)系人信息
對于示例的UI界面我就不再多說了,相信大家都會。我寫一個方法來獲取手機聯(lián)系人的信息,把獲取到的聯(lián)系人信息通過return一個List返回給調用者,一共我們需要做三件事。
- 新建一個聯(lián)系人的Modle來映射我們的聯(lián)系人信息
- 在AndroidManifest.xml中添加訪問聯(lián)系人的權限(安卓版本6.0以下)
- 編寫我們的方法
- 假設我們想要拿到聯(lián)系人的電話號和名稱,我們就可以寫這樣一個簡單的modle:
class Contact{
private String name;
private String num;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setNum(String num){
this.num = num;
}
public String getNum(){
return num;
}
}
- 因為我們需要讀取手機聯(lián)系人信息,所以我們需要在Androidmanifest.xml中添加讀取聯(lián)系人信息的權限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
- 現(xiàn)在我們開始寫我們的方法,思路是這樣的:
因為我們需要利用Context來get我們的ContentResolver實例,所以這個方法需要一個Context參數(shù),并且要有一個List返回值把我們拿到的信息返回給調用者。
public List<Contact> getContactDate(Context context){
List<Contact> list = new ArrayList<>();
Cursor c = null;
c = context.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,null,null,null);
while(c.moveToNext){
Contact con = new Contact();
//添加聯(lián)系人姓名
con.setName(c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
//添加聯(lián)系人電話號
con.setNum(c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NUMBER)));
list.add(con);
}
return list;
}
到這里我們就把我們的工具方法寫好了,當我們需要獲取系人信息的時候,直接調用這個方法就能拿到手機電話簿中所有聯(lián)系人的姓名和電話了。
本篇到此結束。