详细介绍Android通讯录的导出和导入

通讯录导出到SD卡时,会在SD卡中生成一个vcf文件,用于保存联系人姓名,手机号码。

vCard 规范容许公开交换个人数据交换 (Personal Data Interchange PDI)信息,在传统纸质商业名片可找到这些信息。规范定义电子名片(或叫vCard)的格式。

而在Android上使用vcard就要借助第三方包:我已经上传,看后面的链接地址

下载后里面会有2个Example {ReadExample.java / WriteExample.java} 。
但是凭借这两个Example,不足以让你更好的完成其他信息的备份和恢复,于是你要看下源码。

其中比较的2个类的源码如下.

 

/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package a_vcard.android.syncml.pim.vcard;//import android.content.AbstractSyncableContentProvider;//import android.content.ContentResolver;//import android.content.ContentUris;//import android.content.ContentValues;//import android.net.Uri;import a_vcard.android.provider.Contacts;import a_vcard.android.provider.Contacts.ContactMethods;//import android.provider.Contacts.Extensions;//import android.provider.Contacts.GroupMembership;//import android.provider.Contacts.Organizations;//import android.provider.Contacts.People;import a_vcard.android.provider.Contacts.Phones;//import android.provider.Contacts.Photos;import a_vcard.android.syncml.pim.PropertyNode;import a_vcard.android.syncml.pim.VNode;import a_vcard.android.telephony.PhoneNumberUtils;import a_vcard.android.text.TextUtils;import a_vcard.android.util.Log;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Locale;import java.util.Map;import java.util.Map.Entry;/** * The parameter class of VCardComposer. * This class standy by the person-contact in * Android system, we must use this class instance as parameter to transmit to * VCardComposer so that create vCard string. */// TODO: rename the class name, next steppublic class ContactStruct {    private static final String LOG_TAG = "ContactStruct";        // Note: phonetic name probably should be "LAST FIRST MIDDLE" for European languages, and    //       space should be added between each element while it should not be in Japanese.    //       But unfortunately, we currently do not have the data and are not sure whether we should    //       support European version of name ordering.    //    // TODO: Implement the logic described above if we really need European version of    //        phonetic name handling. Also, adding the appropriate test case of vCard would be    //        highly appreciated.    public static final int NAME_ORDER_TYPE_ENGLISH = 0;    public static final int NAME_ORDER_TYPE_JAPANESE = 1;    /** MUST exist */    public String name;    public String phoneticName;    /** maybe folding */    public List notes = new ArrayList();    /** maybe folding */    public String title;    /** binary bytes of pic. */    public byte[] photoBytes;    /** The type of Photo (e.g. JPEG, BMP, etc.) */    public String photoType;    /** Only for GET. Use addPhoneList() to PUT. */    public List phoneList;    /** Only for GET. Use addContactmethodList() to PUT. */    public List contactmethodList;    /** Only for GET. Use addOrgList() to PUT. */    public List organizationList;    /** Only for GET. Use addExtension() to PUT */    public Map> extensionMap;    // Use organizationList instead when handling ORG.    @Deprecated    public String company;        public static class PhoneData {        public int type;        /** maybe folding */        public String data;        public String label;        public boolean isPrimary;     }    public static class ContactMethod {        // Contacts.KIND_EMAIL, Contacts.KIND_POSTAL        public int kind;        // e.g. Contacts.ContactMethods.TYPE_HOME, Contacts.PhoneColumns.TYPE_HOME        // If type == Contacts.PhoneColumns.TYPE_CUSTOM, label is used.        public int type;        public String data;        // Used only when TYPE is TYPE_CUSTOM.        public String label;        public boolean isPrimary;    }        public static class OrganizationData {        public int type;        public String companyName;        public String positionName;        public boolean isPrimary;    }    /**     * Add a phone info to phoneList.     * @param data phone number     * @param type type col of content://contacts/phones     * @param label lable col of content://contacts/phones     */    public void addPhone(int type, String data, String label, boolean isPrimary){        if (phoneList == null) {            phoneList = new ArrayList();        }        PhoneData phoneData = new PhoneData();        phoneData.type = type;                StringBuilder builder = new StringBuilder();        String trimed = data.trim();        int length = trimed.length();        for (int i = 0; i < length; i++) {            char ch = trimed.charAt(i);            if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) {                builder.append(ch);            }        }        phoneData.data = PhoneNumberUtils.formatNumber(builder.toString());        phoneData.label = label;        phoneData.isPrimary = isPrimary;        phoneList.add(phoneData);    }    /**     * Add a contactmethod info to contactmethodList.     * @param kind integer value defined in Contacts.java     * (e.g. Contacts.KIND_EMAIL)     * @param type type col of content://contacts/contact_methods     * @param data contact data     * @param label extra string used only when kind is Contacts.KIND_CUSTOM.     */    public void addContactmethod(int kind, int type, String data,            String label, boolean isPrimary){        if (contactmethodList == null) {            contactmethodList = new ArrayList();        }        ContactMethod contactMethod = new ContactMethod();        contactMethod.kind = kind;        contactMethod.type = type;        contactMethod.data = data;        contactMethod.label = label;        contactMethod.isPrimary = isPrimary;        contactmethodList.add(contactMethod);    }        /**     * Add a Organization info to organizationList.     */    public void addOrganization(int type, String companyName, String positionName,            boolean isPrimary) {        if (organizationList == null) {            organizationList = new ArrayList();        }        OrganizationData organizationData = new OrganizationData();        organizationData.type = type;        organizationData.companyName = companyName;        organizationData.positionName = positionName;        organizationData.isPrimary = isPrimary;        organizationList.add(organizationData);    }    /**     * Set "position" value to the appropriate data. If there's more than one     * OrganizationData objects, the value is set to the last one. If there's no     * OrganizationData object, a new OrganizationData is created, whose company name is     * empty.       *      * TODO: incomplete logic. fix this:     *      * e.g. This assumes ORG comes earlier, but TITLE may come earlier like this, though we do not     * know how to handle it in general cases...     * ----     * TITLE:Software Engineer     * ORG:Google     * ----     */    public void setPosition(String positionValue) {        if (organizationList == null) {            organizationList = new ArrayList();        }        int size = organizationList.size();        if (size == 0) {            addOrganization(Contacts.OrganizationColumns.TYPE_OTHER, "", null, false);            size = 1;        }        OrganizationData lastData = organizationList.get(size - 1);        lastData.positionName = positionValue;    }        public void addExtension(PropertyNode propertyNode) {        if (propertyNode.propValue.length() == 0) {            return;        }        // Now store the string into extensionMap.        List list;        String name = propertyNode.propName;        if (extensionMap == null) {            extensionMap = new HashMap>();        }        if (!extensionMap.containsKey(name)){            list = new ArrayList();            extensionMap.put(name, list);        } else {            list = extensionMap.get(name);        }                        list.add(propertyNode.encode());    }        private static String getNameFromNProperty(List elems, int nameOrderType) {        // Family, Given, Middle, Prefix, Suffix. (1 - 5)        int size = elems.size();        if (size > 1) {            StringBuilder builder = new StringBuilder();            boolean builderIsEmpty = true;            // Prefix            if (size > 3 && elems.get(3).length() > 0) {                builder.append(elems.get(3));                builderIsEmpty = false;            }            String first, second;            if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) {                first = elems.get(0);                second = elems.get(1);            } else {                first = elems.get(1);                second = elems.get(0);            }            if (first.length() > 0) {                if (!builderIsEmpty) {                    builder.append(' ');                }                builder.append(first);                builderIsEmpty = false;            }            // Middle name            if (size > 2 && elems.get(2).length() > 0) {                if (!builderIsEmpty) {                    builder.append(' ');                }                builder.append(elems.get(2));                builderIsEmpty = false;            }            if (second.length() > 0) {                if (!builderIsEmpty) {                    builder.append(' ');                }                builder.append(second);                builderIsEmpty = false;            }            // Suffix            if (size > 4 && elems.get(4).length() > 0) {                if (!builderIsEmpty) {                    builder.append(' ');                }                builder.append(elems.get(4));                builderIsEmpty = false;            }            return builder.toString();        } else if (size == 1) {            return elems.get(0);        } else {            return "";        }    }        public static ContactStruct constructContactFromVNode(VNode node,            int nameOrderType) {        if (!node.VName.equals("VCARD")) {            // Impossible in current implementation. Just for safety.            Log.e(LOG_TAG, "Non VCARD data is inserted.");            return null;        }        // For name, there are three fields in vCard: FN, N, NAME.        // We prefer FN, which is a required field in vCard 3.0 , but not in vCard 2.1.        // Next, we prefer NAME, which is defined only in vCard 3.0.        // Finally, we use N, which is a little difficult to parse.        String fullName = null;        String nameFromNProperty = null;        // Some vCard has "X-PHONETIC-FIRST-NAME", "X-PHONETIC-MIDDLE-NAME", and        // "X-PHONETIC-LAST-NAME"        String xPhoneticFirstName = null;        String xPhoneticMiddleName = null;        String xPhoneticLastName = null;                ContactStruct contact = new ContactStruct();        // Each Column of four properties has ISPRIMARY field        // (See android.provider.Contacts)        // If false even after the following loop, we choose the first        // entry as a "primary" entry.        boolean prefIsSetAddress = false;        boolean prefIsSetPhone = false;        boolean prefIsSetEmail = false;        boolean prefIsSetOrganization = false;                for (PropertyNode propertyNode: node.propList) {            String name = propertyNode.propName;            if (TextUtils.isEmpty(propertyNode.propValue)) {                continue;            }                        if (name.equals("VERSION")) {                // vCard version. Ignore this.            } else if (name.equals("FN")) {                fullName = propertyNode.propValue;            } else if (name.equals("NAME") && fullName == null) {                // Only in vCard 3.0. Use this if FN does not exist.                // Though, note that vCard 3.0 requires FN.                fullName = propertyNode.propValue;            } else if (name.equals("N")) {                nameFromNProperty = getNameFromNProperty(propertyNode.propValue_vector,                        nameOrderType);            } else if (name.equals("SORT-STRING")) {                contact.phoneticName = propertyNode.propValue;            } else if (name.equals("SOUND")) {                if (propertyNode.paramMap_TYPE.contains("X-IRMC-N") &&                        contact.phoneticName == null) {                    // Some Japanese mobile phones use this field for phonetic name,                    // since vCard 2.1 does not have "SORT-STRING" type.                    // Also, in some cases, the field has some ';' in it.                    // We remove them.                    StringBuilder builder = new StringBuilder();                    String value = propertyNode.propValue;                    int length = value.length();                    for (int i = 0; i < length; i++) {                        char ch = value.charAt(i);                        if (ch != ';') {                            builder.append(ch);                        }                    }                    contact.phoneticName = builder.toString();                } else {                    contact.addExtension(propertyNode);                }            } else if (name.equals("ADR")) {                List values = propertyNode.propValue_vector;                boolean valuesAreAllEmpty = true;                for (String value : values) {                    if (value.length() > 0) {                        valuesAreAllEmpty = false;                        break;                    }                }                if (valuesAreAllEmpty) {                    continue;                }                int kind = Contacts.KIND_POSTAL;                int type = -1;                String label = "";                boolean isPrimary = false;                for (String typeString : propertyNode.paramMap_TYPE) {                    if (typeString.equals("PREF") && !prefIsSetAddress) {                        // Only first "PREF" is considered.                        prefIsSetAddress = true;                        isPrimary = true;                    } else if (typeString.equalsIgnoreCase("HOME")) {                        type = Contacts.ContactMethodsColumns.TYPE_HOME;                        label = "";                    } else if (typeString.equalsIgnoreCase("WORK") ||                             typeString.equalsIgnoreCase("COMPANY")) {                        // "COMPANY" seems emitted by Windows Mobile, which is not                        // specifically supported by vCard 2.1. We assume this is same                        // as "WORK".                        type = Contacts.ContactMethodsColumns.TYPE_WORK;                        label = "";                    } else if (typeString.equalsIgnoreCase("POSTAL")) {                        kind = Contacts.KIND_POSTAL;                    } else if (typeString.equalsIgnoreCase("PARCEL") ||                             typeString.equalsIgnoreCase("DOM") ||                            typeString.equalsIgnoreCase("INTL")) {                        // We do not have a kind or type matching these.                        // TODO: fix this. We may need to split entries into two.                        // (e.g. entries for KIND_POSTAL and KIND_PERCEL)                    } else if (typeString.toUpperCase().startsWith("X-") &&                            type < 0) {                        type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;                        label = typeString.substring(2);                    } else if (type < 0) {                        // vCard 3.0 allows iana-token. Also some vCard 2.1 exporters                        // emit non-standard types. We do not handle their values now.                        type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;                        label = typeString;                    }                }                // We use "HOME" as default                if (type < 0) {                    type = Contacts.ContactMethodsColumns.TYPE_HOME;                }                                                // adr-value    = 0*6(text-value ";") text-value                //              ; PO Box, Extended Address, Street, Locality, Region, Postal                //              ; Code, Country Name                String address;                List list = propertyNode.propValue_vector;                int size = list.size();                if (size > 1) {                    StringBuilder builder = new StringBuilder();                    boolean builderIsEmpty = true;                    if (Locale.getDefault().getCountry().equals(Locale.JAPAN.getCountry())) {                        // In Japan, the order is reversed.                        for (int i = size - 1; i >= 0; i--) {                            String addressPart = list.get(i);                            if (addressPart.length() > 0) {                                if (!builderIsEmpty) {                                    builder.append(' ');                                }                                builder.append(addressPart);                                builderIsEmpty = false;                            }                        }                    } else {                        for (int i = 0; i < size; i++) {                            String addressPart = list.get(i);                            if (addressPart.length() > 0) {                                if (!builderIsEmpty) {                                    builder.append(' ');                                }                                builder.append(addressPart);                                builderIsEmpty = false;                            }                        }                    }                    address = builder.toString().trim();                } else {                    address = propertyNode.propValue;                 }                contact.addContactmethod(kind, type, address, label, isPrimary);            } else if (name.equals("ORG")) {                // vCard specification does not specify other types.                int type = Contacts.OrganizationColumns.TYPE_WORK;                boolean isPrimary = false;                                for (String typeString : propertyNode.paramMap_TYPE) {                    if (typeString.equals("PREF") && !prefIsSetOrganization) {                        // vCard specification officially does not have PREF in ORG.                        // This is just for safety.                        prefIsSetOrganization = true;                        isPrimary = true;                    }                    // XXX: Should we cope with X- words?                }                List list = propertyNode.propValue_vector;                 int size = list.size();                StringBuilder builder = new StringBuilder();                for (Iterator iter = list.iterator(); iter.hasNext();) {                    builder.append(iter.next());                    if (iter.hasNext()) {                        builder.append(' ');                    }                }                contact.addOrganization(type, builder.toString(), "", isPrimary);            } else if (name.equals("TITLE")) {                contact.setPosition(propertyNode.propValue);            } else if (name.equals("ROLE")) {                contact.setPosition(propertyNode.propValue);            } else if (name.equals("PHOTO")) {                // We prefer PHOTO to LOGO.                String valueType = propertyNode.paramMap.getAsString("VALUE");                if (valueType != null && valueType.equals("URL")) {                    // TODO: do something.                } else {                    // Assume PHOTO is stored in BASE64. In that case,                    // data is already stored in propValue_bytes in binary form.                    // It should be automatically done by VBuilder (VDataBuilder/VCardDatabuilder)                     contact.photoBytes = propertyNode.propValue_bytes;                    String type = propertyNode.paramMap.getAsString("TYPE");                    if (type != null) {                        contact.photoType = type;                    }                }            } else if (name.equals("LOGO")) {                // When PHOTO is not available this is not URL,                // we use this instead of PHOTO.                String valueType = propertyNode.paramMap.getAsString("VALUE");                if (valueType != null && valueType.equals("URL")) {                    // TODO: do something.                } else if (contact.photoBytes == null) {                    contact.photoBytes = propertyNode.propValue_bytes;                    String type = propertyNode.paramMap.getAsString("TYPE");                    if (type != null) {                        contact.photoType = type;                    }                }            } else if (name.equals("EMAIL")) {                int type = -1;                String label = null;                boolean isPrimary = false;                for (String typeString : propertyNode.paramMap_TYPE) {                    if (typeString.equals("PREF") && !prefIsSetEmail) {                        // Only first "PREF" is considered.                        prefIsSetEmail = true;                        isPrimary = true;                    } else if (typeString.equalsIgnoreCase("HOME")) {                        type = Contacts.ContactMethodsColumns.TYPE_HOME;                    } else if (typeString.equalsIgnoreCase("WORK")) {                        type = Contacts.ContactMethodsColumns.TYPE_WORK;                    } else if (typeString.equalsIgnoreCase("CELL")) {                        // We do not have Contacts.ContactMethodsColumns.TYPE_MOBILE yet.                        type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;                        label = Contacts.ContactMethodsColumns.MOBILE_EMAIL_TYPE_NAME;                    } else if (typeString.toUpperCase().startsWith("X-") &&                            type < 0) {                        type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;                        label = typeString.substring(2);                    } else if (type < 0) {                        // vCard 3.0 allows iana-token.                        // We may have INTERNET (specified in vCard spec),                        // SCHOOL, etc.                        type = Contacts.ContactMethodsColumns.TYPE_CUSTOM;                        label = typeString;                    }                }                // We use "OTHER" as default.                if (type < 0) {                    type = Contacts.ContactMethodsColumns.TYPE_OTHER;                }                contact.addContactmethod(Contacts.KIND_EMAIL,                        type, propertyNode.propValue,label, isPrimary);            } else if (name.equals("TEL")) {                int type = -1;                String label = null;                boolean isPrimary = false;                boolean isFax = false;                for (String typeString : propertyNode.paramMap_TYPE) {                    if (typeString.equals("PREF") && !prefIsSetPhone) {                        // Only first "PREF" is considered.                        prefIsSetPhone = true;                        isPrimary = true;                    } else if (typeString.equalsIgnoreCase("HOME")) {                        type = Contacts.PhonesColumns.TYPE_HOME;                    } else if (typeString.equalsIgnoreCase("WORK")) {                        type = Contacts.PhonesColumns.TYPE_WORK;                    } else if (typeString.equalsIgnoreCase("CELL")) {                        type = Contacts.PhonesColumns.TYPE_MOBILE;                    } else if (typeString.equalsIgnoreCase("PAGER")) {                        type = Contacts.PhonesColumns.TYPE_PAGER;                    } else if (typeString.equalsIgnoreCase("FAX")) {                        isFax = true;                    } else if (typeString.equalsIgnoreCase("VOICE") ||                            typeString.equalsIgnoreCase("MSG")) {                        // Defined in vCard 3.0. Ignore these because they                        // conflict with "HOME", "WORK", etc.                        // XXX: do something?                    } else if (typeString.toUpperCase().startsWith("X-") &&                            type < 0) {                        type = Contacts.PhonesColumns.TYPE_CUSTOM;                        label = typeString.substring(2);                    } else if (type < 0){                        // We may have MODEM, CAR, ISDN, etc...                        type = Contacts.PhonesColumns.TYPE_CUSTOM;                        label = typeString;                    }                }                // We use "HOME" as default                if (type < 0) {                    type = Contacts.PhonesColumns.TYPE_HOME;                }                if (isFax) {                    if (type == Contacts.PhonesColumns.TYPE_HOME) {                        type = Contacts.PhonesColumns.TYPE_FAX_HOME;                     } else if (type == Contacts.PhonesColumns.TYPE_WORK) {                        type = Contacts.PhonesColumns.TYPE_FAX_WORK;                     }                }                contact.addPhone(type, propertyNode.propValue, label, isPrimary);            } else if (name.equals("NOTE")) {                contact.notes.add(propertyNode.propValue);            } else if (name.equals("BDAY")) {                contact.addExtension(propertyNode);            } else if (name.equals("URL")) {                contact.addExtension(propertyNode);            } else if (name.equals("REV")) {                                // Revision of this VCard entry. I think we can ignore this.                contact.addExtension(propertyNode);            } else if (name.equals("UID")) {                contact.addExtension(propertyNode);            } else if (name.equals("KEY")) {                // Type is X509 or PGP? I don't know how to handle this...                contact.addExtension(propertyNode);            } else if (name.equals("MAILER")) {                contact.addExtension(propertyNode);            } else if (name.equals("TZ")) {                contact.addExtension(propertyNode);            } else if (name.equals("GEO")) {                contact.addExtension(propertyNode);            } else if (name.equals("NICKNAME")) {                // vCard 3.0 only.                contact.addExtension(propertyNode);            } else if (name.equals("CLASS")) {                // vCard 3.0 only.                // e.g. CLASS:CONFIDENTIAL                contact.addExtension(propertyNode);            } else if (name.equals("PROFILE")) {                // VCard 3.0 only. Must be "VCARD". I think we can ignore this.                contact.addExtension(propertyNode);            } else if (name.equals("CATEGORIES")) {                // VCard 3.0 only.                // e.g. CATEGORIES:INTERNET,IETF,INDUSTRY,INFORMATION TECHNOLOGY                contact.addExtension(propertyNode);            } else if (name.equals("SOURCE")) {                // VCard 3.0 only.                contact.addExtension(propertyNode);            } else if (name.equals("PRODID")) {                // VCard 3.0 only.                // To specify the identifier for the product that created                // the vCard object.                contact.addExtension(propertyNode);            } else if (name.equals("X-PHONETIC-FIRST-NAME")) {                xPhoneticFirstName = propertyNode.propValue;            } else if (name.equals("X-PHONETIC-MIDDLE-NAME")) {                xPhoneticMiddleName = propertyNode.propValue;            } else if (name.equals("X-PHONETIC-LAST-NAME")) {                xPhoneticLastName = propertyNode.propValue;            } else {                // Unknown X- words and IANA token.                contact.addExtension(propertyNode);            }        }        if (fullName != null) {            contact.name = fullName;        } else if(nameFromNProperty != null) {            contact.name = nameFromNProperty;        } else {            contact.name = "";        }        if (contact.phoneticName == null &&                (xPhoneticFirstName != null || xPhoneticMiddleName != null ||                        xPhoneticLastName != null)) {            // Note: In Europe, this order should be "LAST FIRST MIDDLE". See the comment around            //       NAME_ORDER_TYPE_* for more detail.            String first;            String second;            if (nameOrderType == NAME_ORDER_TYPE_JAPANESE) {                first = xPhoneticLastName;                second = xPhoneticFirstName;            } else {                first = xPhoneticFirstName;                second = xPhoneticLastName;            }            StringBuilder builder = new StringBuilder();            if (first != null) {                builder.append(first);            }            if (xPhoneticMiddleName != null) {                builder.append(xPhoneticMiddleName);            }            if (second != null) {                builder.append(second);            }            contact.phoneticName = builder.toString();        }                // Remove unnecessary white spaces.        // It is found that some mobile phone emits  phonetic name with just one white space        // when a user does not specify one.        // This logic is effective toward such kind of weird data.        if (contact.phoneticName != null) {            contact.phoneticName = contact.phoneticName.trim();        }        // If there is no "PREF", we choose the first entries as primary.        if (!prefIsSetPhone &&                contact.phoneList != null &&                 contact.phoneList.size() > 0) {            contact.phoneList.get(0).isPrimary = true;        }        if (!prefIsSetAddress && contact.contactmethodList != null) {            for (ContactMethod contactMethod : contact.contactmethodList) {                if (contactMethod.kind == Contacts.KIND_POSTAL) {                    contactMethod.isPrimary = true;                    break;                }            }        }        if (!prefIsSetEmail && contact.contactmethodList != null) {            for (ContactMethod contactMethod : contact.contactmethodList) {                if (contactMethod.kind == Contacts.KIND_EMAIL) {                    contactMethod.isPrimary = true;                    break;                }            }        }        if (!prefIsSetOrganization &&                contact.organizationList != null &&                contact.organizationList.size() > 0) {            contact.organizationList.get(0).isPrimary = true;        }                return contact;    }        public String displayString() {        if (name.length() > 0) {            return name;        }        if (contactmethodList != null && contactmethodList.size() > 0) {            for (ContactMethod contactMethod : contactmethodList) {                if (contactMethod.kind == Contacts.KIND_EMAIL && contactMethod.isPrimary) {                    return contactMethod.data;                }            }        }        if (phoneList != null && phoneList.size() > 0) {            for (PhoneData phoneData : phoneList) {                if (phoneData.isPrimary) {                    return phoneData.data;                }            }        }        return "";    }    //    private void pushIntoContentProviderOrResolver(Object contentSomething,//            long myContactsGroupId) {//        ContentResolver resolver = null;//        AbstractSyncableContentProvider provider = null;//        if (contentSomething instanceof ContentResolver) {//            resolver = (ContentResolver)contentSomething;//        } else if (contentSomething instanceof AbstractSyncableContentProvider) {//            provider = (AbstractSyncableContentProvider)contentSomething;//        } else {//            Log.e(LOG_TAG, "Unsupported object came.");//            return;//        }////        ContentValues contentValues = new ContentValues();//        contentValues.put(People.NAME, name);//        contentValues.put(People.PHONETIC_NAME, phoneticName);////        if (notes.size() > 1) {//            StringBuilder builder = new StringBuilder();//            for (String note : notes) {//                builder.append(note);//                builder.append("\n");//            }//            contentValues.put(People.NOTES, builder.toString());//        } else if (notes.size() == 1){//            contentValues.put(People.NOTES, notes.get(0));//        }////        Uri personUri;//        long personId = 0;//        if (resolver != null) {//            personUri = Contacts.People.createPersonInMyContactsGroup(//                    resolver, contentValues);//            if (personUri != null) {//                personId = ContentUris.parseId(personUri);//            }//        } else {//            personUri = provider.nonTransactionalInsert(People.CONTENT_URI, contentValues);//            if (personUri != null) {//                personId = ContentUris.parseId(personUri);//                ContentValues values = new ContentValues();//                values.put(GroupMembership.PERSON_ID, personId);//                values.put(GroupMembership.GROUP_ID, myContactsGroupId);//                Uri resultUri = provider.nonTransactionalInsert(//                        GroupMembership.CONTENT_URI, values);//                if (resultUri == null) {//                    Log.e(LOG_TAG, "Faild to insert the person to MyContact.");//                    provider.nonTransactionalDelete(personUri, null, null);//                    personUri = null;//                }//            }//        }////        if (personUri == null) {//            Log.e(LOG_TAG, "Failed to create the contact.");//            return;//        }////        if (photoBytes != null) {//            if (resolver != null) {//                People.setPhotoData(resolver, personUri, photoBytes);//            } else {//                Uri photoUri = Uri.withAppendedPath(personUri, Contacts.Photos.CONTENT_DIRECTORY);//                ContentValues values = new ContentValues();//                values.put(Photos.DATA, photoBytes);//                provider.update(photoUri, values, null, null);//            }//        }////        long primaryPhoneId = -1;//        if (phoneList != null && phoneList.size() > 0) {//            for (PhoneData phoneData : phoneList) {//                ContentValues values = new ContentValues();//                values.put(Contacts.PhonesColumns.TYPE, phoneData.type);//                if (phoneData.type == Contacts.PhonesColumns.TYPE_CUSTOM) {//                    values.put(Contacts.PhonesColumns.LABEL, phoneData.label);//                }//                // Already formatted.//                values.put(Contacts.PhonesColumns.NUMBER, phoneData.data);////                // Not sure about Contacts.PhonesColumns.NUMBER_KEY ...//                values.put(Contacts.PhonesColumns.ISPRIMARY, 1);//                values.put(Contacts.Phones.PERSON_ID, personId);//                Uri phoneUri;//                if (resolver != null) {//                    phoneUri = resolver.insert(Phones.CONTENT_URI, values);//                } else {//                    phoneUri = provider.nonTransactionalInsert(Phones.CONTENT_URI, values);//                }//                if (phoneData.isPrimary) {//                    primaryPhoneId = Long.parseLong(phoneUri.getLastPathSegment());//                }//            }//        }////        long primaryOrganizationId = -1;//        if (organizationList != null && organizationList.size() > 0) {//            for (OrganizationData organizationData : organizationList) {//                ContentValues values = new ContentValues();//                // Currently, we do not use TYPE_CUSTOM.//                values.put(Contacts.OrganizationColumns.TYPE,//                        organizationData.type);//                values.put(Contacts.OrganizationColumns.COMPANY,//                        organizationData.companyName);//                values.put(Contacts.OrganizationColumns.TITLE,//                        organizationData.positionName);//                values.put(Contacts.OrganizationColumns.ISPRIMARY, 1);//                values.put(Contacts.OrganizationColumns.PERSON_ID, personId);////                Uri organizationUri;//                if (resolver != null) {//                    organizationUri = resolver.insert(Organizations.CONTENT_URI, values);//                } else {//                    organizationUri = provider.nonTransactionalInsert(//                            Organizations.CONTENT_URI, values);//                }//                if (organizationData.isPrimary) {//                    primaryOrganizationId = Long.parseLong(organizationUri.getLastPathSegment());//                }//            }//        }////        long primaryEmailId = -1;//        if (contactmethodList != null && contactmethodList.size() > 0) {//            for (ContactMethod contactMethod : contactmethodList) {//                ContentValues values = new ContentValues();//                values.put(Contacts.ContactMethodsColumns.KIND, contactMethod.kind);//                values.put(Contacts.ContactMethodsColumns.TYPE, contactMethod.type);//                if (contactMethod.type == Contacts.ContactMethodsColumns.TYPE_CUSTOM) {//                    values.put(Contacts.ContactMethodsColumns.LABEL, contactMethod.label);//                }//                values.put(Contacts.ContactMethodsColumns.DATA, contactMethod.data);//                values.put(Contacts.ContactMethodsColumns.ISPRIMARY, 1);//                values.put(Contacts.ContactMethods.PERSON_ID, personId);////                if (contactMethod.kind == Contacts.KIND_EMAIL) {//                    Uri emailUri;//                    if (resolver != null) {//                        emailUri = resolver.insert(ContactMethods.CONTENT_URI, values);//                    } else {//                        emailUri = provider.nonTransactionalInsert(//                                ContactMethods.CONTENT_URI, values);//                    }//                    if (contactMethod.isPrimary) {//                        primaryEmailId = Long.parseLong(emailUri.getLastPathSegment());//                    }//                } else {  // probably KIND_POSTAL//                    if (resolver != null) {//                        resolver.insert(ContactMethods.CONTENT_URI, values);//                    } else {//                        provider.nonTransactionalInsert(//                                ContactMethods.CONTENT_URI, values);//                    }//                }//            }//        }////        if (extensionMap != null && extensionMap.size() > 0) {//            ArrayList contentValuesArray;//            if (resolver != null) {//                contentValuesArray = new ArrayList();//            } else {//                contentValuesArray = null;//            }//            for (Entry> entry : extensionMap.entrySet()) {//                String key = entry.getKey();//                List list = entry.getValue();//                for (String value : list) {//                    ContentValues values = new ContentValues();//                    values.put(Extensions.NAME, key);//                    values.put(Extensions.VALUE, value);//                    values.put(Extensions.PERSON_ID, personId);//                    if (resolver != null) {//                        contentValuesArray.add(values);//                    } else {//                        provider.nonTransactionalInsert(Extensions.CONTENT_URI, values);//                    }//                }//            }//            if (resolver != null) {//                resolver.bulkInsert(Extensions.CONTENT_URI,//                        contentValuesArray.toArray(new ContentValues[0]));//            }//        }////        if (primaryPhoneId >= 0 || primaryOrganizationId >= 0 || primaryEmailId >= 0) {//            ContentValues values = new ContentValues();//            if (primaryPhoneId >= 0) {//                values.put(People.PRIMARY_PHONE_ID, primaryPhoneId);//            }//            if (primaryOrganizationId >= 0) {//                values.put(People.PRIMARY_ORGANIZATION_ID, primaryOrganizationId);//            }//            if (primaryEmailId >= 0) {//                values.put(People.PRIMARY_EMAIL_ID, primaryEmailId);//            }//            if (resolver != null) {//                resolver.update(personUri, values, null, null);//            } else {//                provider.nonTransactionalUpdate(personUri, values, null, null);//            }//        }//    }////    /**//     * Push this object into database in the resolver.//     *///    public void pushIntoContentResolver(ContentResolver resolver) {//        pushIntoContentProviderOrResolver(resolver, 0);//    }////    /**//     * Push this object into AbstractSyncableContentProvider object.//     *///    public void pushIntoAbstractSyncableContentProvider(//            AbstractSyncableContentProvider provider, long myContactsGroupId) {//        boolean successful = false;//        provider.beginTransaction();//        try {//            pushIntoContentProviderOrResolver(provider, myContactsGroupId);//            successful = true;//        } finally {//            provider.endTransaction(successful);//        }//    }        public boolean isIgnorable() {        return TextUtils.isEmpty(name) &&                TextUtils.isEmpty(phoneticName) &&                (phoneList == null || phoneList.size() == 0) &&                (contactmethodList == null || contactmethodList.size() == 0);    }}


