androidandroid-contacts

Select one contact number from a list of multiple contact numbers


I want to fetch only the first contact number from a list of contact numbers of a particular user, with the help of cursor. Here is my code:

private ArrayList<ArrayList<String>> getAllContacts() {

        ArrayList<ArrayList<String>> nameList = new ArrayList<ArrayList<String>>();
        ArrayList<String> person=new ArrayList<>();
        ArrayList<String> number=new ArrayList<>();
        ArrayList<String> temp=new ArrayList<>();
        ContentResolver cr = getContentResolver();
        Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
                null, null, null, null);

        if ((cur!=null ? cur.getCount() : 0) > 0) {
            while (cur!=null && cur.moveToNext()) {

                String id = cur.getString(
                        cur.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cur.getString(cur.getColumnIndex(
                        ContactsContract.Contacts.DISPLAY_NAME));
                person.add(name);

                if (cur.getInt(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);

                    if(pCur.getCount()==1) {
                        while (pCur.moveToNext()) {
                            String phoneNo = pCur.getString(pCur.getColumnIndex(
                                    ContactsContract.CommonDataKinds.Phone.NUMBER));
                            number.add(phoneNo);
                        }
                    }
                    else{
                        while (pCur.moveToNext()) {
                            String phoneNo = pCur.getString(pCur.getColumnIndex(
                                    ContactsContract.CommonDataKinds.Phone.NUMBER));
                            temp.add(phoneNo);
                        }
                        number.add(temp.get(0));
                        temp.clear();
                    }
                    pCur.close();
                }
            }
        }
        if (cur!=null) {
            cur.close();
        }
        Log.d("contacts",String.valueOf(number.size())+" "+String.valueOf(person.size())); //the lists aren't of equal size

        if(person.size()==number.size()){
            nameList.add(person);
            nameList.add(number);
        }
        else{
            //don't know what to do here
        }
        return nameList;

    }

But, the code still fetches multiple contact numbers saved for a single user, in other words person.size() is not equal to number.size(). What do I do?


Solution

  • The array sizes are not the same because not all contacts have phone-numbers, you are correctly checking for HAS_PHONE_NUMBER and only if true, getting that contact's phone numbers - which means number.size() would be < person.size() on most phones.

    I would suggest instead of keeping separate Arrays for names and phones, having a single Array with a simple java class that represents a person.

    Other than that, your code is very inefficient, as you're doing a ton of queries, while you can do just one.

    Here's an example with the two suggestions above:

    class Person {
        long id,
        String name,
        String firstPhone;
    
        public Person(id, name, firstPhone) {
            this.id = id;
            this.name = name;
            this.firstPhone = firstPhone;
        }
    }
    
    Map<Long, Person> mapping = new HashMap<>(); // mapping between a contact-id to a Person object
    
    String[] projection = {Data.CONTACT_ID, Data.DISPLAY_NAME, Phone.NUMBER};
    
    // query phones only
    String selection = Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'";
    ContentResolver cr = getContentResolver();
    Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null);
    
    while (cur != null && cur.moveToNext()) {
        long id = cur.getLong(0);
        String name = cur.getString(1); // full name
        String phone = cur.getString(2); // phone
    
        Log.d(TAG, "got " + id + ", " + name + " - " + data);
    
        // only add a new object if we haven't seen this person before
        if (!mapping.containsKey(id)) {
            Person person = new Person(id, name, phone);
            mapping.put(id, person);
        }
    }
    cur.close();
    
    Array<Person> people = mapping.values();
    

    EDIT

    Set<Long> ids = new HashSet<Long>();
    Array<String> names = new ArrayList<String>();
    Array<String> numbers = new ArrayList<String>();
    
    String[] projection = {Data.CONTACT_ID, Data.DISPLAY_NAME, Phone.NUMBER};
    
    // query phones only
    String selection = Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'";
    ContentResolver cr = getContentResolver();
    Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null);
    
    while (cur != null && cur.moveToNext()) {
        long id = cur.getLong(0);
        String name = cur.getString(1); // full name
        String phone = cur.getString(2); // phone
    
        Log.d(TAG, "got " + id + ", " + name + " - " + data);
    
        // only add a new object if we haven't seen this person before
        if (ids.add(id)) {
            names.add(name);
            numbers.add(phone);
        }
    }
    cur.close();