参考:https://developer.android.google.cn/guide/topics/providers/contacts-provider.html
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<