/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package a_vcard.android.provider;//import com.android.internal.R;//import android.content.ContentResolver;//import android.content.ContentUris;//import android.content.ContentValues;//import android.content.Context;//import android.content.Intent;//import android.database.Cursor;//import android.graphics.Bitmap;//import android.graphics.BitmapFactory;//import android.net.Uri;//import android.text.TextUtils;//import android.util.Log;//import android.widget.ImageView;//import java.io.ByteArrayInputStream;//import java.io.InputStream;/** * The Contacts provider stores all information about contacts. */public class Contacts {    private static final String TAG = "Contacts";        public static final String AUTHORITY = "contacts";//    /**//     * The content:// style URL for this provider//     *///    public static final Uri CONTENT_URI =//        Uri.parse("content://" + AUTHORITY);    /** Signifies an email address row that is stored in the ContactMethods table */    public static final int KIND_EMAIL = 1;    /** Signifies a postal address row that is stored in the ContactMethods table */    public static final int KIND_POSTAL = 2;    /** Signifies an IM address row that is stored in the ContactMethods table */    public static final int KIND_IM = 3;    /** Signifies an Organization row that is stored in the Organizations table */    public static final int KIND_ORGANIZATION = 4;    /** Signifies an Phone row that is stored in the Phones table */    public static final int KIND_PHONE = 5;    /**     * no public constructor since this is a utility class     */    private Contacts() {}//    /**//     * Columns from the Settings table that other columns join into themselves.//     *///    public interface SettingsColumns {//        /**//         * The _SYNC_ACCOUNT to which this setting corresponds. This may be null.//         * 

