正文  设备功能 > 联系人/Contacts >

Android 2.0读取所有联系人姓名与电话

在网上看到的读取所有联系人姓名与电话的代码都是这样的: ContentResolver cr = getContentResolver(); Cursor curso...

 

在网上看到的读取所有联系人姓名与电话的代码都是这样的:

ContentResolver cr = getContentResolver();   

Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); 

while (cursor.moveToNext()) 

    // 取得联系人名字 

    int nameFieldColumnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME); 

    String name = cursor.getString(nameFieldColumnIndex); 

    string += (name); 

 

    // 取得联系人ID 

    String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); 

    Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " 

            + contactId, null, null); 

 

    // 取得电话号码(可能存在多个号码) 

    while (phone.moveToNext()) 

    { 

        String strPhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 

        string += (":" + strPhoneNumber); 

    } 

    string += "\n"; 

    phone.close(); 

cursor.close();

如果有n个联系人且每个联系人都存有电话号码的话,就得查询n+1次。

在园子里看到一个帖子说可以通过

Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, "*")

取得所有联系人的信息,我在Android 4.0模拟器跟2.3.7的真机上测试都不成功。

联系人的各种类型的信息都存储在Data表中,所以查询Data表并限制其MIMETYPE为Phone.CONTENT_ITEM_TYPE即可以查到所有姓名与电话

Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {

                CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.DISPLAY_NAME }, null, null, null);

上述代码可以查到所有联系人的姓名与电话,但是如果直接挨个输出的话会有问题,如果一个人存储了两个电话号码的话,在Data表中会有两条记录,比如一个叫张三的人,存储了他两个电话:11111,22222。那么输出结果中会有两条关于张三的记录,并不会合并到一起,所以我想到先把cursor查询到的所有数据存储到Map里,以DISPLAY_NAME为键,以NUMBER组成的List为值,即

HashMap<String,ArrayList<String>>

于是有了如下代码:

ContentResolver cr = getContentResolver();

HashMap<String,ArrayList<String>> hs=new HashMap<String,ArrayList<String>>();

Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {

    CommonDataKinds.Phone.NUMBER, CommonDataKinds.Phone.DISPLAY_NAME }, null, null, null);

while (phone.moveToNext()) {

  String strPhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

  String name = phone.getString(phone.getColumnIndex(CommonDataKinds.Phone.DISPLAY_NAME));

  ArrayList<String> ad=hs.get(name);

  if(ad==null){

    ad=new ArrayList<String>();

    ad.add(strPhoneNumber);

    hs.put(dis, ad);

  }

  else

    ad.add(strPhoneNumber);

}

phone.close();

 

这样就可以解决一个姓名对应多个号码的问题,但还有问题,可能是两个联系人同名,但他们属于不同的联系人,在数据库中表现为有不同的contact_id,那么可以将上述代码修改一下,将projection参数处添加上ContactsContract.CommonDataKinds.Phone.CONTACT_ID,然后把Map改为以contact_id为建,以DISPLAY_NAME与NUMBER组成的LIST为值,把DISPLAY_NAME统一存储为LIST的第一项。当然也可以定义一个类,包含姓名字段及电话号码组成的LIST字段,电话号码的LIST中的元素还可以是Map,以号码的TYPE为键。

 

作者:AngelDevil