Контакты Android Отображать имя и номера телефонов в одном запросе к базе данных? - PullRequest
49 голосов
/ 05 июля 2011

Я пытаюсь получить список контактов из собственной базы данных с их отображаемым именем и номером телефона (любой или все). Существует много способов получения этой информации с помощью нескольких запросов к базе данных телефона, но это приводит к значительным накладным расходам.

Вот запрос, над которым я работал, но он приводит к

Uri uri                = ContactsContract.Contacts.CONTENT_URI;
String[] projection    = new String[] { ContactsContract.Contacts._ID,
                                        ContactsContract.Contacts.DISPLAY_NAME,
                                        ContactsContract.CommonDataKinds.Phone.NUMBER};
String selection       = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
String[] selectionArgs = null;
String sortOrder       = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

Cursor people          = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);

int index_id    = people.getColumnIndex(ContactsContract.Contacts._ID);
int indexName   = people.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

people.moveToFirst();
do {
    String _id    = people.getString(index_id);
    String name   = people.getString(indexName);
    String number = people.getString(indexNumber);
    // Do work...
} while (people.moveToNext());

А вот и полученная ошибка.

E/AndroidRuntime(21549): Caused by: java.lang.IllegalArgumentException: Invalid column data1
E/AndroidRuntime(21549):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:144)
E/AndroidRuntime(21549):    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:114)
E/AndroidRuntime(21549):    at android.content.ContentProviderProxy.bulkQueryInternal(ContentProviderNative.java:372)
E/AndroidRuntime(21549):    at android.content.ContentProviderProxy.query(ContentProviderNative.java:408)
E/AndroidRuntime(21549):    at android.content.ContentResolver.query(ContentResolver.java:264)

Мысли? Я полагаю, что объединение может быть необходимо для получения всех столбцов в одном запросе.

Ответы [ 3 ]

104 голосов
/ 06 июля 2011

Попробуйте этот код:

Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
String[] projection    = new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER};

Cursor people = getContentResolver().query(uri, projection, null, null, null);

int indexName = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
int indexNumber = people.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

if(people.moveToFirst()) {
    do {
        String name   = people.getString(indexName);
        String number = people.getString(indexNumber);
        // Do work...
    } while (people.moveToNext());
}
14 голосов
/ 06 июля 2011

API контактов чрезвычайно сложен и имеет несколько неявных объединений .

Прочитайте ContactContract и ContactsProvider2 , если вы можете позволить себе время.

Что ты хочешь?Таблицы связаны следующим образом:

  • Контакт 1 - * Необработанный контакт
  • Необработанный контакт 1 - * Номер телефона (таблица данных)

API работает следующим образом: вы выбираете самый нижний элемент (номер телефона) и неявное присоединение к самому верхнему элементу (контакту).

Вы хотите использовать случай PHONE URI (ContactsProvider2 / строка 4377).Это должно выбрать все телефонные номера и присоединиться к контакту.

Объедините URI телефона с некоторой магией пользовательского интерфейса (для группировки), запросите DISPLAY_NAME и номер телефона (DATA1?), И вы сможете решитьпроблема.

1 голос
/ 24 марта 2015

Телефонные номера хранятся в отдельной таблице и должны запрашиваться отдельно. Для запроса таблицы телефонных номеров используйте URI, хранящийся в переменной SDK ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Используйте условие WHERE, чтобы получить номера телефонов для указанного контакта.

private String displayName(Uri contactUri) {
        HashSet detail = ContactDetail.getInstance().getContactArray();
        Log.d("ITEM", contactUri.toString());
        String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
        Cursor queryCursor = getActivity().getContentResolver()
                .query(contactUri, null, null, null, null);
        queryCursor.moveToFirst();
        String name = queryCursor.getString(queryCursor.getColumnIndex("display_name"));
        String id = queryCursor.getString(
                queryCursor.getColumnIndex(ContactsContract.Contacts._ID));

        if (Integer.parseInt(queryCursor.getString(queryCursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
            Cursor pCur = getActivity().getContentResolver().query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                    new String[]{id}, null);
            while (pCur.moveToNext()) {
                String number = pCur.getString(pCur.getColumnIndex("data1"));
                Log.d("Contact Name: ", number);
            }
            pCur.close();
        }


        return name;
    }

Выполните второй запрос к базе данных SQLite контактов Android. Телефонные номера сопоставляются с URI, хранящимся в ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Идентификатор контакта хранится в таблице телефона как ContactsContract.CommonDataKinds.Phone.CONTACT_ID, а предложение WHERE используется для ограничения возвращаемых данных.

...