50

我正在尝试从本机数据库中获取联系人列表及其显示名称和电话号码(任何或全部)。有许多方法可以通过对手机数据库的多次查询来获取此信息,但这会带来相当大的开销。

这是我一直在处理的查询,但结果是

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)

想法?我相信可能需要连接才能在单个查询中获取所有列。

4

3 回答 3

105

试试这个代码:

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());
}
于 2011-07-05T20:20:19.813 回答
14

联系人 API 非常棘手,并且有几个隐式连接

如果您有时间,请阅读ContactContractContactsProvider2 。

你想要什么?这些表是这样链接的:

  • 联系人 1--* 原始联系人
  • 原始联系人 1--* 电话号码(数据表)

API 的工作方式如下:您选择最底部的元素(电话号码)并隐式连接到最顶部的元素(联系人)。

您想使用 PHONE URI 案例(ContactsProvider2 / 第 4377 行)。这应该选择所有电话号码并加入联系人。

将 PHONE uri 与一些 UI 魔术(用于分组)结合起来,请求 DISPLAY_NAME 和 PHONE 号码(DATA1?),您应该能够解决问题。

于 2011-07-05T20:09:41.990 回答
1

电话号码存储在自己的表中,需要单独查询。要查询电话号码表,请使用存储在 SDK 变量 ContactsContract.CommonDataKinds.Phone.CONTENT_URI 中的 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;
    }

对 Android 联系人 SQLite 数据库执行第二次查询。根据存储在 ContactsContract.CommonDataKinds.Phone.CONTENT_URI 中的 URI 查询电话号码。联系人 ID 作为 ContactsContract.CommonDataKinds.Phone.CONTACT_ID 存储在电话表中,并且 WHERE 子句用于限制返回的数据。

于 2015-03-24T17:43:46.443 回答