這幾天導師安排我一個任務就是研究一下Android通訊錄獲取聯系人、通話記錄、短信的方法,還有看看不同Android版本之間的異同是否能做到兼容之類的事情。Android通訊錄這一塊,我個人感覺是挺亂的,網上一堆關於查詢本地數據庫獲取聯系人的方法,但似乎都沒有仔細說明數據有哪些重要的表,它們之間有什么聯系。下面是本人查詢資料總結的一下知識點,方便童鞋們以后用到。
Android聯系人數據庫文件(contact2.db)
有研究過手機通訊錄數據的童鞋肯定知道一個數據庫文件:目前是contact2.db(哥的手機是Android4.04的)
在此路徑下可以找到:/data/data/com.android.providers.contacts/databases/contact2.db
將其導入可視化數據庫管理器當中(我這里用的是SQLiteDatabase Browser)

有以上那么多張表,看到頭暈的有木有,我們主要關注一些比較重要的表就行了。
以上我用紅框標志的是比較重要的幾個表:
1、contacts表
該表保存了所有的手機測聯系人,每個聯系人占一行,該表保存了聯系人的ContactID、聯系次數、最后一次聯系的時間、是否含有號碼、是否被添加到收藏夾等信息。
2、raw_contacts表
該表保存了所有創建過的手機測聯系人,每個聯系人占一行,表里有一列標識該聯系人是否被刪除,該表保存了兩個ID: RawContactID和ContactID,從而將contacts表和raw_contacts表聯系起來。該表保存了聯系人的RawContactID、ContactID、聯系次數、最后一次聯系的時間、是否被添加到收藏夾、顯示的名字、用於排序的漢語拼音等信息。
3、 mimetypes 表
該表定義了所有的MimeTypeID,即聯系人的各個字段的唯一標志。

4、data表
? 該表保存了所有創建過的手機測聯系人的所有信息,每個字段占一行 ,該表保存了兩個ID: MimeTypeID和RawContactID,從而將data表和raw_contacts表聯系起來。
? 聯系人的所有信息保存在列data1至data15中,各列中保存的內容根據MimeTypeID的不同而不同。如保存號碼(MimeTypeID=5)的那行數據中,data1列保存號碼,data2列保存號碼類型(手機號碼/家庭號碼/工作號碼等)。

對聯系人的基本操作(增刪改查)
權限設置
讀取聯系人
分為以下步驟:
1、先讀取contacts表,獲取ContactsID;
2、再在raw_contacts表中根據ContactsID獲取RawContactsID;
3、然后就可以在data表中根據RawContactsID獲取該聯系人的各數據了。
private void queryContacts() {
// 獲取用來操作數據的類的對象,對聯系人的基本操作都是使用這個對象
ContentResolver cr = getContentResolver();
// 查詢contacts表的所有記錄
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null,
null, null, null);
// 如果記錄不為空
if (cursor.getCount() > 0) {
// 游標初始指向查詢結果的第一條記錄的上方,執行moveToNext函數會判斷
// 下一條記錄是否存在,如果存在,指向下一條記錄。否則,返回false。
while (cursor.moveToNext()) {
String rawContactId = "";
// 從Contacts表當中取得ContactId
String id = cursor.getString(cursor
.getColumnIndex(ContactsContract.Contacts._ID));
Log.v("contactID", id);
// 獲取RawContacts表的游標
Cursor rawContactCur = cr.query(RawContacts.CONTENT_URI, null,
RawContacts._ID + "=?", new String[] { id }, null);
// 該查詢結果一般只返回一條記錄,所以我們直接讓游標指向第一條記錄
if (rawContactCur.moveToFirst()) {
// 讀取第一條記錄的RawContacts._ID列的值
rawContactId = rawContactCur.getString(rawContactCur
.getColumnIndex(RawContacts._ID));
Log.v("rawContactID", rawContactId);
}
// 關閉游標
rawContactCur.close();
// 讀取號碼
if (Integer
.parseInt(cursor.getString(cursor
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
// 根據查詢RAW_CONTACT_ID查詢該聯系人的號碼
Cursor phoneCur = cr
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID
+ "=?",
new String[] { rawContactId }, null);
// 上面的ContactsContract.CommonDataKinds.Phone.CONTENT_URI
// 可以用下面的phoneUri代替
// Uri
// phoneUri=Uri.parse("content://com.android.contacts/data/phones");
// 一個聯系人可能有多個號碼,需要遍歷
while (phoneCur.moveToNext()) {
// 獲取號碼
String number = phoneCur
.getString(phoneCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.v("number", number);
// 獲取號碼類型
String type = phoneCur
.getString(phoneCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
Log.v("type", type);
}
phoneCur.close();
}
}
cursor.close();
}
}
新建聯系人
新建聯系人時, 根據contacts、raw_ contacts兩張表中ID的使用情況,自動生成ContactID和RawContactID。
Android源碼新建重復姓名的聯系人的ContactID是不重復的,所以會重復顯示。
用下面的代碼新建聯系人,如果多次新建的聯系人的姓名是一樣的,生成的ContactID也會重復, RawContactID不會重復,我們在讀取聯系人的時候可以獲取所有同姓名聯系人的號碼等信息,在顯示聯系人的時候,重復姓名的聯系人的所有字段信息都會合並起來顯示為一個聯系人。
public void addContact(String name, String phoneNum) {
ContentValues values = new ContentValues();
Uri rawContactUri = getContentResolver().insert(
RawContacts.CONTENT_URI, values);
long rawContactId = ContentUris.parseId(rawContactUri);
// 向data表插入數據
if (name != "") {
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
values.put(StructuredName.GIVEN_NAME, name);
getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
values);
}
// 向data表插入電話號碼
if (phoneNum != "") {
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
values.put(Phone.NUMBER, phoneNum);
values.put(Phone.TYPE, Phone.TYPE_MOBILE);
getContentResolver().insert(ContactsContract.Data.CONTENT_URI,
values);
}
}
刪除聯系人
Android幫助文檔:When a raw contact is deleted, all of its Data rows as well asStatusUpdates, AggregationExceptions, PhoneLookup rows are deleted automatically.
所以,要刪除聯系人,我們只需要將raw_contacts表中指定RawContactID的行刪除,其他表中與之關聯的數據都會自動刪除。
// 刪除聯系人
public void deleteContact(long rawContactId) {
getContentResolver().delete(
ContentUris.withAppendedId(RawContacts.CONTENT_URI,
rawContactId), null, null);
}
更新聯系人
聯系人的所有信息都是保存在data表中,所以要更新聯系人,我們只需要根據RawContactID和MIMETYPE修改data表中的內容。
// 更新聯系人
public void updataCotact(long rawContactId) {
ContentValues values = new ContentValues();
values.put(Phone.NUMBER, "13800138000");
values.put(Phone.TYPE, Phone.TYPE_MOBILE);
String where = ContactsContract.Data.RAW_CONTACT_ID + "=? AND "
+ ContactsContract.Data.MIMETYPE + "=?";
String[] selectionArgs = new String[] { String.valueOf(rawContactId),
Phone.CONTENT_ITEM_TYPE };
getContentResolver().update(ContactsContract.Data.CONTENT_URI, values,
where, selectionArgs);
}
