Android15_ContentProvider之ContentResolver
ContentProvider之ContentResolver短信 sms
文件 /data/data/com.android.providers.telephony/databases/mmssms.db
这个数据库有13张表,sms表存了短信信息。
sms表字段
id primary key integer 与words表内的source_id关联
thread_id 会话id,一个联系人的会话一个id,与threads表内的_id关联 integer
address 对方号码 text
person 联系人id integer
date 发件日期 integer
protocol 通信协议,判断是短信还是彩信 integer 0:SMS_RPOTO, 1:MMS_PROTO
read 是否阅读 integer default 0 0:未读, 1:已读
status 状态 integer default-1 -1:接收,
0:complete,
64: pending,
128: failed
type 短信类型 integer 1:inbox
2:sent
3:draft56
4:outbox
5:failed
6:queued
body 内容
service_center 服务中心号码
subject 主题
reply_path_present
locked
error_code
seen
短信常用uri
content://sms/inbox 收件箱content://sms/sent 已发送
content://sms/draft 草稿
content://sms/outbox 发件中
content://sms/failed 失败
content://sms/queued 待发送
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| msg_id | INTEGER | The ID of MM whcich this Address entry belongs to. | Pdu主键关联 |
| contact_id | INTEGER | The ID of contact entry in Phone Book | |
| address | TEXT | The address text | |
| type | INTEGER | Type of address,must be one Of PduHeaders.BCC, PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO. | |
| charset | INTEGER | Character set of entry |
表4.2 android_metadata(语言)
| 字段名 | 类型 | 描述 | 备注 |
| locale | TEXT | 本地采用语言 | 例如:zh_CN |
表4.3 attachments (附件)
| 字段名 | 类型 | 描述 | 备注 |
| sms_id | INTEGER | 短信id | FK,短信表主键 |
| content_url | TEXT | url | |
| offset | INTEGER | 偏移量 |
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| address | TEXT | 发送或接收的电话号码 |
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| _data | TEXT | 处理加密解密的数据 |
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| mid | INTEGER | The identifier of the message which this part belongs to. | Pdu主键关联 |
| seq | INTEGER | The order of the part 所发送Part的顺序 | |
| ct | TEXT | The content type of the part 彩信数据类型 | |
| name | TEXT | The name of the part Part名称 | |
| chset | INTEGER | The charset of the part. 字符集 | |
| cd | TEXT | The content disposition of the part. 内容配置 | |
| fn | TEXT | The file name of the part. 文件名称 | |
| cid | TEXT | The content ID of the part | |
| cl | TEXT | The content location of the part | |
| ctt_s | INTEGER | The start of content-type of the message | |
| ctt_t | TEXT | The type of content-type of the message | |
| _data | TEXT | The location(on filesystem) of the binary data of the part. 数据的位置 如:/data/data/com.providers.telephony/app_parts/PART_1300271462558 | 这个字段基本没什么用,不能直接读取这个文件,读取同样需要通过ContentProvider,URI为”conteng://mms/part” |
| text | TEXT |
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| thread_id | INTEGER | Threads 的PK | FK |
| date | INTEGER | The date the message was sent. 发送日期 | |
| read | INTEGER | Has the message been read 已读为1,未读为0 | |
| m_id | TEXT | The Message-ID of the message. | |
| sub | TEXT | The subject of the message, if present 主题 | |
| sub_cs | INTEGER | The character set of the subject, if present 主题所用字符集 | |
| ct_t | TEXT | The Content-Type of the message | |
| ct_l | TEXT | The Content-Location of the message. | |
| exp | INTEGER | The expiry time of the message. 过期时间 | |
| m_cls | TEXT | The class of the message. | |
| m_type | INTEGER | The type of the message defined by MMS spec | |
| v | INTEGER | The version of specification that this message conform. | |
| m_size | INTEGER | The size of the message 彩信大小 | |
| pri | INTEGER | The priority of the message. | |
| rr | INTEGER | The read-report of the message. | |
| rpt_a | INTEGER | Whether the report is allowed. | |
| resp_st | INTEGER | The response-status of the message. | |
| st | INTEGER | The status of the message. | |
| tr_id | TEXT | The transaction-id of the message. | |
| retr_st | INTEGER | The retrieve-status of the message. | |
| retr_txt | TEXT | The retrieve-text of the message. | |
| retr_txt_cs | INTEGER | The character set of the retrieve-text. | |
| read_status | INTEGER | The read-status of the message. | |
| ct_cls | INTEGER | The content-class of the message. | |
| resp_txt | TEXT | The response-text of the message. | |
| d_tm | INTEGER | The delivery-time of the message. | |
| d_rpt | INTEGER | The delivery-report of the message. | |
| locked | INTEGER | Has the message been locked? | |
| sim_id | INTEGER | ||
| seen | INTEGER | Indicates whether this message has been seen by the user. The "seen" flag will be used to figure out whether we need to throw up a statusbar notification or not. | 有看为1,否则为0 |
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| proto_type | INTEGER | The type of transport protocol(MMS or SMS). | |
| msg_id | INTEGER | The ID of the message to be sent or downloaded. | |
| msg_type | INTEGER | The type of the message to be sent or downloaded. This field is only valid for MM. For SM, its value is always | |
| err_type | INTEGER | The type of the error code. | |
| err_code | INTEGER | The error code of sending/retrieving process. | |
| retry_index | INTEGER | How many times we tried to send or download the message. | |
| due_time | INTEGER | The time to do next retry. | |
| pending_sim_id | INTEGER | ||
| last_try | INTEGER | The time we last tried to send or download the message. |
表4.9 rate(彩信发送时间)
| 字段名 | 类型 | 描述 | 备注 |
| sent_time | INTEGER | When a message was successfully sent. |
表4.10 raw(This table is used by the SMS dispatcher to hold incomplete partial messages until all the parts arrive.)
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| _data | INTEGER | 处理加密解密的数据 | |
| reference_number | INTEGER | one per full message | |
| count | INTEGER | the number of parts | |
| sequence | INTEGER | the part number of this message | |
| destination_port | INTEGER | ||
| address | TEXT | ||
| sim_id | INTEGER | ||
| pdu | TEXT | the raw PDU for this part |
表4.11 sms(短信)
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| thread_id | INTEGER | Threads 的PK | FK 在短信界面里显示在第一组的第一行 |
| address | TEXT | 对方短信号码 | |
| person | INTEGER | 存在电话薄里的名字,不存在的为空 | |
| date | INTEGER | 日期 | |
| protocol | INTEGER | 发送短信为空,收到为0 | |
| read | INTEGER | 已读未读 | 已读为1,未读为0 |
| status | INTEGER | a TP-Status value or -1 if it status hasn't been received | |
| type | INTEGER | 发短信为2,收到短信为1 | |
| reply_path_present | INTEGER | 发短信为空,收到的为0 | |
| subject | TEXT | 主题 | |
| body | TEXT | 短信内容 | |
| service_center | TEXT | 运营商服务电话 | |
| locked | INTEGER | 是否锁掉了。 | 0为未锁,1已锁 |
| sim_id | INTEGER | ||
| error_code | INTEGER | The error code of sending/retrieving process. | |
| seen | INTEGER | Indicates whether this message has been seen by the user. The "seen" flag will be used to figure out whether we need to throw up a statusbar notification or not. | 有看为1,否则为0 |
表4.12 sr_pending(This table is used by the SMS dispatcher to hold pending delivery status
| 字段名 | 类型 | 描述 | 备注 |
| reference_number | INTEGER | ||
| action | TEXT | ||
| data | TEXT |
表4.13 threads(在ConversationList.java中显示的当前短信)
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| date | INTEGER | The date at which the thread was created. 日期 | |
| message_count | INTEGER | The message count of the thread. 短信总条数 | |
| recipient_ids | TEXT | canonical_addresses的主键 | FK |
| snippet | TEXT | The snippet of the latest message in the thread. 在最前面显示的短信 | |
| snippet_cs | INTEGER | The charset of the snippet. | |
| read | INTEGER | Indicates whether all messages of the thread have been read. | 已读为1,未读为0 |
| type | INTEGER | Type of the thread, either Threads.COMMON_THREAD or Threads.BROADCAST_THREAD. | push的短信为0 |
| error | INTEGER | Indicates whether there is a transmission error in the thread. | 有错误为1,没有为0 |
| has_attachment | INTEGER | Indicates whether this thread contains any attachments. | 没有为1,有为0 |
表4.15 words
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER | 如果是短信则与source_id相同;如果为彩信则是: (2<<32)+source_id | |
| index_text | TEXT | 存储的信息内容 | |
| source_id | INTEGER | 如果是短信则表示sms的_id 如果是彩信则表示pdu的_id | |
| table_to_use | INTEGER | 短信为1,彩信为2 |
| 字段名 | 类型 | 描述 | 备注 |
| docid | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| c0_id | INTEGER | 如果是短信则与source_id相同;如果为彩信则是: (2<<32)+ c2source_id | |
| c1index_text | TEXT | 存储的信息内容 | |
| c2source_id | INTEGER | 如果是短信则表示sms的_id 如果是彩信则表示pdu的_id | |
| c3table_to_use | INTEGER | 短信为1,彩信为2 |
| 字段名 | 类型 | 描述 | 备注 |
| level | INTEGER PRIMARY_KEY | 主键ID | |
| idx | INTEGER PRIMARY_KEY | 主键ID | |
| start_block | INTEGER | 开始块 | |
| leaves_end_block | INTEGER | ||
| end_block | INTEGER | 结束块 | |
| root | BLOB |
| 字段名 | 类型 | 描述 | 备注 |
| blockid | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| block | BLOB |
simcontacts.db 中的表相对较少,只有三个:
数据库simcontacts.db中表的定义见表4.19至4.21所示:
表4.19 android_metadata
| 字段名 | 类型 | 描述 | 备注 |
| locale | TEXT | 本地采用语言 | 例如:zh_CN |
表4.20 simPeople
| 字段名 | 类型 | 描述 | 备注 |
| _id | INTEGER PRIMARY_KEY | 主键ID | 系统生成 |
| name | TEXT | ||
| number | TEXT | ||
| simid | INTEGER | ||
| email | TEXT | ||
| pinyin | TEXT | 拼音 |
| 字段名 | 类型 | 描述 | 备注 |
| token | TEXT | ||
| source | INTEGER | 与simPeople的_id进行关联 |
联系人的主要数据存放在raw_contacts和data表里,它两构成主从表关系。
raw_contacts表结构:
data表结构:
每个联系人在raw_contacts里有一条记录,像地址,名称,email,电话等等数据都在data存放在data里,这样设计的好处是易扩展,比如要增加一个联系人的email地址时,只要在data里增加一条记录。
联系人的数据库比较复杂,在联系人相关应用开发中,一般也不直接通过数据库字段来操作,主要用视图(指定的Uri)来操作。
下面说说我在开发工作中用到的一些联系人的数据。
名字:
Uri: Uri.parse("content://com.android.contacts/data")
PREFIX = "data4"; //名称前缀
MID_NAME = "data5";//中间名
GIVEN_NAME = "data2";//名字
FAMILY_NAME = "data3";//姓氏
MID_PINYIN="data8"; //中间名拼音
String FAMILY_NAME_PINYIN="data9"; //姓氏拼音
String SUFIX = "data6"; //名称后缀
String SUFIX_PINYIN="data7"; //名字拼音
电话:
Uri: Uri.parse("content://com.android.contacts/data/phones"
phone: "data1";//号码
Type: "data2";//这个字段是整形值,指示电话类型
类型对应关系如下:
TYPE_CUSTOM = 0;
TYPE_HOME = 1;
TYPE_MOBILE = 2;
TYPE_WORK = 3;
TYPE_FAX_WORK = 4;
TYPE_FAX_HOME = 5;
TYPE_PAGER = 6;
TYPE_OTHER = 7;
Email:
Uri:Uri.parse("content://com.android.contacts/data/emails")
Email: "data1";//邮箱地址
Type: "data2";//这个字段是整形值,指示Email类型
类型对应关系如下:
TYPE_CUSTOM = 0;
TYPE_HOME = 1;
TYPE_WORK = 2;
TYPE_OTHER = 3;
TYPE_MOBILE = 4;
地址:
Uri:Uri.parse("content://com.android.contacts/data/postals")
STREET="data4";//街道
CITY="data8";//城市
STATE="data7";//州
ZIP_CODE="data9";//邮政编码
Type:"data2";//type的类型如下
TYPE_CUSTOM = 0;
TYPE_HOME = 1;
TYPE_WORK = 2;
TYPE_OTHER = 3;
联系人权限设置
<!-- 读联系人权限 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!-- 写联系人权限 -->
<uses-permissionandroid:name="android.permission.WRITE_CONTACTS" />
- Uri insert(Uri uri, ContentValues values) 返回值是Uri,得到Uri中的数据用 ContentUris.parseId
- int delete(Uri uri, String where, String[] whereArgs)
- int update(Uri uri, ContentValues values, String where, String[] whereArgs)
- Cursor query(Uri uri, String[] projection, String where, String[] whereArgs, String sortOrder)最后参数 _id desc 表示按id进行排序
- Uri CONTACTS_URI = ContactsContract.Contacts.CONTENT_URI;
- Uri PHONE_URI = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
- Uri EMAIL_URI = ContactsContract.CommonDataKinds.Email.CONTENT_URI;
(一)、Android系统管理联系人的Uri如下:
- ContactsContract.Contacts.CONTENT_URI 管理联系人的Uri
- ContactsContract.CommonDataKinds.Phone.CONTENT_URI 管理联系人的电话的Uri
- ContactsContract.CommonDataKinds.Email.CONTENT_URI 管理联系人的Email的Uri
- 联系人id字段名称为:ContactsContract.Contacts._ID
- 联系人name 字段为:ContactContract.Contracts.DISPLAY_NAME
- 电话信息表的外键id为:ContactsContract.CommonDataKinds.Phone.CONTACT_ID
- 电话号码 字段为:ContactsContract.CommonDataKinds.Phone.NUMBER.
- Email 字段为:ContactsContract.CommonDataKinds.Email.DATA
- 其外键为:ContactsContract.CommonDataKinds.Email.CONTACT_ID
(二)、Android为多媒体提供的ContentProvider的Uri如下:
- MediaStore.Audio.Media.EXTERNAL_CONTENT_URI 存储在SD卡上的音频文件
- MediaStore.Video.Media.EXTERNAL_CONTENT_URI 存储在 SD卡上的视频
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI 存储在 SD卡上的图片文件内容
- MediaStore.Audio.Media.INTERNAL_CONTENT_URI 手机内部存储器上的音频文件
- MediaStore.Video.Media.INTERNAL_CONTENT_URI 手机内部存储器上的视频
- MediaStore.Images.Media.INTERNAL_CONTENT_URI 手机内部存储器上的图片
【数据库中主要字段:】
- 图片名称字段:Media.DISPLAY_NAME
- 图片的详细描述字段:Media.DESCRIPTION
- 图片的保存位置字段:Media.DATA
(三)、短信Uri:
- content://sms 所有短信
- content://sms/outbox 发送箱中的短信
- content://sms/inbox 收件箱中短信
- 短信手机号码 : address
- 短信标题: subject
- 短信内容:body
- 短信发送时间戳:date
- 短信类型:type 【0:待发信息; 1:接收到信息; 2:发出】
- _id
(四)、通话记录Uri:
- content://call_log/calls 所有通话记录 "_id", "number", "date", "type"
- 首先,URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源。
- URL是uniform resource locator,统一资源定位器,它是一种具体的URI,即URL可以用来标识一个资源,而且还指明了如何locate这个资源。
- URN,uniform resource name,统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com。
publicstatic List<Map<String, Object>> selectContactsMsg(
ContentResolver resolver, ContentValues values) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
String uri_contacts = "content://com.android.contacts/raw_contacts";
String uri_contacts_phones = "content://com.android.contacts/data/phones";
String uri_contacts_emails = "content://com.android.contacts/data/emails";
// 从raw_contacts表中或许联系人的id和联系人的姓名。
Cursor cursor_contacts = resolver.query(Uri.parse(uri_contacts),
new String[] { "_id", "display_name" }, null, null, null);
// 遍历所有的联系人的信息
while (cursor_contacts.moveToNext()) {
int contacts_id = cursor_contacts.getInt(cursor_contacts
.getColumnIndex("_id"));
String display_name = cursor_contacts.getString(cursor_contacts
.getColumnIndex("display_name"));
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", contacts_id);
map.put("display_name", display_name);
// 以下开始获取电话号码
// 根据每个联系人的id再去data表中查找相应的电话号码。
Cursor cursor_phones = resolver.query(
Uri.parse(uri_contacts_phones), new String[] {
"raw_contact_id", "data1" }, "raw_contact_id=?",
new String[] { contacts_id + "" }, null);
// 因为电话号码可能是多个,所以需要再遍历,组合在一起形成一个电话号码的字符串,放到StringBuilder中
StringBuilder sb = new StringBuilder();
while (cursor_phones.moveToNext()) {
sb.append(cursor_phones.getString(1));
sb.append(" | ");
}
// 将生成的电话号码放到map集合中
map.put("phones", sb.toString());
// 以下开始或许Email信息
Cursor cursor_emails = resolver.query(
Uri.parse(uri_contacts_emails), new String[] {
"raw_contact_id", "data1" }, "raw_contact_id=?",
new String[] { contacts_id + "" }, null);
StringBuilder sb2 = new StringBuilder();
while (cursor_emails.moveToNext()) {
sb2.append(cursor_emails.getString(1));
sb2.append(" | ");
}
map.put("emails", sb2.toString());
// 将包含有id、联系人姓名、手机号码、emails的map放到list集合中
list.add(map);
}
return list;
}
// 以下方法是利用常量值所写的插入联系人的方法。如果希望封装成方法,再增加一个Map集合的参数,用来传入信息即可。
publicvoid insertContacts(ContentValues values, ContentResolver resolver) {
// 首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId
Uri rawContactUri = resolver.insert(
ContactsContract.RawContacts.CONTENT_URI, values);
long rawContactId = ContentUris.parseId(rawContactUri);
// 往data表入姓名数据
values.clear();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
values.put(
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
"王向军");
values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
"王向军");
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
// 往data表入电话数据
values.clear();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, "13520551441");
values.put(ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
// 往data表入Email数据
values.clear();
values.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
values.put(ContactsContract.Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Email.DATA,
"237235475@qq.com");
values.put(ContactsContract.CommonDataKinds.Email.TYPE,
ContactsContract.CommonDataKinds.Email.TYPE_WORK);
resolver.insert(ContactsContract.Data.CONTENT_URI, values);
}
publicclass ContactsResolverHelper {
/*
* / 以下代码是插入新联系人的子过程。其中第三个参数:List集合表示要插入到通讯录中的新数据(该集合中有三个值,分别是:姓名、电话、email)。
*/
publicvoid insertContacts(ContentResolver resolver, ContentValues values,
List<String> list) {
String uri_rawcontacts = "content://com.android.contacts/raw_contacts";
String uri_data = "content://com.android.contacts/data";
Uri uri = Uri.parse(uri_contacts);
// 首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId
Uri rawContactUri = resolver.insert(Uri.parse(uri_rawcontacts), values);
long contact_id = ContentUris.parseId(rawContactUri);
// 往data表中插入一条用户的名称信息
values.put("raw_contact_id", contact_id);
values.put("mimetype", "vnd.android.cursor.item/name");
values.put("data1", list.get(0));
values.put("data2", list.get(0));
resolver.insert(uri_data, values);
// 往data表中插入电话信息
values.clear();
values.put("raw_contact_id", contact_id);
values.put("mimetype", "vnd.android.cursor.item/phone_v2");
values.put("data1", list.get(1));
values.put("data2", 2);// 2,Phone.TYPE_MOBILE ,表示手机号码
resolver.insert(uri_data, values);
// 往data表中插入Email信息
values.clear();
values.put("raw_contact_id", contact_id);
values.put("mimetype", "vnd.android.cursor.item/email_v2");
values.put("data1", list.get(2));
values.put("data2", 2);// 2,Email.TYPE_WORK , 表示工作用Email号码
resolver.insert(uri_data, values);
}
// 以下代码是删除联系人信息的方法。
publicstaticint deleteContacts(ContentResolver resolver, String where,
String[] whereArgs) {
String uri_contacts = "content://com.android.contacts/raw_contacts";
return resolver.delete(Uri.parse(uri_contacts), where, whereArgs);
}
// 以下代码是查询联系人信息的方法。
publicstatic Cursor selectContactsName(ContentResolver resolver,
String[] projection, String where, String[] whereArgs,
String sortOrder) {
String uri_contacts = "content://com.android.contacts/raw_contacts";
return resolver.query(Uri.parse(uri_contacts), projection, where,
whereArgs, sortOrder);
}
publicstatic List<Map<String, Object>> selectContactsMsg(
ContentResolver resolver, ContentValues values) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
String uri_contacts = "content://com.android.contacts/raw_contacts";
String uri_contacts_phones = "content://com.android.contacts/data/phones";
String uri_contacts_emails = "content://com.android.contacts/data/emails";
// 从raw_contacts表中或许联系人的id和联系人的姓名。
Cursor cursor_contacts = resolver.query(Uri.parse(uri_contacts),
new String[] { "_id", "display_name" }, null, null, null);
// 遍历所有的联系人的信息
while (cursor_contacts.moveToNext()) {
int contacts_id = cursor_contacts.getInt(cursor_contacts
.getColumnIndex("_id"));
String display_name = cursor_contacts.getString(cursor_contacts
.getColumnIndex("display_name"));
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", contacts_id);
map.put("display_name", display_name);
// 以下开始获取电话号码
// 根据每个联系人的id再去data表中查找相应的电话号码。
Cursor cursor_phones = resolver.query(
Uri.parse(uri_contacts_phones), new String[] {
"raw_contact_id", "data1" }, "raw_contact_id=?",
new String[] { contacts_id + "" }, null);
// 因为电话号码可能是多个,所以需要再遍历,组合在一起形成一个电话号码的字符串,放到StringBuilder中
StringBuilder sb = new StringBuilder();
while (cursor_phones.moveToNext()) {
sb.append(cursor_phones.getString(1));
sb.append(" | ");
}
// 将生成的电话号码放到map集合中
map.put("phones", sb.toString());
// 以下开始或许Email信息
Cursor cursor_emails = resolver.query(
Uri.parse(uri_contacts_emails), new String[] {
"raw_contact_id", "data1" }, "raw_contact_id=?",
new String[] { contacts_id + "" }, null);
StringBuilder sb2 = new StringBuilder();
while (cursor_emails.moveToNext()) {
sb2.append(cursor_emails.getString(1));
sb2.append(" | ");
}
map.put("emails", sb2.toString());
// 将包含有id、联系人姓名、手机号码、emails的map放到list集合中
list.add(map);
}
return list;
}
// 以下代码是更新联系人姓名的方法。
publicstaticint updateContactsName(ContentValues values,
ContentResolver resolver, String oldName, String newName) {
String uri_contacts = "content://com.android.contacts/raw_contacts";
String uri_contacts_data = "content://com.android.contacts/data";
// 先更新raw_contacts表中的联系人姓名,共有四列需要更新
values.put("display_name", newName);
values.put("display_name_alt", newName);
values.put("sort_key", newName);
values.put("sort_key_alt", newName);
int count1 = resolver.update(Uri.parse(uri_contacts), values,
"display_name=?", new String[] { oldName });
// 再更新data表中联系人的姓名,共有两列
values.clear();
values.put("data1", newName);
values.put("data2", newName);
int count2 = resolver.update(Uri.parse(uri_contacts_data), values,
"data1=? and mimetype_id=?", new String[] { oldName, "7" });
// 返回2,则说明六项都被更新。如果只返回1,则说明没有修改完全
return count1 + count2;
}
}

浙公网安备 33010602011771号