Android入門:增刪改查通訊錄

一、通訊錄應用介紹

通訊錄應用是Android自帶的應用程序,我們看到此應用的時候,可能隻認為這是一個應用,用數據庫存儲數據,但是實際上不是這樣的。
通訊錄是ContentProvider的應用,通訊錄由兩部分組成:
(1)com.android.providers.contacts的ContentProvider:真正存儲數據的ContentProvider
(2)com.android.contacts:運用ContentResolver獲取數據的圖形用戶界面;

二、獲取ContactProvider的源代碼

Android源代碼:   http://my.oschina.net/zhanglubing/blog/40623 用git獲取;
如果要獲取ContactProvider,則安裝git,並打開git bash,輸入
git clone https://android.googlesource.com/platform/packages/providers/ContactsProvider.git 即可;
目錄結構如下:

為何要獲取ContactProvider的源代碼呢?
因為如果要訪問ContentProvider,必須要瞭解URI的設置(authority,path等);隻有查看源代碼才能夠知道;
AndroidManifest.xml為清單文件,列出瞭ContactProvider的authorities,以及要訪問通訊錄需要的權限;
[html] 
<uses-permission android:name="android.permission.READ_CONTACTS" /> 
<uses-permission android:name="android.permission.WRITE_CONTACTS" /> 

主要的通訊錄程序為ContactsProvider2.java,authorities為:contacts或com.android.contacts;

三、通訊錄數據庫結構介紹

表結構如下:

 



通訊錄是存放在/data/data/com.android.providers.contacts/databases/contacts2.db,裡面主要的表有:
(1)raw_contacts:存放聯系人的ID,
_id屬性為主鍵,聲明為autoincrement,即不需要手動設置,其他屬性也不需要手動設置就有默認值;
display_name屬性為姓名;
(2)mimetypes:存放數據的類型,比如"vnd.android.cursor.item/name"表示“姓名”類型的數據,"vnd.android.cursor.item/phone_v2"表示“電話”類型的數據;
(3)data:存放具體的數據;
raw_contact_id屬性用來連接raw_contacts表,每條記錄表示一個具體數據;我們主要的數據(email、phone等)都存放在data表;
data1屬性存放總數據;
data2屬性:
-如果此記錄存放姓名,則data2存放名;
-如果此記錄存放電話,則data2存放類型,比如手機、傢電;
-如果此記錄存放組織,則data2存放類型,比如公司、其他;
-如果此記錄存放地址,則data2存放類型,比如住宅,單位等;

四、對通信錄做增刪改查

簡單的說:對通訊錄操作就是對一個普通的ContentProvider操作;

1.Query

(1)根據電話號碼查詢姓名

[java] 
//根據電話號碼查詢姓名(在一個電話打過來時,如果此電話在通訊錄中,則顯示姓名) 
    public void testReadNameByPhone(){ 
        String phone = "12345678"; 
        //uri=  content://com.android.contacts/data/phones/filter/# 
        Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/"+phone);     
        ContentResolver resolver = this.getContext().getContentResolver(); 
        Cursor cursor = resolver.query(uri, new String[]{Data.DISPLAY_NAME}, null, null, null); //從raw_contact表中返回display_name 
        if(cursor.moveToFirst()){ 
            Log.i("Contacts", "name="+cursor.getString(0)); 
        } 
    } 

(2)查詢所有的聯系人

[java] 
//讀取通訊錄的全部的聯系人 
//需要先在raw_contact表中遍歷id,並根據id到data表中獲取數據 
public void testReadAll(){ 
    //uri = content://com.android.contacts/contacts 
    Uri uri = Uri.parse("content://com.android.contacts/contacts"); //訪問raw_contacts表 
    ContentResolver resolver = this.getContext().getContentResolver(); 
    Cursor cursor = resolver.query(uri, new String[]{Data._ID}, null, null, null);  //獲得_id屬性 
    while(cursor.moveToNext()){ 
        StringBuilder buf = new StringBuilder(); 
        int id = cursor.getInt(0);//獲得id並且在data中尋找數據 
        buf.append("id="+id); 
        uri = Uri.parse("content://com.android.contacts/contacts/"+id+"/data"); //如果要獲得data表中某個id對應的數據,則URI為content://com.android.contacts/contacts/#/data 
        Cursor cursor2 = resolver.query(uri, new String[]{Data.DATA1,Data.MIMETYPE}, null,null, null);  //data1存儲各個記錄的總數據,mimetype存放記錄的類型,如電話、email等 
        while(cursor2.moveToNext()){ 
            String data = cursor2.getString(cursor2.getColumnIndex("data1")); 
            if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/name")){       //如果是名字 
                buf.append(",name="+data); 
            } 
            else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/phone_v2")){  //如果是電話 
                buf.append(",phone="+data); 
            } 
            else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/email_v2")){  //如果是email 
                buf.append(",email="+data); 
            } 
            else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/postal-address_v2")){ //如果是地址 
                buf.append(",address="+data); 
            } 
            else if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/organization")){  //如果是組織 
                buf.append(",organization="+data); 
            } 
        } 
        String str = buf.toString(); 
        Log.i("Contacts", str); 
    } 

 

