一.前言
1.1 Android的电话本的机制.
Android的电话本通过contentProvider封装好的。我们只要通过sdk提供的Uri和字段来对其进行增、删、改、查。
1.2 权限
- <uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission>
- <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
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打开看下,如图:
二. api
从上图,可以看出左边是.db文件的表,点开各表后可以看出主要的表有raw_contacts,contacts,data
2.1 三张主表.
从api中可以看到android.provider.ContactsContract是sdk2.0的类库,从api和上面的图都可以看出关于电话本主要信息都存在
ContactsContract.Data,
ContactsContract.RawContacts,
ContactsContract.Contacts
三张表里
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
Email数据有三个字段存储:ADDRESS为Email值;TYPE为类型,当为自定义(TYPE_CUSTOM)时,LABEL字段要写入用户自定义的类型;
Type Alias Data column String ADDRESS
DATA1
Email address itself. int TYPE
DATA2
Allowed values are:
TYPE_CUSTOM
. Put the actual type inLABEL
.TYPE_HOME
TYPE_WORK
TYPE_OTHER
TYPE_MOBILE
String LABEL
DATA3
2.2.2 IM 对应 ContactsContract.CommonDataKinds.Im
Im有5个字段
Type Alias Data column String DATA
DATA1
int TYPE
DATA2
Allowed values are:
TYPE_CUSTOM
. Put the actual type inLABEL
.TYPE_HOME
TYPE_WORK
TYPE_OTHER
String LABEL
DATA3
String PROTOCOL
DATA5
Allowed values:
PROTOCOL_CUSTOM
. Also provide the actual protocol name asCUSTOM_PROTOCOL
.PROTOCOL_AIM
PROTOCOL_MSN
PROTOCOL_YAHOO
PROTOCOL_SKYPE
PROTOCOL_QQ
PROTOCOL_GOOGLE_TALK
PROTOCOL_ICQ
PROTOCOL_JABBER
PROTOCOL_NETMEETING
String CUSTOM_PROTOCOL
DATA6
2.2.3 Phone 对应 ContactsContract.CommonDataKinds.Phone
2.2.4 Postal address 通讯地址 对应 ContactsContract.CommonDataKinds.StructuredPostal
Type Alias Data column String NUMBER
DATA1
int TYPE
DATA2
Allowed values are:
TYPE_CUSTOM
. Put the actual type inLABEL
.TYPE_HOME
TYPE_MOBILE
TYPE_WORK
TYPE_FAX_WORK
TYPE_FAX_HOME
TYPE_PAGER
TYPE_OTHER
TYPE_CALLBACK
TYPE_CAR
TYPE_COMPANY_MAIN
TYPE_ISDN
TYPE_MAIN
TYPE_OTHER_FAX
TYPE_RADIO
TYPE_TELEX
TYPE_TTY_TDD
TYPE_WORK_MOBILE
TYPE_WORK_PAGER
TYPE_ASSISTANT
TYPE_MMS
String LABEL
DATA3
最长用的有 TYPE:类型;STREET:街道;CITY:市;REGION:省;POSTCODE:邮政编码;
Type Alias Data column String FORMATTED_ADDRESS
DATA1
int TYPE
DATA2
Allowed values are:
TYPE_CUSTOM
. Put the actual type inLABEL
.TYPE_HOME
TYPE_WORK
TYPE_OTHER
String LABEL
DATA3
String STREET
DATA4
String POBOX
DATA5
Post Office Box number String NEIGHBORHOOD
DATA6
String CITY
DATA7
String REGION
DATA8
String POSTCODE
DATA9
String COUNTRY
DATA10
三.代码
3.1根据API写代码.
在api里 ContactsContract.Data 和ContactsContract.RawContacts文档里有关于insert ,update, delete,query的代码,显示出操作各自的表的代码。可以根据这些来完成我们自己的逻辑。
3.2 查询 (查出全部联系人,在只显示姓名)需要如图:
需求分析:由于列表中只需要姓名,所以在查询表时就只查询出姓名信息就好。当点击某个联系人再查出Email,phone等详细信息。
3.2.1 查询联系人总表代码:
说明:由于姓名可以直接在ContactsContract.Contacts表里查到,所以如下
- public static final String[] PROJECTION_CONTACTS = { Contacts._ID,
- Contacts.PHOTO_ID, Contacts.IN_VISIBLE_GROUP,
- Contacts.HAS_PHONE_NUMBER, Contacts.DISPLAY_NAME,
- Contacts.CUSTOM_RINGTONE };
- /**
- * wu0wu
- *
- * 功能:查询所有联系人PROJECTION_CONTACTS信息
- *
- * */
- public static void _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 (int i = 0; i < PROJECTION_CONTACTS.length; 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();
- }
- }
- }
- private static int[] getColumnIndexs(String[] projections, Cursor c) {
- int[] ret = new int[projections.length];
- for (int i = 0; i < projections.length; i++) {
- ret[i] = c.getColumnIndex(projections[i]);
- }
- return ret;
- }
3.2.2 根据contactId查询联系人详细
- // phone
- private static final String[] PROJECTION_PHONENUMBER_CONTACT = {
- Phone.NUMBER, Phone.TYPE, Phone.LABEL };
- /* DISPLAY_NAME唯一性 */
- private static final String[] PROJECTION_DISPLAYNAME_CONTACT = { StructuredName.DISPLAY_NAME };
- private static final String[] PROJECTION_EAMIL_CONTACT = { Email.DATA1,
- Email.TYPE, Email.LABEL };
- // IM
- private static final String[] PROJECTION_IM_CONTACT = new String[] {
- Im.DATA, Im.TYPE, Im.LABEL, Im.PROTOCOL };
- // address
- private static final String[] PROJECTION_ADDRESS_CONTACT = new String[] {
- StructuredPostal.STREET, StructuredPostal.CITY,
- StructuredPostal.REGION, StructuredPostal.POSTCODE,
- StructuredPostal.COUNTRY, StructuredPostal.TYPE,
- StructuredPostal.LABEL, StructuredPostal.POBOX,
- StructuredPostal.NEIGHBORHOOD, };
- // Organization
- private static final String[] PROJECTION_ORGANIZATION_CONTACT = new String[] {
- Organization.COMPANY, Organization.TYPE, Organization.LABEL,
- Organization.TITLE };
- // note
- private static final String[] PROJECTION_NOTES_CONTACT = new String[] { Note.NOTE };
- // nickname
- private static final String[] PROJECTION_NICKNAMES_CONTACT = new String[] {
- Nickname.NAME, Nickname.TYPE, Nickname.LABEL };
- // website
- private static final String[] PROJECTION_WEBSITES_CONTACT = new String[] {
- Website.URL, Website.TYPE, Website.LABEL };
- /**
- * 功能:根据contactId查询联系人详细
- *
- * 在android.provider.ContactsContract.Data表里查询
- * */
- public static void _getContactByContactId(ContentResolver cr,
- String contactId) {
- Cursor c = null;
- c = cr.query(Data.CONTENT_URI, null, Data.CONTACT_ID + "=?",
- new String[] { contactId }, null);
- String mimeType = null;
- String[] contentValue = null;
- ArrayList<String[]> displayNameList = new ArrayList<String[]>();// 存显示名
- ArrayList<String[]> phoneList = new ArrayList<String[]>();// 存电话号码,可多个
- ArrayList<String[]> emailList = new ArrayList<String[]>();// 存Email,可多个
- ArrayList<String[]> imList = new ArrayList<String[]>();// 存im,可多个
- ArrayList<String[]> postalList = new ArrayList<String[]>();// 存postal地址,可多个
- ArrayList<String[]> organizationList = new ArrayList<String[]>();// 存organization组织,可多个
- ArrayList<String[]> noteList = new ArrayList<String[]>();// 存note备注
- ArrayList<String[]> nicknameList = new ArrayList<String[]>();// 存Nickname昵称
- ArrayList<String[]> websiteList = new ArrayList<String[]>();// 存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);
- } else if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
- // 每个contentValue存一类PROJECTION_PHONENUMBER_CONTACT数据
- contentValue = MyUtils.getStringInContactCursor(c,
- PROJECTION_PHONENUMBER_CONTACT);
- phoneList.add(contentValue);
- } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
- contentValue = MyUtils.getStringInContactCursor(c,
- PROJECTION_EAMIL_CONTACT);
- emailList.add(contentValue);
- } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
- contentValue = MyUtils.getStringInContactCursor(c,
- PROJECTION_IM_CONTACT);
- imList.add(contentValue);
- } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
- contentValue = MyUtils.getStringInContactCursor(c,
- PROJECTION_ADDRESS_CONTACT);
- postalList.add(contentValue);
- } else if (Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {
- contentValue = MyUtils.getStringInContactCursor(c,
- PROJECTION_ORGANIZATION_CONTACT);
- organizationList.add(contentValue);
- } else if (Note.CONTENT_ITEM_TYPE.equals(mimeType)) {
- contentValue = MyUtils.getStringInContactCursor(c,
- PROJECTION_NOTES_CONTACT);
- noteList.add(contentValue);
- } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {
- contentValue = MyUtils.getStringInContactCursor(c,
- PROJECTION_NICKNAMES_CONTACT);
- nicknameList.add(contentValue);
- } else if (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);
- }
用到的两个方法:
- public static String[] getStringInContactCursor(Cursor c,
- String[] projection) {
- String[] contentValue = new String[projection.length];
- for (int i = 0; i < contentValue.length; i++) {
- String value = c.getString(c.getColumnIndex(projection[i]));
- if (value == null) {
- contentValue[i] = "";
- } else {
- contentValue[i] = value;
- }
- }
- return contentValue;
- }
- public static void logContactsDetails(String title, String[] projection,
- ArrayList<String[]> data) {
- Log.e("wu0wu", "--------" + title + "--------");
- for (int i = 0; i < data.size(); i++) {
- for (int j = 0; j < data.get(i).length; j++) {
- Log.e("wu0wu", projection[j] + "=" + data.get(i)[j]);
- }
- }
- }
3.3 新建联系人
接口方法:
- /**
- * 新建联系人的接口
- *
- * @param String
- * accountName,accountType 为账号名账号类型,一般为NULL
- * @throws RemoteException
- * @throws OperationApplicationException
- */
- public static String _insertContact(ContentResolver cr, String accountName,
- String accountType, String displayName, ArrayList<String[]> phone,
- ArrayList<String[]> email, ArrayList<String[]> im,
- ArrayList<String[]> address, ArrayList<String[]> organization,
- ArrayList<String[]> notes, ArrayList<String[]> nickname,
- ArrayList<String[]> website) throws RemoteException,
- OperationApplicationException {
- ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
- String rawId = "";
- long rawContactId = insertRawContact(cr, accountName, accountType);
- rawId = Long.toString(rawContactId);
- if (displayName != null) {
- insertContactDisplayname(ops, StructuredName.CONTENT_ITEM_TYPE,
- rawId, displayName);
- }
- if (phone != null) {
- for (int j = 0; j < phone.size(); j++) {
- String[] item = phone.get(j);
- insertItemToContact(ops, Phone.CONTENT_ITEM_TYPE, rawId,
- PROJECTION_PHONENUMBER_CONTACT, item);
- }
- }
- if (email != null) {
- for (int j = 0; j < email.size(); j++) {
- String[] item = email.get(j);
- insertItemToContact(ops, Email.CONTENT_ITEM_TYPE, rawId,
- PROJECTION_EAMIL_CONTACT, item);
- }
- }
- if (im != null) {
- for (int j = 0; j < im.size(); j++) {
- String[] item = im.get(j);
- insertItemToContact(ops, Im.CONTENT_ITEM_TYPE, rawId,
- PROJECTION_IM_CONTACT, item);
- }
- }
- if (address != null) {
- for (int j = 0; j < address.size(); j++) {
- String[] item = address.get(j);
- insertItemToContact(ops, StructuredPostal.CONTENT_ITEM_TYPE,
- rawId, PROJECTION_ADDRESS_CONTACT, item);
- }
- }
- if (organization != null) {
- for (int j = 0; j < organization.size(); j++) {
- String[] item = organization.get(j);
- insertItemToContact(ops, Organization.CONTENT_ITEM_TYPE, rawId,
- PROJECTION_ORGANIZATION_CONTACT, item);
- }
- }
- if (notes != null) {
- for (int j = 0; j < notes.size(); j++) {
- String[] item = notes.get(j);
- insertItemToContact(ops, Note.CONTENT_ITEM_TYPE, rawId,
- PROJECTION_NOTES_CONTACT, item);
- }
- }
- if (nickname != null) {
- for (int j = 0; j < nickname.size(); j++) {
- String[] item = nickname.get(j);
- insertItemToContact(ops, Nickname.CONTENT_ITEM_TYPE, rawId,
- PROJECTION_NICKNAMES_CONTACT, item);
- }
- }
- if (website != null) {
- for (int j = 0; j < website.size(); j++) {
- String[] item = website.get(j);
- insertItemToContact(ops, Website.CONTENT_ITEM_TYPE, rawId,
- PROJECTION_WEBSITES_CONTACT, item);
- }
- }
- cr.applyBatch(ContactsContract.AUTHORITY, ops);
- return rawId;
- }
- /*
- * 通过往ROWCONTACT里插入数据,获得rawId
- *
- * @param cr
- *
- * @param accountName 一般为NULL
- *
- * @param accountType 一般为NULL
- *
- * @return
- */
- private static long insertRawContact(ContentResolver cr,
- String accountName, String accountType) {
- ContentValues values = new ContentValues();
- 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);
- long rawContactId = ContentUris.parseId(rawContactUri);
- return rawContactId;
- }
- private static void insertContactDisplayname(
- ArrayList<ContentProviderOperation> ops, String mimeType,
- String rawContactId, String displayName) throws RemoteException,
- OperationApplicationException {
- ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI).withValue(
- Data.MIMETYPE, mimeType).withValue(Data.RAW_CONTACT_ID,
- rawContactId).withValue(StructuredName.DISPLAY_NAME,
- displayName).build());
- }
- private static void insertItemToContact(
- ArrayList<ContentProviderOperation> ops, String mimeType,
- String rawContactId, String[] PROJECTION_CONTACT, String[] item)
- throws RemoteException, OperationApplicationException {
- // ContentValues values = new ContentValues();
- // values.put(Data.RAW_CONTACT_ID, rawContactId);
- // values.put(Data.MIMETYPE, mimeType);
- // for (int i = 0; i < PROJECTION_CONTACT.length; 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 (int i = 0; i < PROJECTION_CONTACT.length; i++) {
- builder.withValue(PROJECTION_CONTACT[i], item[i]);
- }
- ops.add(builder.build());
- }