最近有个从获取系统联系人信息的需求,网上也有很多的示例,可以数据库中获取的联系人姓名、手机号、但我的需求是从联系人信息中获取比较多的信息,如号码是手机号,还是住宅电话,还是单位的手机号。查阅了很多资料后,任然无果。
在经过了各种的百度和试验后,终于搞出了我想要的结果。



android检查联系人权限 android读取系统联系人_android检查联系人权限



 下面说下我的解决方法。


我们先要了解系统联系人数据库,该数据库存放在data->data->con.andorid.providers.contacts->databases目录下,contacts2.db为该数据库(手机需root,或者使用模拟器)。




android检查联系人权限 android读取系统联系人_手机_02



 将该文件导出到电脑中,用SQLite Expert Personal 3打开。




android检查联系人权限 android读取系统联系人_android_03



 如图所示,该数据库中有茫茫多的表,大家不要惊慌,像图上标注的,我们需要关注的只有这三张表,raw_contacts、data、mimetypes。下面我们来分析下各张表结构。


raw_contacts表存放的联系人列表,只有联系人的编号_id,是我们所要的。




android检查联系人权限 android读取系统联系人_android_04



mimetypes表存放的是数据标识。如下图




android检查联系人权限 android读取系统联系人_android_05



 如_id为1时,为联系人的邮箱信息。为5时,为联系人的手机号码信息。data表为存放数据的表,所有的信息,如姓名、手机号、邮箱都在此表中存放,我们要查询的信息都在此表中,而比中数据杂乱,Android的提供的联系人字段中,没有针对的,如家用电话,就没有像Contact_Data_FamilyPhone这样的字段提供。所以我们执行根据Data表中我们刚插入的信息来分析。




android检查联系人权限 android读取系统联系人_android_06



 如表所示,我们的数据基本都在data1中存放。对比手机中添加的数据,我们可知。




android检查联系人权限 android读取系统联系人_android检查联系人权限_07



 raw_contact_id为raw_contacs表中的_id字段,mimetyepe_id为表mimetype表中的_id,我们根据此值来获取我们想要的数据,而我们遇到的还是原来的问题,如何知道哪个data1是手机号,哪个是住宅手机号呢?我们发现相同的mimetype_id,但data2不同,所以可结合mimetype_id和data2来确定我们想要的数据。感觉已经成功了呢,但是!我们去查询mimetype_id发现根本取不到该字段信息。




android检查联系人权限 android读取系统联系人_数据库_08



好的,今天我们就介绍到这,别忘了点赞哦。

开个玩笑。。。
 经过分析,发现我们是访问不到真正的数据库表的,我们访问的是view_data表中的数据。



android检查联系人权限 android读取系统联系人_数据库_09


 而该视图提供的字段中,mimetype_id访问不到,但minetype是可以访问到的。所以我们根据前边的分析,可根据该视图提供mimetype字段来确定我们的数据。下面贴主要代码,我会多添点注释来解释为什么这么做。

//访问raw_contacts表的URI,我们需要先从该表中查出联系人ID。
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
//访问data表(应该是视图)的URI,从该表中获取我们想要的数据。     
Uri dataUri = Uri.parse("content://com.android.contacts/data");
//查看数据表,进行连表查询,确定数据。
Cursor cursor = mContentResolver.query(uri, null, null, null, null);
List<EntityContact> contactList = new ArrayList<EntityContact>();
while(cursor.moveToNext()){
    String id = cursor.getString(cursor.getColumnIndex("_id"));
    //查找data表
    Cursor data = mContentResolver.query(dataUri, null,"raw_contact_id = ?", new String[]{id}, null);

    EntityContact contact = new EntityContact();
    while(data.moveToNext()){
                //对数据进行筛选,每一次循环结束,筛选出一条用户的数据。
        String data1 = data.getString(data.getColumnIndex("data1"));
        String minetype = data.getString(data.getColumnIndex("mimetype"));
        String data2 = data.getString(data.getColumnIndex("data2"));
        if(minetype.equals("vnd.android.cursor.item/name")){
        contact.setName(data1);
    } 
    if(minetype.equals("vnd.android.cursor.item/phone_v2")){
    //手机号。
    if(data2.equals("1")){
    //住宅手机号
    contact.setHome_num(data1);
    } else if(data2.equals("2")){
        //手机号
        contact.setMobile_num(data1);
        } else if(data2.equals("3")){
            //单位手机号。
            contact.setOffice_num(data1);
            }
        } 
    if(minetype.equals("vnd.android.cursor.item/email_v2")){
        if(data2.equals("1")){
        //私人邮箱
        contact.setEmail(data1);
        } else if(data2.equals("2")){
            //单位邮箱。
        }
    } 
    if(minetype.equals("vnd.android.cursor.item/postal-address_v2")){
        if(data2.equals("1")){
        //居住地址。
        contact.setHome_address(data1);
        } else if(data2.equals("2")){
        //单位地址
        contact.setOffice_address(data1);
        }
    } 
    if(minetype.equals("vnd.android.cursor.item/photo")){
        byte blob[] = data.getBlob(data.getColumnIndex("data15"));
        //查看blob数据。
        String photo = Base64.encodeToString(blob, Base64.NO_WRAP);
        contact.setPhoto(photo);
    }
    if(minetype.equals("vnd.android.cursor.item/note")){
        contact.setExtend(data1);
    }
}
    contactList.add(contact);  
    //关闭游标。   
    data.close();
    cusor.close();

以上就是访问数据库的全部代码。
第一次写博客,逻辑比较混乱,代码有不对的地方,请大家多多指教。