Type: TEXT

// */// public static final String _SYNC_ACCOUNT = "_sync_account";//// /**// * The key of this setting.// *

Type: TEXT

// */// public static final String KEY = "key";//// /**// * The value of this setting.// *

Type: TEXT

// */// public static final String VALUE = "value";// }//// /**// * The settings over all of the people// */// public static final class Settings implements BaseColumns, SettingsColumns {// /**// * no public constructor since this is a utility class// */// private Settings() {}//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/settings");//// /**// * The directory twig for this sub-table// */// public static final String CONTENT_DIRECTORY = "settings";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "key ASC";//// /**// * A setting that is used to indicate if we should sync down all groups for the// * specified account. For this setting the _SYNC_ACCOUNT column must be set.// * If this isn't set then we will only sync the groups whose SHOULD_SYNC column// * is set to true.// *

// * This is a boolean setting. It is true if it is set and it is anything other than the// * emptry string or "0".// */// public static final String SYNC_EVERYTHING = "syncEverything";//// public static String getSetting(ContentResolver cr, String account, String key) {// // For now we only support a single account and the UI doesn't know what// // the account name is, so we're using a global setting for SYNC_EVERYTHING.// // Some day when we add multiple accounts to the UI this should honor the account// // that was asked for.// String selectString;// String[] selectArgs;// if (false) {// selectString = (account == null)// ? "_sync_account is null AND key=?"// : "_sync_account=? AND key=?";// selectArgs = (account == null)// ? new String[]{key}// : new String[]{account, key};// } else {// selectString = "key=?";// selectArgs = new String[] {key};// }// Cursor cursor = cr.query(Settings.CONTENT_URI, new String[]{VALUE},// selectString, selectArgs, null);// try {// if (!cursor.moveToNext()) return null;// return cursor.getString(0);// } finally {// cursor.close();// }// }//// public static void setSetting(ContentResolver cr, String account, String key,// String value) {// ContentValues values = new ContentValues();// // For now we only support a single account and the UI doesn't know what// // the account name is, so we're using a global setting for SYNC_EVERYTHING.// // Some day when we add multiple accounts to the UI this should honor the account// // that was asked for.// //values.put(_SYNC_ACCOUNT, account);// values.put(KEY, key);// values.put(VALUE, value);// cr.update(Settings.CONTENT_URI, values, null, null);// }// }// /** * Columns from the People table that other tables join into themselves. */ public interface PeopleColumns { /** * The person's name. *

