I have something like this so far, but it seems like ContactsContract.Data URI returns multiple records with the same CONTACT_ID and LOOKUP_KEY. Is there any way to make this cursor return distinct records?
private static final Uri URI = ContactsContract.Data.CONTENT_URI;
@SuppressLint("InlinedApi")
private static final String[] PROJECTION = {
ContactsContract.Data._ID,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.LOOKUP_KEY,
ContactsContract.Data.DISPLAY_NAME_PRIMARY
};
private static final String SELECTION =
ContactsContract.Data.DISPLAY_NAME_PRIMARY + " LIKE ?" +
" AND " + ContactsContract.Data.MIMETYPE + " = " + ContactsContract.CommonDataKinds.Organization.MIMETYPE +
" AND " + ContactsContract.CommonDataKinds.Organization.COMPANY + " LIKE ?";
private static final String SORT_ORDER =
ContactsContract.Data.DISPLAY_NAME_PRIMARY + " ASC";
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
String contactsFilter = getFilter(contactsSearch);
String companyFilter = getFilter(companySearch);
// Starts the query
return new CursorLoader(
getActivity(),
URI,
PROJECTION,
SELECTION,
new String[] { contactsFilter, companyFilter},
SORT_ORDER
);
}
Here's an example of the dump of this cursor:
42 {
_id=74752
contact_id=12603
lookup=2645ie9ffe868ace3d43
display_name=Person 1
}
43 {
_id=74753
contact_id=12603
lookup=2645ie9ffe868ace3d43
display_name=Person 1
}
44 {
_id=74756
contact_id=12603
lookup=2645ie9ffe868ace3d43
display_name=Person 1
}
_ID is different, but I want the cursor to return 1 record per person and all 3 of these are the same person.
Thoughts?
The Contacts DB is organized in three main tables:
Contacts- each entry represents one contact, and groups together one or moreRawContactsRawContacts- each entry represents data about a contact that was synced in by someSyncAdapter(e.g. Whatsapp, Google, Facebook, Viber), this groups multiple Data entriesData- The actual data about a contact, emails, phones, etc. each line is a single piece of data that belongs to a singleRawContactUsually what happens is that an app (e.g. Google, Whatsapp, Linkedin) that wishes to create a new contact will create a new row in the
RawContactstable that will usually contain just a name, and then use that row's _ID to add rows into theDatatable for phones, emails, addresses, photos, etc.You are querying over the
Datatable which means that if a certain contact has raw-contacts from 2 sources (e.g. 2 Google accounts) and both raw contacts contain a Data row with a certain company name, your cursor will return 2 results for that contact.I would recommend not using
CursorLoaderhere, instead create a regularCursorfrom your projection/selection/selection-args, traverse it to get the data and then use aHashMapby contact-id (or some other method) to make the entries distinct by their Contact ID.