Android联系人显示姓名和电话号码(s)在单一数据库查询



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

这是我一直在处理的查询,但它导致

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)

想法吗?我认为可能需要一个连接来获取单个查询中的所有列。

试试下面的代码:

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());
}

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

如果你有时间,请阅读ContactContract和ContactsProvider2。

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

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

API的工作原理是这样的:选择最底部的元素(电话号码)并隐式连接到最顶部的元素(联系人)。

您希望使用PHONE URI大小写(ContactsProvider2/line 4377)。这应该选择所有的电话号码,并加入到联系人。

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

电话号码存储在单独的表中,需要单独查询。要查询电话号码表,请使用存储在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子句用于限制返回的数据

最新更新