10.Android通讯录-联系人查询

作者: android_赵乐玮 | 来源:发表于2017-04-28 15:38 被阅读863次

    相关内容:

    1. 联系人数据库结构
    2. 内容提供者(略)

    官方文档:https://developer.android.com/guide/topics/providers/contacts-provider.html

    1.数据库结构

    相关表共三个:Contacts、RawContacts、Data

    1.ContactsContract.Contacts 原始联系表
    ---- URI: ContactsContract.Contacts.CONTENT_URI
    表示不同联系人的行,基于聚合的原始联系人行。

    字段说明:
    1.Contacts.CONTENT_DIRECTORY | Constant Value:"photo"         |
    2.Contacts.DISPLAY_PHOTO:    | Constant Value:"display_photo" | 全尺寸照片
    3.Contacts.PHOTO:            | Constant Value:"data15"        | 照片缩略图
    4.Contacts.PHOTO_FILE_ID:    | Constant Value:"data14"        | 全尺寸照片的文件ID (用此查询,See: ContactsContract.DisplayPhoto)
    

    2.ContactsContract.RawContacts联系人数据摘要表
    ---- URI: ContactsContract.RawContacts.CONTENT_URI
    包含联系人数据摘要的行,针对特定用户帐户和类型。

    字段说明:
    1.RawContacts._ID  - long                |  id   不解释 ,永远唯一
    2.RawContacts.CONTACT_ID  - long
    3.RawContacts.AGGREGATION_MODE - int
    4.RawContacts.DELETED - int              |  是否删除  0:正常 , 1:删除
    5.RawContacts.TIMES_CONTACTED  - int     |  联系的次数
    6.RawContacts.LAST_TIME_CONTACTED - long |  最近联系时间
    7.RawContacts.STARRED -int               |  是否是常用联系人  0:不是 ,1:是
    8.RawContacts.CUSTOM_RINGTONE  - String  |  自定义铃声
    9.RawContacts.SEND_TO_VOICEMAIL - int    |  是否使用语音信息  0:不是 ,1:是
    10.RawContacts.ACCOUNT_NAME - String     |  账户名称 与ACCOUNT_TYPE对应
    11.RawContacts.ACCOUNT_TYPE  - String    |  账户类型 比如:Gmail 
    12.RawContacts.DATA_SET - String         |  账户数据
    13.RawContacts.SOURCE_ID - String        |   
    14.RawContacts.VERSION - int             |  当前版本号
    15.RawContacts.DIRTY - int               |  标记此条记录是否更改过
    
    

    3.ContactsContract.Data 联系人详细信息表
    ---- URI: ContactsContract.Data.CONTENT_URI 或 ContactsContract.Phone.CONTENT_URI
    包含原始联系人详细信息(例如电子邮件地址或电话号码)的行。

    字段说明:
    1.Data._ID - long             
    2.Data.MIMETYPE - String       |  数据类型,详细见下段
    3.Data.RAW_CONTACT_ID - long   |  同RawContacts.CONTACT_ID  
    4.Data.IS_PRIMARY - int        |  标记重要  0 or 1
    5.Data.IS_SUPER_PRIMARY - int  |  默认使用此条数据 0 or 1
    6.Data.DATA_VERSION  - int     |  数据版本
    7.Data.Data1                   |  与MIMETYPE有关,当为Phone.CONTENT_ITEM_TYPE时,Data1 就是电话号码
    8.Data.Data2~~Data.Data15     
    
    2.Data.MIMETYPE  参数列表 : 
    StructuredName.CONTENT_ITEM_TYPE
    Phone.CONTENT_ITEM_TYPE
    Email.CONTENT_ITEM_TYPE
    Photo.CONTENT_ITEM_TYPE
    Organization.CONTENT_ITEM_TYPE
    Im.CONTENT_ITEM_TYPE
    Nickname.CONTENT_ITEM_TYPE
    Note.CONTENT_ITEM_TYPE
    StructuredPostal.CONTENT_ITEM_TYPE
    GroupMembership.CONTENT_ITEM_TYPE
    Website.CONTENT_ITEM_TYPE
    Event.CONTENT_ITEM_TYPE
    Relation.CONTENT_ITEM_TYPE
    SipAddress.CONTENT_ITEM_TYPE
    

    2.查询联系人列表

    知道表结构后就可以很快的查取数据了,这里不讲内容提供者如何查询,直接上代码
    重点在getContactsList() 和 getContactList() 两个方法
    getContactsList() 返回数据结构:ContactsBean(String name, List<String> number)的List集合
    getContactList() 返回数据结构 :ContactBean(String name, String number)的List集合

    • 看情况选择:getContactsList() 数据结构清晰 ,getContactList() 速度快

    查询到数据后应注意:

    1. 查询后的联系人姓名可能为空
    2. 查询后的电话号码可能有空格
    3. 查询后的电话号码可能为空
    4. 查询后的电话号码可能不是数字
      下面代码已经做了相应处理, 代码仅供参考,暂不考虑性能,自行优化(静态Bean类)

    获取联系人列表流程

    1. 通过ContentResolver查询数据库, Uri可根据上表合理选择(此处选择Contacts表的uri),得到返回的cusor
    2. 遍历cusor获取所有的联系人姓名
    3. 根据联系人姓名查询其拥有的联系电话(不止一个),(此处选择Data表)
    public static List<ContactsBean> getContactsList(Context context) {
            Logger.d("SMSHelper", "-----------SMSHelper#getContactsList()----------");
            Logger.d("SMSHelper", "开始查询 Contacts 表");
            List<ContactsBean> list = new ArrayList<ContactsBean>();
            ContactsBean bean = null;
            ContentResolver resolver = context.getContentResolver();
            Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    
            if (cursor == null && cursor.getCount() <= 0) {
                return null;
            }
            Logger.d("SMSHelper", "cursor.getCount():" + cursor.getCount());
    
            while (cursor.moveToNext()) {
                bean = new ContactsBean();
    
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));//姓名
    
                wirteNumbers(resolver, name, bean);
                list.add(bean);
            }
            cursor.close();
            return list;
        }
    
       /**
         * 根据联系人姓名查询电话
         * 并写入
         */
        private static void wirteNumbers(final ContentResolver contentResolver, String name, final ContactsBean bean) {
            Logger.d("SMSHelper", "开始查询 Data 表 : 查询联系人:" + name);
            Cursor dataCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,
                    new String[]{ContactsContract.Data.DATA1},
                    ContactsContract.Data.DISPLAY_NAME + "= ? ",
                    new String[]{name}, null);
            if (dataCursor == null) {
                Logger.w("SMSHelper", "dataCursor == null ");
                return;
            }
            if (dataCursor.getCount() > 0) {
                bean.setName(name);
                Logger.w("SMSHelper", " 电话信息 -- size: " + dataCursor.getCount());
                while (dataCursor.moveToNext()) {
                    String number = dataCursor.getString(dataCursor.getColumnIndex(ContactsContract.Data.DATA1));
                    if (TextUtils.isEmpty(number) || !TextUtils.isDigitsOnly(number = number.replace(" ", ""))) {
                        Logger.w("SMSHelper", " 电话信息(异常) -- number: " + number);
                        continue;
                    }
                    bean.getNumList().add(number);
                    Logger.w("SMSHelper", " 电话信息 -- number: " + number);
                }
                dataCursor.close();
            } else {
                Logger.w("SMSHelper", " 无电话信息 -- name: " + name);
            }
            return;
        }
    
    

    完整代码

    package app.utils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.content.ContentResolver;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.provider.ContactsContract;
    import android.telephony.SmsManager;
    import android.text.TextUtils;
    
    import com.google.common.collect.Lists;
    
    /**
     * 短信电话相关工具类<br/>
     * 目录: <br/>
     * 1.发送短信 sendSMS() <br/>
     * 2.拨打电话短信 callPhone() <br/>
     * 3.获取所有短信记录getAllSms() <br/>
     * 4.获取所有联系人getContactsList() <br/>
     * 5.获取所有联系人getContactList() : 与第4条所生成的数据结构不同 <br/>
        
     * <b>注</b>:使用时请添加相关权限
     *
     * @author 赵LW QQ:739043667
     */
    public class SMSHelper {
    
        /**
         * 发送短信 (需要权限SMS_Send)
         *
         * @param num  电话
         * @param text 短信内容
         */
        public static void sendSMS(String num, String text) {
            SmsManager.getDefault().sendTextMessage(num, null, text, null, null);
        }
    
        public static void callPhone(Context context, String num) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:" + num));
            // 开启系统拨号器
            context.startActivity(intent);
        }
    
        /**
         * 获取所有联系人 需要权限
         * <uses-permission android:name="android.permission.READ_CONTACTS" />
         * 数据结构:ContactBean(String displayName, String numList)
         *
         * @param
         * @return
         */
        public static List<ContactBean> getContactList(Context context) {
    
            Logger.d("SMSHelper", "-----------SMSHelper#getContactList()----------");
            Logger.d("SMSHelper", "开始查询 Data 表");
            List<ContactBean> list = new ArrayList<ContactBean>();
    
            ContactsContract.Data._ID
            ContentResolver resolver = context.getContentResolver();
            Cursor cursor = resolver.query(ContactsContract.Data.CONTENT_URI, null, null, null, null);
    
            if (cursor == null && cursor.getCount() <= 0) {
                return null;
            }
            Logger.d("SMSHelper", "cursor.getCount():" + cursor.getCount());
    
            while (cursor.moveToNext()) {
    
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
                String number = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DATA1));
    
                //数据清洗
                if (TextUtils.isEmpty(number)) {
                    continue;
                }
                if (!TextUtils.isDigitsOnly(number = number.replace(" ", ""))) {
                    continue;
                }
    
                if (TextUtils.isEmpty(name)) {
                    name = number;
                }
                list.add(new ContactBean(name, number));
            }
            cursor.close();
            return list;
        }
    
        /**
         * 获取所有联系人
         * 数据结构:ContactsBean(String displayName, List<String> numList)
         * <p/>
         * 需要权限:
         * <uses-permission android:name="android.permission.READ_CONTACTS" />
         *
         * @param
         * @return List<ContactsBean>
         */
        public static List<ContactsBean> getContactsList(Context context) {
    
            Logger.d("SMSHelper", "-----------SMSHelper#getContactsList()----------");
            Logger.d("SMSHelper", "开始查询 Contacts 表");
            List<ContactsBean> list = new ArrayList<ContactsBean>();
            ContactsBean bean = null;
            ContentResolver resolver = context.getContentResolver();
            Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    
            if (cursor == null && cursor.getCount() <= 0) {
                return null;
            }
            Logger.d("SMSHelper", "cursor.getCount():" + cursor.getCount());
    
            while (cursor.moveToNext()) {
                bean = new ContactsBean();
    
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));//姓名
    
                wirteNumbers(resolver, name, bean);
                list.add(bean);
            }
            cursor.close();
            return list;
        }
    
        /**
         * 根据联系人姓名查询电话
         * 并写入
         */
        private static void wirteNumbers(final ContentResolver contentResolver, String name, final ContactsBean bean) {
            Logger.d("SMSHelper", "开始查询 Data 表 : 查询联系人:" + name);
    
            Cursor dataCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,
                    new String[]{ContactsContract.Data.DATA1},
                    ContactsContract.Data.DISPLAY_NAME + "= ? ",
                    new String[]{name}, null);
            if (dataCursor == null) {
                Logger.w("SMSHelper", "dataCursor == null ");
    
                return;
            }
            if (dataCursor.getCount() > 0) {
                bean.setName(name);
                Logger.w("SMSHelper", " 电话信息 -- size: " + dataCursor.getCount());
                while (dataCursor.moveToNext()) {
                    String number = dataCursor.getString(dataCursor.getColumnIndex(ContactsContract.Data.DATA1));
    
                    if (TextUtils.isEmpty(number) || !TextUtils.isDigitsOnly(number = number.replace(" ", ""))) {
                        Logger.w("SMSHelper", " 电话信息(异常) -- number: " + number);
                        continue;
                    }
                    bean.getNumList().add(number);
                    Logger.w("SMSHelper", " 电话信息 -- number: " + number);
                }
                dataCursor.close();
            } else {
                Logger.w("SMSHelper", " 无电话信息 -- name: " + name);
            }
            return;
        }
    
        /**
         * 获取短信记录 (需要bean: Smsinfo.java和 Read_SMS权限)
         * <p>
         * <uses-permission android:name="android.permission.READ_SMS" />
         *
         * @return List<Smsinfo>
         * @author zlw QQ:739043667
         */
        public static List<SmsInfo> getAllSms(Context context) {
            List<SmsInfo> smsinfos = new ArrayList<SmsInfo>();
    
            Uri uri = Uri.parse("content://sms/");
            ContentResolver resolver = context.getContentResolver();
            Cursor cursor = resolver.query(uri, new String[]{"address", "date", "type", "body"}, null, null, null);
    
            SmsInfo smsinfo = null;
            while (cursor.moveToNext()) {
                String address = cursor.getString(0);
                String date = cursor.getString(1);
                String type = cursor.getString(2);
                String body = cursor.getString(3);
                smsinfo = new SmsInfo(address, date, type, body);
                smsinfos.add(smsinfo);
            }
    
            cursor.close();
            return smsinfos;
        }
    
        /**
         * 短信信息Bean 类
         *
         * @param
         * @author zlw QQ:739043667
         * @return
         */
        public static class SmsInfo {
            String address;
            String date;
            String type;
            String body;
    
            public SmsInfo(String address, String date, String type, String body) {
                super();
                this.address = address;
                this.date = date;
                this.type = type;
                this.body = body;
            }
    
            public String getAddress() {
                return address;
            }
    
            public void setAddress(String address) {
                this.address = address;
            }
    
            public String getDate() {
                return date;
            }
    
            public void setDate(String date) {
                this.date = date;
            }
    
            public String getType() {
                return type;
            }
    
            public void setType(String type) {
                this.type = type;
            }
    
            public String getBody() {
                return body;
            }
    
            public void setBody(String body) {
                this.body = body;
            }
    
        }
    
        /**
         * 联系人集合Bean类
         */
        public static class ContactsBean {
    
            private String name;
            private List<String> numList;
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public List<String> getNumList() {
                return numList;
            }
    
            public void setNumList(List<String> numList) {
                this.numList = numList;
            }
    
            public ContactsBean() {
                numList = Lists.newArrayList();
            }
    
            public ContactsBean(String displayName, List<String> numList) {
                super();
                this.name = displayName;
                if (numList == null) {
                    this.numList = Lists.newArrayList();
                } else {
                    this.numList = numList;
                }
            }
    
            @Override
            public String toString() {
                return "ContactsBean [name=" + name + ", numList=" + numList + "]";
            }
        }
    
    
        /**
         * 联系人Bean类
         */
        public static class ContactBean {
    
            private String name;
            private String number;
    
            public ContactBean() {
            }
    
            public ContactBean(String name, String number) {
                this.name = name;
                this.number = number;
            }
    
            public String getName() {
                return name;
            }
    
            @Override
            public String toString() {
                return "ContactBean{" +
                        "name='" + name + '\'' +
                        ", number='" + number + '\'' +
                        '}';
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public String getNumber() {
                return number;
            }
    
            public void setNumber(String number) {
                this.number = number;
            }
        }
    
    }
    

    相关文章

      网友评论

      • 7768b209fbfa:Cursor dataCursor = contentResolver.query(
        ContactsContract.Data.CONTENT_URI,
        null,
        ContactsContract.Data.CONTACT_ID + "= ? AND " + ContactsContract.Data.MIMETYPE + "= ?",
        new String[]{String.valueOf(contactId), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE},
        null
        );
      • 7768b209fbfa:根据联系人姓名查询电话会有重名问题吧,还是用 ID 会严谨一些
        android_赵乐玮:当时确实出现了重名问题,还得手动过滤一遍才能用,多谢指点;

      本文标题:10.Android通讯录-联系人查询

      本文链接:https://www.haomeiwen.com/subject/mnyozttx.html