Simplifying Interaction with Contacts

Dave Smith
Dave Smith

With the introduction of the new ContactsContract to replace the previous Contacts API in Android 2.0, came a drastic increase in both functional capability and API complexity for applications wishing to interact with the Contacts Provider. This level of access allows applications to make very detailed and specific additions and updates to the Contacts/People database on the device; however it can make some of the common simpler operations seem like they require an unnecessary amount of code.

We are going to look at some ways to try to simplify some common interactions that an application may need to have with the Contacts Provider through the use of a few Intents that ContactsContract provides. In this article, we are going to use Intents to let the existing device Contacts UI handle the following operations, simply returning a result to our application where appropriate:

  • Selecting a contact
  • Adding a new contact
  • Searching for an existing contact to edit

The ContactsContract API certainly provides all the functionality necessary for you to build your own UI to manage the data your application is interested in by way of making queries, updates, and inserts on the URIs for each table in the Content Provider. However, in many cases the system-defined UI for these tasks is not only adequate, but helps provide a consistent experience to the user.

Selecting (Picking) A Contact

This operation involves displaying a list of the the users contacts so they can select one to perform further actions on (perhaps to send that person and email or call them). Rather than creating your own picker UI, you can use the following code to create an Intent and launch the Contacts application’s existing picker:

Intent intent = new Intent(Intent.ACTION_PICK);
intent.setData(ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);

Since we have launched the new Activity expecting a result, onActivityResult() will be called when the user is finished, and the data Uri will contain a lookup URI that can be used to inspect the details of the Contact selected by the user:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if(requestCode == PICK_CONTACT && resultCode == RESULT_OK) {
    //returns a lookup URI to the contact just selected
    Uri selectedContact = data.getData();
  }
}

Adding a New Contact

This operation involves inserting a new contact on the user’s device. Due to the large number of tables involved in storing all the common kinds of data (phone, email, address, etc.), constructing this insert using the raw provider queries can be quite daunting. ContactsContract provides a series of actions and extras in the ContactsContract.Intents.Insert utility class.

Intent intent = new Intent(Intent.ACTION_INSERT);
intent.setType(ContactsContract.Contacts.CONTENT_TYPE);

// Just two examples of information you can send to pre-fill data
intent.putExtra(ContactsContract.Intents.Insert.NAME, "Dave Smith");
intent.putExtra(ContactsContract.Intents.Insert.COMPANY, "Xcellent Creations, Inc.");
startActivityForResult(intent, ADD_CONTACT);

There is a host of extras defined in ContactsContract.Intents.Insert that can be used to pre-fill data in the add form, but here is a list of some more common choices:

  • ContactsContract.Intents.Insert.NAME
    • Full name of the new contact
  • ContactsContract.Intents.Insert.COMPANY
    • Company/Organization of the new contact
  • ContactsContract.Intents.Insert.EMAIL
    • Email address of the new contact
  • ContactsContract.Intents.Insert.PHONE
    • Phone number of the new contact
  • ContactsContract.Intents.Insert.POSTAL
    • Address for the new contact

As with the picker, launching the new Activity with a result expectation will call onActivityResult() with a lookup Uri for the newly created Contact record, so that your application can display the details of the insert if you wish.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if(requestCode == ADD_CONTACT && resultCode == RESULT_OK) {
    //returns a lookup URI to the contact just inserted
    Uri newContact = data.getData();
  }
}

Search for a Contact

Finally, the ContactsContract API includes another convenience intent to look for a specific contact record by telephone number or email address. The Intent action ContactsContract.Intents.SHOW_OR_CREATE_CONTACT can be passed with a mailto: or tel: scheme Uri, and it will search for a matching contact. If a match is found, the contacts details are displayed for further review or editing (all within the standard Contacts application UI). If no match is found, by default a dialog will be displayed asking if the user would like to create a contact with the given email or phone.

Intent intent = new Intent(ContactsContract.Intents.SHOW_OR_CREATE_CONTACT);
//PICK ONE of the following:
//For searching via telephone number
// intent.setData(Uri.fromParts("tel", "8001234567", null));
//For searching via email address
// intent.setData(Uri.fromParts("mailto", "johndoe@gmail.com", null));

//We'll use an email search for the example
intent.setData(Uri.fromParts("mailto", "johndoe@gmail.com", null));

startActivity(intent);

The same extra parameters may be passed along with the Intent to pre-fill the entry form in case the matched contact is edited or if the user opts to create a new contact. In addition, a special extra is defined (ContactsContract.Intents.EXTRA_FORCE_CREATE) that allows you to skip over the user dialog and immediately open the create contact form if no matches are found.

Here is an example that includes some fields to be pre-filled and skips the dialog for creating a new contact:

Intent intent = new Intent(ContactsContract.Intents.SHOW_OR_CREATE_CONTACT);
intent.setData(Uri.fromParts("tel", "8001234567", null));

//If no match and we create, skip the user prompt dialog
intent.putExtra(ContactsContract.Intents.EXTRA_FORCE_CREATE, true);

//Values to tag along for an insert
intent.putExtra(ContactsContract.Intents.Insert.NAME, "David Smith");
intent.putExtra(ContactsContract.Intents.Insert.COMPANY, "Xcellent Creations, Inc.");

startActivity(intent);

Notice in this case that we aren’t interested in any result returned by the Contacts application. With the SHOW_OR_CREATE_CONTACT Intent, no interesting data is returned from the operation.

Hopefully these tips will help take the complexity out of using the Contacts API for those cases where your application does not need to utilize the full access of the Content Provider!