I know on some phones contact ids change even on reboot, but I can't reproduce this on my own phone. But I can reproduce following case and would like to know if this case is solveable at least:
- install whatsapp - it will add it's contacts to the
ContentProvider - read contacts from
ContactProvider=> I get data set 1 - delete whatsapp, reinstall it - it will add it's contacts to the
ContentProvideragain - read contacts from
ContentProvider=> I get data set 2
Result:
Between data set 1 and data set 2 I don't see any consistent data.
E.g.:
ContactsContract.Data.CONTACT_ID => changes, e.g. from 598 to 679
ContactsContract.Data.LOOKUP_KEY => changes as well, e.g. 3514i2b4948808eec75c9.3789r593-2D374B39.2797r594-2D374B39 to 3514i2b4948808eec75c9.2797r603-2D374B39.3789r670-2D374B39
* of course, some raw ids stay the same, but no common id for a full contact stays the same as far as I can see
What I want
I need an identifier for a contact that I can persistent in my app's database and that will also work after a change like the one described above. I need an identifier for a contact (not a raw contact), raw contacts may change of course during the lifetime of a contact (like in the example I describe above)...
Any ideas how I can solve this problem?
Code
For the sake of completeness, here's how I query the data from the ContentProvider, at least the cursor:
private fun getCursor(offset: Int?, count: Int?): Cursor? {
val selection = arrayOf(
ContactsContract.Data.RAW_CONTACT_ID,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Data.LOOKUP_KEY,
ContactsContract.Data.PHOTO_ID,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.Data.ACCOUNT_TYPE_AND_DATA_SET,
ContactsContract.CommonDataKinds.Email.DATA,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.LABEL,
ContactsContract.Contacts.Data.MIMETYPE,
ContactsContract.RawContacts.ACCOUNT_NAME,
ContactsContract.CommonDataKinds.Phone.IS_PRIMARY,
ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP,
ContactsContract.RawContacts.SOURCE_ID
)
return AppProvider.get().context.contentResolver.query(
ContactsContract.Data.CONTENT_URI,
selection, null, null,
ContactsContract.Data.CONTACT_ID + " ASC" + if (offset != null && count != null) " limit $count offset $offset" else "")
}
LOOKUP_KEYis your friend.So it's not a stable ID on its own, but it helps the ContactsContract DB to figure out the new contactID in case it changed.
You should use a pair of
<CONTACT_ID, LOOKUP_KEY>to keep track of contacts. In normal use, use theCONTACT_IDvalue, but if your code gets a hint that theCONTACT_IDhas changed (either missing, or unexpected contact name), you can use theLOOKUP_KEYto find the new contact-id.You can use Contacts.getLookupUri(long, String) to get a URI you can always use to quickly find a contact no matter what its
CONTACT_IDorLOOKUP_KEYactual values are.