Type: TEXT

*/ public static final String NAME = "name"; /** * Phonetic equivalent of the person's name, in a locale-dependent * character set (e.g. hiragana for Japanese). * Used for pronunciation and/or collation in some languages. *

Type: TEXT

*/ public static final String PHONETIC_NAME = "phonetic_name"; /** * The display name. If name is not null name, else if number is not null number, * else if email is not null email. *

Type: TEXT

*/ public static final String DISPLAY_NAME = "display_name"; /** * The field for sorting list phonetically. The content of this field * may not be human readable but phonetically sortable. *

Type: TEXT

* @hide Used only in Contacts application for now. */ public static final String SORT_STRING = "sort_string"; /** * Notes about the person. *

Type: TEXT

*/ public static final String NOTES = "notes"; /** * The number of times a person has been contacted *

Type: INTEGER

*/ public static final String TIMES_CONTACTED = "times_contacted"; /** * The last time a person was contacted. *

Type: INTEGER

*/ public static final String LAST_TIME_CONTACTED = "last_time_contacted"; /** * A custom ringtone associated with a person. Not always present. *

Type: TEXT (URI to the ringtone)

*/ public static final String CUSTOM_RINGTONE = "custom_ringtone"; /** * Whether the person should always be sent to voicemail. Not always * present. *

Type: INTEGER (0 for false, 1 for true)

*/ public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; /** * Is the contact starred? *

Type: INTEGER (boolean)

*/ public static final String STARRED = "starred"; /** * The server version of the photo *

Type: TEXT (the version number portion of the photo URI)

*/ public static final String PHOTO_VERSION = "photo_version"; }//// /**// * This table contains people.// */// public static final class People implements BaseColumns, SyncConstValue, PeopleColumns,// PhonesColumns, PresenceColumns {// /**// * no public constructor since this is a utility class// */// private People() {}//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/people");//// /**// * The content:// style URL for filtering people by name. The filter// * argument should be passed as an additional path segment after this URI.// */// public static final Uri CONTENT_FILTER_URI =// Uri.parse("content://contacts/people/filter");//// /**// * The content:// style URL for the table that holds the deleted// * contacts.// */// public static final Uri DELETED_CONTENT_URI =// Uri.parse("content://contacts/deleted_people");//// /**// * The content:// style URL for filtering people that have a specific// * E-mail or IM address. The filter argument should be passed as an// * additional path segment after this URI. This matches any people with// * at least one E-mail or IM {@link ContactMethods} that match the// * filter.// *// * Not exposed because we expect significant changes in the contacts// * schema and do not want to have to support this.// * @hide// */// public static final Uri WITH_EMAIL_OR_IM_FILTER_URI =// Uri.parse("content://contacts/people/with_email_or_im_filter");//// /**// * The MIME type of {@link #CONTENT_URI} providing a directory of// * people.// */// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/person";//// /**// * The MIME type of a {@link #CONTENT_URI} subdirectory of a single// * person.// */// public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/person";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = People.NAME + " ASC";//// /**// * The ID of the persons preferred phone number.// *

Type: INTEGER (foreign key to phones table on the _ID field)

// */// public static final String PRIMARY_PHONE_ID = "primary_phone";//// /**// * The ID of the persons preferred email.// *

