How can I programmatically delete duplicate contacts in Android/Java?

I am trying to create an Android contacts app/service that will do the following once every 24 hours:

1 - Get contacts from an XML file on our web server and put them into an array.
2 - Loop through the array, inserting those contacts into the phone's address book.
3 - Delete all the contacts with the same name to stop duplicates.

I have managed to get steps 1 and 2 working correctly, as well as a service that runs every 24 hours. However, I cannot delete contacts with the same name. I've only managed to get it to delete all the contacts on the phone including personal ones etc.

If someone could show me how to delete only contacts with the same display name as those in my XML file, that would be very helpful.

Here is part of my code without any delete functions. This gets the contacts from the XML file and inserts them into the phone successfully.

        String folderPath = "http://mywebsite.co.uk/phonebook.xml";
        String xmlFile = folderPath;
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder;

        try
        /// gets the main nodes in the config and saves them to a list
        {

            dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(xmlFile);
            doc.getDocumentElement().normalize();
            //System.out.println("Root element is:" + doc.getDocumentElement().getNodeName());
            NodeList mainList = doc.getElementsByTagName("RECORD");
            List<String> list = new ArrayList<String>();          

            for (int temp = 0; temp < mainList.getLength(); temp++) {

                Node mainNode = mainList.item(temp);
                Element eElement = (Element) mainNode;
                list.add(getChildElementContent(eElement, "NAME") + ": " + getChildElementContent(eElement, "NUMBER"));
                System.out.println(list.get(temp));

                ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
                int rawContactInsertIndex = ops.size();

                ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
                        .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                        .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
                        .build());

                ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                        .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, (getChildElementContent(eElement, "NUMBER")))
                        .build());

                ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                        .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, (getChildElementContent(eElement, "NAME")))
                        .build());

                ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValueBackReference(ContactsContract.RawContacts.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                        .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, "Company")
                        .build());


                try {
                    ContentProviderResult[] res = getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

                    startService(new Intent(this, MyService.class));

                } catch (RemoteException e) {
                    e.printStackTrace();
                } catch (OperationApplicationException e) {
                    e.printStackTrace();
                }
            }

Open in new window

Ross HambletonNetwork AdministratorAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Molnár IstvánHelpDesk / ProgrammerCommented:
1. you can add another function that checks for duplicates:

    public static <T> ArrayList<T> removeDuplicates(ArrayList<T> list) 
    { 
  
        // Create a new ArrayList 
        ArrayList<T> newList = new ArrayList<T>(); 
  
        // Traverse through the first list 
        for (T element : list) { 
  
            // If this element is not present in newList 
            // then add it 
            if (!newList.contains(element)) { 
  
                newList.add(element); 
            } 
        } 
  
        // return the new list 
        return newList; 
    } 

then use it :

        ArrayList<Integer> 
            list = new ArrayList<>( 
                Arrays 
                    .asList(1, 10, 1, 2, 2, 3, 3, 10, 3, 4, 5, 5)); 

        ArrayList<Integer> 
            newList = removeDuplicates(list); 

Open in new window


link: How to Remove Duplicates from ArrayList in Java

2. "add the contents to a Set (which will not allow duplicates) and then add the Set back to the ArrayList" (!destroys the ordering of the elements!)
Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);

Open in new window


How do I remove repeated elements from ArrayList?

3. In Java 8:
List<String> deduped = list.stream().distinct().collect(Collectors.toList());

Open in new window


How do I remove repeated elements from ArrayList?

4. use .Contain function (!doesn't affect your list ordering):

ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();

Iterator iterator = l1.iterator();

        while (iterator.hasNext())
        {
            YourClass o = (YourClass) iterator.next();
            if(!l2.contains(o)) l2.add(o);
        }

Open in new window


How do I remove repeated elements from ArrayList?

PS: Here is a somewhat similar question - Link

Hope it helps
Ross HambletonNetwork AdministratorAuthor Commented:
Thanks for your help, but I need to delete duplicates from the phone, not the list. The arraylist needs to stay the same because it must insert all the contacts every day. The phone will then start to have many duplicates because the list is inserted everyday.

What I want is code that makes the phone delete any contacts that are in the arraylist. Or to delete any contacts that were inserted by this app, using a unique ID or something?

Does this make sense?
Michael HurleyHelpDesk TechnicianCommented:
Hi Ross!
Were you able to try this out?  (This is from Molnar's research above)

Here i have inserted data in sqlite database first and then Write select query with group by name.

Hope it helps:
ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC ");
        String lastnumber = "0";

        if (cur.getCount() > 0)
        {
            while (cur.moveToNext())
            {
                String number = null;
                String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                if (Integer.parseInt(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
                {
                    Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]
                    { id }, null);
                    while (pCur.moveToNext())
                    {
                        number = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                        Log.e("lastnumber ", lastnumber);
                        Log.e("number", number);

                        if (number.equals(lastnumber))
                        {

                        }
                        else
                        {
                            lastnumber = number;

                            Log.e("lastnumber ", lastnumber);
                            int type = pCur.getInt(pCur.getColumnIndex(Phone.TYPE));
                            switch (type)
                            {
                                case Phone.TYPE_HOME:
                                    Log.e("Not Inserted", "Not inserted");
                                    break;
                                case Phone.TYPE_MOBILE:

                                    databaseHandler.insertContact(id, name, lastnumber, 0);
                                    break;
                                case Phone.TYPE_WORK:
                                    Log.e("Not Inserted", "Not inserted");
                                    break;
                            }

                        }

                    }
                    pCur.close();
                }

            }
        }

Open in new window

Ross HambletonNetwork AdministratorAuthor Commented:
Thank you for that Michael . I'm not sure how this will work with my code because I'm not using an SQL database, only an XML file. For example, the following part is not working because I don't have a database.

databaseHandler.insertContact(id, name, lastnumber, 0);

Open in new window


Where as my code inserts like this:

ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                        .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex)
                        .withValue(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                        .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, (getChildElementContent(eElement, "NUMBER")))
                        .build());

Open in new window


I'm a beginner with Android development, so any further help would be greatly appreciated.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.