1.获取联系人详细信息

在(一)中我们只是获取了联系人的ID和NAME,但是这是远远不够的,怎么样获取其他的值呢?

	public void fetchContactInformation() {
		String id,name,phoneNumber,email;
		ContentResolver contentResolver = this.getContentResolver();
		Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,
				null, null, null, null);
		while(cursor.moveToNext()) {
			id=cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID));
			name=cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME));
			
			//Fetch Phone Number
			Cursor phoneCursor = contentResolver.query(
					android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
					null, android.provider.ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+id, null, null);
			while(phoneCursor.moveToNext()) {
				phoneNumber = phoneCursor.getString(
						phoneCursor.getColumnIndex(android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER));
				System.out.println("id="+id+" name="+name+" phoneNumber="+phoneNumber);
			}
			phoneCursor.close();
			
			//Fetch email
			Cursor emailCursor = contentResolver.query(
					android.provider.ContactsContract.CommonDataKinds.Email.CONTENT_URI, 
					null, android.provider.ContactsContract.CommonDataKinds.Email.CONTACT_ID+"="+id, null, null);
			while(emailCursor.moveToNext()) {
				email = emailCursor.getString(
						emailCursor.getColumnIndex(android.provider.ContactsContract.CommonDataKinds.Email.DATA));
				System.out.println("id="+id+" name="+name+" email="+email);
			}
			emailCursor.close();
		}
		cursor.close();
	}


结果:

11-06 14:38:32.049: I/System.out(26534): id=4 name=张三 phoneNumber=1-234-56
11-06 14:38:32.138: I/System.out(26534): id=5 name=李四 phoneNumber=654-321
11-06 14:38:32.138: I/System.out(26534): id=5 name=李四 phoneNumber=987-654-321
11-06 14:38:32.188: I/System.out(26534): id=5 name=李四 email=wssiqi@126.com
在这里,我们通过

android.provider.ContactsContract.Contacts.CONTENT_URI 来获取联系人的ID和NAME

android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI 获取联系人的电话号码

android.provider.ContactsContract.CommonDataKinds.Email.CONTENT_URI 获取联系人的邮箱地址

关键是ContactsContract下面有很多类,很不容易找到到底哪个类包含我们需要的内容。怎样通过比较简单的方法获取所有信息呢?

为了更好的解决这个问题,我们需要先分析联系人的信息是怎样存储在Android上的。


2.Android 联系人存储方式

Android是将联系人信息存储在Sqlite数据库中的,如果想知道Sqlite的详细信息,请百度或者Google。

如何查看Sqlite中Contacts数据库,请参考http://www.cnblogs.com/luxiaofeng54/archive/2011/03/15/1985183.html,我也是从这里了解的。

2.1 联系人 表Contacts

上面这张图就是表contacts的内容,可以从中看出这张表的信息,常用的有_id,display_name

contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,
				null, null, null, null);

编译后的内容是这样的:

SELECT times_contacted, contacts_status_updates.status AS contact_status, custom_ringtone, has_phone_number, contacts_status_updates.status_label AS contact_status_label, lookup, contacts_status_updates.status_icon AS contact_status_icon, last_time_contacted, display_name, in_visible_group, _id, starred, agg_presence.mode AS contact_presence, contacts_status_updates.status_res_package AS contact_status_res_package, contacts_status_updates.status_ts AS contact_status_ts, photo_id, send_to_voicemail FROM view_contacts_restricted LEFT OUTER JOIN agg_presence ON (_id = presence_contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id)
省略掉我们不关心的内容,就成了这个:

SELECT * FROM view_contacts_restricted
view_contacts_restricted是一个视图,你可以把它当作一个表,view_contacts_restricted的主要内容来自于表contacts,所以我们只能从android.provider.ContactsContract.Contacts.CONTENT_URI获取到ID和DisplayName,要获取到其他信息,就需要从data表获取。

2.2 联系人 表data

这个表就是存储联系人相关信息的表。mimetype表如下:


获取Phone Number的URI:

contentResolver.query(android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
		null, null, null, null);

编译后的内容:

SELECT data_version, contact_id, lookup, data12, data11, data10, mimetype, data15, data14, data13, data_sync1, data_sync3, data_sync2, data_sync4, account_type, custom_ringtone, status_updates.status AS status, data1, data4, data5, data2, data3, data8, data9, group_sourceid, data6, account_name, data7, display_name, in_visible_group, contacts_status_updates.status_res_package AS contact_status_res_package, is_primary, contacts_status_updates.status_ts AS contact_status_ts, raw_contact_id, times_contacted, contacts_status_updates.status AS contact_status, status_updates.status_res_package AS status_res_package, status_updates.status_icon AS status_icon, contacts_status_updates.status_icon AS contact_status_icon, presence.mode AS mode, version, last_time_contacted, res_package, _id, status_updates.status_ts AS status_ts, dirty, is_super_primary, photo_id, send_to_voicemail, contacts_status_updates.status_label AS contact_status_label, status_updates.status_label AS status_label, starred, agg_presence.mode AS contact_presence, sourceid FROM view_data_restricted data LEFT OUTER JOIN agg_presence ON (agg_presence.presence_contact_id=contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) LEFT OUTER JOIN presence ON (presence_data_id=data._id) LEFT OUTER JOIN status_updates ON (status_updates.status_update_data_id=data._id) WHERE (1 AND mimetype = 'vnd.android.cursor.item/phone_v2')
主要的信息为:

