仿Android6.0联系人列表

本文介绍了Android6.0中联系人数据的存储结构,包括contacts、raw_contacts、data和mimetypes表,以及如何通过ContactsContract类获取联系人姓名和电话号码。同时展示了如何实现按首字母排序的联系人列表,利用SideBar作为字母导航,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

  最近因为项目需要,研究了Android联系人相关内容,包括联系人数据库,获取联系人数据,使用ListView展示联系人。我将按照以下几点记录:
  
  Android存储联系人数据库表结构
  获取联系人数据
  联系人列表效果

  一Android存储联系人数据库表结构
  要想搞清楚Android联系人内容,首先就得清楚这些内容在Android中是怎么存储的,为了搞清楚这个问题,可以直接取出Android中存储联系人的数据库contact2.db。它的存储路径:
  /data/data/com.android.providers.contacts/databases.contacts2.db
  如果是模拟器,可以直接取出来。如果是真机的话需要获取root权限。取出之后用可以查看SQLite数据库的软件(我用的是SQLiteSpy)打开,结构如下:
这里写图片描述

  这里包括了很多表,而我们只看几个比较重要的表,contacts,data,mimetypes,raw_contacts。

  contacts表
  该表保存了所有的手机联系人,包括每个联系人id、联系次数(times_contacted)、最后一次联系的时间(last_time_contactde)、是否含有电话号码(has_phone_number)、是否被收藏(starred)等信息。来看看以下字段:
  _id :表id,主要用于其他表通过该字段来查找相应的数据。
  lookup:该字段是不会改变的,联系人的信息可能改变,但是该字段是一直存储不会改变的。
  name_raw_contact_id:这个字段对于我们暂时没有什么作用,先忽略他。
  这里写图片描述

   raw_contacts表
   该表中的字段比较多,也包含了大量的信息,对于我们实现联系人列表有很大的作用,这里我只调几个字段来看看,其他的可以自己查看:
   _id:其他表如contacts,data表可以通过raw_contact_id来查找raw_contacts表中的数据。
   contact_id:通过该字段raw_contacts表就可以去查找contacts表,这样两张表就联系起来了。
   display_name(display_name_alt):联系人姓名,不用多说。
   sort_key:我们在取数据时可以安装该字段来排序。这样我们取到的数据就是排好顺序的。
   phone_book_label:联系人首字母,我们可以取得该字段来实现类似微信通讯录联系人的效果。
   deleted:该联系人是否被删除。
   这里写图片描述

  mimetypes表
  这个表很有意思也很重要,他主要是定义了联系人的数据类型,如果我们想自己定义一个联系人属性需要在这个表中添加,例如:我想扩展添加一个微信号,我们可以这样vnd.android.cursor.item/weichat,可以存储微信号等属性,有兴趣的可以去自己实现一下。
  

  data表
  该表保存了所有创建过的手机联系人的信息保存在列data1至data15中,该表保存了两个ID:mimetype_id和raw_contact_id,从而将data表和
raw_contacts表,mimetypes表联系起来了。在看看mimetype_id这个字段代表是什么意思呢,看上图就明白了,他其实代表的是该行的数据类型,下图中第一行mimetype_id 为1,那么对应到mimetypes表中是vnd.android.cursor.item/phone_v2,表示改行数据是电话号码。接着看data1就是号码,data2是号码类型(住宅,手机,座机等等)。改表也是可以扩展的。
这里写图片描述

  以上几个表都是比较重要的,从这几个表中我们基本上可以满足我们做联系人列表的需求了。这里还要说一下,可能细心一点的话,会发觉有些不同表中有同一字段,这是不是违背了数据库设计规范造成数据冗余呢,Google不可能想不到这个问题,这样做主要是为了用成本较低的存储空间,去换取在表中联合查询时减少的时间。用空间换时间是不错的选择。
  到这儿,已经对联系人数据库有了初步的认识,接下来我们就来看看怎么获取这些表中的数据。
  
  获取联系人数据
  
  Android4.0之后在android.provider包下有一个ContactsContract类,用来管理联系人信息。该类结构比较复杂,有三个比较重要的内部类ConstractContact.Data,ConstractContact.RawContacts,ConstractContact.Contacts。这三个类实际上就是对应着上边介绍的data,raw_contacts,contacts三张表。
  在ConstractContact.Phone中有个 Phone.CONTENT_URI字段,看源码可以知道他指向的是“content:// com.android.contacts/data/phones”,而这个url实际上对应这data,contacts,raw_contacts,这三个表。再一次证明我们的联系人数据就是从三张表取的。
  来看看具体代码,我们取出联系人的姓名和电话号码,并安装首字母排序
  

private static final String PHONE_BOOK_LABLE="phonebook_label";
    /**需要查询的字段**/
    private static final String[]PHONES_PROJECTION={Phone.DISPLAY_NAME
            ,Phone.NUMBER,PHONE_BOOK_LABLE};
    /**联系人显示名称**/
    private static final int PHONES_DISPLAY_NAME_INDEX = 0;

    /**电话号码**/
    private static final int PHONES_NUMBER_INDEX = 1;
 ContentResolver mResolver=getContentResolver();
                    //查询联系人数据,query的参数Phone.SORT_KEY_PRIMARY表示将结果集按Phone.SORT_KEY_PRIMARY排序
                    Cursor cursor=mResolver.query(Phone.CONTENT_URI
                            ,PHONES_PROJECTION,null,null,Phone.SORT_KEY_PRIMARY);
                    if(cursor!=null){
                        while (cursor.moveToNext()){
                            ContactsModel model=new ContactsModel();
                            model.setPhone(cursor.getString(PHONES_NUMBER_INDEX));
                            if(TextUtils.isEmpty(model.getPhone())){
                                continue;
                            }
                            model.setName(cursor.getString(PHONES_DISPLAY_NAME_INDEX));
                            model.setPhonebook_label(cursor.getString(cursor.getColumnIndex(PHONE_BOOK_LABLE)));
                            contactsModelList.add(model);
                        }
                        cursor.close();
                    }

  来看看以下字段phonebook_label,就是在raw_contact表中,存储的是首字母。我可以用他来作为分组的label

private static final String PHONE_BOOK_LABLE="phonebook_label";

  该数组是我们需要查询字段的集合,需要查询什么字段,直接在该数组中添加就ok了。
  

/**需要查询的字段**/
    private static final String[]PHONES_PROJECTION={Phone.DISPLAY_NAME
            ,Phone.NUMBER,PHONE_BOOK_LABLE};

  为了方便,我直接在取数据时就以Phone.SORT_KEY_PRIMARY(实际上就是“sort_key”字段)排好序了。这样我们就取得了联系人数据了。这里我们定义一下联系人model:
  

/**
 * Created by Administrator on 2015/11/23.
 */
public class ContactsModel {
   
    private String name;
    private String phone;
    private String phonebook_label;

    public String getPhonebook_label() {
        return phonebook_label;
    }

    public void setPhonebook_label(String phonebook_label) {
        this.phonebook_label = phonebook_label;
    }


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

  还有一个非常重要的就是需要添加读取联系人权限(如果需要增删改查还需要写权限)。在清单文件AndroidManifest.xml中添加:
 

<
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值