2.Insert

(1)一步一步添加數據

[java] 
//一步一步添加數據 
    public void testAddContacts(){ 
        //插入raw_contacts表,並獲取_id屬性 
        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); 
        ContentResolver resolver = this.getContext().getContentResolver(); 
        ContentValues values = new ContentValues(); 
        long contact_id = ContentUris.parseId(resolver.insert(uri, values)); 
        //插入data表 
        uri = Uri.parse("content://com.android.contacts/data"); 
        //add Name 
        values.put("raw_contact_id", contact_id); 
        values.put(Data.MIMETYPE,"vnd.android.cursor.item/name"); 
        values.put("data2", "zdong"); 
        values.put("data1", "xzdong"); 
        resolver.insert(uri, values); 
        values.clear(); 
        //add Phone 
        values.put("raw_contact_id", contact_id); 
        values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2"); 
        values.put("data2", "2");   //手機 
        values.put("data1", "87654321"); 
        resolver.insert(uri, values); 
        values.clear(); 
        //add email 
        values.put("raw_contact_id", contact_id); 
        values.put(Data.MIMETYPE,"vnd.android.cursor.item/email_v2"); 
        values.put("data2", "2");   //單位 
        values.put("data1", "www.aiwalls.com"); 
        resolver.insert(uri, values); 
    } 

 作者:xiazdong

(2)批量添加數據

核心代碼:
(1)ContentProviderOperation operation = ContentProviderOperation.newInsert(uri).withValue("key","value").build();
(2)resolver.applyBatch("authorities",operations);//批量提交

[java] 
<span style="font-size:18px;">public void testAddContactsInTransaction() throws Exception { 
        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); 
        ContentResolver resolver = this.getContext().getContentResolver(); 
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); 
        // 向raw_contact表添加一條記錄 
        //此處.withValue("account_name", null)一定要加,不然會拋NullPointerException 
        ContentProviderOperation operation1 = ContentProviderOperation 
                .newInsert(uri).withValue("account_name", null).build(); 
        operations.add(operation1); 
        // 向data添加數據 
        uri = Uri.parse("content://com.android.contacts/data"); 
        //添加姓名 
        ContentProviderOperation operation2 = ContentProviderOperation 
                .newInsert(uri).withValueBackReference("raw_contact_id", 0) 
                //withValueBackReference的第二個參數表示引用operations[0]的操作的返回id作為此值 
                .withValue("mimetype", "vnd.android.cursor.item/name") 
                .withValue("data2", "xzdong").build(); 
        operations.add(operation2); 
        //添加手機數據 
        ContentProviderOperation operation3 = ContentProviderOperation 
                .newInsert(uri).withValueBackReference("raw_contact_id", 0) 
                .withValue("mimetype", "vnd.android.cursor.item/phone_v2") 
                .withValue("data2", "2").withValue("data1", "0000000").build(); 
        operations.add(operation3); 
        resolver.applyBatch("com.android.contacts", operations); 
    }</span> 

3.Delete

核心思想:
(1)先在raw_contacts表根據姓名查出id;
(2)在data表中隻要raw_contact_id匹配的都刪除;

[java] 
public void testDelete()throws Exception{ 
    String name = "xzdong"; 
    //根據姓名求id 
    Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); 
    ContentResolver resolver = this.getContext().getContentResolver(); 
    Cursor cursor = resolver.query(uri, new String[]{Data._ID},"display_name=?", new String[]{name}, null); 
    if(cursor.moveToFirst()){ 
        int id = cursor.getInt(0); 
        //根據id刪除data中的相應數據 
        resolver.delete(uri, "display_name=?", new String[]{name}); 
        uri = Uri.parse("content://com.android.contacts/data"); 
        resolver.delete(uri, "raw_contact_id=?", new String[]{id+""}); 
    } 

4.Update

核心思想:
(1)不需要更新raw_contacts,隻需要更新data表;
(2)uri=content://com.android.contacts/data 表示對data表進行操作;
[java] 
public void testUpdate()throws Exception{ 
    int id = 1; 
    String phone = "999999"; 
    Uri uri = Uri.parse("content://com.android.contacts/data");//對data表的所有數據操作 
    ContentResolver resolver = this.getContext().getContentResolver(); 
    ContentValues values = new ContentValues(); 
    values.put("data1", phone); 
    resolver.update(uri, values, "mimetype=? and raw_contact_id=?", new String[]{"vnd.android.cursor.item/phone_v2",id+""})  

 作者:xiazdong

發佈留言