本文测试平台: Android 6.0 , API 23

辅助阅读:
Android官网有关联系人的开发指南:
https://developer.android.com/guide/topics/providers/contacts-provider.html

相关API:
https://developer.android.com/reference/android/provider/ContactsContract.html

所有字段和MIMETYPE声明:
https://developer.android.com/reference/android/provider/ContactsContract.Data.html

准备好了吗?


1:获取所有联系人的id

final ContentResolver contentResolver = getContentResolver();Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, new String[]{"_id"}, null, null, null);//cursor.getCount() 就是联系人的总数

枚举所有联系人的id:

if (cursor != null && cursor.getCount() > 0) {    if (cursor.moveToFirst()) {        do {            int contactIdIndex = cursor.getColumnIndex(ContactsContract.Contacts._ID);//获取 id 所在列的索引            String contactId = cursor.getString(contactIdIndex);//联系人id            //do something...        } while (cursor.moveToNext());        cursor.close();    }}

2:通过联系人的id,获取所有字段值
通过步骤1, 得到了联系人的id(contactId).

/*** 根据MIMETYPE类型, 返回对应联系人的data1字段的数据*/private String getData1(final ContentResolver contentResolver, String contactId, final String mimeType) {  StringBuilder stringBuilder = new StringBuilder();  Cursor dataCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,          new String[]{ContactsContract.Data.DATA1},          ContactsContract.Data.CONTACT_ID + "=?" + " AND "                  + ContactsContract.Data.MIMETYPE + "='" + mimeType + "'",          new String[]{String.valueOf(contactId)}, null);  if (dataCursor != null && dataCursor.getCount() > 0) {      if (dataCursor.moveToFirst()) {          do {              stringBuilder.append(dataCursor.getString(dataCursor.getColumnIndex(ContactsContract.Data.DATA1)));              stringBuilder.append("_");//多个值,之间的分隔符.可以自定义;          } while (dataCursor.moveToNext());      }      dataCursor.close();  }  return stringBuilder.toString();}

上面的方法,封装了取值的过程. 其实很容易看懂;

ContactsContract.Data.DATA1 -->就是包含值的字段名,也就是需要返回的字段;contactId mimeType -->这2个查询的条件.//其中contactId表示联系人的id,就是对应的那个联系人;//mimeType, 这个表示,你需要获取联系人的什么字段.(比如,邮箱,公司,地址等)//这个是常量值, 后面会介绍取值范围.

3:所有字段的MIMETYPE解释

String[] MIMETYPES = new String[]{ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE,//联系人名称ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,//联系人电话(可能包含多个)ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,//邮箱(多个)ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE,//公司ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE,//备注ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE,//地址ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE,//网站ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.Relation.CONTENT_ITEM_TYPE,ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE};

4:使用方法:
只需要把 联系人的id 和 MIMETYPE类型, 作为参数, 传递给步骤2的方法中.即可;


当然, 你也可以通过以下方法获取信息:

/*联系人电话信息*/Cursor contactsCursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,//注意这个uri        null,        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId,//contactId 是上面提到过的联系人id        null, null);        //    int phoneIndex = contactsCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);//获取联系人 号码的索引    int nameIndex = contactsCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);//获取 名字 所在列的索引 // final String phoneNumber = contactsCursor.getString(phoneIndex);//联系人的号码 final String name = contactsCursor.getString(nameIndex);//联系人名字//    contactsCursor.close();//记得close}/*联系人邮箱信息*/Cursor emailCursor = contentResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,//注意URI        null,        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + contactId,        null, null);//int emailIndex = emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA);// final String email = emailCursor.getString(emailIndex);//联系人邮箱//    emailCursor.close();}//这种方式, 我暂时还无法获取所有的字段...聪明的你,肯定比我厉害.

2017-01-08更新:
以上方法完全可行, 补充打印联系人的所有字段,及其值:

//此方法可以打印所有字段的详细信息private static void logData(final ContentResolver contentResolver, String contactId) {     Cursor dataCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,             null,             ContactsContract.Data.CONTACT_ID + "=?",             new String[]{String.valueOf(contactId)}, null);     if (dataCursor != null) {         if (dataCursor.getCount() > 0) {             L.e("----------------------start--------------------");             L.i("数量:" + dataCursor.getCount() + " 列数:" + dataCursor.getColumnCount());             if (dataCursor.moveToFirst()) {                 do {                     for (int i = 0; i < dataCursor.getColumnCount(); i++) {                         final String columnName = dataCursor.getColumnName(i);                         final int columnIndex = dataCursor.getColumnIndex(columnName);                         final int type = dataCursor.getType(columnIndex);                         String data = "", ty = "";                         if (type == Cursor.FIELD_TYPE_NULL) {                             ty = "NULL";                             data = "空值";                         } else if (type == Cursor.FIELD_TYPE_BLOB) {                             ty = "BLOB";                             data = String.valueOf(dataCursor.getBlob(columnIndex));                         } else if (type == Cursor.FIELD_TYPE_FLOAT) {                             ty = "FLOAT";                             data = String.valueOf(dataCursor.getFloat(columnIndex));                         } else if (type == Cursor.FIELD_TYPE_INTEGER) {                             ty = "INTEGER";                             data = String.valueOf(dataCursor.getInt(columnIndex));                         } else if (type == Cursor.FIELD_TYPE_STRING) {                             ty = "STRING";                             data = dataCursor.getString(columnIndex);                         }                         L.i("第" + i + "列->名称:" + columnName + " 索引:" + columnIndex + " 类型:" + ty + " 值:" + data);                     }                 } while (dataCursor.moveToNext());             }             L.e("------------------------end---------------------");         }         dataCursor.close();     } }
//输出结果大致如下:0->名称:sort_key 索引:0 类型:STRING 值:熊志文第1->名称:photo_uri 索引:1 类型:STRING 值:content://com.android.contacts/display_photo/8332->名称:status_label 索引:2 类型:NULL 值:空值第3->名称:status_ts 索引:3 类型:NULL 值:空值第4->名称:status_res_package 索引:4 类型:NULL 值:空值第5->名称:display_name 索引:5 类型:STRING 值:熊志文第6->名称:last_time_used 索引:6 类型:NULL 值:空值第7->名称:phone_number 索引:7 类型:NULL 值:空值第8->名称:mimetype 索引:8 类型:STRING 值:vnd.android.cursor.item/phone_v2第9->名称:phonebook_label_alt 索引:9 类型:STRING 值:X第10->名称:data6 索引:10 类型:NULL 值:空值第11->名称:version 索引:11 类型:INTEGER 值:512->名称:photo_id 索引:12 类型:INTEGER 值:247613->名称:data3 索引:13 类型:NULL 值:空值第14->名称:custom_ringtone 索引:14 类型:NULL 值:空值第15->名称:times_contacted 索引:15 类型:INTEGER 值:016->名称:account_type_and_data_set 索引:16 类型:STRING 值:com.meizu.account第17->名称:dirty 索引:17 类型:INTEGER 值:018->名称:data7 索引:18 类型:NULL 值:空值第19->名称:data15 索引:19 类型:NULL 值:空值第20->名称:address 索引:20 类型:INTEGER 值:-221->名称:raw_contact_is_user_profile 索引:21 类型:INTEGER 值:022->名称:data_set 索引:22 类型:NULL 值:空值第23->名称:phonebook_label 索引:23 类型:STRING 值:X第24->名称:data10 索引:24 类型:NULL 值:空值第25->名称:organization_note 索引:25 类型:NULL 值:空值第26->名称:contact_type 索引:26 类型:INTEGER 值:027->名称:res_package 索引:27 类型:NULL 值:空值第28->名称:account_type 索引:28 类型:STRING 值:com.meizu.account第29->名称:data11 索引:29 类型:NULL 值:空值第30->名称:display_name_alt 索引:30 类型:STRING 值:熊志文第31->名称:lookup 索引:31 类型:STRING 值:3303r692-984CA4C69394.3303r969-984CA4C69394第32->名称:phonetic_name 索引:32 类型:NULL 值:空值第33->名称:last_time_contacted 索引:33 类型:INTEGER 值:034->名称:contact_last_updated_timestamp 索引:34 类型:INTEGER 值:133169050235->名称:data13 索引:35 类型:NULL 值:空值第36->名称:in_visible_group 索引:36 类型:INTEGER 值:137->名称:chat_capability 索引:37 类型:NULL 值:空值第38->名称:data9 索引:38 类型:NULL 值:空值第39->名称:carrier_presence 索引:39 类型:INTEGER 值:040->名称:data_sync1 索引:40 类型:NULL 值:空值第41->名称:sort_key_alt 索引:41 类型:STRING 值:熊志文第42->名称:contact_presence 索引:42 类型:NULL 值:空值第43->名称:data_version 索引:43 类型:INTEGER 值:144->名称:phonetic_name_style 索引:44 类型:STRING 值:045->名称:name_raw_contact_id 索引:45 类型:INTEGER 值:69246->名称:raw_contact_id 索引:46 类型:INTEGER 值:96947->名称:send_to_voicemail 索引:47 类型:INTEGER 值:048->名称:data4 索引:48 类型:STRING 值:+861507098951249->名称:data12 索引:49 类型:NULL 值:空值第50->名称:contact_status 索引:50 类型:NULL 值:空值第51->名称:contact_status_label 索引:51 类型:NULL 值:空值第52->名称:pinned 索引:52 类型:INTEGER 值:053->名称:status_icon 索引:53 类型:NULL 值:空值第54->名称:status 索引:54 类型:NULL 值:空值第55->名称:data1 索引:55 类型:STRING 值:1507098951256->名称:mz_last_op_package 索引:56 类型:NULL 值:空值第57->名称:phonebook_bucket 索引:57 类型:INTEGER 值:2458->名称:data_sync2 索引:58 类型:NULL 值:空值第59->名称:contact_status_res_package 索引:59 类型:NULL 值:空值第60->名称:in_default_directory 索引:60 类型:INTEGER 值:161->名称:_id 索引:61 类型:INTEGER 值:325562->名称:hash_id 索引:62 类型:NULL 值:空值第63->名称:is_super_primary 索引:63 类型:INTEGER 值:064->名称:data5 索引:64 类型:NULL 值:空值第65->名称:contact_id 索引:65 类型:INTEGER 值:96966->名称:data8 索引:66 类型:NULL 值:空值第67->名称:is_primary 索引:67 类型:INTEGER 值:168->名称:data_sync4 索引:68 类型:NULL 值:空值第69->名称:record_type 索引:69 类型:INTEGER 值:070->名称:has_phone_number 索引:70 类型:INTEGER 值:171->名称:sns_type 索引:71 类型:INTEGER 值:072->名称:display_name_source 索引:72 类型:INTEGER 值:4073->名称:photo_file_id 索引:73 类型:INTEGER 值:83374->名称:data_sync3 索引:74 类型:NULL 值:空值第75->名称:backup_id 索引:75 类型:NULL 值:空值第76->名称:data14 索引:76 类型:NULL 值:空值第77->名称:contact_status_ts 索引:77 类型:NULL 值:空值第78->名称:phonebook_bucket_alt 索引:78 类型:INTEGER 值:2479->名称:mode 索引:79 类型:NULL 值:空值第80->名称:data2 索引:80 类型:STRING 值:781->名称:group_sourceid 索引:81 类型:NULL 值:空值第82->名称:starred 索引:82 类型:INTEGER 值:083->名称:photo_thumb_uri 索引:83 类型:STRING 值:content://com.android.contacts/contacts/969/photo84->名称:times_used 索引:84 类型:NULL 值:空值第85->名称:contact_status_icon 索引:85 类型:NULL 值:空值第86->名称:distance 索引:86 类型:INTEGER 值:-187->名称:contact_chat_capability 索引:87 类型:NULL 值:空值第88->名称:account_name 索引:88 类型:STRING 值:844129989->名称:sourceid 索引:89 类型:NULL 值:空值

附加获取头像的方法:

/*** 获取联系人的图片*/public static Bitmap getPhoto(final ContentResolver contentResolver, String contactId) {   Bitmap photo = null;   Cursor dataCursor = contentResolver.query(ContactsContract.Data.CONTENT_URI,           new String[]{"data15"},           ContactsContract.Data.CONTACT_ID + "=?" + " AND "                   + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'",           new String[]{String.valueOf(contactId)}, null);   if (dataCursor != null) {       if (dataCursor.getCount() > 0) {           dataCursor.moveToFirst();           byte[] bytes = dataCursor.getBlob(dataCursor.getColumnIndex("data15"));           if (bytes != null) {               photo = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);           }       }       dataCursor.close();   }   return photo;}

开源地址:https://github.com/angcyo/ContactsPicker


至此: 文章就结束了,如有疑问: QQ群:274306954 欢迎您的加入.

更多相关文章

  1. Android获取通话记录【名称,号码,日期,通话时间,类型】
  2. Android(安卓)常用RGB值以及中英文名称
  3. [android源码下载索引贴】微信+二维码那都不是事......
  4. Android开发从零开始之java-泛型初步
  5. 链接器解析多重定义的全局变量
  6. android获取经纬度和地方名称
  7. android Uri获取真实路径转换成File的方法
  8. Android之再谈文件操作和SDcard读写
  9. Android之Audio常用属性变量

随机推荐

  1. Presto on Spark:扩展 Presto 以支持大规
  2. Python_学习之Pycharm配置技巧
  3. 【源码下载】150款+炫酷的CSS3 loading加
  4. Redis 6.0 稳定版发布,支持多线程 IO
  5. 为什么越来越多的人想成为全栈工程师?
  6. 【源码下载】50套高大上的后台管理系统模
  7. Apache Kafka 不需要管理员:删除 Apache Z
  8. React应该如何优雅的绑定事件?
  9. Apache Kafka 2.6.0 有哪些值得关心的变
  10. Delta Lake 第一篇论文发布了