百度通讯录一大把的例子,不过在项目的实际中漏洞还是挺多的,因为现在的通讯录太强大了,特殊字符也能输入,而且我还有同事的通讯录里竟然有用表情来做联系人名字的,这下百度的例子就测底蒙了,所以还是得自己动手,优化了一下,分享的同时也记录下自己的劳动成果,几年后也可以回头看看自己走过的码路
1 /** 通讯录 **/ 2 @SuppressLint("DefaultLocale") 3 public class DoctorContactActivity extends BaseActivity { 4 5 private List<DoctorContacts> cList = new ArrayList<DoctorContacts>(); 6 private List<String> telItem = new ArrayList<String>(); 7 private List<ContactsAll> allList = new ArrayList<ContactsAll>(); 8 private final String[] PHONES_PROJECTION = new String[] { 9 Phone.DISPLAY_NAME, Phone.NUMBER, Photo.PHOTO_ID, Phone.CONTACT_ID }; 10 // 存放国标一级汉字不同读音的起始区位码 11 private static final int[] secPosValueList = { 1601, 1637, 1833, 2078, 12 2274, 2302, 2433, 2594, 2787, 3106, 3212, 3472, 3635, 3722, 3730, 13 3858, 4027, 4086, 4390, 4558, 4684, 4925, 5249, 5600 }; 14 // 存放国标一级汉字不同读音的起始区位码对应读音 15 private static final char[] firstLetter = { 'a', 'b', 'c', 'd', 'e', 'f', 16 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 17 'w', 'x', 'y', 'z' }; 18 private static final int GB_SP_DIFF = 160; 19 private Context context; 20 private PinnedSectionListView listView; 21 private ContactsSidebar sidebar; 22 private DoctorContactsAdapter adapter = null; 23 private String TAG = "DoctorContactActivity"; 24 private static HanyuPinyinOutputFormat spellFormat = new HanyuPinyinOutputFormat(); 25 26 @SuppressLint("DefaultLocale") 27 @Override 28 protected void onCreate(Bundle savedInstanceState) { 29 // TODO Auto-generated method stub 30 super.onCreate(savedInstanceState); 31 context = DoctorContactActivity.this; 32 setContentView(R.layout.activity_friends_message_contact); 33 listView = (PinnedSectionListView) findViewById(R.id.friends_message_contact_listview); 34 sidebar = (ContactsSidebar) findViewById(R.id.sidebar); 35 allList.clear(); 36 cList.clear(); 37 // UPPERCASE:大写 (ZHONG) 38 // LOWERCASE:小写 (zhong) 39 spellFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); 40 // WITHOUT_TONE:无音标 (zhong) 41 // WITH_TONE_NUMBER:1-4数字表示英标 (zhong4) 42 // WITH_TONE_MARK:直接用音标符(必须WITH_U_UNICODE否则异常) (zhòng) 43 spellFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); 44 // WITH_V:用v表示ü (nv) 45 // WITH_U_AND_COLON:用"u:"表示ü (nu:) 46 // WITH_U_UNICODE:直接用ü (nü) 47 spellFormat.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE); 48 // new Thread(new Runnable() { 49 // public void run() { 50 getPhoneContacts(); 51 // } 52 // }).start(); 53 54 // for(int i = 0;i<5;i++){ 55 // DoctorContacts c = new DoctorContacts(); 56 // c.setFirstGrapheme("-1");//自定义分组 57 // c.setMobileNo("测试"); 58 // c.setName("测试"); 59 // cList.add(c); 60 // } 61 checkTelBook(); 62 adapter = new DoctorContactsAdapter(context, allList); 63 listView.setAdapter(adapter); 64 sidebar.setListView(listView); 65 } 66 67 private void checkTelBook() { 68 telItem.clear(); 69 for (DoctorContacts c : cList) { 70 if (c.getMobileNo() != null) { 71 telItem.add(c.getMobileNo()); 72 } 73 } 74 if (telItem.size() == 0) { 75 Toast.makeText(context, "您的通讯录中没有联系人", 0).show(); 76 return; 77 } 78 String telList = new Gson().toJson(telItem); 79 String umerId = UMDocApplication.getInstance().getPerson().getUmerId(); 80 String easemobName = UMDocApplication.getInstance().getPerson() 81 .getEasemobName(); 82 showDialog("正在加载中..."); 83 ApiClient.checkTelBook(umerId, easemobName, telList, 84 new ApiClient.ClientCallback() { 85 86 @Override 87 public void onSuccess(Object data) { 88 // TODO Auto-generated method stub 89 TelsEntity rEntity = (TelsEntity) data; 90 if (rEntity.reqResult.equals("success")) { 91 if (rEntity.data != null) { 92 List<TelEntity> list = rEntity.data; 93 for (TelEntity telEntity : list) { 94 DoctorContacts contacts = new DoctorContacts(); 95 contacts.setFirstGrapheme("-1"); 96 contacts.setMobileNo(telEntity.getTel()); 97 contacts.setStatus(telEntity.getStatus()); 98 contacts.setUserId(telEntity 99 .getEasemobName());100 String tel = getContactsName(telEntity101 .getTel());102 if (tel != null) {103 contacts.setName(tel);104 }105 106 cList.add(contacts);107 }108 SortContactList(cList);109 String grapheme = null;110 for (DoctorContacts c : cList) {111 if (!c.getFirstGrapheme().equals(grapheme)) {112 ContactsAll contacts = new ContactsAll();113 contacts.setMsg(c.getFirstGrapheme()114 .toUpperCase());115 contacts.setTypeMsg(0);116 contacts.setTypeSection(0);117 allList.add(contacts);118 grapheme = c.getFirstGrapheme();119 }120 ContactsAll all = new ContactsAll();121 all.setTypeMsg(1);122 all.setTypeSection(1);123 all.setContent(c);124 allList.add(all);125 all = null;126 }127 adapter.notifyDataSetChanged();128 }129 }130 closeDialog();131 }132 133 @Override134 public void onFailure(String message) {135 // TODO Auto-generated method stub136 closeDialog();137 Log.e(TAG, "checkTelBook " + message);138 }139 140 @Override141 public void onError(Exception e) {142 // TODO Auto-generated method stub143 closeDialog();144 Log.e(TAG, "checkTelBook " + e.getMessage());145 }146 });147 }148 149 /** 根据电话号码获取联系人信息并且过滤改联系人 **/150 private String getContactsName(String tel) {151 if (tel == null) {152 return "";153 }154 String result = null;155 for (DoctorContacts c : cList) {156 if (c.getMobileNo() != null && tel.equals(c.getMobileNo())) {157 result = c.getName();158 cList.remove(c);159 break;160 }161 }162 return result;163 }164 165 /** 得到手机通讯录联系人信息 **/166 @SuppressLint("NewApi")167 private void getPhoneContacts() {168 ContentResolver resolver = context.getContentResolver();169 170 // 获取手机联系人171 Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,172 PHONES_PROJECTION, null, null, null);173 174 if (phoneCursor != null) {175 while (phoneCursor.moveToNext()) {176 DoctorContacts contacts = new DoctorContacts();177 // 得到联系人名称178 String contactName = phoneCursor.getString(0);179 if (contactName == null)180 continue;181 182 // 得到手机号码183 String phoneNumber = phoneCursor.getString(1);184 185 // 得到联系人ID186 // Long contactid = phoneCursor.getLong(2);187 188 // 得到联系人头像ID189 // Long photoid = phoneCursor.getLong(3);190 191 // 得到联系人头像Bitamp192 // Bitmap contactPhoto = null;193 194 // photoid 大于0 表示联系人有头像 如果没有给此人设置头像则给他一个默认的195 // if (photoid > 0) {196 // Uri uri = ContentUris.withAppendedId(197 // ContactsContract.Contacts.CONTENT_URI, contactid);198 // InputStream input = ContactsContract.Contacts199 // .openContactPhotoInputStream(resolver, uri);200 // contactPhoto = BitmapFactory.decodeStream(input);201 // if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH)202 // input =203 // ContactsContract.Contacts.openContactPhotoInputStream(resolver,204 // uri, bigPicture);205 // else206 // input =207 // ContactsContract.Contacts.openContactPhotoInputStream(resolver,208 // uri);209 // if (input != null) {210 // IOUtils.closeQuietly(input);211 // } else {212 // contactPhoto = BitmapFactory.decodeResource(213 // context.getResources(), R.drawable.pic_head_none_login);214 // }215 contacts.setMobileNo(phoneNumber);216 contacts.setName(contactName);217 if (phoneNumber.startsWith("1")) {218 cList.add(contacts);219 }220 221 }222 223 phoneCursor.close();224 }225 }226 227 /**228 * 对指定的list集合进行字母排序229 * 230 * @param cList231 */232 @SuppressWarnings("unchecked")233 private void SortContactList(List<DoctorContacts> cList) {234 for (DoctorContacts contact : cList) {235 // 表示没有自定义236 237 if (contact.getFirstGrapheme() == null238 || contact.getFirstGrapheme().equals("")) {239 contact.setFirstGrapheme(getSpells(contact.getName()));240 }241 // 把所有数字转换为#分组242 if (contact.getFirstGrapheme() != null243 && !contact.getFirstGrapheme().equals("-1")244 && isInteger(contact.getFirstGrapheme())) {245 contact.setFirstGrapheme("#");246 }247 248 }249 @SuppressWarnings("rawtypes")250 Comparator comp = new Comparator() {251 public int compare(Object o1, Object o2) {252 DoctorContacts c1 = (DoctorContacts) o1;253 DoctorContacts c2 = (DoctorContacts) o2;254 if (c1.getFirstGrapheme().compareToIgnoreCase(255 c2.getFirstGrapheme()) < 0)256 return -1;257 else if (c1.getFirstGrapheme().equalsIgnoreCase(258 c2.getFirstGrapheme()))259 return 0;260 else if (c1.getFirstGrapheme().compareToIgnoreCase(261 c2.getFirstGrapheme()) > 0)262 return 1;263 return 0;264 }265 };266 Collections.sort(cList, comp);267 }268 269 /**270 * 判断字符串是否是整数271 */272 public boolean isInteger(String value) {273 try {274 Integer.parseInt(value);275 return true;276 } catch (NumberFormatException e) {277 return false;278 }279 }280 281 /**282 * 获取一个字符串的首字母283 * 284 * @param characters285 * 字符串286 * @return 首字母287 */288 private String getSpells(String characters) {289 char c = characters.toCharArray()[0];290 String result = null;291 try {292 // 获取汉字的拼音,如果不是汉字则返回null293 String[] pinyin = PinyinHelper.toHanyuPinyinStringArray(c,294 spellFormat);295 if (pinyin != null) {296 result = String.valueOf(pinyin[0].toCharArray()[0])297 .toLowerCase();// 取拼音的首个字母298 }299 } catch (BadHanyuPinyinOutputFormatCombination e) {300 // TODO Auto-generated catch block301 Log.e(TAG, "getSpells " + e.getMessage());302 e.printStackTrace();303 }304 if (result == null) { // 如果上面没有取到则用自己的方法再取一次305 306 if (!isNumeric(characters)) {// 如果为特殊字符,比如表情等,自动归类为#307 Log.d(TAG, "getSpells " + characters + "字符转换为# --isNumeric");308 return "#";309 }310 Log.d(TAG, "getSpells " + characters311 + "没取到,进入自定义获取 --getFirstLetter");312 StringBuffer buffer = new StringBuffer();313 for (int i = 0; i < characters.length(); i++) {314 char ch = characters.charAt(i);315 // 判断是否为汉字,如果左移7为0就不是汉字,否则是汉字316 if ((ch >> 7) == 0) {317 buffer.append(characters.substring(0, 1));318 break;319 } else if (String.valueOf(ch) != null) {// 获取汉字的首字母320 char spell = getFirstLetter(ch);321 if (String.valueOf(spell) != null)322 buffer.append(String.valueOf(spell));// 表示获取每个汉字的首字母323 break;// 以获取到首字母就截至获取下一个324 }325 }326 result = buffer.toString().trim().toLowerCase();327 }328 329 return result;330 }331 332 /** 判断是否为数字 **/333 public static boolean isNumeric(String str) {334 for (int i = str.length(); --i >= 0;) {335 if (!Character.isDigit(str.charAt(i))) {336 return false;337 }338 }339 return true;340 }341 342 /** 获取首字母,因为上面的过滤,所以此方法只会进来数字或特殊字符 **/343 private Character getFirstLetter(char ch) {344 345 byte[] uniCode = null;346 try {347 uniCode = String.valueOf(ch).getBytes("GBK");348 if (uniCode == null) {349 return null;350 }351 } catch (UnsupportedEncodingException e) {352 Log.e(TAG, "getFirstLetter " + e.getMessage());353 e.printStackTrace();354 return null;355 }356 if (uniCode[0] < 128 && uniCode[0] > 0) { // 非汉字357 return null;358 }359 char c = convert(uniCode);360 return c;361 }362 363 /**364 * 获取一个汉字的拼音首字母。 GB码两个字节分别减去160,转换成10进制码组合就可以得到区位码365 * 例如汉字“你”的GB码是0xC4/0xE3,分别减去0xA0(160)就是0x24/0x43366 * 0x24转成10进制就是36,0x43是67,那么它的区位码就是3667,在对照表中读音为‘n’367 */368 private static char convert(byte[] bytes) {369 char result = '-';// 初始值370 int secPosValue = 0;371 int i;372 for (i = 0; i < bytes.length; i++) {373 bytes[i] -= GB_SP_DIFF;374 }375 secPosValue = bytes[0] * 100 + bytes[1];376 for (i = 0; i < 23; i++) {377 if (secPosValue >= secPosValueList[i]378 && secPosValue < secPosValueList[i + 1]) {379 result = firstLetter[i];380 break;381 }382 }383 return result;384 }385 386 public void back(View view) {387 finish();388 }389 }
这几个表情是我自己添加的,还有一些手机可以输入聊天表情的,这里就不截图了