Type: INTEGER (foreign key to contact_methods table on the// * _ID field)

// */// public static final String PRIMARY_EMAIL_ID = "primary_email";//// /**// * The ID of the persons preferred organization.// *

Type: INTEGER (foreign key to organizations table on the// * _ID field)

// */// public static final String PRIMARY_ORGANIZATION_ID = "primary_organization";//// /**// * Mark a person as having been contacted.// *// * @param resolver the ContentResolver to use// * @param personId the person who was contacted// */// public static void markAsContacted(ContentResolver resolver, long personId) {// Uri uri = ContentUris.withAppendedId(CONTENT_URI, personId);// uri = Uri.withAppendedPath(uri, "update_contact_time");// ContentValues values = new ContentValues();// // There is a trigger in place that will update TIMES_CONTACTED when// // LAST_TIME_CONTACTED is modified.// values.put(LAST_TIME_CONTACTED, System.currentTimeMillis());// resolver.update(uri, values, null, null);// }//// /**// * @hide Used in vCard parser code.// */// public static long tryGetMyContactsGroupId(ContentResolver resolver) {// Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,// Groups.SYSTEM_ID + "='" + Groups.GROUP_MY_CONTACTS + "'", null, null);// if (groupsCursor != null) {// try {// if (groupsCursor.moveToFirst()) {// return groupsCursor.getLong(0);// }// } finally {// groupsCursor.close();// }// }// return 0;// }//// /**// * Adds a person to the My Contacts group.// *// * @param resolver the resolver to use// * @param personId the person to add to the group// * @return the URI of the group membership row// * @throws IllegalStateException if the My Contacts group can't be found// */// public static Uri addToMyContactsGroup(ContentResolver resolver, long personId) {// long groupId = tryGetMyContactsGroupId(resolver);// if (groupId == 0) {// throw new IllegalStateException("Failed to find the My Contacts group");// }//// return addToGroup(resolver, personId, groupId);// }//// /**// * Adds a person to a group referred to by name.// *// * @param resolver the resolver to use// * @param personId the person to add to the group// * @param groupName the name of the group to add the contact to// * @return the URI of the group membership row// * @throws IllegalStateException if the group can't be found// */// public static Uri addToGroup(ContentResolver resolver, long personId, String groupName) {// long groupId = 0;// Cursor groupsCursor = resolver.query(Groups.CONTENT_URI, GROUPS_PROJECTION,// Groups.NAME + "=?", new String[] { groupName }, null);// if (groupsCursor != null) {// try {// if (groupsCursor.moveToFirst()) {// groupId = groupsCursor.getLong(0);// }// } finally {// groupsCursor.close();// }// }//// if (groupId == 0) {// throw new IllegalStateException("Failed to find the My Contacts group");// }//// return addToGroup(resolver, personId, groupId);// }//// /**// * Adds a person to a group.// *// * @param resolver the resolver to use// * @param personId the person to add to the group// * @param groupId the group to add the person to// * @return the URI of the group membership row// */// public static Uri addToGroup(ContentResolver resolver, long personId, long groupId) {// ContentValues values = new ContentValues();// values.put(GroupMembership.PERSON_ID, personId);// values.put(GroupMembership.GROUP_ID, groupId);// return resolver.insert(GroupMembership.CONTENT_URI, values);// }//// private static final String[] GROUPS_PROJECTION = new String[] {// Groups._ID,// };//// /**// * Creates a new contacts and adds it to the "My Contacts" group.// *// * @param resolver the ContentResolver to use// * @param values the values to use when creating the contact// * @return the URI of the contact, or null if the operation fails// */// public static Uri createPersonInMyContactsGroup(ContentResolver resolver,// ContentValues values) {//// Uri contactUri = resolver.insert(People.CONTENT_URI, values);// if (contactUri == null) {// Log.e(TAG, "Failed to create the contact");// return null;// }//// if (addToMyContactsGroup(resolver, ContentUris.parseId(contactUri)) == null) {// resolver.delete(contactUri, null, null);// return null;// }// return contactUri;// }//// public static Cursor queryGroups(ContentResolver resolver, long person) {// return resolver.query(GroupMembership.CONTENT_URI, null, "person=?",// new String[]{String.valueOf(person)}, Groups.DEFAULT_SORT_ORDER);// }//// /**// * Set the photo for this person. data may be null// * @param cr the ContentResolver to use// * @param person the Uri of the person whose photo is to be updated// * @param data the byte[] that represents the photo// */// public static void setPhotoData(ContentResolver cr, Uri person, byte[] data) {// Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);// ContentValues values = new ContentValues();// values.put(Photos.DATA, data);// cr.update(photoUri, values, null, null);// }//// /**// * Opens an InputStream for the person's photo and returns the photo as a Bitmap.// * If the person's photo isn't present returns the placeholderImageResource instead.// * @param person the person whose photo should be used// */// public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri person) {// Uri photoUri = Uri.withAppendedPath(person, Contacts.Photos.CONTENT_DIRECTORY);// Cursor cursor = cr.query(photoUri, new String[]{Photos.DATA}, null, null, null);// try {// if (!cursor.moveToNext()) {// return null;// }// byte[] data = cursor.getBlob(0);// if (data == null) {// return null;// }// return new ByteArrayInputStream(data);// } finally {// cursor.close();// }// }//// /**// * Opens an InputStream for the person's photo and returns the photo as a Bitmap.// * If the person's photo isn't present returns the placeholderImageResource instead.// * @param context the Context// * @param person the person whose photo should be used// * @param placeholderImageResource the image resource to use if the person doesn't// * have a photo// * @param options the decoding options, can be set to null// */// public static Bitmap loadContactPhoto(Context context, Uri person,// int placeholderImageResource, BitmapFactory.Options options) {// if (person == null) {// return loadPlaceholderPhoto(placeholderImageResource, context, options);// }//// InputStream stream = openContactPhotoInputStream(context.getContentResolver(), person);// Bitmap bm = stream != null ? BitmapFactory.decodeStream(stream, null, options) : null;// if (bm == null) {// bm = loadPlaceholderPhoto(placeholderImageResource, context, options);// }// return bm;// }//// private static Bitmap loadPlaceholderPhoto(int placeholderImageResource, Context context,// BitmapFactory.Options options) {// if (placeholderImageResource == 0) {// return null;// }// return BitmapFactory.decodeResource(context.getResources(),// placeholderImageResource, options);// } /** * A sub directory of a single person that contains all of their Phones. */ public static final class Phones implements BaseColumns, PhonesColumns, PeopleColumns { /** * no public constructor since this is a utility class */ private Phones() {} /** * The directory twig for this sub-table */ public static final String CONTENT_DIRECTORY = "phones"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = "number ASC"; } /** * A subdirectory of a single person that contains all of their * ContactMethods. */ public static final class ContactMethods implements BaseColumns, ContactMethodsColumns, PeopleColumns { /** * no public constructor since this is a utility class */ private ContactMethods() {} /** * The directory twig for this sub-table */ public static final String CONTENT_DIRECTORY = "contact_methods"; /** * The default sort order for this table */ public static final String DEFAULT_SORT_ORDER = "data ASC"; }// /**// * The extensions for a person// */// public static class Extensions implements BaseColumns, ExtensionsColumns {// /**// * no public constructor since this is a utility class// */// private Extensions() {}//// /**// * The directory twig for this sub-table// */// public static final String CONTENT_DIRECTORY = "extensions";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "name ASC";//// /**// * The ID of the person this phone number is assigned to.// *

Type: INTEGER (long)

// */// public static final String PERSON_ID = "person";// }// }//// /**// * Columns from the groups table.// */// public interface GroupsColumns {// /**// * The group name.// *

Type: TEXT

// */// public static final String NAME = "name";//// /**// * Notes about the group.// *

Type: TEXT

// */// public static final String NOTES = "notes";//// /**// * Whether this group should be synced if the SYNC_EVERYTHING settings is false// * for this group's account.// *

Type: INTEGER (boolean)

// */// public static final String SHOULD_SYNC = "should_sync";//// /**// * The ID of this group if it is a System Group, null otherwise.// *

Type: TEXT

// */// public static final String SYSTEM_ID = "system_id";// }//// /**// * This table contains the groups for an account.// */// public static final class Groups// implements BaseColumns, SyncConstValue, GroupsColumns {// /**// * no public constructor since this is a utility class// */// private Groups() {}//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/groups");//// /**// * The content:// style URL for the table that holds the deleted// * groups.// */// public static final Uri DELETED_CONTENT_URI =// Uri.parse("content://contacts/deleted_groups");//// /**// * The MIME type of {@link #CONTENT_URI} providing a directory of// * groups.// */// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroup";//// /**// * The MIME type of a {@link #CONTENT_URI} subdirectory of a single// * group.// */// public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contactsgroup";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = NAME + " ASC";//// /**// *// */// public static final String GROUP_ANDROID_STARRED = "Starred in Android";//// /**// * The "My Contacts" system group.// */// public static final String GROUP_MY_CONTACTS = "Contacts";// }// /** * Columns from the Phones table that other columns join into themselves. */ public interface PhonesColumns { /** * The type of the the phone number. *

Type: INTEGER (one of the constants below)

*/ public static final String TYPE = "type"; public static final int TYPE_CUSTOM = 0; public static final int TYPE_HOME = 1; public static final int TYPE_MOBILE = 2; public static final int TYPE_WORK = 3; public static final int TYPE_FAX_WORK = 4; public static final int TYPE_FAX_HOME = 5; public static final int TYPE_PAGER = 6; public static final int TYPE_OTHER = 7; /** * The user provided label for the phone number, only used if TYPE is TYPE_CUSTOM. *

Type: TEXT

*/ public static final String LABEL = "label"; /** * The phone number as the user entered it. *

Type: TEXT

*/ public static final String NUMBER = "number"; /** * The normalized phone number *

Type: TEXT

*/ public static final String NUMBER_KEY = "number_key"; /** * Whether this is the primary phone number *

Type: INTEGER (if set, non-0 means true)

*/ public static final String ISPRIMARY = "isprimary"; }//// /**// * This table stores phone numbers and a reference to the person that the// * contact method belongs to. Phone numbers are stored separately from// * other contact methods to make caller ID lookup more efficient.// */// public static final class Phones// implements BaseColumns, PhonesColumns, PeopleColumns {// /**// * no public constructor since this is a utility class// */// private Phones() {}//// public static final CharSequence getDisplayLabel(Context context, int type,// CharSequence label, CharSequence[] labelArray) {// CharSequence display = "";//// if (type != People.Phones.TYPE_CUSTOM) {// CharSequence[] labels = labelArray != null? labelArray// : context.getResources().getTextArray(// com.android.internal.R.array.phoneTypes);// try {// display = labels[type - 1];// } catch (ArrayIndexOutOfBoundsException e) {// display = labels[People.Phones.TYPE_HOME - 1];// }// } else {// if (!TextUtils.isEmpty(label)) {// display = label;// }// }// return display;// }//// public static final CharSequence getDisplayLabel(Context context, int type,// CharSequence label) {// return getDisplayLabel(context, type, label, null);// }//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/phones");//// /**// * The content:// style URL for filtering phone numbers// */// public static final Uri CONTENT_FILTER_URL =// Uri.parse("content://contacts/phones/filter");//// /**// * The MIME type of {@link #CONTENT_URI} providing a directory of// * phones.// */// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone";//// /**// * The MIME type of a {@link #CONTENT_URI} subdirectory of a single// * phone.// */// public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "name ASC";//// /**// * The ID of the person this phone number is assigned to.// *

Type: INTEGER (long)

// */// public static final String PERSON_ID = "person";// }//// public static final class GroupMembership implements BaseColumns, GroupsColumns {// /**// * no public constructor since this is a utility class// */// private GroupMembership() {}//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/groupmembership");//// /**// * The content:// style URL for this table// */// public static final Uri RAW_CONTENT_URI =// Uri.parse("content://contacts/groupmembershipraw");//// /**// * The directory twig for this sub-table// */// public static final String CONTENT_DIRECTORY = "groupmembership";// /**// * The MIME type of {@link #CONTENT_URI} providing a directory of all// * person groups.// */// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contactsgroupmembership";//// /**// * The MIME type of a {@link #CONTENT_URI} subdirectory of a single// * person group.// */// public static final String CONTENT_ITEM_TYPE =// "vnd.android.cursor.item/contactsgroupmembership";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "group_id ASC";//// /**// * The row id of the accounts group.// *

Type: TEXT

// */// public static final String GROUP_ID = "group_id";//// /**// * The sync id of the group.// *

Type: TEXT

// */// public static final String GROUP_SYNC_ID = "group_sync_id";//// /**// * The account of the group.// *

Type: TEXT

// */// public static final String GROUP_SYNC_ACCOUNT = "group_sync_account";//// /**// * The row id of the person.// *

Type: TEXT

// */// public static final String PERSON_ID = "person";// }// /** * Columns from the ContactMethods table that other tables join into * themseleves. */ public interface ContactMethodsColumns { /** * The kind of the the contact method. For example, email address, * postal address, etc. *

Type: INTEGER (one of the values below)

*/ public static final String KIND = "kind"; /** * The type of the contact method, must be one of the types below. *

Type: INTEGER (one of the values below)

*/ public static final String TYPE = "type"; public static final int TYPE_CUSTOM = 0; public static final int TYPE_HOME = 1; public static final int TYPE_WORK = 2; public static final int TYPE_OTHER = 3; /** * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future. */ public static final int MOBILE_EMAIL_TYPE_INDEX = 2; /** * @hide This is temporal. TYPE_MOBILE should be added to TYPE in the future. * This is not "mobile" but "CELL" since vCard uses it for identifying mobile phone. */ public static final String MOBILE_EMAIL_TYPE_NAME = "_AUTO_CELL"; /** * The user defined label for the the contact method. *

Type: TEXT

*/ public static final String LABEL = "label"; /** * The data for the contact method. *

Type: TEXT

*/ public static final String DATA = "data"; /** * Auxiliary data for the contact method. *

Type: TEXT

*/ public static final String AUX_DATA = "aux_data"; /** * Whether this is the primary organization *

Type: INTEGER (if set, non-0 means true)

*/ public static final String ISPRIMARY = "isprimary"; }//// /**// * This table stores all non-phone contact methods and a reference to the// * person that the contact method belongs to.// */// public static final class ContactMethods// implements BaseColumns, ContactMethodsColumns, PeopleColumns {// /**// * The column with latitude data for postal locations// *

Type: REAL

// */// public static final String POSTAL_LOCATION_LATITUDE = DATA;//// /**// * The column with longitude data for postal locations// *

Type: REAL

