Android應用學習記錄------通訊錄的增,刪,改,查

轉:http://lichangsong.blog.51cto.com/7997447/1306033


最近兩天在做通訊錄的增刪改查功能。原以爲Android會將通訊錄的所有數據都集合到一個數據庫表中,然後知道其ContentProvider提供Uri後,通過ContentResolver的query(),insert(),update(),delete()方法直接操作數據庫的數據,j_0064.gif今天把其所有功能實現後,才發現並非自己當初想象的那麼簡單,好了,廢話不多說。





一.權限

操作通訊錄必須在AndroidManifest.xml中先添加2個權限,

1
2
<uses-permissionandroid:name="android.permission.READ_CONTACTS"/>
<uses-permissionandroid:name="android.permission.WRITE_CONTACTS"/>





二.通訊錄數據庫表介紹 (重點)



1.minetypes表


001424406.jpg




2.data表

001756305.jpg



3.raw_contacts表

002006950.jpg



002007600.jpg


注意: 3表第二個圖是接第一圖的右邊的,因爲大小的原因,截成了2張圖。

首先說一下,聯繫人的信息操作前,必須把數據庫的這3個表仔細看一下,看不懂也沒關係,等會對進行增刪改查的操作的時候,再回來對照數據庫,這樣你能夠更加方便理解和記憶代碼。否則,死記代碼,過兩天就忘的一乾二淨。

通訊錄是存放在/data/data/com.android.providers.contacts/databases/contacts2.db,裏面主要的表有:


(1)raw_contacts:存放聯繫人的 ID,_id屬性爲主鍵,聲明爲autoincrement,即不需要手動設置,其他屬性也不需要手動設置就有默認值;display_name屬性爲姓名;sort_key屬性可以用於查詢後的排序

(2)mimetypes:存放數據的類型,比如"vnd.android.cursor.item/name"表示“姓名”類型的數據,"vnd.android.cursor.item/phone_v2"表示“電話”類型的數據;

(3)data:存放具體的數據;raw_contact_id 屬性用來連接raw_contacts表,每條記錄表示一個具體數據;raw_contact_id 需要重點記住,手機中顯示的每一個聯繫人對應一個固定的raw_contact_idraw_contact_id 對應着 raw_contacts表的 _id ,他倆是相同的值,兩個表之間的關係必須理清。(我剛開始就是沒有理清表之間的關係,以及各個字段代表的意思,做起來就感覺很混亂,這3個表很重要)我們主要的數據(email、phone等)都存放在data表;

data1屬性存放總數據;

data2屬性:

-如果此記錄存放姓名,則data2存放名;

-如果此記錄存放電話,則data2存放類型,比如手機、家電;

-如果此記錄存放組織,則data2存放類型,比如公司、其他;

-如果此記錄存放地址,則data2存放類型,比如住宅,單位等






三.重要數據

URI

對raw_contacts表添加、刪除、更新操作:

URI =content://com.android.contacts/raw_contacts;

Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;

對data表添加、刪除、更新操作:
URI =content://com.android.contacts/data;
根據email對data表查詢

URI =content://com.android.contacts/data/emails/filter/*

根據電話號碼對data表查詢

URI =content://com.android.contacts/data/phone/filter/*

如果要根據ID查詢電話,可以
URI =content://com.android.contacts/data;

然後where條件爲:raw_contact_id=? and mimetype = ?


MIMETYPE


電話:vnd.android.cursor.item/phone_v2
姓名:vnd.android.cursor.item/name
郵件:vnd.android.cursor.item/email_v2
通信地址:vnd.android.cursor.item/postal-address_v2
組織:vnd.android.cursor.item/organization
照片:vnd.android.cursor.item/photo

Data中的常量


Data._ID: "_id"

Data.DISPLAY_NAME:“display_name”

Data.DATA1:“data1”

Data.DATA2:“data2”

Data.RAW_CONTACT_ID:“raw_contact_id”

Data.MIMETYPE:“mimetype”







四.增刪改查的實現


1.query


(1)查詢所有的聯繫人

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//讀取通訊錄的全部的聯繫人
//需要先在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();
    //獲得_id屬性
    Cursor cursor = resolver.query(uri,new String[]{Data._ID},null, null,null);  
    while(cursor.moveToNext()){
        StringBuilder buf =new StringBuilder();
        //獲得id並且在data中尋找數據 
        intid = cursor.getInt(0);
        buf.append("id="+id);
        uri = Uri.parse("content://com.android.contacts/contacts/"+id+"/data");
        //data1存儲各個記錄的總數據,mimetype存放記錄的類型,如電話、email等
        Cursor cursor2 = resolver.query(uri,new String[]{Data.DATA1,Data.MIMETYPE},null,null,null); 
        while(cursor2.moveToNext()){
            Stringdata = cursor2.getString(cursor2.getColumnIndex("data1"));
            if(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/name")){      //如果是名字
                buf.append(",name="+data);
            }
            elseif(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/phone_v2")){ //如果是電話
                buf.append(",phone="+data);
            }
            elseif(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/email_v2")){ //如果是email
                buf.append(",email="+data);
            }
            elseif(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/postal-address_v2")){//如果是地址
                buf.append(",address="+data);
            }
            elseif(cursor2.getString(cursor2.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/organization")){ //如果是組織
                buf.append(",organization="+data);
            }
        }
        Stringstr = buf.toString();
        Log.i("Contacts", str);
    }
}


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

1
2
3
4
5
6
7
8
9
10
11
12
//根據電話號碼查詢姓名(在一個電話打過來時,如果此電話在通訊錄中,則顯示姓名)
    publicvoid 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.Insert


注意:對某個聯繫人插入姓名、電話等記錄時必須要插入Data.MIMETYPE(或者是"mimetype")屬性,而不是插入"mimetype_id"!

比如:values.put(Data.MIMETYPE,"vnd.android.cursor.item/phone_v2")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//一步一步添加數據
    publicvoid testAddContacts(){
        //插入raw_contacts表,並獲取_id屬性
        Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
        ContentResolver resolver =this.getContext().getContentResolver();
        ContentValues values =new ContentValues();
        longcontact_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","[email protected]");
        resolver.insert(uri, values);
    }

批量添加數據



核心代碼:

(1)ContentProviderOperation operation = ContentProviderOperation.newInsert(uri).withValue("key","value").build();

(2)resolver.applyBatch("authorities",operations);//批量提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void testAddContactsInTransaction() throwsException {
    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);


3.Delete


核心思想:
(1)先在raw_contacts表根據姓名(此處的姓名爲name記錄的data2的數據而不是data1的數據)查出id;
(2)在data表中只要raw_contact_id匹配的都刪除;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void testDelete()throwsException{
    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()){
        intid = 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表進行操作;

1
2
3
4
5
6
7
8
9
public void testUpdate()throwsException{
    intid = 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+""}) 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章