如何在单个请求中检索 phone numbers/photo id/firstname/lastname?
How to retrieve phone numbers/photo id/firstname/lastname within a single request?
我目前正在使用这个问题的答案:How to get all contacts first name, last name, email, phone number, etc without duplicates 来检索用户联系人列表,对于每个联系人,所有 phone 号码、名字、姓氏和照片 ID。
我对这个答案的看法是它为每个需要的数据创建一个请求。它在我的应用程序上造成了性能问题。我想从一个请求中检索所有这些信息,但我很难理解 Android 的查询是如何管理的以及我要查找的存储数据在哪里。
我尝试过的例子(我做了很多测试都没有成功,以下是我最后一次尝试的):
new CursorLoader(
this,
ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.HAS_PHONE_NUMBER + "!=0 AND (" + ContactsContract.Data.MIMETYPE + "=?)",
new String[]{ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE},
ContactsContract.Data.CONTACT_ID)
;
以及我要检索的信息:
int firstNameCol = cursor.getColumnIndex(CommonDataKinds.StructuredName.GIVEN_NAME);
int lastNameCol = cursor.getColumnIndex(CommonDataKinds.StructuredName.FAMILY_NAME);
int photoIdCol = cursor.getColumnIndex(CommonDataKinds.StructuredName.PHOTO_ID);
int phoneCol = cursor.getColumnIndex(Phone.NUMBER);
该请求有两个问题:
我每个联系人只有一个 phone 号码,但是我的一些联系人有多个号码,我想找回它们
我没有检索名字和姓氏(我得到的是一个奇怪的数字)
请注意,我不想检索 DISPLAY_NAME,我想要 given_name 和 family_name。另请注意,我希望每个联系人有一个结果,而不是每个 phone 号码有一个结果(即一个结果包含一对多 phone 号码)
有没有想法在单个请求中做到这一点?
编辑:尝试使用来自@pskink 的另一段代码,但我收到 "column '_id' does not exists" 错误
String[] projection = {
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
ContactsContract.CommonDataKinds.StructuredName.PHOTO_ID
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?, ?, ?)";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
ContactsContract.CommonDataKinds.StructuredName.PHOTO_ID
};
//String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
//Uri uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
Uri uri = ContactsContract.Data.CONTENT_URI;
// ok, let's work...
return new CursorLoader(
this, uri, projection, selection, selectionArgs, null
);
感谢@pskink,我现在可以通过一个快速的单一请求来检索我想要的内容。不幸的是,我不能使用 CursorAdapter,我必须请求整个数据库并将结果存储在一个对象模型中,但是结果非常快所以没关系。
完整代码如下:
public ArrayList<ContactModel> retrieveContactList(){
ArrayList<ContactModel> list = new ArrayList<>();
LongSparseArray<ContactModel> array = new LongSparseArray<>();
Set<String> set = new HashSet<String>();
set.add(ContactsContract.Data.MIMETYPE);
set.add(ContactsContract.Data.CONTACT_ID);
set.add(ContactsContract.Data.PHOTO_ID);
set.add(ContactsContract.CommonDataKinds.Phone.NUMBER);
set.add(ContactsContract.CommonDataKinds.Phone.TYPE);
set.add(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
set.add(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
set.add(ContactsContract.Contacts.PHOTO_ID);
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = set.toArray(new String[0]);
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
Cursor cursor = this.context.getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder
);
final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int phoneIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
final int phoneTypeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
final int givenNameIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
final int familyNameIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
final int photoIdIdx = cursor.getColumnIndex(ContactsContract.Data.PHOTO_ID);
while (cursor.moveToNext()) {
long id = cursor.getLong(idIdx);
ContactModel addressBookContact = array.get(id);
if (addressBookContact == null) {
addressBookContact = new ContactModel(id);
array.put(id, addressBookContact);
list.add(addressBookContact);
}
Long photoId = cursor.getLong(photoIdIdx);
if (photoId != null){
addressBookContact.addPhotoId(photoId);
}
switch (cursor.getString(mimeTypeIdx)) {
case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE:
// row's data: see ContactsContract.CommonDataKinds.Phone
addressBookContact.addPhone(cursor.getInt(phoneTypeIdx), cursor.getString(phoneIdx));
break;
case ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE:
// row's data: see ContactsContract.CommonDataKinds.StructuredName
addressBookContact.addName(cursor.getString(givenNameIdx), cursor.getString(familyNameIdx));
break;
}
}
cursor.close();
return list;
}
我目前正在使用这个问题的答案:How to get all contacts first name, last name, email, phone number, etc without duplicates 来检索用户联系人列表,对于每个联系人,所有 phone 号码、名字、姓氏和照片 ID。
我对这个答案的看法是它为每个需要的数据创建一个请求。它在我的应用程序上造成了性能问题。我想从一个请求中检索所有这些信息,但我很难理解 Android 的查询是如何管理的以及我要查找的存储数据在哪里。
我尝试过的例子(我做了很多测试都没有成功,以下是我最后一次尝试的):
new CursorLoader(
this,
ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.HAS_PHONE_NUMBER + "!=0 AND (" + ContactsContract.Data.MIMETYPE + "=?)",
new String[]{ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE},
ContactsContract.Data.CONTACT_ID)
;
以及我要检索的信息:
int firstNameCol = cursor.getColumnIndex(CommonDataKinds.StructuredName.GIVEN_NAME);
int lastNameCol = cursor.getColumnIndex(CommonDataKinds.StructuredName.FAMILY_NAME);
int photoIdCol = cursor.getColumnIndex(CommonDataKinds.StructuredName.PHOTO_ID);
int phoneCol = cursor.getColumnIndex(Phone.NUMBER);
该请求有两个问题:
我每个联系人只有一个 phone 号码,但是我的一些联系人有多个号码,我想找回它们
我没有检索名字和姓氏(我得到的是一个奇怪的数字)
请注意,我不想检索 DISPLAY_NAME,我想要 given_name 和 family_name。另请注意,我希望每个联系人有一个结果,而不是每个 phone 号码有一个结果(即一个结果包含一对多 phone 号码)
有没有想法在单个请求中做到这一点?
编辑:尝试使用来自@pskink 的另一段代码,但我收到 "column '_id' does not exists" 错误
String[] projection = {
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
ContactsContract.CommonDataKinds.StructuredName.PHOTO_ID
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?, ?, ?)";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
ContactsContract.CommonDataKinds.StructuredName.PHOTO_ID
};
//String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
//Uri uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
Uri uri = ContactsContract.Data.CONTENT_URI;
// ok, let's work...
return new CursorLoader(
this, uri, projection, selection, selectionArgs, null
);
感谢@pskink,我现在可以通过一个快速的单一请求来检索我想要的内容。不幸的是,我不能使用 CursorAdapter,我必须请求整个数据库并将结果存储在一个对象模型中,但是结果非常快所以没关系。
完整代码如下:
public ArrayList<ContactModel> retrieveContactList(){
ArrayList<ContactModel> list = new ArrayList<>();
LongSparseArray<ContactModel> array = new LongSparseArray<>();
Set<String> set = new HashSet<String>();
set.add(ContactsContract.Data.MIMETYPE);
set.add(ContactsContract.Data.CONTACT_ID);
set.add(ContactsContract.Data.PHOTO_ID);
set.add(ContactsContract.CommonDataKinds.Phone.NUMBER);
set.add(ContactsContract.CommonDataKinds.Phone.TYPE);
set.add(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
set.add(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
set.add(ContactsContract.Contacts.PHOTO_ID);
Uri uri = ContactsContract.Data.CONTENT_URI;
String[] projection = set.toArray(new String[0]);
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
Cursor cursor = this.context.getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder
);
final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int phoneIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
final int phoneTypeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
final int givenNameIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
final int familyNameIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
final int photoIdIdx = cursor.getColumnIndex(ContactsContract.Data.PHOTO_ID);
while (cursor.moveToNext()) {
long id = cursor.getLong(idIdx);
ContactModel addressBookContact = array.get(id);
if (addressBookContact == null) {
addressBookContact = new ContactModel(id);
array.put(id, addressBookContact);
list.add(addressBookContact);
}
Long photoId = cursor.getLong(photoIdIdx);
if (photoId != null){
addressBookContact.addPhotoId(photoId);
}
switch (cursor.getString(mimeTypeIdx)) {
case ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE:
// row's data: see ContactsContract.CommonDataKinds.Phone
addressBookContact.addPhone(cursor.getInt(phoneTypeIdx), cursor.getString(phoneIdx));
break;
case ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE:
// row's data: see ContactsContract.CommonDataKinds.StructuredName
addressBookContact.addName(cursor.getString(givenNameIdx), cursor.getString(familyNameIdx));
break;
}
}
cursor.close();
return list;
}