Search code examples
androidandroid-intentandroid-contentproviderandroid-contacts

Get specific contact information from URI returned from Intent.ACTION_PICK


I am writing an Android app that has a data type that represents a person (specifically, the parent or guardian of a child). I'd like to be able to "import" the relevant data fields from the Contacts database in the Android device. (This should be optional; that is, it will not be a requirement that the parent/guardian is already in the Contacts database, nor will the Contacts database be updated if they add new parents/guardians.)

So far, I have written code to start a new Intent to choose the specific Contact (using Intent.ACTION_PICK). I then get a URI that represents a specific Contact in the database.

Unfortunately, I don't know what the next step is. It seems like this should be the simplest thing in the world to do, but apparently not. I've read through the documentation on the Android developer website, and I've looked through more than one Android book. No joy.

The specific information I'd like to get, is:

  1. The contact's name (first and last separately if possible)

  2. The contact's (primary) email address

  3. The contact's cell phone number

I imagine that this should be possible by querying using the ContentResolver, but I have no idea how to do this with the URI returned from the Intent. Most of the documentation assumes you have the Contact ID, not the Contact's URI. Also, I have no idea what kind of fields I can put into the projection for the query, assuming that this is even the right way to do what I want.

Here is my starting code:

// In a button's onClick event handler:
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);

// In onActivityResult:
if (resultCode == RESULT_OK) {
    if (requestCode == PICK_CONTACT) {
        contactURI = data.getData();
        // NOW WHAT?
    }
}

Solution

  • As it turns out, there is a better way to do this.

    As I mentioned, the ContactsContract.Contacts.Entity class was not available until API 11. However, the ContactsContract.Data class was available way back in API 5, and you can use that class in largely the same way that you use the Entity class.

    I've updated my code. It is very similar to the code for the Entity class, and works largely the same way. However, I've tested it with my phone running Gingerbread, and it works just fine.

    One change I had to make is this: There doesn't seem to be a way to get the ContactsContract.Data.RAW_CONTACT_ID from the initial query, and that ID is not the same as the ID you get from e.g. ContactsContract.Contacts._ID. Instead, I queried on the ContactsContract.Contacts.DISPLAY_NAMEconstant, which is consistent across pretty much every ContactsContract class.

    Here's the working code:

            Cursor cursor;  // Cursor object
            String mime;    // MIME type
            int dataIdx;    // Index of DATA1 column
            int mimeIdx;    // Index of MIMETYPE column
            int nameIdx;    // Index of DISPLAY_NAME column
    
            // Get the name
            cursor = getContentResolver().query(params[0],
                    new String[] { ContactsContract.Contacts.DISPLAY_NAME },
                    null, null, null);
            if (cursor.moveToFirst()) {
                nameIdx = cursor.getColumnIndex(
                        ContactsContract.Contacts.DISPLAY_NAME);
                name = cursor.getString(nameIdx);
    
                // Set up the projection
                String[] projection = {
                        ContactsContract.Data.DISPLAY_NAME,
                        ContactsContract.Contacts.Data.DATA1,
                        ContactsContract.Contacts.Data.MIMETYPE };
    
                // Query ContactsContract.Data
                cursor = getContentResolver().query(
                        ContactsContract.Data.CONTENT_URI, projection,
                        ContactsContract.Data.DISPLAY_NAME + " = ?",
                        new String[] { name },
                        null);
    
                if (cursor.moveToFirst()) {
                    // Get the indexes of the MIME type and data
                    mimeIdx = cursor.getColumnIndex(
                            ContactsContract.Contacts.Data.MIMETYPE);
                    dataIdx = cursor.getColumnIndex(
                            ContactsContract.Contacts.Data.DATA1);
    
                    // Match the data to the MIME type, store in variables
                    do {
                        mime = cursor.getString(mimeIdx);
                        if (ContactsContract.CommonDataKinds.Email
                                .CONTENT_ITEM_TYPE.equalsIgnoreCase(mime)) {
                            email = cursor.getString(dataIdx);
                        }
                        if (ContactsContract.CommonDataKinds.Phone
                                .CONTENT_ITEM_TYPE.equalsIgnoreCase(mime)) {
                            phone = cursor.getString(dataIdx);
                            phone = PhoneNumberUtils.formatNumber(phone);
                        }
                    } while (cursor.moveToNext());
                }
            }