Android系统中的联系人也是通过ContentProvider来对外提供数据的,我们这里实现获取所有联系人、通过电话号码获取联系人、添加联系人、使用事务添加联系人。
获取所有联系人
1. Android系统中的联系人也是通过ContentProvider来对外提供数据的
2. 数据库路径为:/data/data/com.android.providers.contacts/database/contacts2.db
3. 我们需要关注的有3张表
raw_contacts:其中保存了联系人id
data:和raw_contacts是多对一的关系,保存了联系人的各项数据
mimetypes:为数据类型
4. Provider的authorites为com.android.contacts
5. 查询raw_contacts表的路径为:contacts
6. 查询data表的路径为:contacts/#/data
这个路径为连接查询,要查询“mimetype”字段可以根据“mimetype_id”查询到mimetypes表中的数据
7. 先查询raw_contacts得到每个联系人的id,在使用id从data表中查询对应数据,根据mimetype分类数据
示例:
- //查询所有联系人
- public void testGetAll() {
- ContentResolver resolver = getContext().getContentResolver();
- Uri uri = Uri.parse("content://com.android.contacts/contacts");
- Cursor idCursor = resolver.query(uri, new String[] { "_id" }, null, null, null);
- while (idCursor.moveToNext()) {
- //获取到raw_contacts表中的id
- int id = idCursor.getInt(0);
- //根据获取到的ID查询data表中的数据
- uri = Uri.parse("content://com.android.contacts/contacts/" + id + "/data");
- Cursor dataCursor = resolver.query(uri, new String[] { "data1", "mimetype" }, null, null, null);
- StringBuilder sb = new StringBuilder();
- sb.append("id=" + id);
- //查询联系人表中的
- while (dataCursor.moveToNext()) {
- String data = dataCursor.getString(0);
- String type = dataCursor.getString(1);
- if ("vnd.android.cursor.item/name".equals(type))
- sb.append(", name=" + data);
- else if ("vnd.android.cursor.item/phone_v2".equals(type))
- sb.append(", phone=" + data);
- else if ("vnd.android.cursor.item/email_v2".equals(type))
- sb.append(", email=" + data);
- }
- System.out.println(sb);
- }
- }
通过电话号码获取联系人
1. 系统内部提供了根据电话号码获取data表数据的功能,路径为:data/phones/filter/*
2. 用电话号码替换“*”部分就可以查到所需数据,获取“display_name”可以获取到联系人显示名
示例:
- //根据电话号码查询联系人名称
- public void testGetName() {
- ContentResolver resolver = getContext().getContentResolver();
- Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/1111");
- Cursor c = resolver.query(uri, new String[] { "display_name" }, null, null, null);
- while (c.moveToNext()) {
- System.out.println(c.getString(0));
- }
- }
添加联系人
1. 先向raw_contacts表插入id,路径为:raw_contacts
2. 得到id之后再向data表插入数据,路径为:data
示例:
- //添加联系人
- ublic void testInsert() {
- ContentResolver resolver = getContext().getContentResolver();
- Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
- ContentValues values = new ContentValues();
- // 向raw_contacts插入一条除了ID之外, 其他全部为NULL的记录, ID是自动生成的
- long id = ContentUris.parseId(resolver.insert(uri, values));
- //添加联系人姓名
- uri = Uri.parse("content://com.android.contacts/data");
- values.put("raw_contact_id", id);
- values.put("data2", "FHM");
- values.put("mimetype", "vnd.android.cursor.item/name");
- resolver.insert(uri, values);
- //添加联系人电话
- values.clear(); // 清空上次的数据
- values.put("raw_contact_id", id);
- values.put("data1", "18600000000");
- values.put("data2", "2");
- values.put("mimetype", "vnd.android.cursor.item/phone_v2");
- resolver.insert(uri, values);
- //添加联系人邮箱
- values.clear();
- values.put("raw_contact_id", id);
- values.put("data1", "zxx@itcast.cn");
- values.put("data2", "1");
- values.put("mimetype", "vnd.android.cursor.item/email_v2");
- resolver.insert(uri, values);
使用事务添加联系人
1. 在添加联系人得时候是分多次访问Provider,如果在过程中出现异常,会出现数据不完整的情况,这些操作应该放在一次事务中
2. 使用ContentResolver的applyBatch(String authority,ArrayList<ContentProviderOperation> operations) 方法可以将多个操作在一个事务中执行
3. 文档位置:
file:///F:/android-sdk-windows/docs/reference/android/provider/ContactsContract.RawContacts.html
示例:
- //使用事务添加联系人
- public void testInsertBatch() throws Exception {
- ContentResolver resolver = getContext().getContentResolver();
- ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
- ContentProviderOperation operation1 = ContentProviderOperation //
- .newInsert(Uri.parse("content://com.android.contacts/raw_contacts")) //
- .withValue("_id", null) //
- .build();
- operations.add(operation1);
- ContentProviderOperation operation2 = ContentProviderOperation //
- .newInsert(Uri.parse("content://com.android.contacts/data")) //
- .withValueBackReference("raw_contact_id", 0) //
- .withValue("data2", "ZZH") //
- .withValue("mimetype", "vnd.android.cursor.item/name") //
- .build();
- operations.add(operation2);
- ContentProviderOperation operation3 = ContentProviderOperation //
- .newInsert(Uri.parse("content://com.android.contacts/data")) //
- .withValueBackReference("raw_contact_id", 0) //
- .withValue("data1", "18612312312") //
- .withValue("data2", "2") //
- .withValue("mimetype", "vnd.android.cursor.item/phone_v2") //
- .build();
- operations.add(operation3);
- ContentProviderOperation operation4 = ContentProviderOperation //
- .newInsert(Uri.parse("content://com.android.contacts/data")) //
- .withValueBackReference("raw_contact_id", 0) //
- .withValue("data1", "zq@itcast.cn") //
- .withValue("data2", "2") //
- .withValue("mimetype", "vnd.android.cursor.item/email_v2") //
- .build();
- operations.add(operation4);
- // 在事务中对多个操作批量执行
- resolver.applyBatch("com.android.contacts", operations);
- }
- ContactsContract.RawContacts
-
-
- long _ID read-only Row ID;update rather than to delete and re-insert it.
- long CONTACT_ID read-only ContactsContract.Contacts 中的ID
- int AGGREGATION_MODE read/write 组合模式;值为AGGREGATION_MODE_DEFAULT, AGGREGATION_MODE_DISABLED 或AGGREGATION_MODE_SUSPENDED.
- int DELETED read/write 删除标记;0 or 1;1has been marked for deletion.
- int TIMES_CONTACTED read/write 已经联系次数
- long LAST_TIME_CONTACTED read/write 上次联系的时间戳
- int STARRED read/write 特别友好的联系人;1 if favorite;0 otherwise
- int CUSTOM_RINGTONE read/write 与该记录相关的手机铃声
- int SEND_TO_VOICEMAIL read/write 当这个Raw来电时,是否转发的语言信箱;1是或0否
- String ACCOUNT_NAME read/write-once 账号名
- String ACCOUNT_TYPE read/write-once 账号密码
- int VERSION read-only 版本;当列或相关数据修改是,将会自动修改
- int DIRTY read/write 版本发生改变的标记;同步的 当Raw contact发生改变时,自动设为1(除 URI has the CALLER_IS_SYNCADAPTER外)
-
-
- ContactsContract.Contacts
-
-
- long _ID read-only Row ID.建议用LOOKUP_KEY代替
- String LOOKUP_KEY read-only 与提示如何找到特定联系的值
- long NAME_RAW_CONTACT_ID read-only
- long PNOTO_ID read-only ContactsContract.Data table holding the photo. That row has the mime type CONTENT_ITEM_TYPE.
- String DISPLAY_NAME_PRIMARY read-only 联系人显示的名字
- int IN_VISIBLE_GROUP read-only 这个联系人在UI中是否可见;
- int HAS_PHONE_NUMBER read-only 该联系人否至少有一个手机号码
- int TIMES_CONTACTED read-only 与该联系人联系的次数
- long LAST_TIME_CONTACTED read/write 上次联系的时间戳
- String CUSTOM_RINGTONE read/write 与联系人相关的铃声
- int STARRED read/write 是否是常用联系人
- int SEND_TO_VOICEMAIL read/write
- int CONTACT_PRESENCE read-only Contact IM presence status
- String CONTACT_STATUS read-only Contact's latest status update. Automatically computed as the latest of all constituent raw contacts' status updates.
- long CONTACT_STATUS_TIMESTAMP read-only 插入或修改的最新时间
- String CONTACT_STATUS_RES_PACKAGE read-only The package containing resources for this status: label and icon
- long CONTACT_STATUS_LABEL read-only The resource ID of the label describing the source of contact status, e.g. "Google Talk". This resource is scoped by the CONTACT_STATUS_RES_PACKAGE
- long CONTACT_STATUS_ICON read-only The resource ID of the label describing the source of contact status, e.g. "Google Talk". This resource is scoped by the CONTACT_STATUS_RES_PACKAGE.
-
-
- ContactsContract.Data
-
-
- long _ID read-only Row ID
- String MIMETYPE read/write-once StructuredName.CONTENT_ITEM_TYPE ;Phone.CONTENT_ITEM_TYPE;Email.CONTENT_ITEM_TYPE ;Organization.CONTENT_ITEM_TYPE;Im.CONTENT_ITEM_TYPE ;Nickname.CONTENT_ITEM_TYPE ;Note.CONTENT_ITEM_TYPE;StructuredPostal.CONTENT_ITEM_TYPE;GroupMembership.CONTENT_ITEM_TYPE ;Website.CONTENT_ITEM_TYPE;Event.CONTENT_ITEM_TYPE ;Relation.CONTENT_ITEM_TYPE;
- long RAW_CONTACT_ID read/write The id of the row in the ContactsContract.RawContacts table that this data belongs to.
- int IS_PRIMARY read/write Whether this is the primary entry of its kind for the raw contact it belongs to. "1" if true, "0" if false.
- int IS_SUPER_PRIMARY read/write Whether this is the primary entry of its kind for the aggregate contact it belongs to. Any data record that is "super primary" must also be "primary". For example, the super-primary entry may be interpreted as the default contact value of its kind (for example, the default phone number to use for the contact).
-
-
- ContactsContract.Groups
- long _ID read/write Row ID
- String TITLE read/write The display title of this group
- String NOTE read/write Notes about the group
- int SUMMARY_COUNT read-only The total number of Contacts that have ContactsContract.CommonDataKinds.GroupMembership in this group. Read-only value that is only present when querying CONTENT_SUMMARY_URI.
- int SUMMARY_WITH_PHONES read-only The total number of Contacts that have both ContactsContract.CommonDataKinds.GroupMembership in this group, and also have phone numbers. Read-only value that is only present when querying CONTENT_SUMMARY_URI.
- int GROUP_VISIBLE read-only 群组是否在数据库中可见1 or 0
- int DELETED read/write 删除标记 0,default;1 if the row has been marked for deletion
- int SHOULD_SYNC read/write Whether this group should be synced if the SYNC_EVERYTHING settings is false for this group's account.
java代码:
删除联系人
java代码:
更新联系人信息
java代码:
更新电话号码
java代码:
添加联系人
java代码: