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:
The contact's name (first and last separately if possible)
The contact's (primary) email address
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?
}
}
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_NAME
constant, 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());
}
}