我试图从本地数据库获取联系人列表,其中包含显示名称和电话号码(任何或全部)。有许多方法可以通过对电话数据库的多次查询来获得这些信息,但是这会带来相当大的开销。
这是我一直在处理的查询,但它导致
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子句用于限制返回的数据