利用Contacts Provider读取手机联系人信息
2017-10-01 19:42
393 查看
参考:https://developer.android.google.cn/guide/topics/providers/contacts-provider.html
(联系人)Contact:代表联系人,包含了多种联系渠道。
(原始联系人)RawContact:每个原始联系人代表某个联系人的一种具体的联系渠道,比如E-mail、手机通讯录、推特等等。
(数据)Data:储存大多数实际的信息,比如手机号码、邮箱地址等等。
举例说明:假设手机用户为A,它有一个联系人B。A与B通过电子邮件、电话、推特三种渠道产生过联系,那么联系人B就对应三个原始联系人B,每个原始联系人B中会记录一种联系渠道(A使用的联系账户、账户类型),而具体的信息(手机号码、邮箱地址)会存放在数据表中。
因此,查询某个联系人的某项信息的一般步骤为:
在Contact表中查到该联系人对应的ID;
在RawContact表中查到该联系人ID对应的原始联系人的ID;
在Data表中查到原始联系人ID对应的数据行,并通过投影取得需要的数据。
判断应用是否具有读取手机通讯录的权限
可以在创建对象时即开始加载,也可以在需要时再加载。
在子线程中执行查询,不会阻塞UI线程。
加载结束后通过一个UnmodifiableMap返回联系人姓名到电话号码的映射。
支持设置加载完毕后执行的回调。
使用方法:通过静态方法getService()获取ContactManager实例,并设置是否需要立即开始加载、监听器等附加信息。
下面的例子中,信息加载完毕后会通过Log的方式打印出来:
Contacts Provider组织结构
Contacts Provider组织结构由三部分构成,如下图所示:(联系人)Contact:代表联系人,包含了多种联系渠道。
(原始联系人)RawContact:每个原始联系人代表某个联系人的一种具体的联系渠道,比如E-mail、手机通讯录、推特等等。
(数据)Data:储存大多数实际的信息,比如手机号码、邮箱地址等等。
举例说明:假设手机用户为A,它有一个联系人B。A与B通过电子邮件、电话、推特三种渠道产生过联系,那么联系人B就对应三个原始联系人B,每个原始联系人B中会记录一种联系渠道(A使用的联系账户、账户类型),而具体的信息(手机号码、邮箱地址)会存放在数据表中。
Contact表、RawContact表、Data表之间的联系
Contact、RawContact、Data分别对应三张数据库表,三张表都有一个_ID字段作为主键。在此基础上,RawContact表有一个CONTACT_ID列,代表这个原始联系人对应的联系人的_ID;Data表有一个Raw_CONTACT_ID列,代表这个数据行对应的原始联系人的_ID。因此,查询某个联系人的某项信息的一般步骤为:
在Contact表中查到该联系人对应的ID;
在RawContact表中查到该联系人ID对应的原始联系人的ID;
在Data表中查到原始联系人ID对应的数据行,并通过投影取得需要的数据。
实例:获取手机通讯录中所有联系人对应的手机号码
下面是一个用于加载联系人手机号码信息的ContactManager类,具有以下功能:判断应用是否具有读取手机通讯录的权限
android.permission.READ_CONTACTS。
可以在创建对象时即开始加载,也可以在需要时再加载。
在子线程中执行查询,不会阻塞UI线程。
加载结束后通过一个UnmodifiableMap返回联系人姓名到电话号码的映射。
支持设置加载完毕后执行的回调。
使用方法:通过静态方法getService()获取ContactManager实例,并设置是否需要立即开始加载、监听器等附加信息。
import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.provider.ContactsContract; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.util.SparseArray; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; /** * Created by swt369 on 2017/10/1. * Provide a simple way for managing contacts */ public class ContactManager { private static final Map<Context,ContactManager> INSTANCES = new HashMap<>(); private final Context context; private OnFinishLoadListener onFinishListener; private boolean loaded = false; private Map<String,List<String>> nameToCallNumbers = null; private ContactManager(Context context, boolean loadAtOnce, @Nullable OnFinishLoadListener onFinishListener){ this.context = context; this.onFinishListener = onFinishListener; if(loadAtOnce){ load(); } } /** * * @param context The context the Manager is running in * @param loadAtOnce True if needed to load at once * @param onFinishListener the callback that will be invoked when the loading is over * @return A instance of the ContactManager * @throws SecurityException When the application failed to get the android.permission.READ_CONTACTS */ public static ContactManager getService(Context context, boolean loadAtOnce, @Nullable OnFinishLoadListener onFinishListener) throws SecurityException{ int granted = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS); if(granted != PackageManager.PERMISSION_GRANTED){ throw new SecurityException("Need READ_CONTACTS permission"); } ContactManager contactManager = INSTANCES.get(context); if(contactManager == null){ contactManager = new ContactManager(context,loadAtOnce,onFinishListener); INSTANCES.put(context,contactManager); } return contactManager; } public void setOnFinishListener(OnFinishLoadListener onFinishListener){ this.onFinishListener = onFinishListener; } public void load(){ if(!loaded){ new LoadThread().start(); }else{ onFinishListener.onFinishLoad(Collections.unmodifiableMap(nameToCallNumbers)); } } public interface OnFinishLoadListener{ void onFinishLoad(Map<String, List<String>> nameToCallNumbers); } private class LoadThread extends Thread{ @Override public void run() { List<Integer> listIDs = new LinkedList<>(); SparseArray<String> idToName = new SparseArray<>(); SparseArray<List<String>> idToCallNumber = new SparseArray<>(); //Get all the _IDs and names in the table Contact Cursor cursorForContactID = null; try { cursorForContactID = context.getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME}, null, null, null ); if(cursorForContactID != null){ int indexID = cursorForContactID.getColumnIndex(ContactsContract.Contacts._ID); int indexName = cursorForContactID.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); //build the INSTANCES from ID to name. while(cursorForContactID.moveToNext()){ int id = cursorForContactID.getInt(indexID); listIDs.add(id); idToName.put(id, cursorForContactID.getString(indexName)); } } }finally { if (cursorForContactID != null) { cursorForContactID.close(); } } //Get all the _IDs in the table RawContact,which is equal to the raw_contact_IDs in the table Data. for(Integer ID : listIDs){ LinkedList<Integer> listRawContacts = new LinkedList<>(); Cursor cursorForRawContactID = null; try { cursorForRawContactID = context.getContentResolver().query( ContactsContract.RawContacts.CONTENT_URI, new String[]{ContactsContract.RawContacts._ID}, ContactsContract.RawContacts.CONTACT_ID + " = ?", new String[]{String.valueOf(ID)}, null ); if(cursorForRawContactID == null){ continue; } //build the INSTANCES from ID to raw_contact_ID. while (cursorForRawContactID.moveToNext()){ listRawContacts.add(cursorForRawContactID.getInt(cursorForRawContactID.getColumnIndex(ContactsContract.RawContacts._ID))); } }finally { if (cursorForRawContactID != null) { cursorForRawContactID.close(); } } //Build the INSTANCES from ID to phone numbers via raw_contact_ID. LinkedList<String> numbers = new LinkedList<>(); for(Integer rawID : listRawContacts){ Cursor cursorForCallNumbers = null; try { cursorForCallNumbers = context.getContentResolver().query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER}, ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID + " = ?", new String[]{String.valueOf(rawID)}, null ); if(cursorForCallNumbers != null){ while(cursorForCallNumbers.moveToNext()){ numbers.add(cursorForCallNumbers.getString( cursorForCallNumbers.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))); } } }finally { if (cursorForCallNumbers != null) { cursorForCallNumbers.close(); } } } idToCallNumber.put(ID,numbers); } //Build the INSTANCES from name to phone numbers via ID. nameToCallNumbers = new HashMap<>(); for(Integer id : listIDs){ nameToCallNumbers.put(idToName.get(id), idToCallNumber.get(id)); } loaded = true; //invoke the callback if not null. if(onFinishListener != null){ onFinishListener.onFinishLoad(Collections.unmodifiableMap(nameToCallNumbers)); } } } }
下面的例子中,信息加载完毕后会通过Log的方式打印出来:
ContactManager.getService(this, true, new ContactManager.OnFinishLoadListener() { @Override public void onFinishLoad(Map<String, List<String>> nameToCallNumbers) { for(Map.Entry<String, List<String>> entry : nameToCallNumbers.entrySet()){ Log.i("联系人", entry.getKey() + ": " + entry.getValue()); } } });
相关文章推荐
- 利用ContentResolver内容访问者获取手机联系人信息
- android利用ContentResolver访问者获取手机联系人信息
- 利用ContentProvider获取手机中联系人的信息
- 读取手机联系人信息
- 在android中读取联系人信息的程序,包括读取联系人姓名、手机号码和邮箱
- Android笔记--读取手机通讯录获取联系人信息
- Android读取手机联系人信息
- 自定义listview读取手机联系人信息
- 读取手机内联系人信息
- 越狱的 ios 如何 获取 读取 提取 手机上的 短信 通话记录 联系人 等信息
- 读取手机中的联系人信息(android.provider.ContactsContract)
- [android开发]ContentResolver读取手机联系人信息
- 在android中读取联系人信息的程序,包括读取联系人姓名、手机号码和邮箱
- 实现读取手机中所有联系人的主要信息(名称和联系电话),并以ListView显示
- Android项目——读取手机联系人信息
- 读取手机联系人信息
- 利用ContactPicker元件选择手机联系人信息
- Android项目——读取手机联系人信息
- 读取手机联系人信息
- 由系统的内容提供器读取手机联系人信息