Reputation: 2569
I'm currently using the answer to this question: How to get all contacts first name, last name, email, phone number, etc without duplicates to retrieve the user contact list with, for each contact, all phone numbers, the firstname, lastname and the photo id.
The issue I've with that answer is it's creating one request per data wanted. It's creating performances issues on my app. I would like to retrieve all these information from a single request, but I've got a lot of difficulty to understand how Android's query are managed and where are stored data I'm looking for.
Example of what I've tried (I've done a lot of test without success, following one is the last one I've tried):
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)
;
And information I would like to retrieve:
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);
There is two issues with that request:
I only get one phone number per contact, however some of my contacts have several numbers and I would like to retrieve them
I'm not retrieving the firstname and the lastname (I get a weird number instead)
Please note that I don't want to retrieve the DISPLAY_NAME, I want both given_name and family_name. Please also note I would like to have one result per contact and not one result per phone number (i.e one result contain one to many phone numbers)
Any idea to do that in a single request?
EDIT: trying with another piece of code from @pskink but I get a "column '_id' does not exists" error
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
);
Upvotes: 0
Views: 941
Reputation: 2569
Thanks to @pskink, I've now a fast single request to retrieve what I want. Unfortunately, I cannot use the CursorAdapter and I've to request the whole DB and store result in an object model, but the result is very fast so it's OK.
Here's the complete code:
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;
}
Upvotes: 1