Хорошо, после многих копаний я нашел то, что, как я считаю, был ответом. Решения, которые я нашел, отличаются в зависимости от того, какой уровень API Android вы используете. Тем не менее, они совсем не такие, поэтому, если есть лучшие решения, я бы с удовольствием узнал.
В любом случае первым шагом является получение идентификатора контакта, выполнив запрос в URI, возвращенный из Intent.ACTION_PICK. Пока мы здесь, мы также должны получить отображаемое имя, а строка, представляющая, имеет ли контакт номер телефона или нет. (Мы не будем нуждаться в них для современного решения, но мы будем нуждаться в них для устаревшего решения.)
String id, name, phone, hasPhone;
int idx;
Cursor cursor = getContentResolver().query(contactUri, null, null, null, null);
if (cursor.moveToFirst()) {
idx = cursor.getColumnIndex(ContactsContract.Contacts._ID);
id = cursor.getString(idx);
idx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
name = cursor.getString(idx);
idx = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
hasPhone = cursor.getString(idx);
}
Для записи столбцы, возвращенные из этого URI, являются большей частью полями, представленными константами в ContactsContract.Profile (включая константы, унаследованные от других интерфейсов). Не включены PHOTO_FILE_ID, PHOTO_THUMBNAIL_URI или PHOTO_URI (но PHOTO_ID есть ).
Теперь, когда у нас есть идентификатор, нам нужно получить соответствующие данные. Первое (и самое простое) решение - запросить Entity. Запросы Entity запрашивают сразу все данные контактов для контакта или необработанного контакта. Каждая строка представляет собой один Raw Contact, доступ к которому осуществляется с помощью констант в ContactsContract. Contacts.Entity . Обычно вы будете иметь дело только с RAW_CONTACT_ID, DATA1 и MIMETYPE. Однако, если вы хотите, чтобы имя и фамилия были указаны отдельно, тип имени MIME содержит имя в DATA2 и фамилию в DATA3.
Вы загружаете переменные, сопоставляя столбец MIMETYPE с ContactsContract.CommonDataKinds константы; например, тип MIME для электронной почты находится в ContactsContract.CommonDataKinds. Email.CONTENT_ITEM_TYPE .
// Build the Entity URI.
Uri.Builder b = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, id).buildUpon();
b.appendPath(ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);
URI contactUri = b.build();
// Create the projection (SQL fields) and sort order.
String[] projection = {
ContactsContract.Contacts.Entity.RAW_CONTACT_ID,
ContactsContract.Contacts.Entity.DATA1,
ContactsContract.Contacts.Entity.MIMETYPE };
String sortOrder = ContactsContract.Contacts.Entity.RAW_CONTACT_ID + " ASC";
cursor = getContentResolver().query(contactUri, projection, null, null, sortOrder);
String mime;
int mimeIdx = cursor.getColumnIndex(ContactsContract.Contacts.Entity.MIMETYPE);
int dataIdx = cursor.getColumnIndex(ContactsContract.Contacts.Entity.DATA1);
if (cursor.moveToFirst()) {
do {
mime = cursor.getString(mimeIdx);
if (mime.equalsIgnoreCase(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
email = cursor.getString(dataIdx);
}
if (mime.equalsIgnoreCase(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
phone = cursor.getString(dataIdx);
}
//...etc.
} while (cursor.moveToNext());
}
К сожалению, Entities не были внедрены в API 11 (Android 3.0, Honeycomb), что означает, что этот код несовместим с примерно 65% устройств Android на рынке (на момент написания этой статьи). Если вы попробуете, вы получите IllegalArgumentException из URI.
Второе решение - построить строку запроса и сделать один запрос для каждого типа данных, который вы хотите использовать:
// Get phone number - if they have one
if ("1".equalsIgnoreCase(hasPhone)) {
cursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = "+ id,
null, null);
if (cursor.moveToFirst()) {
colIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
phone = cursor.getString(colIdx);
}
cursor.close();
}
// Get email address
cursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + id,
null, null);
if (cursor.moveToFirst()) {
colIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS);
email = cursor.getString(colIdx);
}
cursor.close();
// ...etc.
Очевидно, что это приведет к множеству отдельных запросов к базе данных, поэтому по соображениям эффективности это не рекомендуется.
Решение, которое я придумал, - попробовать версию, которая использует запросы Entity, поймать IllegalArgumentException и поместить унаследованный код внутри блока catch:
try {
//Build the Entity URI.
Uri.Builder b = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, id).buildUpon();
b.appendPath(ContactsContract.Contacts.Entity.CONTENT_DIRECTORY);
//...etc...
} catch (IllegalArgumentException e) {
//Get phone number - if they have one
if ("1".equalsIgnoreCase(hasPhone)) {
//...etc...
} finally {
//If you want to display the info in GUI objects, put the code here
}
Я надеюсь, что это помогает кому-то. И, опять же, если есть лучшие способы сделать это, я все уши.