Android 2.0中电话本contact的读写操作(增删改查)

来源:互联网 发布:python web后端开发 编辑:程序博客网 时间:2024/05/29 07:09

一.前言

     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打开看下,如图:

 

      从上图,可以看出左边是.db文件的表,点开各表后可以看出主要的表有raw_contacts,contacts,data


二. api

      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

TypeAliasData columnStringADDRESSDATA1Email address itself.intTYPEDATA2Allowed values are:

  • TYPE_CUSTOM. Put the actual type in LABEL.
  • TYPE_HOME
  • TYPE_WORK
  • TYPE_OTHER
  • TYPE_MOBILE

StringLABELDATA3 Email数据有三个字段存储:ADDRESS为Email值;TYPE为类型,当为自定义(TYPE_CUSTOM)时,LABEL字段要写入用户自定义的类型;

   2.2.2 IM 对应 ContactsContract.CommonDataKinds.Im 

TypeAliasData columnStringDATADATA1 intTYPEDATA2Allowed values are:

  • TYPE_CUSTOM. Put the actual type in LABEL.
  • TYPE_HOME
  • TYPE_WORK
  • TYPE_OTHER

StringLABELDATA3 StringPROTOCOLDATA5

Allowed values:

  • PROTOCOL_CUSTOM. Also provide the actual protocol name as CUSTOM_PROTOCOL.
  • PROTOCOL_AIM
  • PROTOCOL_MSN
  • PROTOCOL_YAHOO
  • PROTOCOL_SKYPE
  • PROTOCOL_QQ
  • PROTOCOL_GOOGLE_TALK
  • PROTOCOL_ICQ
  • PROTOCOL_JABBER
  • PROTOCOL_NETMEETING

StringCUSTOM_PROTOCOLDATA6

Im有5个字段

  2.2.3 Phone 对应 ContactsContract.CommonDataKinds.Phone

TypeAliasData columnStringNUMBERDATA1 intTYPEDATA2Allowed values are:

  • TYPE_CUSTOM. Put the actual type in LABEL.
  • 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

StringLABELDATA3

2.2.4 Postal address 通讯地址 对应 ContactsContract.CommonDataKinds.StructuredPostal

TypeAliasData columnStringFORMATTED_ADDRESSDATA1 intTYPEDATA2Allowed values are:

  • TYPE_CUSTOM. Put the actual type in LABEL.
  • TYPE_HOME
  • TYPE_WORK
  • TYPE_OTHER

StringLABELDATA3 StringSTREETDATA4 StringPOBOXDATA5Post Office Box numberStringNEIGHBORHOODDATA6 StringCITYDATA7 StringREGIONDATA8 StringPOSTCODEDATA9 StringCOUNTRYDATA10

最长用的有 TYPE:类型;STREET:街道;CITY:市;REGION:省;POSTCODE:邮政编码;

三.代码

     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查询联系人详细

// phoneprivate static final String[] PROJECTION_PHONENUMBER_CONTACT = {Phone.NUMBER, Phone.TYPE, Phone.LABEL };/* DISPLAY_NAME唯一性 */private static final String[] PROJECTION_DISPLAYNAME_CONTACT = { StructuredName.DISPLAY_NAME };// Emailprivate static final String[] PROJECTION_EAMIL_CONTACT = { Email.DATA1,Email.TYPE, Email.LABEL };// IMprivate static final String[] PROJECTION_IM_CONTACT = new String[] {Im.DATA, Im.TYPE, Im.LABEL, Im.PROTOCOL };// addressprivate 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, };// Organizationprivate static final String[] PROJECTION_ORGANIZATION_CONTACT = new String[] {Organization.COMPANY, Organization.TYPE, Organization.LABEL,Organization.TITLE };// noteprivate static final String[] PROJECTION_NOTES_CONTACT = new String[] { Note.NOTE };// nicknameprivate static final String[] PROJECTION_NICKNAMES_CONTACT = new String[] {Nickname.NAME, Nickname.TYPE, Nickname.LABEL };// websiteprivate 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();// logMyUtils.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());}



原创粉丝点击