Android快速获取通信录列表、首字母、并排序

关键点

  • 只使用一个Cursor 同时获取 手机号、首字母、并排序 (200多联系人大概在20ms左右)
  • 首字母的获取根据不同版本获取方式不同,在Android5.0以上使用 phonebook_label字段,在5.0 以下使用 ContactsContract.Contacts.SORT_KEY_PRIMARY也就是sort_key字段, 国内部分机型发现在 5.0以上 并不存在 phonebook_label字段,根据这种情况坐做了适配。
  • 实际开发中无法完美覆盖所有机型,所以需要对可能的异常情况做 catch (比如手机本地没有用户首字母)

关键代码

public class ContactInfoUtils {    private ContactInfoUtils(){};    /**     * 从手机通信录中 检索 用户联系人 姓名及手机号信息     * @param context     * @return     */    /**     * 从 手机本地通信录 加载 联系人信息     * @param context     * @return     */    public static List loadContactInfo(Context context){        List contactInfos = new ArrayList<>();        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;        ContentResolver reslover = context.getContentResolver();        String[] projection = {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,                ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.Contacts.SORT_KEY_PRIMARY};        if (Build.VERSION.SDK_INT >= 19){ //5.0 以上 ,sort_key_primary 是原汉字,排序字段变成了 phonebook_label            projection[2] = "phonebook_label";            Cursor testCursor = null;            try {                testCursor = reslover.query(uri, new String[]{"phonebook_label"}, null, null, null);            }catch (Exception e){                //有些手机厂商 没有 phonebook_label 这个字段                projection[2] = ContactsContract.Contacts.SORT_KEY_PRIMARY;            }finally {                if (testCursor!=null){                    testCursor.close();                }            }        }        Cursor cursor = reslover.query(uri, projection, null, null,                projection[2]);        if (cursor == null)            return Collections.EMPTY_LIST;        while (cursor.moveToNext()) {            // 联系人姓名            String name = cursor                    .getString(0);            // 获得联系人手机号 ,过滤空格 和"-"符号            String phoneNumber = cursor.getString(1)                    .replaceAll(" ","")                    .replaceAll("-","");            if (phoneNumber.length() > 11){                phoneNumber = phoneNumber.substring(phoneNumber.length()-11,phoneNumber.length());            }            //只取有 name 的情况 (根据自己的业务需求来)            if (name == null || !isValidPhone(phoneNumber))                continue;            // Sort Key,读取的联系人按照姓名从 A->Z 排序分组。            String sort_key_primary = cursor                    .getString(2);            ContactInfo contactInfo = new ContactInfo();            contactInfo.setUserName(name);            String firstLetterOfName = null;            if (name.length() > 0){                //如果 手机本地有 优先取手机的 首字母                if (sort_key_primary!=null && sort_key_primary.length()>0){                    sort_key_primary = sort_key_primary.toUpperCase();                    if (sort_key_primary.charAt(0) >='A' && sort_key_primary.charAt(0) <='Z'){                        firstLetterOfName = sort_key_primary.substring(0,1);                    }                }else {//如果手机本地没有保存首字母,则使用第三方控件自己获取                    String selling = CharacterParser.convert(name.substring(0, 1));                    if (selling!= null && selling.length()>0){                        String character = selling.substring(0, 1).toUpperCase();                        if (character.charAt(0)>='A' && character.charAt(0)<='Z'){                            firstLetterOfName = character;                        }                    }                }            }            if (firstLetterOfName == null)                firstLetterOfName ="#";            contactInfo.setFirstLetterOfName(firstLetterOfName);            contactInfo.setMobilePhone(phoneNumber);            if (contactInfo.getUserName()!=null && contactInfo.getMobilePhone()!=null){                contactInfos.add(contactInfo);            }        }        cursor.close();        return contactInfos;    }    /**     * 提供 类似 手机通信录的 排序规则 ,保证将# 排在最下面     */    private static Comparator  COMPARE_LIKE_PHONE_CONTACTS = new Comparator (){        private int compareUserName(ContactInfo lhs,ContactInfo rhs){            if (lhs.getUserName() == null && rhs.getUserName() == null)                return 0;            else if (lhs.getUserName() == null)                return -1;            else if (rhs.getUserName() == null)                return 1;            else return lhs.getUserName().compareTo(rhs.getUserName());        }        @Override        public int compare(ContactInfo lhs, ContactInfo rhs) {            int result;            //先比较 首字母大小            // 因为 默认的 "#" 符号比较 char code 是 比 'A'小的,所以 需要特殊处理 '#'的情况            if (lhs.getFirstLetterOfName().equals("#")){                if (!rhs.getFirstLetterOfName().equals("#"))                    return 1;                else                    return compareUserName(lhs,rhs);            }else if (rhs.getFirstLetterOfName().equals("#")){                return -1;            }            result = lhs.getFirstLetterOfName().compareTo(rhs.getFirstLetterOfName());            //如果首字母大小一样,则 使用 姓名,比较规则 是Java默认的 字符串比较规则            if (result == 0){                return compareUserName(lhs,rhs);            }            return result;        }    };}

更多相关文章

  1. Android(安卓)小众良心的应用市场推荐
  2. Android手机游戏开发知识点总结
  3. 纪念我开始学习android的文章
  4. Android(安卓)dp方式的屏幕适配工具使用(bat批处理方式)
  5. 神奇的 Magisk
  6. 对手机厂商来说,“Android”并不是一个功能
  7. 为手机定制ROM
  8. Android(安卓)硬解码 MediaCodec 遇到的(部分手机绿屏)API21
  9. TL-android通过USB使用真机调试程序

随机推荐

  1. android Launcher2分析
  2. 轻松搞定android Listview下拉刷新 上拉(
  3. 学习笔记Android轮播图框架Banner
  4. Android-Android Support兼容包详解
  5. 程序员之路
  6. 更改系统给APP应用分配最大的内存空间
  7. Android studio APK 加固打包
  8. Android 中文 API —— ImageSwitcher,Ga
  9. Android sqlite数据库存取图片信息
  10. Android httpClient Get&Post方法