No one seems to be answering your question.
The reason you see duplicate contacts is because you are asking for phone numbers not contacts .
There are 3 main tables in Android:
Contacts table - has one element for each contact tableRawContacts - has one element for each account (for example, Google, Outlook, Whatsapp, etc.) - several RawContacts are associated with one Contact TableData - has one element for each part (name, email address, phone, address, etc.) - each data element is associated with one RawContact , and several rows of Data are associated with each RawContact .
You request CommonDataKinds.Phone.CONTENT_URI , which is part of the Data table, so if a contact has more than one phone and / or it has the same phone from several sources (for example, Google and Whatsapp), you are the same phone with the same CONTACT_ID more than once.
The solution is to use a HashMap (and not a HashSet ), where the key is CONTACT_ID , so you can map several phones to a contact:
String[] projection = new String[] { CommonDataKinds.Phone.CONTACT_ID, CommonDataKinds.Phone.DISPLAY_NAME, CommonDataKinds.Phone.NUMBER }; Cursor cursor = getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI, projection, null, null, null); HashMap<Long, Contact> contacts = new HashMap<>(); while (cursor.moveToNext()) { long id = cursor.getLong(0); String name = cursor.getString(1); String phone = cursor.getString(2); Contact c = contacts.get(id); if (c == null) {
If you want to sort your HashMap by name:
List<Contact> values = new ArrayList<>(contacts.values()); Collections.sort(values, new Comparator<Contact> { public int compare(Contact a, Contact b) { return a.name.compareTo(b.name); } }); // iterate the sorted list, per contact: for (Contact contact : values) { Log.i(TAG, "contact " + contact.name + ": "); // iterate the list of phones within each contact: for (String phone : contact.phones) { Log.i(TAG, "\t phone: " + phone); } }
source share