I have an app which inserts/updates a contact in the phone book using below code, the code works but the problem I am facing is if there is similar contact with the same phone number eg. a WhatsApp, dou, Viber etc. contact then those app contact takes over my contacts DisplayName and merges together but due to this, we are having multiple duplicate entries in some versions of android like (Samsung, LG, MI A5 stock android) etc.
But works on some phones like MI Max and a few others, does anyone have a solution to this problem or is there I am missing some fields that need to be present to avoid duplicate contacts.
private fun insertContact(contact: Contact): Boolean {
try {
val operations = ArrayList<ContentProviderOperation>()
ContentProviderOperation.newInsert(RawContacts.CONTENT_URI).apply {
withValue(RawContacts.ACCOUNT_NAME, "abcd@gmail.com")
withValue(RawContacts.ACCOUNT_TYPE, "google.com")
operations.add(build())
}
ContentProviderOperation.newInsert(Data.CONTENT_URI).apply {
withValueBackReference(Data.RAW_CONTACT_ID, 0)
withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
withValue(StructuredName.GIVEN_NAME, contact.firstName)
withValue(StructuredName.FAMILY_NAME, contact.lastName)
withValue(StructuredName.SUFFIX, "AppName")
operations.add(build())
}
addUpdatePhone(operations, contact.phoneNumbers)
//similar function for other fields email, address, birthday, profilePic etc
val results = context.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
return true
} catch (e: Exception) {
LOG.e( "Error inserting contact")
return false
}
}
private fun updateContact(contact: contact, rawContactId: String): Boolean {
try {
val operations = ArrayList<ContentProviderOperation>()
ContentProviderOperation.newUpdate(Data.CONTENT_URI).apply {
val selection = "${Data.RAW_CONTACT_ID} = ? AND ${Data.MIMETYPE} = ?"
val selectionArgs = arrayOf(rawContactId, StructuredName.CONTENT_ITEM_TYPE)
withSelection(selection, selectionArgs)
withValue(StructuredName.GIVEN_NAME, contact.firstName)
withValue(StructuredName.FAMILY_NAME, contact.lastName)
withValue(StructuredName.SUFFIX, "AppName")
operations.add(build())
}
addUpdatePhone(operations, contact.phoneNumbers, true, rawContactId)
//similar function for other fields email, address, birthday, profilePic etc
context.contentResolver.applyBatch(ContactsContract.AUTHORITY, operations)
return true
} catch (e: Exception) {
LOG.e("Error updating contact")
return false
}
}
private fun addUpdatePhone(operations: ArrayList<ContentProviderOperation>, phoneNumbers: List<PhoneNumber>, isUpdate: Boolean = false, rawContactId: String = "") {
if(isUpdate) {
//delete old data with the given raw_contact_id
ContentProviderOperation.newDelete(Data.CONTENT_URI).apply {
val selection = "${Data.RAW_CONTACT_ID} = ? AND ${Data.MIMETYPE} = ? "
val selectionArgs = arrayOf(rawContactId, Phone.CONTENT_ITEM_TYPE)
withSelection(selection, selectionArgs)
operations.add(build())
}
}
phoneNumbers.forEach {
//add new rows of phone number for the given raw_contact_id
ContentProviderOperation.newInsert(Data.CONTENT_URI).apply {
if(isUpdate) {
withValue(Data.RAW_CONTACT_ID, rawContactId)
} else {
withValueBackReference(Data.RAW_CONTACT_ID, 0)
}
withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
withValue(Phone.TYPE, it.type)
withValue(Phone.LABEL, it.label)
withValue(Phone.NUMBER, it.value)
withValue(Phone.NORMALIZED_NUMBER, it.value.normalizeNumber())
operations.add(build())
}
}
}
//similar functions as above for other fields
private fun otherUpdateFunAsAbove() {}