// */// public static final String POSTAL_LOCATION_LONGITUDE = AUX_DATA;//// /**// * The predefined IM protocol types. The protocol can either be non-present, one// * of these types, or a free-form string. These cases are encoded in the AUX_DATA// * column as:// * - null// * - pre:// * - custom:// */// public static final int PROTOCOL_AIM = 0;// public static final int PROTOCOL_MSN = 1;// public static final int PROTOCOL_YAHOO = 2;// public static final int PROTOCOL_SKYPE = 3;// public static final int PROTOCOL_QQ = 4;// public static final int PROTOCOL_GOOGLE_TALK = 5;// public static final int PROTOCOL_ICQ = 6;// public static final int PROTOCOL_JABBER = 7;//// public static String encodePredefinedImProtocol(int protocol) {// return "pre:" + protocol;// }//// public static String encodeCustomImProtocol(String protocolString) {// return "custom:" + protocolString;// }//// public static Object decodeImProtocol(String encodedString) {// if (encodedString == null) {// return null;// }//// if (encodedString.startsWith("pre:")) {// return Integer.parseInt(encodedString.substring(4));// }//// if (encodedString.startsWith("custom:")) {// return encodedString.substring(7);// }//// throw new IllegalArgumentException(// "the value is not a valid encoded protocol, " + encodedString);// }//// /**// * This looks up the provider name defined in// * {@link android.provider.Im.ProviderNames} from the predefined IM protocol id.// * This is used for interacting with the IM application.// *// * @param protocol the protocol ID// * @return the provider name the IM app uses for the given protocol, or null if no// * provider is defined for the given protocol// * @hide// */// public static String lookupProviderNameFromId(int protocol) {// switch (protocol) {// case PROTOCOL_GOOGLE_TALK:// return Im.ProviderNames.GTALK;// case PROTOCOL_AIM:// return Im.ProviderNames.AIM;// case PROTOCOL_MSN:// return Im.ProviderNames.MSN;// case PROTOCOL_YAHOO:// return Im.ProviderNames.YAHOO;// case PROTOCOL_ICQ:// return Im.ProviderNames.ICQ;// case PROTOCOL_JABBER:// return Im.ProviderNames.JABBER;// case PROTOCOL_SKYPE:// return Im.ProviderNames.SKYPE;// case PROTOCOL_QQ:// return Im.ProviderNames.QQ;// }// return null;// }//// /**// * no public constructor since this is a utility class// */// private ContactMethods() {}//// public static final CharSequence getDisplayLabel(Context context, int kind,// int type, CharSequence label) {// CharSequence display = "";// switch (kind) {// case KIND_EMAIL: {// if (type != People.ContactMethods.TYPE_CUSTOM) {// CharSequence[] labels = context.getResources().getTextArray(// com.android.internal.R.array.emailAddressTypes);// try {// display = labels[type - 1];// } catch (ArrayIndexOutOfBoundsException e) {// display = labels[ContactMethods.TYPE_HOME - 1];// }// } else {// if (!TextUtils.isEmpty(label)) {// if (label.toString().equals(MOBILE_EMAIL_TYPE_NAME)) {// display =// context.getString(// com.android.internal.R.string.mobileEmailTypeName);// } else {// display = label;// }// }// }// break;// }//// case KIND_POSTAL: {// if (type != People.ContactMethods.TYPE_CUSTOM) {// CharSequence[] labels = context.getResources().getTextArray(// com.android.internal.R.array.postalAddressTypes);// try {// display = labels[type - 1];// } catch (ArrayIndexOutOfBoundsException e) {// display = labels[ContactMethods.TYPE_HOME - 1];// }// } else {// if (!TextUtils.isEmpty(label)) {// display = label;// }// }// break;// }//// default:// display = context.getString(R.string.untitled);// }// return display;// }//// /**// * Add a longitude and latitude location to a postal address.// *// * @param context the context to use when updating the database// * @param postalId the address to update// * @param latitude the latitude for the address// * @param longitude the longitude for the address// */// public void addPostalLocation(Context context, long postalId,// double latitude, double longitude) {// final ContentResolver resolver = context.getContentResolver();// // Insert the location// ContentValues values = new ContentValues(2);// values.put(POSTAL_LOCATION_LATITUDE, latitude);// values.put(POSTAL_LOCATION_LONGITUDE, longitude);// Uri loc = resolver.insert(CONTENT_URI, values);// long locId = ContentUris.parseId(loc);//// // Update the postal address// values.clear();// values.put(AUX_DATA, locId);// resolver.update(ContentUris.withAppendedId(CONTENT_URI, postalId), values, null, null);// }//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/contact_methods");//// /**// * The content:// style URL for sub-directory of e-mail addresses.// */// public static final Uri CONTENT_EMAIL_URI =// Uri.parse("content://contacts/contact_methods/email");//// /**// * The MIME type of {@link #CONTENT_URI} providing a directory of// * phones.// */// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact-methods";//// /**// * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\// * multiple {@link Contacts#KIND_EMAIL} entries.// */// public static final String CONTENT_EMAIL_TYPE = "vnd.android.cursor.dir/email";//// /**// * The MIME type of a {@link #CONTENT_EMAIL_URI} sub-directory of\// * multiple {@link Contacts#KIND_POSTAL} entries.// */// public static final String CONTENT_POSTAL_TYPE = "vnd.android.cursor.dir/postal-address";//// /**// * The MIME type of a {@link #CONTENT_URI} sub-directory of a single// * {@link Contacts#KIND_EMAIL} entry.// */// public static final String CONTENT_EMAIL_ITEM_TYPE = "vnd.android.cursor.item/email";//// /**// * The MIME type of a {@link #CONTENT_URI} sub-directory of a single// * {@link Contacts#KIND_POSTAL} entry.// */// public static final String CONTENT_POSTAL_ITEM_TYPE// = "vnd.android.cursor.item/postal-address";//// /**// * The MIME type of a {@link #CONTENT_URI} sub-directory of a single// * {@link Contacts#KIND_IM} entry.// */// public static final String CONTENT_IM_ITEM_TYPE = "vnd.android.cursor.item/jabber-im";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "name ASC";//// /**// * The ID of the person this contact method is assigned to.// *

Type: INTEGER (long)

// */// public static final String PERSON_ID = "person";// }//// /**// * The IM presence columns with some contacts specific columns mixed in.// */// public interface PresenceColumns extends Im.CommonPresenceColumns {// /**// * The IM service the presence is coming from. Formatted using either// * {@link Contacts.ContactMethods#encodePredefinedImProtocol} or// * {@link Contacts.ContactMethods#encodeCustomImProtocol}.// *

Type: STRING

// */// public static final String IM_PROTOCOL = "im_protocol";//// /**// * The IM handle the presence item is for. The handle is scoped to// * the {@link #IM_PROTOCOL}.// *

Type: STRING

// */// public static final String IM_HANDLE = "im_handle";//// /**// * The IM account for the local user that the presence data came from.// *

Type: STRING

// */// public static final String IM_ACCOUNT = "im_account";// }//// /**// * Contains presence information about contacts.// * @hide// */// public static final class Presence// implements BaseColumns, PresenceColumns, PeopleColumns {// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/presence");//// /**// * The ID of the person this presence item is assigned to.// *

Type: INTEGER (long)

// */// public static final String PERSON_ID = "person";//// /**// * Gets the resource ID for the proper presence icon.// *// * @param status the status to get the icon for// * @return the resource ID for the proper presence icon// */// public static final int getPresenceIconResourceId(int status) {// switch (status) {// case Contacts.People.AVAILABLE:// return com.android.internal.R.drawable.presence_online;//// case Contacts.People.IDLE:// case Contacts.People.AWAY:// return com.android.internal.R.drawable.presence_away;//// case Contacts.People.DO_NOT_DISTURB:// return com.android.internal.R.drawable.presence_busy;//// case Contacts.People.INVISIBLE:// return com.android.internal.R.drawable.presence_invisible;//// case Contacts.People.OFFLINE:// default:// return com.android.internal.R.drawable.presence_offline;// }// }//// /**// * Sets a presence icon to the proper graphic// *// * @param icon the icon to to set// * @param serverStatus that status// */// public static final void setPresenceIcon(ImageView icon, int serverStatus) {// icon.setImageResource(getPresenceIconResourceId(serverStatus));// }// }// /** * Columns from the Organizations table that other columns join into themselves. */ public interface OrganizationColumns { /** * The type of the organizations. *

Type: INTEGER (one of the constants below)

*/ public static final String TYPE = "type"; public static final int TYPE_CUSTOM = 0; public static final int TYPE_WORK = 1; public static final int TYPE_OTHER = 2; /** * The user provided label, only used if TYPE is TYPE_CUSTOM. *

Type: TEXT

*/ public static final String LABEL = "label"; /** * The name of the company for this organization. *

Type: TEXT

*/ public static final String COMPANY = "company"; /** * The title within this organization. *

Type: TEXT

*/ public static final String TITLE = "title"; /** * The person this organization is tied to. *

Type: TEXT

*/ public static final String PERSON_ID = "person"; /** * Whether this is the primary organization *

Type: INTEGER (if set, non-0 means true)

*/ public static final String ISPRIMARY = "isprimary"; }//// /**// * A sub directory of a single person that contains all of their Phones.// */// public static final class Organizations implements BaseColumns, OrganizationColumns {// /**// * no public constructor since this is a utility class// */// private Organizations() {}//// public static final CharSequence getDisplayLabel(Context context, int type,// CharSequence label) {// CharSequence display = "";//// if (type != TYPE_CUSTOM) {// CharSequence[] labels = context.getResources().getTextArray(// com.android.internal.R.array.organizationTypes);// try {// display = labels[type - 1];// } catch (ArrayIndexOutOfBoundsException e) {// display = labels[Organizations.TYPE_WORK - 1];// }// } else {// if (!TextUtils.isEmpty(label)) {// display = label;// }// }// return display;// }//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/organizations");//// /**// * The directory twig for this sub-table// */// public static final String CONTENT_DIRECTORY = "organizations";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "company, title, isprimary ASC";// }//// /**// * Columns from the Photos table that other columns join into themselves.// */// public interface PhotosColumns {// /**// * The _SYNC_VERSION of the photo that was last downloaded// *

Type: TEXT

// */// public static final String LOCAL_VERSION = "local_version";//// /**// * The person this photo is associated with.// *

Type: TEXT

// */// public static final String PERSON_ID = "person";//// /**// * non-zero if a download is required and the photo isn't marked as a bad resource.// * You must specify this in the columns in order to use it in the where clause.// *

Type: INTEGER(boolean)

// */// public static final String DOWNLOAD_REQUIRED = "download_required";//// /**// * non-zero if this photo is known to exist on the server// *

Type: INTEGER(boolean)

// */// public static final String EXISTS_ON_SERVER = "exists_on_server";//// /**// * Contains the description of the upload or download error from// * the previous attempt. If null then the previous attempt succeeded.// *

Type: TEXT

// */// public static final String SYNC_ERROR = "sync_error";//// /**// * The image data, or null if there is no image.// *

Type: BLOB

// */// public static final String DATA = "data";//// }//// /**// * The photos over all of the people// */// public static final class Photos implements BaseColumns, PhotosColumns, SyncConstValue {// /**// * no public constructor since this is a utility class// */// private Photos() {}//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/photos");//// /**// * The directory twig for this sub-table// */// public static final String CONTENT_DIRECTORY = "photo";//// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "person ASC";// }//// public interface ExtensionsColumns {// /**// * The name of this extension. May not be null. There may be at most one row for each name.// *

