Search code examples
androiddeviceandroid-contactscontactsimport-contacts

Fetching more than 10000 contacts from android device


I want to retrieve >10000 contacts from the android device. To fetch that much contact it takes about 8-10 min. Is there any other possible way to do this. I have implemented a method its working fine but when it comes to large number of contacts it taking it time to fetch the contacts.

 ContentResolver cr = getActivity().getApplication().getContentResolver();
    Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
    if (cur.getCount() > 0) {
        while (cur.moveToNext()) {
            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()) {
                    int phoneType = pCur.getInt(pCur.getColumnIndex(
                            ContactsContract.CommonDataKinds.Phone.TYPE));
                    String phoneNumber = pCur.getString(pCur.getColumnIndex(
                            ContactsContract.CommonDataKinds.Phone.NUMBER));

                    phoneNumber = phoneNumber.replace(" ","");
                    phoneNumber = phoneNumber.replace("-","");

                    boolean addNumber = stringCheck(phoneNumber,symbols);

                    if (!addNumber){

                        if (phoneNumber.length() == 10){
                            addContact(phoneNumber,phoneType,name);
                        }else if (phoneNumber.length() == 11){
                            phoneNumber = phoneNumber.substring(1);
                            addContact(phoneNumber,phoneType,name);

                        }else if (phoneNumber.length() == 12){
                            phoneNumber = phoneNumber.substring(2);
                            addContact(phoneNumber,phoneType,name);

                        }else if (phoneNumber.length() == 13){
                            phoneNumber = phoneNumber.substring(3);
                            addContact(phoneNumber,phoneType,name);
                        }

                    }

                }
                pCur.close();
            }
        }
    }

Solution

  • If 900 out of the 1000 contacts have phone numbers, you're currently querying the DB 901 times, you can reduce it to only two queries:

    1. Give me all contacts information
    2. Give me all phone numbers

    Then you use the contact-id field on both to match the phone to the right contacts.

    Also, as noted in other answers, you really should add projection to all your queries to improve performance.

    Another improvement you can make is to avoid runtime cur.getColumnIndex() calls, if you have a projection, you should already know the index - so use it hard-coded

    Map<Long, List<String>> phones = new HashMap<>();
    ContentResolver cr = getActivity().getApplication().getContentResolver();
    
    // First build a mapping: contact-id > list of phones
    Cursor cur = cr.query(Phone.CONTENT_URI, new String[] { Phone.CONTACT_ID, Phone.Number }, null, null, null);
    while (cur != null && cur.moveToNext()) {
       long contactId = cur.getLong(0);
       String phone = cur.getString(1);
       List list;
       if (phones.contains(contactId)) {
          list = phones.get(contactId);
       } else {
          list = new ArrayList<String>();
          phones.put(contactId, list);
       }
       list.add(phone);
    }
    cur.close();
    
    // Next query for all contacts, and use the phones mapping
    cur = cr.query(Contacts.CONTENT_URI, new String[] { Contacts._ID, Contacts.DISPLAY_NAME }, null, null, null);
    while (cur != null && cur.moveToNext()) {
       long id = cur.getLong(0);
       String name = cur.getString(1);
       List<String> contactPhones = phones.get(id);
       addContact(id, name, contactPhones);
    }