一.前言
1.1 Android的电话本的机制.
Android的电话本通过contentProvider封装好的。我们只要通过sdk提供的Uri和字段来对其进行增、删、改、查。
1.2 权限
1.3 找到ContentProvider维护的Sqlist数据库文件( .db)
ContentProvider其实自己管理一个Sqlist数据库文件( .db)。这个文件的路径为/data/data/com.android.providers.contacts/databases/contacts2.db。如图:
1.4 查看ContentProvider维护的Sqlist数据库文件( .db)
在模拟器中的电话本里创建几个联系人,打开1.2中的.db文件,可以用数据库查看工具SQLite Expert Professional打开看下,如图:
从上图,可以看出左边是.db文件的表,点开各表后可以看出主要的表有raw_contacts,contacts,data
二. api
2.1 三张主表.
从api中可以看到android.provider.ContactsContract是sdk2.0的类库,从api和上面的图都可以看出关于电话本主要信息都存在
2.1.1 以上三张表的关联关系.
ContactsContract.Data, ContactsContract.RawContacts, ContactsContract.Contacts 三张表的关联,
ContactsContract.RawContacts表里包含ContactsContract.Contacts的contact_id;ContactsContract.Data表里有ContactsContract.RawContacts的raw_contact_id,和ContactsContract.Contacts的contact_id
2.2 各数据对应的类库,电话本各字段的数据结构
2.2.1 Email对应ContactsContract.CommonDataKinds.Email
Type
Alias
Data column
String
Email address itself. Email数据有三个字段存储:ADDRESS为Email值;TYPE为类型,当为自定义(TYPE_CUSTOM)时,LABEL字段要写入用户自定义的类型;
2.2.2 IM对应 ContactsContract.CommonDataKinds.Im
2.2.3 Phone 对应 ContactsContract.CommonDataKinds.Phone
2.2.4 Postal address 通讯地址 对应 ContactsContract.CommonDataKinds.StructuredPostal
三.代码
3.1根据API写代码.
在api里 ContactsContract.Data 和ContactsContract.RawContacts文档里有关于insert ,update, delete,query的代码,显示出操作各自的表的代码。可以根据这些来完成我们自己的逻辑。
3.2 查询 (查出全部联系人,在只显示姓名)需要如图:
需求分析:由于列表中只需要姓名,所以在查询表时就只查询出姓名信息就好。当点击某个联系人再查出Email,phone等详细信息。
3.2.1 查询联系人总表代码:
说明:由于姓名可以直接在ContactsContract.Contacts表里查到,所以如下
publicstaticfinalString[] PROJECTION_CONTACTS = { Contacts._ID,
Contacts.PHOTO_ID, Contacts.IN_VISIBLE_GROUP,
Contacts.HAS_PHONE_NUMBER, Contacts.DISPLAY_NAME,
Contacts.CUSTOM_RINGTONE };
/**
* wu0wu
*
* 功能:查询所有联系人PROJECTION_CONTACTS信息
*
* */
publicstaticvoid_getContacts(ContentResolver cr) {
Cursor cursorContact = null;
try{
cursorContact = cr.query(ContactsContract.Contacts.CONTENT_URI,
PROJECTION_CONTACTS, Contacts.IN_VISIBLE_GROUP + "=1",
null,null);
Log.e("wu0wu","联系人个数="+ cursorContact.getCount());
int[] indexs = getColumnIndexs(PROJECTION_CONTACTS, cursorContact);
while(cursorContact.moveToNext()) {
Log.e("wu0wu","------------------------------------");
for(inti =0; i
String value = cursorContact.getString(indexs[i]);
Log.e("wu0wu", PROJECTION_CONTACTS[i] +"="+ value);
}
}
} catch(Exception e) {
Log.e("wu0wu", e.toString());
} finally{
if(cursorContact !=null) {
cursorContact.close();
}
}
}
privatestaticint[] getColumnIndexs(String[] projections, Cursor c) {
int[] ret =newint[projections.length];
for(inti =0; i
ret[i] = c.getColumnIndex(projections[i]);
}
returnret;
}
3.2.2 根据contactId查询联系人详细
// phone
privatestaticfinalString[] PROJECTION_PHONENUMBER_CONTACT = {
Phone.NUMBER, Phone.TYPE, Phone.LABEL };
/* DISPLAY_NAME唯一性 */
privatestaticfinalString[] PROJECTION_DISPLAYNAME_CONTACT = { StructuredName.DISPLAY_NAME };
privatestaticfinalString[] PROJECTION_EAMIL_CONTACT = { Email.DATA1,
Email.TYPE, Email.LABEL };
// IM
privatestaticfinalString[] PROJECTION_IM_CONTACT =newString[] {
Im.DATA, Im.TYPE, Im.LABEL, Im.PROTOCOL };
// address
privatestaticfinalString[] PROJECTION_ADDRESS_CONTACT =newString[] {
StructuredPostal.STREET, StructuredPostal.CITY,
StructuredPostal.REGION, StructuredPostal.POSTCODE,
StructuredPostal.COUNTRY, StructuredPostal.TYPE,
StructuredPostal.LABEL, StructuredPostal.POBOX,
StructuredPostal.NEIGHBORHOOD, };
// Organization
privatestaticfinalString[] PROJECTION_ORGANIZATION_CONTACT =newString[] {
Organization.COMPANY, Organization.TYPE, Organization.LABEL,
Organization.TITLE };
// note
privatestaticfinalString[] PROJECTION_NOTES_CONTACT =newString[] { Note.NOTE };
// nickname
privatestaticfinalString[] PROJECTION_NICKNAMES_CONTACT =newString[] {
Nickname.NAME, Nickname.TYPE, Nickname.LABEL };
// website
privatestaticfinalString[] PROJECTION_WEBSITES_CONTACT =newString[] {
Website.URL, Website.TYPE, Website.LABEL };
/**
* 功能:根据contactId查询联系人详细
*
* 在android.provider.ContactsContract.Data表里查询
* */
publicstaticvoid_getContactByContactId(ContentResolver cr,
String contactId) {
Cursor c = null;
c = cr.query(Data.CONTENT_URI, null, Data.CONTACT_ID +"=?",
newString[] { contactId },null);
String mimeType = null;
String[] contentValue = null;
ArrayList displayNameList = newArrayList();// 存显示名
ArrayList phoneList = newArrayList();// 存电话号码,可多个
ArrayList emailList = newArrayList();// 存Email,可多个
ArrayList imList = newArrayList();// 存im,可多个
ArrayList postalList = newArrayList();// 存postal地址,可多个
ArrayList organizationList = newArrayList();// 存organization组织,可多个
ArrayList noteList = newArrayList();// 存note备注
ArrayList nicknameList = newArrayList();// 存Nickname昵称
ArrayList websiteList = newArrayList();// 存Website网站
while(c.moveToNext()) {
// 根据mimeType分类信息
mimeType = c.getString(c.getColumnIndex(Data.MIMETYPE));
if(StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_DISPLAYNAME_CONTACT);
displayNameList.add(contentValue);
} elseif(Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
// 每个contentValue存一类PROJECTION_PHONENUMBER_CONTACT数据
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_PHONENUMBER_CONTACT);
phoneList.add(contentValue);
} elseif(Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_EAMIL_CONTACT);
emailList.add(contentValue);
} elseif(Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_IM_CONTACT);
imList.add(contentValue);
} elseif(StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_ADDRESS_CONTACT);
postalList.add(contentValue);
} elseif(Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_ORGANIZATION_CONTACT);
organizationList.add(contentValue);
} elseif(Note.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_NOTES_CONTACT);
noteList.add(contentValue);
} elseif(Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_NICKNAMES_CONTACT);
nicknameList.add(contentValue);
} elseif(Website.CONTENT_ITEM_TYPE.equals(mimeType)) {
contentValue = MyUtils.getStringInContactCursor(c,
PROJECTION_WEBSITES_CONTACT);
websiteList.add(contentValue);
}
}
c.close();
// log
MyUtils.logContactsDetails("displayName",PROJECTION_DISPLAYNAME_CONTACT, displayNameList);
MyUtils.logContactsDetails("phoneNumber",PROJECTION_PHONENUMBER_CONTACT, phoneList);
MyUtils.logContactsDetails("Email", PROJECTION_EAMIL_CONTACT,emailList);
MyUtils.logContactsDetails("IM", PROJECTION_IM_CONTACT, imList);
MyUtils.logContactsDetails("Address", PROJECTION_ADDRESS_CONTACT,postalList);
MyUtils.logContactsDetails("Organization",PROJECTION_ORGANIZATION_CONTACT, organizationList);
MyUtils.logContactsDetails("Note", PROJECTION_NOTES_CONTACT, noteList);
MyUtils.logContactsDetails("NickName", PROJECTION_NICKNAMES_CONTACT,nicknameList);
MyUtils.logContactsDetails("WebSit", PROJECTION_WEBSITES_CONTACT,websiteList);
}
用到的两个方法:
publicstaticString[] getStringInContactCursor(Cursor c,
String[] projection) {
String[] contentValue = newString[projection.length];
for(inti =0; i
String value = c.getString(c.getColumnIndex(projection[i]));
if(value ==null) {
contentValue[i] = "";
} else{
contentValue[i] = value;
}
}
returncontentValue;
}
publicstaticvoidlogContactsDetails(String title, String[] projection,
ArrayList data) {
Log.e("wu0wu","--------"+ title +"--------");
for(inti =0; i
for(intj =0; j
Log.e("wu0wu", projection[j] +"="+ data.get(i)[j]);
}
}
}
3.3 新建联系人
接口方法:
/**
* 新建联系人的接口
*
* @param String
* accountName,accountType 为账号名账号类型,一般为NULL
* @throws RemoteException
* @throws OperationApplicationException
*/
publicstaticString _insertContact(ContentResolver cr, String accountName,
String accountType, String displayName, ArrayList phone,
ArrayList email, ArrayList im,
ArrayList address, ArrayList organization,
ArrayList notes, ArrayList nickname,
ArrayList website) throwsRemoteException,
OperationApplicationException {
ArrayList ops = newArrayList();
String rawId = "";
longrawContactId = insertRawContact(cr, accountName, accountType);
rawId = Long.toString(rawContactId);
if(displayName !=null) {
insertContactDisplayname(ops, StructuredName.CONTENT_ITEM_TYPE,
rawId, displayName);
}
if(phone !=null) {
for(intj =0; j
String[] item = phone.get(j);
insertItemToContact(ops, Phone.CONTENT_ITEM_TYPE, rawId,
PROJECTION_PHONENUMBER_CONTACT, item);
}
}
if(email !=null) {
for(intj =0; j
String[] item = email.get(j);
insertItemToContact(ops, Email.CONTENT_ITEM_TYPE, rawId,
PROJECTION_EAMIL_CONTACT, item);
}
}
if(im !=null) {
for(intj =0; j
String[] item = im.get(j);
insertItemToContact(ops, Im.CONTENT_ITEM_TYPE, rawId,
PROJECTION_IM_CONTACT, item);
}
}
if(address !=null) {
for(intj =0; j
String[] item = address.get(j);
insertItemToContact(ops, StructuredPostal.CONTENT_ITEM_TYPE,
rawId, PROJECTION_ADDRESS_CONTACT, item);
}
}
if(organization !=null) {
for(intj =0; j
String[] item = organization.get(j);
insertItemToContact(ops, Organization.CONTENT_ITEM_TYPE, rawId,
PROJECTION_ORGANIZATION_CONTACT, item);
}
}
if(notes !=null) {
for(intj =0; j
String[] item = notes.get(j);
insertItemToContact(ops, Note.CONTENT_ITEM_TYPE, rawId,
PROJECTION_NOTES_CONTACT, item);
}
}
if(nickname !=null) {
for(intj =0; j
String[] item = nickname.get(j);
insertItemToContact(ops, Nickname.CONTENT_ITEM_TYPE, rawId,
PROJECTION_NICKNAMES_CONTACT, item);
}
}
if(website !=null) {
for(intj =0; j
String[] item = website.get(j);
insertItemToContact(ops, Website.CONTENT_ITEM_TYPE, rawId,
PROJECTION_WEBSITES_CONTACT, item);
}
}
cr.applyBatch(ContactsContract.AUTHORITY, ops);
returnrawId;
}
/*
* 通过往ROWCONTACT里插入数据,获得rawId
*
* @param cr
*
* @param accountName 一般为NULL
*
* @param accountType 一般为NULL
*
* @return
*/
privatestaticlonginsertRawContact(ContentResolver cr,
String accountName, String accountType) {
ContentValues values = newContentValues();
values.put(RawContacts.ACCOUNT_NAME, accountName);
values.put(RawContacts.ACCOUNT_TYPE, accountType);
// values.put(Contacts.DISPLAY_NAME, displayName);
Uri rawContactUri = cr.insert(RawContacts.CONTENT_URI, values);
longrawContactId = ContentUris.parseId(rawContactUri);
returnrawContactId;
}
privatestaticvoidinsertContactDisplayname(
ArrayList ops, String mimeType,
String rawContactId, String displayName) throwsRemoteException,
OperationApplicationException {
ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI).withValue(
Data.MIMETYPE, mimeType).withValue(Data.RAW_CONTACT_ID,
rawContactId).withValue(StructuredName.DISPLAY_NAME,
displayName).build());
}
privatestaticvoidinsertItemToContact(
ArrayList ops, String mimeType,
String rawContactId, String[] PROJECTION_CONTACT, String[] item)
throwsRemoteException, OperationApplicationException {
// ContentValues values = new ContentValues();
// values.put(Data.RAW_CONTACT_ID, rawContactId);
// values.put(Data.MIMETYPE, mimeType);
// for (int i = 0; i
// values.put(PROJECTION_CONTACT[i], item[i]);
// }
// Uri dataUri = cr.insert(Data.CONTENT_URI, values);
Builder builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
builder.withYieldAllowed(true);
builder.withValue(Data.RAW_CONTACT_ID, rawContactId);
builder.withValue(Data.MIMETYPE, mimeType);
for(inti =0; i
builder.withValue(PROJECTION_CONTACT[i], item[i]);
}
ops.add(builder.build());
}