Skip to content

Instantly share code, notes, and snippets.

@ggcespia
Last active April 28, 2020 18:42
Show Gist options
  • Save ggcespia/c5d521a4d2444c82e436bb490c56f6e2 to your computer and use it in GitHub Desktop.
Save ggcespia/c5d521a4d2444c82e436bb490c56f6e2 to your computer and use it in GitHub Desktop.
Create Contact Entry in Android SDK

In the 'old' days, you had to make 2 different interfaces to add contacts programmatically to Android. There was an SDK3 and SDK5 solution (yes, that long ago). Now, you may use a single API to add contact information to Android Contacts programmatically. As an FYI, I've developed Android, BREW, BlackBerry, J2ME, Palm OS, Symbian Series 40 and 60, iOS, Windows Mobile, Windows Phone and Windows 10 cross platform apps starting in 2002. The downside to the 'old' way is that you need WRITE_CONTACTS permission (and sometimes READ_CONTACTS) -these were triggered by using cr.applyBatch.

Today, you can accomplish the same task without requiring those permissions by using an Intent. The 'trick' with the intent is in the intent.putExtra(Insert.POSTAL, addr) and intent.putExtra(ContactsContract.Intents.Insert.Name, sName) values ALONG WITH using the putParcelableArrayListExtra function. Remember, you have to add the Insert.POSTAL and Insert.NAME along with the parcelable array.

Here is a sample that parses a VCard and opens the Contacts intent pre-populated with the data you need.
BPSocket.spit(string, char) splits the string on the character (BPSocket abstracted this to be cross platform) BBUtils.Utf8Decode(BPSocket.URLdecode(string)) - Again, abstracted calls to URL Decode the string (removing %xx, etc.) and then decoding that into UTF8 text (the string came from a url call).

