Advertisement
Android SDK

Android Essentials: Using the Contact Picker

by

This tutorial will not only show you how to launch the contact picker and get results, but also how to use those results in Android SDK 2.0 and above.

Getting Started

This tutorial will start out simple, but then we’ll get in to some of the technical details of using Contacts with the ContactsContract class, which was introduced in API Level 5. Make sure you have your Android development environment installed and configured correctly. You’re free to build upon any application you have, start a new one from scratch, or follow along using the InviteActivity code in our open source project.

We’ll then be adding functionality to allow a user to choose one of their existing contacts and send a canned message to them. We’re going to dive right in, so have all of your code and tools ready. Finally, make sure your device or emulator has some contacts configured (with names and emails) within the Contacts application.

Step 1: Creating Your Layout

There are two essential form controls necessary for the contact picker to work. First, we need an EditText field where the resulting email will show. Second, we need some way for the user to launch the contact picker. A Button control works well for this.

The following Layout segment has both of these elements defined appropriately:

<RelativeLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent">
    <EditText
        android:layout_height="wrap_content"
        android:hint="@string/invite_email_hint"
        android:id="@+id/invite_email"
        android:inputType="textEmailAddress"
        android:layout_width="wrap_content"
        android:layout_toLeftOf="@+id/do_email_picker"
        android:layout_alignParentLeft="true"></EditText>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/do_email_picker"
        android:text="@string/pick_email_label"
        android:layout_alignParentRight="true"
        android:onClick="doLaunchContactPicker"></Button>
</RelativeLayout>

This layout XML is part of a larger layout. Here’s what it looks like in the layout designer, complete with the string resources filled out:

Using Contact Picker

Step 2: Launching the Contact Picker

Now you need to write the code to handle the Button push, which will launch the contact picker. One of the most powerful features of the Android platform is that you can leverage other applications’ functionality by using the Intent mechanism. An Intent can be used along with the startActivityForResult() method to launch another Android application and retrieve the result. In this case, you can use an Intent to pick a contact from the data provided by the Contacts content provider.

Here’s the implementation of doLaunchContactPicker():

import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.CommonDataKinds.Email;

private static final int CONTACT_PICKER_RESULT = 1001;

public void doLaunchContactPicker(View view) {
    Intent contactPickerIntent = new Intent(Intent.ACTION_PICK,
            Contacts.CONTENT_URI);
    startActivityForResult(contactPickerIntent, CONTACT_PICKER_RESULT);
}

Note: The import commands are important here. Make sure you’re using the Contacts class from the ContactsContract and not the older android.provider.Contacts one.

Once launched, the contacts picker in your application will look something like this:

Using Contact Picker

Step 3: Handling the Results

Now you are ready to handle the results of the picker. Once the user taps on one of the contacts in the picker, focus will return to the calling Activity (your application’s Activity). You can grab the result from the contacts picker by implementing the onActivityResult() method of your Activity. Here you can check that the result matches your requestCode and that the result was good. Your onActivityResult() method implementation should be structured like this:

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
            case CONTACT_PICKER_RESULT:
                // handle contact results
                break;
            }

        } else {
            // gracefully handle failure
            Log.w(DEBUG_TAG, "Warning: activity result not ok");
        }
    }

You’ll get a result other than RESULT_OK if the user cancels the operation or if something else goes wrong.

Step 4: Reading the Result Data

The final parameter to onActivityResult is an Intent called “data.” This parameter contains the results data we are looking for. Different Intents will return different types of results. One option for inspecting the results is to display everything found in the Extras bundle in addition to the data Uri. Here’s a code snippet that will show all of the Extras, should any exist:

Bundle extras = data.getExtras();
Set keys = extras.keySet();
Iterator iterate = keys.iterator();
while (iterate.hasNext()) {
    String key = iterate.next();
    Log.v(DEBUG_TAG, key + "[" + extras.get(key) + "]");
}
Uri result = data.getData();
Log.v(DEBUG_TAG, "Got a result: "
    + result.toString());

We’re not really interested in the Extras bundle for the contacts picker because it doesn’t contain the information we need. We just want the Uri which will lead us to the important contact details.

Step 5: Understanding the Result

In the onActivityResult() callback, we are supplied the Uri to the specific contact that the user chose from the contact picker. Using this Uri directly would allow us to get the basic Contact data, but no details. However, we are interested in determining the email address of the contact. So, an easy way to deal with this is to just grab the contact id from the Uri, which is the number at the end of the path:

