13.5.2 Android联系人操作

了解了联系人记录的存储框架,再编写联系人相关的应用就更为得心应手了。在实践中,对联系人的操作主要有两类,一类是查询操作,另一类则是写入操作。

联系人数据的查询方式多种多样。如果用户的目标是寻找符合一定条件的联系人,例如姓“王”的朋友、手机号为134××××××××的联系人等,就可以从各个联系人快速索引表中获取数据。

比如,查询特定号码的用户,可以使用android.provider.ContactsContract.PhoneLookup来实现:


//搜索电话为phoneNumber的联系人信息

Uri uri=Uri.withAppendedPath(

PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));

Cursor result=getContentResolver().query(uri,

new String[]{PhoneLookup._ID, PhoneLookup.DISPLAY_NAME},

null,

null,

null);


通过快速索引表,能够获取最基本的联系人信息,如果需要使用更复杂的条件搜索到更丰富的联系人信息,就只能使用ContactsContract.RawContacts类提供的相关接口来进行了,比如,查询特定帐号下收藏的所有联系人,可以如下调用:


//构造查询特定帐号下联系人信息的Uri

Uri uri=RawContacts.URI.buildUpon()

.appendQueryParameter(RawContacts.ACCOUNT_NAME, name)

.appendQueryParameter(RawContacts.ACCOUNT_TYPE, type)

.build();

//搜索已收藏的联系人

Cursor result=getContentResolver().query(uri,

new String[]{RawContacts._ID},

RawContacts.STARRED+"<>0",

null,

null);


如果查询的关注点不在联系人上,而是在具体的联系方式上,那就需要使用android.provider.ContactsContract.Data提供的接口。比如:遍历特定联系人的所有电话号码可以如下实现:


Uri uri=ContactsContract.Data.CONTENT_URI;

Cursor result=getContentResolver().query(uri,

new String[]{Phone.Number},

Data._ID+"=?"+"AND"

+Data.MIMETYPE+"='"+Phone.CONTENT_ITEM_TYPE+"'",

new String[]{String.valueOf(contactId)},

null);


与查询数据相比,写入联系人数据的操作更为循规蹈矩,需要依次添加联系人基本信息、联系人帐号记录,以及联系人的各个联系方式。为了使开发者能够便捷地新建或更新联系人信息,可以使用android.content.ContentProviderOperation对象来封装对联系人的操作。Android可以依次批量处理相关联的一组ContentProvider-Operation对象。

比如,新建一个联系人记录,可以如下实现:


//构造操作集合

ArrayList<ContentProviderOperation>ops=

new ArrayList<ContentProviderOperation>();

//在帐号accountName下,插入一条联系人记录

ops.add(ContentProviderOperation.newInsert(

RawContacts.CONTENT_URI)

.withValue(RawContacts.ACCOUNT_TYPE, accountType)

.withValue(RawContacts.ACCOUNT_NAME, accountName)

.build());

//为该联系人添加基本信息

ops.add(ContentProviderOperation.newInsert(

ContactsContract.Data.CONTENT_URI)

.withValueBackReference(Data.RAW_CONTACT_ID,0)

.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)

.withValue(StructuredName.DISPLAY_NAME,"小明")

.build());

//为该联系人添加电话信息

ops.add(ContentProviderOperation.newInsert(

ContactsContract.Data.CONTENT_URI)

.withValueBackReference(Data.RAW_CONTACT_ID,0)

.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)

.withValue(Phone.NUMBER,"134111111")

.withValue(Phone.TYPE, Phone.TYPE_MOBILE)

.build());

//提交请求,这些请求将依次执行

getContentResolver().applyBatch(

ContactsContract.AUTHORITY, ops);


在构造一条联系人记录时,有一个重要的前提是需要有明确的帐号信息。通过android.accounts.AccountManager可以查询和管理设备上的用户帐号。

注意 联系人操作,是Android中最复杂的一件事务,不只是因为联系人数据源具有复杂的数据存储结构,更是由于联系人数据具有严重的版本兼容问题。不同版本的SDK有着不同的联系人存储方式。本节介绍的内容,仅适合于2.0(Api Level 5)以上版本的SDK,在更老的SDK版本中,需要使用android.provider.Contacts类来进行联系人相关的操作,详情参见SDK。