Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fastest way to query contacts with "mobile phone numbers" on Android

I need to get a distinct list of all contacts from a device and their phone numbers. But wait... We know that some contacts may have multiple numbers assigned, it all depends how each of the users stores his contacts. Here is what i do:

    ContentResolver cr = context.getContentResolver();   
    Uri uri = ContactsContract.Contacts.CONTENT_URI;
    String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME };
    String selection =  ContactsContract.Contacts.HAS_PHONE_NUMBER + " = '1'";
    String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
    ArrayList<user> contacts = new ArrayList<user>();

    Cursor users = a.managedQuery(uri, projection, selection, null, sortOrder);

    while (users.moveToNext()) {
        user u = new user();
        u.PhoneId = users.getInt(users.getColumnIndex(ContactsContract.Contacts._ID));
        u.Name = users.getString(users.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

        String homePhone = "", cellPhone = "", workPhone = "", otherPhone = "";
        Cursor contactPhones = cr.query(Phone.CONTENT_URI, null, Phone.CONTACT_ID + " = " + u.PhoneId, null, null);

        while (contactPhones.moveToNext()) {

            String number = contactPhones.getString(contactPhones.getColumnIndex(Phone.NUMBER));
            int type = contactPhones.getInt(contactPhones.getColumnIndex(Phone.TYPE));
            switch (type) {
                case Phone.TYPE_HOME:   homePhone = number; break;
                case Phone.TYPE_MOBILE:  cellPhone = number; break;
                case Phone.TYPE_WORK:   workPhone = number; break;
                case Phone.TYPE_OTHER:  otherPhone = number; break;
                }
        }        
        u.Phone = ((cellPhone!="") ? cellPhone : ((homePhone!="") ? homePhone : ((workPhone!="") ? workPhone : otherPhone)));
    }

    return contacts;

The process works but for my 80 contacts it takes between 1000-2000 miliseconds, and i need to work much faster :)

like image 899
android-developer Avatar asked May 19 '11 23:05

android-developer


1 Answers

Cursor contactPhones = cr.query(Phone.CONTENT_URI, null, 
                                Phone.CONTACT_ID + " = " + u.PhoneId, 
                                null, 
                                null);

This is slightly sub-optimal in that you are encoding the contact ID field directly in the query, rather than making it an argument. This means that the query parser has to re-parse the query each time, rather than being able to use a single cached copy.

Supply the ID as an argument instead:

Cursor contactPhones = cr.query(Phone.CONTENT_URI, null, 
                                Phone.CONTACT_ID + " =? ", 
                                new String[] { Integer.toString(u.PhoneId) }, 
                                null);

The javadoc for ContentResolver.query() reiterates this guidance:

Use question mark parameter markers such as 'phone=?' instead of explicit values in the selection parameter, so that queries that differ only by those values will be recognized as the same for caching purposes.

like image 146
Graham Borland Avatar answered Sep 25 '22 22:09

Graham Borland