Type: TEXT

// */// public static final String NAME = "name";//// /**// * The value of this extension. May not be null.// *

Type: TEXT

// */// public static final String VALUE = "value";// }//// /**// * The extensions for a person// */// public static final class Extensions implements BaseColumns, ExtensionsColumns {// /**// * no public constructor since this is a utility class// */// private Extensions() {}//// /**// * The content:// style URL for this table// */// public static final Uri CONTENT_URI =// Uri.parse("content://contacts/extensions");//// /**// * The MIME type of {@link #CONTENT_URI} providing a directory of// * phones.// */// public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_extensions";//// /**// * The MIME type of a {@link #CONTENT_URI} subdirectory of a single// * phone.// */// public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_extensions";// /**// * The default sort order for this table// */// public static final String DEFAULT_SORT_ORDER = "person, name ASC";//// /**// * The ID of the person this phone number is assigned to.// *

Type: INTEGER (long)

// */// public static final String PERSON_ID = "person";// }//// /**// * Contains helper classes used to create or manage {@link android.content.Intent Intents}// * that involve contacts.// */// public static final class Intents {// /**// * This is the intent that is fired when a search suggestion is clicked on.// */// public static final String SEARCH_SUGGESTION_CLICKED =// "android.provider.Contacts.SEARCH_SUGGESTION_CLICKED";//// /**// * This is the intent that is fired when a search suggestion for dialing a number// * is clicked on.// */// public static final String SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED =// "android.provider.Contacts.SEARCH_SUGGESTION_DIAL_NUMBER_CLICKED";//// /**// * This is the intent that is fired when a search suggestion for creating a contact// * is clicked on.// */// public static final String SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED =// "android.provider.Contacts.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED";//// /**// * Starts an Activity that lets the user pick a contact to attach an image to.// * After picking the contact it launches the image cropper in face detection mode.// */// public static final String ATTACH_IMAGE =// "com.android.contacts.action.ATTACH_IMAGE";//// /**// * Takes as input a data URI with a mailto: or tel: scheme. If a single// * contact exists with the given data it will be shown. If no contact// * exists, a dialog will ask the user if they want to create a new// * contact with the provided details filled in. If multiple contacts// * share the data the user will be prompted to pick which contact they// * want to view.// *

// * For mailto: URIs, the scheme specific portion must be a// * raw email address, such as one built using// * {@link Uri#fromParts(String, String, String)}.// *

// * For tel: URIs, the scheme specific portion is compared// * to existing numbers using the standard caller ID lookup algorithm.// * The number must be properly encoded, for example using// * {@link Uri#fromParts(String, String, String)}.// *

// * Any extras from the {@link Insert} class will be passed along to the// * create activity if there are no contacts to show.// *

// * Passing true for the {@link #EXTRA_FORCE_CREATE} extra will skip// * prompting the user when the contact doesn't exist.// */// public static final String SHOW_OR_CREATE_CONTACT =// "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";//// /**// * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new// * contact if no matching contact found. Otherwise, default behavior is// * to prompt user with dialog before creating.// *

// * Type: BOOLEAN// */// public static final String EXTRA_FORCE_CREATE =// "com.android.contacts.action.FORCE_CREATE";//// /**// * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact// * description to be shown when prompting user about creating a new// * contact.// *

// * Type: STRING// */// public static final String EXTRA_CREATE_DESCRIPTION =// "com.android.contacts.action.CREATE_DESCRIPTION";//// /**// * Intents related to the Contacts app UI.// */// public static final class UI {// /**// * The action for the default contacts list tab.// */// public static final String LIST_DEFAULT =// "com.android.contacts.action.LIST_DEFAULT";//// /**// * The action for the contacts list tab.// */// public static final String LIST_GROUP_ACTION =// "com.android.contacts.action.LIST_GROUP";//// /**// * When in LIST_GROUP_ACTION mode, this is the group to display.// */// public static final String GROUP_NAME_EXTRA_KEY = "com.android.contacts.extra.GROUP";//// /**// * The action for the all contacts list tab.// */// public static final String LIST_ALL_CONTACTS_ACTION =// "com.android.contacts.action.LIST_ALL_CONTACTS";//// /**// * The action for the contacts with phone numbers list tab.// */// public static final String LIST_CONTACTS_WITH_PHONES_ACTION =// "com.android.contacts.action.LIST_CONTACTS_WITH_PHONES";//// /**// * The action for the starred contacts list tab.// */// public static final String LIST_STARRED_ACTION =// "com.android.contacts.action.LIST_STARRED";//// /**// * The action for the frequent contacts list tab.// */// public static final String LIST_FREQUENT_ACTION =// "com.android.contacts.action.LIST_FREQUENT";//// /**// * The action for the "strequent" contacts list tab. It first lists the starred// * contacts in alphabetical order and then the frequent contacts in descending// * order of the number of times they have been contacted.// */// public static final String LIST_STREQUENT_ACTION =// "com.android.contacts.action.LIST_STREQUENT";//// /**// * A key for to be used as an intent extra to set the activity// * title to a custom String value.// */// public static final String TITLE_EXTRA_KEY =// "com.android.contacts.extra.TITLE_EXTRA";//// /**// * Activity Action: Display a filtered list of contacts// *

// * Input: Extra field {@link #FILTER_TEXT_EXTRA_KEY} is the text to use for// * filtering// *

// * Output: Nothing.// */// public static final String FILTER_CONTACTS_ACTION =// "com.android.contacts.action.FILTER_CONTACTS";//// /**// * Used as an int extra field in {@link #FILTER_CONTACTS_ACTION}// * intents to supply the text on which to filter.// */// public static final String FILTER_TEXT_EXTRA_KEY =// "com.android.contacts.extra.FILTER_TEXT";// }//// /**// * Convenience class that contains string constants used// * to create contact {@link android.content.Intent Intents}.// */// public static final class Insert {// /** The action code to use when adding a contact */// public static final String ACTION = Intent.ACTION_INSERT;//// /**// * If present, forces a bypass of quick insert mode.// */// public static final String FULL_MODE = "full_mode";//// /**// * The extra field for the contact name.// *

Type: String

// */// public static final String NAME = "name";//// /**// * The extra field for the contact phonetic name.// *

Type: String

// */// public static final String PHONETIC_NAME = "phonetic_name";//// /**// * The extra field for the contact company.// *

Type: String

// */// public static final String COMPANY = "company";//// /**// * The extra field for the contact job title.// *

Type: String

// */// public static final String JOB_TITLE = "job_title";//// /**// * The extra field for the contact notes.// *

Type: String

// */// public static final String NOTES = "notes";//// /**// * The extra field for the contact phone number.// *

Type: String

// */// public static final String PHONE = "phone";//// /**// * The extra field for the contact phone number type.// *

Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},// * or a string specifying a custom label.

// */// public static final String PHONE_TYPE = "phone_type";//// /**// * The extra field for the phone isprimary flag.// *

Type: boolean

// */// public static final String PHONE_ISPRIMARY = "phone_isprimary";//// /**// * The extra field for an optional second contact phone number.// *

Type: String

// */// public static final String SECONDARY_PHONE = "secondary_phone";//// /**// * The extra field for an optional second contact phone number type.// *

Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},// * or a string specifying a custom label.

// */// public static final String SECONDARY_PHONE_TYPE = "secondary_phone_type";//// /**// * The extra field for an optional third contact phone number.// *

Type: String

// */// public static final String TERTIARY_PHONE = "tertiary_phone";//// /**// * The extra field for an optional third contact phone number type.// *

Type: Either an integer value from {@link android.provider.Contacts.PhonesColumns PhonesColumns},// * or a string specifying a custom label.

// */// public static final String TERTIARY_PHONE_TYPE = "tertiary_phone_type";//// /**// * The extra field for the contact email address.// *

Type: String

// */// public static final String EMAIL = "email";//// /**// * The extra field for the contact email type.// *

Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}// * or a string specifying a custom label.

// */// public static final String EMAIL_TYPE = "email_type";//// /**// * The extra field for the email isprimary flag.// *

Type: boolean

// */// public static final String EMAIL_ISPRIMARY = "email_isprimary";//// /**// * The extra field for an optional second contact email address.// *

Type: String

// */// public static final String SECONDARY_EMAIL = "secondary_email";//// /**// * The extra field for an optional second contact email type.// *

Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}// * or a string specifying a custom label.

// */// public static final String SECONDARY_EMAIL_TYPE = "secondary_email_type";//// /**// * The extra field for an optional third contact email address.// *

Type: String

// */// public static final String TERTIARY_EMAIL = "tertiary_email";//// /**// * The extra field for an optional third contact email type.// *

Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}// * or a string specifying a custom label.

// */// public static final String TERTIARY_EMAIL_TYPE = "tertiary_email_type";//// /**// * The extra field for the contact postal address.// *

Type: String

// */// public static final String POSTAL = "postal";//// /**// * The extra field for the contact postal address type.// *

Type: Either an integer value from {@link android.provider.Contacts.ContactMethodsColumns ContactMethodsColumns}// * or a string specifying a custom label.

// */// public static final String POSTAL_TYPE = "postal_type";//// /**// * The extra field for the postal isprimary flag.// *

Type: boolean

// */// public static final String POSTAL_ISPRIMARY = "postal_isprimary";//// /**// * The extra field for an IM handle.// *

Type: String

// */// public static final String IM_HANDLE = "im_handle";//// /**// * The extra field for the IM protocol// *

