利用Contacts Provider读取手机联系人信息
參考:https://developer.android.google.cn/guide/topics/providers/contacts-provider.html
Contacts Provider組織結(jié)構(gòu)
Contacts Provider組織結(jié)構(gòu)由三部分構(gòu)成,如下圖所示:
- (聯(lián)系人)Contact:代表聯(lián)系人,包含了多種聯(lián)系渠道。
- (原始聯(lián)系人)RawContact:每個(gè)原始聯(lián)系人代表某個(gè)聯(lián)系人的一種具體的聯(lián)系渠道,比如E-mail、手機(jī)通訊錄、推特等等。
- (數(shù)據(jù))Data:儲(chǔ)存大多數(shù)實(shí)際的信息,比如手機(jī)號(hào)碼、郵箱地址等等。
舉例說明:假設(shè)手機(jī)用戶為A,它有一個(gè)聯(lián)系人B。A與B通過電子郵件、電話、推特三種渠道產(chǎn)生過聯(lián)系,那么聯(lián)系人B就對(duì)應(yīng)三個(gè)原始聯(lián)系人B,每個(gè)原始聯(lián)系人B中會(huì)記錄一種聯(lián)系渠道(A使用的聯(lián)系賬戶、賬戶類型),而具體的信息(手機(jī)號(hào)碼、郵箱地址)會(huì)存放在數(shù)據(jù)表中。
Contact表、RawContact表、Data表之間的聯(lián)系
Contact、RawContact、Data分別對(duì)應(yīng)三張數(shù)據(jù)庫表,三張表都有一個(gè)_ID字段作為主鍵。在此基礎(chǔ)上,RawContact表有一個(gè)CONTACT_ID列,代表這個(gè)原始聯(lián)系人對(duì)應(yīng)的聯(lián)系人的_ID;Data表有一個(gè)Raw_CONTACT_ID列,代表這個(gè)數(shù)據(jù)行對(duì)應(yīng)的原始聯(lián)系人的_ID。
因此,查詢某個(gè)聯(lián)系人的某項(xiàng)信息的一般步驟為:
實(shí)例:獲取手機(jī)通訊錄中所有聯(lián)系人對(duì)應(yīng)的手機(jī)號(hào)碼
下面是一個(gè)用于加載聯(lián)系人手機(jī)號(hào)碼信息的ContactManager類,具有以下功能:
- 判斷應(yīng)用是否具有讀取手機(jī)通訊錄的權(quán)限android.permission.READ_CONTACTS。
- 可以在創(chuàng)建對(duì)象時(shí)即開始加載,也可以在需要時(shí)再加載。
- 在子線程中執(zhí)行查詢,不會(huì)阻塞UI線程。
- 加載結(jié)束后通過一個(gè)UnmodifiableMap返回聯(lián)系人姓名到電話號(hào)碼的映射。
- 支持設(shè)置加載完畢后執(zhí)行的回調(diào)。
使用方法:通過靜態(tài)方法getService()獲取ContactManager實(shí)例,并設(shè)置是否需要立即開始加載、監(jiān)聽器等附加信息。
import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.provider.ContactsContract; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.util.SparseArray;import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map;/*** Created by swt369 on 2017/10/1.* Provide a simple way for managing contacts*/public class ContactManager {private static final Map<Context,ContactManager> INSTANCES = new HashMap<>();private final Context context;private OnFinishLoadListener onFinishListener;private boolean loaded = false;private Map<String,List<String>> nameToCallNumbers = null;private ContactManager(Context context, boolean loadAtOnce, @Nullable OnFinishLoadListener onFinishListener){this.context = context;this.onFinishListener = onFinishListener;if(loadAtOnce){load();}}/**** @param context The context the Manager is running in* @param loadAtOnce True if needed to load at once* @param onFinishListener the callback that will be invoked when the loading is over * @return A instance of the ContactManager* @throws SecurityException When the application failed to get the android.permission.READ_CONTACTS*/public static ContactManager getService(Context context, boolean loadAtOnce, @Nullable OnFinishLoadListener onFinishListener)throws SecurityException{int granted = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS);if(granted != PackageManager.PERMISSION_GRANTED){throw new SecurityException("Need READ_CONTACTS permission");}ContactManager contactManager = INSTANCES.get(context);if(contactManager == null){contactManager = new ContactManager(context,loadAtOnce,onFinishListener);INSTANCES.put(context,contactManager);}return contactManager;}public void setOnFinishListener(OnFinishLoadListener onFinishListener){this.onFinishListener = onFinishListener;}public void load(){if(!loaded){new LoadThread().start();}else{onFinishListener.onFinishLoad(Collections.unmodifiableMap(nameToCallNumbers));}}public interface OnFinishLoadListener{void onFinishLoad(Map<String, List<String>> nameToCallNumbers);}private class LoadThread extends Thread{@Overridepublic void run() {List<Integer> listIDs = new LinkedList<>();SparseArray<String> idToName = new SparseArray<>();SparseArray<List<String>> idToCallNumber = new SparseArray<>();//Get all the _IDs and names in the table ContactCursor cursorForContactID = null;try {cursorForContactID = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME},null,null,null);if(cursorForContactID != null){int indexID = cursorForContactID.getColumnIndex(ContactsContract.Contacts._ID);int indexName = cursorForContactID.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);//build the INSTANCES from ID to name.while(cursorForContactID.moveToNext()){int id = cursorForContactID.getInt(indexID);listIDs.add(id);idToName.put(id, cursorForContactID.getString(indexName));}}}finally {if (cursorForContactID != null) {cursorForContactID.close();}}//Get all the _IDs in the table RawContact,which is equal to the raw_contact_IDs in the table Data.for(Integer ID : listIDs){LinkedList<Integer> listRawContacts = new LinkedList<>();Cursor cursorForRawContactID = null;try {cursorForRawContactID = context.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI,new String[]{ContactsContract.RawContacts._ID},ContactsContract.RawContacts.CONTACT_ID + " = ?",new String[]{String.valueOf(ID)},null);if(cursorForRawContactID == null){continue;}//build the INSTANCES from ID to raw_contact_ID.while (cursorForRawContactID.moveToNext()){listRawContacts.add(cursorForRawContactID.getInt(cursorForRawContactID.getColumnIndex(ContactsContract.RawContacts._ID)));}}finally {if (cursorForRawContactID != null) {cursorForRawContactID.close();}}//Build the INSTANCES from ID to phone numbers via raw_contact_ID.LinkedList<String> numbers = new LinkedList<>();for(Integer rawID : listRawContacts){Cursor cursorForCallNumbers = null;try {cursorForCallNumbers = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID + " = ?",new String[]{String.valueOf(rawID)},null);if(cursorForCallNumbers != null){while(cursorForCallNumbers.moveToNext()){numbers.add(cursorForCallNumbers.getString(cursorForCallNumbers.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));}}}finally {if (cursorForCallNumbers != null) {cursorForCallNumbers.close();}}}idToCallNumber.put(ID,numbers);}//Build the INSTANCES from name to phone numbers via ID.nameToCallNumbers = new HashMap<>();for(Integer id : listIDs){nameToCallNumbers.put(idToName.get(id), idToCallNumber.get(id));}loaded = true;//invoke the callback if not null.if(onFinishListener != null){onFinishListener.onFinishLoad(Collections.unmodifiableMap(nameToCallNumbers));}}} }下面的例子中,信息加載完畢后會(huì)通過Log的方式打印出來:
ContactManager.getService(this, true, new ContactManager.OnFinishLoadListener() {@Overridepublic void onFinishLoad(Map<String, List<String>> nameToCallNumbers) {for(Map.Entry<String, List<String>> entry : nameToCallNumbers.entrySet()){Log.i("聯(lián)系人", entry.getKey() + ": " + entry.getValue());}} });總結(jié)
以上是生活随笔為你收集整理的利用Contacts Provider读取手机联系人信息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP100视频解压密码以及目录
- 下一篇: [AHK]--显示器输入源快速切换