The full Uri looks something like:

content://com.android.contacts/contacts/lookup/0r7-2C46324E483C324A3A484634/7

In this case, the resulting id would simply be 7.
We can retrieve the contact identifier using the getLastPathSegment() method, as follows:

// get the contact id from the Uri
String id = result.getLastPathSegment();

Step 6: Querying the Contacts Database for Email

Now that you have the identifier for the chosen contact, you have all the information you need to query the Contacts content provider directly for that contact’s email address. Android content providers are a powerful way of sharing data amongst applications. The interface to them is similar to that of a database and many are database backed, using SQLite, but they need not be.

One way you can query the contacts content provider for the appropriate contact details is by using the default ContentResolver with one of the ContactsContract.CommonDataKinds subclasses. For email, you can use the ContactsContract.CommonDataKinds.Email class as follows:

// query for everything email
cursor = getContentResolver().query(
        Email.CONTENT_URI, null,
        Email.CONTACT_ID + "=?",
        new String[]{id}, null);

Some other useful ContactsContract.CommonDataKinds subclasses include Phone, Photo, Website, Nickname, Organization, and StructuredPostal.

Step 7: Viewing the Query Results

Certainly, you could read the class documentation for the ContactsContract.CommonDataKinds.Email class and determine what kind of results to expect. However, this is not always the case so let’s inspect the results of this call. This is a very handy trick if you are working with a content provider that has less-than-adequate documentation, or is not behaving as expected.

This snippet of code will show you, via LogCat output, every column and value that is returned from the query to the content provider:

cursor.moveToFirst();
String columns[] = cursor.getColumnNames();
for (String column : columns) {
    int index = cursor.getColumnIndex(column);
    Log.v(DEBUG_TAG, "Column: " + column + " == ["
            + cursor.getString(index) + "]");

Now you can see that, indeed, they really did mean for the email to come back via a column called DATA1, aliased to Email.DATA. The Android Contacts system is very flexible, and this sort of generic column name shows where some of that flexibility comes from. The email type, such as Home or Work, is found in Email.TYPE.

Step 8: Retrieving the Email

We have all of the data we need to actually get the email address, or addresses, of the contact picked by the user. When using database Cursors, we have to make sure they are internally referencing a data row we’re interested in, so we start with a call to the moveToFirst() method and make sure it was successful. For this tutorial, we won’t worry about multiple email addresses. Instead, we’ll just use the first result:

if (cursor.moveToFirst()) {
    int emailIdx = cursor.getColumnIndex(Email.DATA);
    email = cursor.getString(emailIdx);
    Log.v(DEBUG_TAG, "Got email: " + email);
}

It’s important to remember that a contact may have many addresses. If you wanted to give the user the option of choosing from multiple email addresses, you could display your own email chooser to pick amongst these after the user has chosen a specific contact.

Step 9: Updating the Form

After all that work to get the email address, don’t forget to update the form. You might also consider informing the user if the contact didn’t have any email address listed.

EditText emailEntry = (EditText)findViewById(R.id.invite_email);
emailEntry.setText(email);
if (email.length() == 0) {
    Toast.makeText(this, "No email found for contact.", Toast.LENGTH_LONG).show();
}

And there it is:

Content Picker

Step 10: Putting it All Together

We skipped over two important items in this tutorial that are worth mentioning now.

First, we didn’t include any error checking; we did this for clarity, but in production code, this is an essential piece of the solution. An easy way to implement some checking would be to to wrap just about everything in a try-catch block.

Second, you need to remember that Cursor objects require management within your Activity lifecycle. Always remember to release Cursor objects when you are done using them.

Here’s the complete implementation of the onActivityResult() method to put these points in perspective:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
        case CONTACT_PICKER_RESULT:
            Cursor cursor = null;
            String email = "";
            try {
                Uri result = data.getData();
                Log.v(DEBUG_TAG, "Got a contact result: "
                        + result.toString());

                // get the contact id from the Uri
                String id = result.getLastPathSegment();

                // query for everything email
                cursor = getContentResolver().query(Email.CONTENT_URI,
                        null, Email.CONTACT_ID + "=?", new String[] { id },
                        null);

                int emailIdx = cursor.getColumnIndex(Email.DATA);

                // let's just get the first email
                if (cursor.moveToFirst()) {
                    email = cursor.getString(emailIdx);
                    Log.v(DEBUG_TAG, "Got email: " + email);
                } else {
                    Log.w(DEBUG_TAG, "No results");
                }
            } catch (Exception e) {
                Log.e(DEBUG_TAG, "Failed to get email data", e);
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
                EditText emailEntry = (EditText) findViewById(R.id.invite_email);
                emailEntry.setText(email);
                if (email.length() == 0) {
                    Toast.makeText(this, "No email found for contact.",
                            Toast.LENGTH_LONG).show();
                }

            }

            break;
        }

    } else {
        Log.w(DEBUG_TAG, "Warning: activity result not ok");
    }
}