Type: the result of {@link Contacts.ContactMethods#encodePredefinedImProtocol}// * or {@link Contacts.ContactMethods#encodeCustomImProtocol}.

// */// public static final String IM_PROTOCOL = "im_protocol";//// /**// * The extra field for the IM isprimary flag.// *

Type: boolean

// */// public static final String IM_ISPRIMARY = "im_isprimary";// }// }}



接着我将给你导入导出通讯录的类


 

package com.hh.assistant.app.vo;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.UnsupportedEncodingException;import java.util.ArrayList;import java.util.List;import a_vcard.android.provider.Contacts;import a_vcard.android.syncml.pim.VDataBuilder;import a_vcard.android.syncml.pim.VNode;import a_vcard.android.syncml.pim.vcard.ContactStruct;import a_vcard.android.syncml.pim.vcard.ContactStruct.ContactMethod;import a_vcard.android.syncml.pim.vcard.ContactStruct.PhoneData;import a_vcard.android.syncml.pim.vcard.VCardComposer;import a_vcard.android.syncml.pim.vcard.VCardException;import a_vcard.android.syncml.pim.vcard.VCardParser;import android.app.Activity;import android.content.ContentUris;import android.content.ContentValues;import android.database.Cursor;import android.net.Uri;import android.os.Environment;import android.provider.ContactsContract;import android.provider.ContactsContract.CommonDataKinds.Email;import android.provider.ContactsContract.CommonDataKinds.Phone;import android.provider.ContactsContract.CommonDataKinds.StructuredName;import android.provider.ContactsContract.RawContacts;import android.provider.ContactsContract.RawContacts.Data;import android.widget.Toast;/** * 联系人信息包装类 *  * @author LW *  */public class ContactInfo {    /** MUST exist */    private String name; // 姓名        /** 联系人电话信息 */    public static class PhoneInfo{        /** 联系电话类型 */        public int type;        /** 联系电话 */        public String number;    }        /** 联系人邮箱信息 */    public static class EmailInfo{        /** 邮箱类型 */        public int type;        /** 邮箱 */        public String email;    }        private List phoneList = new ArrayList(); // 联系号码    private List email = new ArrayList(); // Email    /**     * 构造联系人信息     * @param name 联系人姓名      */    public ContactInfo(String name) {        this.name = name;    }        /** 姓名 */    public String getName() {        return name;    }    /** 姓名 */    public ContactInfo setName(String name) {        this.name = name;        return this;    }    /** 联系电话信息 */    public List getPhoneList() {        return phoneList;    }    /** 联系电话信息 */    public ContactInfo setPhoneList(List phoneList) {        this.phoneList = phoneList;        return this;    }    /** 邮箱信息 */    public List getEmail() {        return email;    }    /** 邮箱信息 */    public ContactInfo setEmail(List email) {        this.email = email;        return this;    }    @Override    public String toString() {        return "{name: "+name+", number: "+phoneList+", email: "+email+"}";    }        /**     * 联系人     *         备份/还原操作     * @author LW     *     */    public static class ContactHandler {        private static ContactHandler instance_ = new ContactHandler();                /** 获取实例 */        public static ContactHandler getInstance(){            return instance_;        }                /**         * 获取联系人指定信息         * @param projection 指定要获取的列数组, 获取全部列则设置为null         * @return         * @throws Exception         */        public Cursor queryContact(Activity context, String[] projection){            // 获取联系人的所需信息            Cursor cur = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, projection, null, null, null);            return cur;        }                /**         * 获取联系人信息         * @param context         * @return         */        public List getContactInfo(Activity context){            List infoList = new ArrayList();                        Cursor cur = queryContact(context, null);                        if(cur.moveToFirst()){                do{                                        // 获取联系人id号                    String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));                    // 获取联系人姓名                    String displayName = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));                    ContactInfo info = new ContactInfo(displayName);// 初始化联系人信息                                        // 查看联系人有多少电话号码, 如果没有返回0                    int phoneCount = cur.getInt(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));                                        if(phoneCount>0){                                                Cursor phonesCursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id , null, null);                                                if(phonesCursor.moveToFirst()) {                            List phoneNumberList = new ArrayList();                            do{                                // 遍历所有电话号码                                String phoneNumber = phonesCursor.getString(phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));                                // 对应的联系人类型                                int type = phonesCursor.getInt(phonesCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));                                                                // 初始化联系人电话信息                                ContactInfo.PhoneInfo phoneInfo = new ContactInfo.PhoneInfo();                                phoneInfo.type=type;                                phoneInfo.number=phoneNumber;                                                                phoneNumberList.add(phoneInfo);                            }while(phonesCursor.moveToNext());                            // 设置联系人电话信息                            info.setPhoneList(phoneNumberList);                        }                    }                                        // 获得联系人的EMAIL                    Cursor emailCur = context.getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, null, ContactsContract.CommonDataKinds.Email.CONTACT_ID+"="+id, null, null);                                        if(emailCur.moveToFirst()){                        List emailList = new ArrayList();                        do{                            // 遍历所有的email                            String email = emailCur.getString(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA1));                            int type = emailCur.getInt(emailCur.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));                                                        // 初始化联系人邮箱信息                            ContactInfo.EmailInfo emailInfo=new ContactInfo.EmailInfo();                            emailInfo.type=type;    // 设置邮箱类型                            emailInfo.email=email;    // 设置邮箱地址                                                        emailList.add(emailInfo);                        }while(emailCur.moveToNext());                                                info.setEmail(emailList);                    }                                        //Cursor postalCursor = getContentResolver().query(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI, null, ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + "=" + id, null, null);                    infoList.add(info);                }while(cur.moveToNext());            }            return infoList;        }                /**         * 备份联系人         */        public void backupContacts(Activity context, List infos){                        try {                                String path = Environment.getExternalStorageDirectory() + "/contacts.vcf";                                OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(path),"UTF-8");                                VCardComposer composer = new VCardComposer();                                for (ContactInfo info : infos)                {                    ContactStruct contact = new ContactStruct();                    contact.name = info.getName();                    // 获取联系人电话信息, 添加至 ContactStruct                     List numberList = info                            .getPhoneList();                    for (ContactInfo.PhoneInfo phoneInfo : numberList)                    {                        contact.addPhone(phoneInfo.type, phoneInfo.number,                                null, true);                    }                    // 获取联系人Email信息, 添加至 ContactStruct                     List emailList = info.getEmail();                    for (ContactInfo.EmailInfo emailInfo : emailList)                    {                        contact.addContactmethod(Contacts.KIND_EMAIL,                                emailInfo.type, emailInfo.email, null, true);                    }                    String vcardString = composer.createVCard(contact,                            VCardComposer.VERSION_VCARD30_INT);                    writer.write(vcardString);                    writer.write("\n");                                        writer.flush();                }                writer.close();                        } catch (UnsupportedEncodingException e) {                e.printStackTrace();            } catch (FileNotFoundException e) {                e.printStackTrace();            } catch (VCardException e) {                e.printStackTrace();            } catch (IOException e) {                e.printStackTrace();            }                        Toast.makeText(context, "备份成功!", Toast.LENGTH_SHORT).show();        }                        /**         * 获取vCard文件中的联系人信息          * @return          */        public List restoreContacts() throws Exception {            List contactInfoList = new ArrayList();                        VCardParser parse = new VCardParser();            VDataBuilder builder = new VDataBuilder();            String file = Environment.getExternalStorageDirectory() + "/contacts.vcf";                        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));                        String vcardString = "";            String line;            while((line = reader.readLine()) != null) {                vcardString += line + "\n";            }            reader.close();                        boolean parsed = parse.parse(vcardString, "UTF-8", builder);                        if(!parsed){                throw new VCardException("Could not parse vCard file: "+ file);            }                        List pimContacts = builder.vNodeList;                        for (VNode contact : pimContacts) {                                ContactStruct contactStruct=ContactStruct.constructContactFromVNode(contact, 1);                // 获取备份文件中的联系人电话信息                List phoneDataList = contactStruct.phoneList;                List phoneInfoList = new ArrayList();                for(PhoneData phoneData : phoneDataList){                    ContactInfo.PhoneInfo phoneInfo = new ContactInfo.PhoneInfo();                    phoneInfo.number=phoneData.data;                    phoneInfo.type=phoneData.type;                    phoneInfoList.add(phoneInfo);                }                                // 获取备份文件中的联系人邮箱信息                List emailList = contactStruct.contactmethodList;                List emailInfoList = new ArrayList();                // 存在 Email 信息                if (null!=emailList)                {                    for (ContactMethod contactMethod : emailList)                    {                        if (Contacts.KIND_EMAIL == contactMethod.kind)                        {                            ContactInfo.EmailInfo emailInfo = new ContactInfo.EmailInfo();                            emailInfo.email = contactMethod.data;                            emailInfo.type = contactMethod.type;                            emailInfoList.add(emailInfo);                        }                    }                }                ContactInfo info = new ContactInfo(contactStruct.name).setPhoneList(phoneInfoList).setEmail(emailInfoList);                contactInfoList.add(info);            }                        return contactInfoList;        }                /**         * 向手机中录入联系人信息         * @param info 要录入的联系人信息         */        public void addContacts(Activity context, ContactInfo info){            ContentValues values = new ContentValues();            //首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId            Uri rawContactUri = context.getContentResolver().insert(RawContacts.CONTENT_URI, values);            long rawContactId = ContentUris.parseId(rawContactUri);                        //往data表入姓名数据            values.clear();            values.put(Data.RAW_CONTACT_ID, rawContactId);            values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);            values.put(StructuredName.GIVEN_NAME, info.getName());            context.getContentResolver().insert(                    android.provider.ContactsContract.Data.CONTENT_URI, values);                        // 获取联系人电话信息            List phoneList = info.getPhoneList();            /** 录入联系电话 */            for (ContactInfo.PhoneInfo phoneInfo : phoneList) {                values.clear();                values.put(android.provider.ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId);                values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);                // 设置录入联系人电话信息                values.put(Phone.NUMBER, phoneInfo.number);                values.put(Phone.TYPE, phoneInfo.type);                // 往data表入电话数据                context.getContentResolver().insert(                        android.provider.ContactsContract.Data.CONTENT_URI, values);            }                        // 获取联系人邮箱信息            List emailList = info.getEmail();                        /** 录入联系人邮箱信息 */            for (ContactInfo.EmailInfo email : emailList) {                values.clear();                values.put(android.provider.ContactsContract.Contacts.Data.RAW_CONTACT_ID, rawContactId);                values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);                // 设置录入的邮箱信息                values.put(Email.DATA, email.email);                values.put(Email.TYPE, email.type);                // 往data表入Email数据                context.getContentResolver().insert(                        android.provider.ContactsContract.Data.CONTENT_URI, values);            }                    }            }}


 

// 获取联系人处理实例        ContactInfo.ContactHandler handler=ContactInfo.ContactHandler.getInstance();                switch (id) {        case R.id.save_linkman:            // 获取要备份的信息            List _infoList = handler.getContactInfo(this);            handler.backupContacts(this, _infoList);    // 备份联系人信息            break;        case R.id.restore_linkman:    // 恢复            try {                // 获取要恢复的联系人信息                List infoList = handler.restoreContacts();                for (ContactInfo contactInfo : infoList) {                    // 恢复联系人                    handler.addContacts(this, contactInfo);                }                                Toast.makeText(this, "导入联系人信息成功!", Toast.LENGTH_LONG);                            } catch (Exception e) {                Toast.makeText(this, "导入联系人信息失败!", Toast.LENGTH_SHORT).show();                e.printStackTrace();            }                        break;        }


由于要对存储卡做读写操作,记得要加读写权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">uses-permission> 

 http://download.csdn.net/detail/yongsdm/6407495

更多相关文章

  1. Android 模拟登陆 保存密码(信息)到手机中 文件信息读取
  2. android studio的安装信息
  3. 获取android系统信息或应用程序信息
  4. iOS、Android获取文件头信息
  5. 【Android】获取apk的版本及包名等信息
  6. android > 获取 通讯录 信息
  7. 【Android】【应用信息】获取应用列表
  8. Android 获取系统应用信息

随机推荐

  1. 完美解决listView滚动条隐藏的问题!
  2. 拥抱 Android Studio 之一:从 ADT 到 Andr
  3. 【魔幻塔防】60关配置文件
  4. ch020 Android SQLite3(第二部分)
  5. 对话框大合集
  6. Android录音实现——使用AtudioRecord
  7. Android Studio学习之-控件总结
  8. Android实现根据条件自动转换手机震动和
  9. Android应用安全之Android平台上的跨应用
  10. android:taskAffinity && android:allowT