1. 程式人生 > >Android 學習筆記 Contacts ContentResolver query、add、update、delete 引數詳解

Android 學習筆記 Contacts ContentResolver query、add、update、delete 引數詳解

1.獲取聯絡人姓名

一個簡單的例子,這個函式獲取裝置上所有的聯絡人ID和聯絡人NAME。

	public void fetchAllContacts() {
		ContentResolver contentResolver = this.getContentResolver();
		Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,
				null, null, null, null);
		cursor.getCount();
		while(cursor.moveToNext()) {
			System.out.println(cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts._ID)));
			System.out.println(cursor.getString(cursor.getColumnIndex(android.provider.ContactsContract.Contacts.DISPLAY_NAME)));
		}
		cursor.close();
	}


執行結果:

  1. 11-0514:13:09.987: I/System.out(4692): 13
  2. 11-0514:13:09.987: I/System.out(4692): 張三  
  3. 11-0514:13:09.987: I/System.out(4692): 31
  4. 11-0514:13:09.987: I/System.out(4692): 李四  

解釋:

  1. ContentResolver contentResolver = this.getContentResolver();  

this在這裡指的是MainActivity,ContentResolver直譯為內容解析器,什麼東東?Android中程式間資料的共享是通過Provider/Resolver進行的。提供資料(內容)的就叫Provider,Resovler提供介面對這個內容進行解讀。

在這裡,系統提供了聯絡人的Provider,那麼我們就需要構建一個Resolver來讀取聯絡人的內容。

  1. Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,  
  2.                 nullnullnullnull);  
根據Android文件,

public final Cursor query (Uri uri, String[] projection,String selection,String[]
 selectionArgs, StringsortOrder)

第一個引數,uri,rui是什麼呢?好吧,上面我們提到了Android提供內容的叫Provider,那麼在Android中怎麼區分各個Provider?有提供聯絡人的,有提供圖片的等等。所以就需要有一個唯一的標識來標識這個Provider,Uri就是這個標識,android.provider.ContactsContract.Contacts.CONTENT_URI就是提供聯絡人的內容提供者,可惜這個內容提供者提供的資料很少。

第二個引數,projection,真不知道為什麼要用這個單詞,這個引數告訴Provider要返回的內容(列Column),比如Contacts Provider提供了聯絡人的ID和聯絡人的NAME等內容,如果我們只需要NAME,那麼我們就應該使用:

  1. Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,  
  2.     new String[]{android.provider.ContactsContract.Contacts.DISPLAY_NAME}, nullnullnull);  
當然,下面列印的你就只能顯示NAME了,因為你返回的結果不包含ID。用null表示返回Provider的所有內容(列Column)。

第三個引數,selection,設定條件,相當於SQL語句中的where。null表示不進行篩選。如果我們只想返回名稱為張三的資料,第三個引數應該設定為:

  1. Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,  
  2.     new String[]{android.provider.ContactsContract.Contacts.DISPLAY_NAME},  
  3.     android.provider.ContactsContract.Contacts.DISPLAY_NAME + "='張三'"nullnull);  
結果:
  1. 11-0515:30:32.188: I/System.out(10271): 張三  
第四個引數,selectionArgs,這個引數是要配合第三個引數使用的,如果你在第三個引數裡面有?,那麼你在selectionArgs寫的資料就會替換掉?,
  1. Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,  
  2.     new String[]{android.provider.ContactsContract.Contacts.DISPLAY_NAME},  
  3.     android.provider.ContactsContract.Contacts.DISPLAY_NAME + "=?",  
  4.                 new String[]{"張三"}, null);  

效果和上面一句的效果一樣。

第五個引數,sortOrder,按照什麼進行排序,相當於SQL語句中的Order by。如果想要結果按照ID的降序排列:

  1. Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,  
  2.                 nullnull,null, android.provider.ContactsContract.Contacts._ID + " DESC");  
結果:
  1. 11-0516:00:32.808: I/System.out(12523): 31
  2. 11-0516:00:32.808: I/System.out(12523): 李四  
  3. 11-0516:00:32.817: I/System.out(12523): 13
  4. 11-0516:00:32.817: I/System.out(12523): 張三  
升序,其實預設排序是升序,+" ASC"寫不寫效果都一樣:
  1. Cursor cursor = contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,  
  2.                 nullnull,null, android.provider.ContactsContract.Contacts._ID + " ASC");  
結果:
  1. 11-0515:59:10.327: I/System.out(12406): 13
  2. 11-0515:59:10.327: I/System.out(12406): 張三  
  3. 11-0515:59:10.327: I/System.out(12406): 31
  4. 11-0515:59:10.327: I/System.out(12406): 李四  

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();
	}

結果:

  1. 11-0614:38:32.049: I/System.out(26534): id=4 name=張三 phoneNumber=1-234-56
  2. 11-0614:38:32.138: I/System.out(26534): id=5 name=李四 phoneNumber=654-321
  3. 11-0614:38:32.138: I/System.out(26534): id=5 name=李四 phoneNumber=987-654-321
  4. 11-0614: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。

2.1 聯絡人 表Contacts

上面這張圖就是表contacts的內容,可以從中看出這張表的資訊,常用的有_id,display_name

  1. contentResolver.query(android.provider.ContactsContract.Contacts.CONTENT_URI,  
  2.                 nullnullnullnull);  

編譯後的內容是這樣的:

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)

省略掉我們不關心的內容,就成了這個:
  1. 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:

  1. contentResolver.query(android.provider.ContactsContract.CommonDataKinds.Phone.CONTENT_URI,   
  2.         nullnullnullnull);