You’ve now got everything you need to complete the application. Remember, though, that if you’re working with real data, take care not to spam your friends too much. ☺

Conclusion

In this tutorial, you’ve learned how to launch the Contacts picker and retrieve the chosen result. You also learned how to inspect the results and retrieve the email address for the picked contact using the contacts content provider. You can use this method to retrieve all sorts of information about a given contact.

About the Authors

Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams TeachYourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to androidwirelessdev+mt@gmail.com, via their blog at androidbook.blogspot.com, and on Twitter @androidwireless.

Need More Help Writing Android Apps? Check out our Latest Books and Resources!

Buy Android Wireless Application Development, 2nd Edition  Buy Sam's Teach Yourself Android Application Development in 24 Hours  Mamlambo code at Code Canyon

Related Posts
  • Code
    Android SDK
    Create a Music Player on Android: Project Setup0d63m preview image@2x
    The Android platform provides resources for handling media playback, which your apps can use to create an interface between the user and their music files. In this tutorial series, we will create a basic music player application for Android. The app will present a list of songs on the user device, so that the user can select songs to play. The app will also present controls for interacting with playback and will continue playing when the user moves away from the app, with a notification displayed while playback elapses.Read More…
  • Code
    ASP.NET
    Preventing Code InjectionCsrf dotnet retina preview
    Often, websites seem to exist primarily to put something into a database in order to pull it out later. While other database methods, such as NoSQL, have gained popularity in recent years, data for many websites still resides in the traditional SQL database. This data often consists of valuable personal information such as credit card numbers and other personal information of interest to identity thieves and criminals. Hackers therefore always look to get this data. One of the most common targets of these attacks is the SQL databases that lie behind many web applications through a process of SQL Injection.Read More…
  • Code
    Databases
    Mapping Relational Databases and SQL to MongoDBMongodb retina preview
    NoSQL databases have emerged tremendously in the last few years owing to their less constrained structure, scalable schema design, and faster access compared to traditional relational databases (RDBMS/SQL). MongoDB is an open source document-oriented NoSQL database which stores data in the form of JSON-like objects. It has emerged as one of the leading databases due to its dynamic schema, high scalability, optimal query performance, faster indexing and an active user community.Read More…
  • Code
    Android SDK
    Android SDK: Next StepsAndroid preview@2x
    In this series, we've begun learning how to develop Android applications from scratch. We started exploring the development tools, got acquainted with the basic elements in an application project, looked at user interface design, interactivity, resources, and data, and we've also took a closer look at what happens when your application is running. What we've covered so far should put you in a good position to get started creating functional Android applications, but Android has a lot more to offer so the range of possibilities is virtually endless. You may therefore struggle to choose what to learn next. In this part, we'll wrap up the series by pointing out some possible directions for future learning. After this, the final part will be a quiz on what we covered throughout the series.Read More…
  • Code
    Android SDK
    Android SDK: App DataAndroid preview@2x
    In this series, we are learning about Android SDK development from scratch. We have already become acquainted with the structure and basic elements in an Android application, including the resources, Manifest, and user interface. As soon as you start to develop functional apps for Android, you will need to store data of one kind or another. The Android platform offers a range of options for data storage in your apps, which we will examine in this tutorial.Read More…
  • Code
    Android SDK
    Android SDK: Create a Book Scanning AppBookscanning series preview@2x
    With the ZXing library, you can create Android applications with barcode scanning functionality. In Android SDK: Create a Barcode Reader, we implemented basic barcode reading with the library in a simple app. In this tutorial series, we will build on what we learned to create an app that will scan books and retrieve related information about them from Google Books API.Read More…