SELECT * FROM view_data_restricted where mimetype = 'vnd.android.cursor.item/phone_v2'


获取Email的URI:

contentResolver.query(android.provider.ContactsContract.CommonDataKinds.Email.CONTENT_URI, 
		null, null, null, null);

编译后的内容:

SELECT data_version, contact_id, lookup, data12, data11, data10, mimetype, data15, data14, data13, data_sync1, data_sync3, data_sync2, data_sync4, account_type, custom_ringtone, status_updates.status AS status, data1, data4, data5, data2, data3, data8, data9, group_sourceid, data6, account_name, data7, display_name, in_visible_group, contacts_status_updates.status_res_package AS contact_status_res_package, is_primary, contacts_status_updates.status_ts AS contact_status_ts, raw_contact_id, times_contacted, contacts_status_updates.status AS contact_status, status_updates.status_res_package AS status_res_package, status_updates.status_icon AS status_icon, contacts_status_updates.status_icon AS contact_status_icon, presence.mode AS mode, version, last_time_contacted, res_package, _id, status_updates.status_ts AS status_ts, dirty, is_super_primary, photo_id, send_to_voicemail, contacts_status_updates.status_label AS contact_status_label, status_updates.status_label AS status_label, starred, agg_presence.mode AS contact_presence, sourceid FROM view_data_restricted data LEFT OUTER JOIN agg_presence ON (agg_presence.presence_contact_id=contact_id) LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) LEFT OUTER JOIN presence ON (presence_data_id=data._id) LEFT OUTER JOIN status_updates ON (status_updates.status_update_data_id=data._id) WHERE (1 AND mimetype = 'vnd.android.cursor.item/email_v2')
主要的信息为:
SELECT * FROM view_data_restricted where mimetype = 'vnd.android.cursor.item/email_v2'

可以看出,Phone number和Email的获取都是从同一张表获取的。 唯一的区别是 mimetype的类型不同。

view_data_restricted的主要内容来自于表data。
从表data可以看出,name,phone number,email存储的方式是一样的,都是data1,后面的data是更详细的信息,区分name,phone number,email 的唯一方式是mimetype_id,区分联系人的唯一标识是raw_contact_id,这个值是从上面的表contacts的_id获取的。


经过以上分析,我们可以知道,要想获取联系人的所有信息,需要先通过contacts表获取联系人ID,然后根据联系人的ID在表data获取想要的内容。

下面我们通过一个URI获取联系人的所有信息:

	public void fetchContactInformationV2() {
		String id;
		String mimetype;
		ContentResolver contentResolver = this.getContentResolver();
		//只需要从Contacts中获取ID,其他的都可以不要,通过查看上面编译后的SQL语句,可以看出将第二个参数
		//设置成null,默认返回的列非常多,是一种资源浪费。
		Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,
				new String[]{android.provider.ContactsContract.Contacts._ID}, null, null, null);
		while(cursor.moveToNext()) {
			id=cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID));
			
			//从一个Cursor获取所有的信息
			Cursor contactInfoCursor = contentResolver.query(
					android.provider.ContactsContract.Data.CONTENT_URI,
					new String[]{android.provider.ContactsContract.Data.CONTACT_ID,
							android.provider.ContactsContract.Data.MIMETYPE,
							android.provider.ContactsContract.Data.DATA1
							}, 
					android.provider.ContactsContract.Data.CONTACT_ID+"="+id, null, null);
			while(contactInfoCursor.moveToNext()) {
				mimetype = contactInfoCursor.getString(
						contactInfoCursor.getColumnIndex(android.provider.ContactsContract.Data.MIMETYPE));
				String value = contactInfoCursor.getString(
						contactInfoCursor.getColumnIndex(android.provider.ContactsContract.Data.DATA1));
				if(mimetype.contains("/name")){
					System.out.println("姓名="+value);
				} else if(mimetype.contains("/im")){
					System.out.println("聊天(QQ)账号="+value);
				} else if(mimetype.contains("/email")) {
					System.out.println("邮箱="+value);
				} else if(mimetype.contains("/phone")) {
					System.out.println("电话="+value);
				} else if(mimetype.contains("/postal")) {
					System.out.println("邮编="+value);
				} else if(mimetype.contains("/photo")) {
					System.out.println("照片="+value);
				} else if(mimetype.contains("/group")) {
					System.out.println("组="+value);
				} 
			}
			System.out.println("*********");
			contactInfoCursor.close();
		}
		cursor.close();
	}
结果:

11-06 17:16:59.068: I/System.out(3737): 电话=1-234-56
11-06 17:16:59.068: I/System.out(3737): 姓名=张三
11-06 17:16:59.068: I/System.out(3737): *********
11-06 17:16:59.108: I/System.out(3737): 电话=654-321
11-06 17:16:59.108: I/System.out(3737): 姓名=李四
11-06 17:16:59.108: I/System.out(3737): 电话=987-654-321
11-06 17:16:59.108: I/System.out(3737): 聊天(QQ)账号=123456
11-06 17:16:59.108: I/System.out(3737): 邮箱=wssiqi@126.com
11-06 17:16:59.108: I/System.out(3737): *********



Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