public Uri AddVCard(String vCardData, Activity ctx) {
    Uri newContactUri = null;
    ArrayList<ContentValues> data = new ArrayList<ContentValues>();

    String[] arSplit = BPSocket.split(vCardData, '&');
    String sOrg = "";
    String sTitle = "";

    Intent intent = new Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI);

    for (int i=0; i<arSplit.length; i++) {
        String keyv = arSplit[i];
        int ixEq = keyv.indexOf('=');

        if (ixEq != -1 && ixEq < keyv.length() - 1) {
            String decoded = BBUtils.Utf8Decode(BPSocket.URLdecode(keyv.substring(ixEq + 1)));
            if (keyv.startsWith("N=")) {
                boolean bAdd = false;
                String sFirst = "";
                String sLast = "";
                String[] arNames = BPSocket.split(decoded, ';');    // last;first;prefix;suffix
                ContentValues nameValues = new ContentValues();
                nameValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);

                if (arNames.length > 0) {   // FAMILY_NAME
                    sLast = arNames[0];
                    nameValues.put(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, sLast);
                    bAdd = true;
                }
                if (arNames.length > 1) {   // GIVEN_NAME
                    sFirst = arNames[1];
                    nameValues.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, sFirst);
                    bAdd = true;
                }
                if (arNames.length> 2) {    // PREFIX
                    nameValues.put(ContactsContract.CommonDataKinds.StructuredName.PREFIX, arNames[2]);
                    bAdd = true;
                }
                if (arNames.length > 3) {   // SUFFIX
                    nameValues.put(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, arNames[3]);
                    bAdd = true;
                }
                if (bAdd) {
                    String sName = "";
                    if (sFirst.length()> 0)
                        sName += sFirst;
                    if (sLast.length() > 0) {
                        if (sName.length() > 0)
                            sName += " ";
                        sName += sLast;
                    }

                    if (sName.length() > 0) {
                        nameValues.put(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, sName);
                        intent.putExtra(ContactsContract.Intents.Insert.NAME, sName);
                    }

                    data.add(nameValues);
                }

            } else if (keyv.startsWith("TITLE=")) {
                sTitle = decoded;
            } else if (keyv.startsWith("ORG=")) {       // org name;level1;level2
                sOrg = decoded;
            } else if (keyv.startsWith("EMAIL")) {
                ContentValues emailValues = new ContentValues();
                emailValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
                emailValues.put(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_WORK);
                emailValues.put(ContactsContract.CommonDataKinds.Email.ADDRESS, decoded);
                data.add(emailValues);

            } else if (keyv.startsWith("TEL")) {
                // vcard: home,msg,work,pref,voice,fax,cell,video,pager,bbs,modem,car
                // we support: WORK, FAX, CELL, MSG, HOME, FAX
                boolean bAdd = false;
                ContentValues telValues = new ContentValues();
                telValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
                if (keyv.indexOf("WORK") != -1) {
                    telValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_WORK);
                    bAdd = true;
                } else if (keyv.indexOf("CELL") != -1) {
                    telValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
                    bAdd = true;
                } else if (keyv.indexOf("MSG") != -1) {
                    telValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_PAGER);
                    bAdd = true;
                } else if (keyv.indexOf("HOME") != -1) {
                    telValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_HOME);
                    bAdd = true;
                } else if (keyv.indexOf("FAX") != -1) {
                    telValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK);
                    bAdd = true;
                }
                if (bAdd) {
                    telValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, decoded);
                    data.add(telValues);
                }
            } else if (keyv.startsWith("NICKNAME=")) {
                ContentValues nickValues = new ContentValues();
                nickValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE);
                nickValues.put(ContactsContract.CommonDataKinds.Nickname.NAME, decoded);
                data.add(nickValues);
            } else if (keyv.startsWith("NOTE=")) {
                ContentValues noteValues = new ContentValues();
                noteValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
                noteValues.put(ContactsContract.CommonDataKinds.Note.NOTE, decoded);
                data.add(noteValues);
            } else if (keyv.startsWith("ADR=")) {
                // ADR dom,intl,postal,parcel,home,work,pref =po box;extended addr;street addr;locality(city);region(state);zip;country
                // ADR-WORK=
                // ADR-HOME=
                // ADR - default to Work
                String sAddr = "";
                String[] arAddr = BPSocket.split(decoded, ';');
                ContentValues addrValues = new ContentValues();
                addrValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);

                if (arAddr.length > 0) {  // po box
                    sAddr = arAddr[0];
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.POBOX, arAddr[0]);
                }
                if (arAddr.length > 2) { // street addr
                    sAddr = arAddr[2];
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.STREET, arAddr[2]);
                }
                if (arAddr.length > 3) { // locality
                    if (sAddr.length() > 0)
                        sAddr += ", ";
                    sAddr += arAddr[3];
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY, arAddr[3]);
                }
                if (arAddr.length > 4) {  // region
                    if (sAddr.length() > 0)
                        sAddr += ", ";
                    sAddr += arAddr[4];
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION, arAddr[4]);
                }
                if (arAddr.length > 5) { // zip
                    if (sAddr.length() > 0)
                        sAddr += " ";
                    sAddr += arAddr[5];
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, arAddr[5]);
                }
                if (arAddr.length > 6) { // county
                    if (sAddr.length() > 0)
                        sAddr += ", ";
                    sAddr += arAddr[6];
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, arAddr[6]);
                }

                if (keyv.indexOf("HOME") != -1) {
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME);
                }  else {
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK);
                }
                if (sAddr.length() > 0) {
                    addrValues.put(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, sAddr);
                    intent.putExtra(Insert.POSTAL, sAddr);
                }
                data.add(addrValues);
            }
        }
    }

    if (sTitle.length() > 0 || sOrg.length() > 0) {
        ContentValues orgValues = new ContentValues();
        orgValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
        if (sOrg.length() > 0)
            orgValues.put(ContactsContract.CommonDataKinds.Organization.COMPANY, sOrg);
        if (sTitle.length() > 0)
            orgValues.put(ContactsContract.CommonDataKinds.Organization.TITLE, sTitle);
        data.add(orgValues);
    }

    intent.putParcelableArrayListExtra(Insert.DATA, data);

    ctx.startActivity(intent);

    return newContactUri;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment