0

I've been trying to optimize my code to obtain contact details from Android contact database. But whatever I try, it still takes around 4-5 seconds to load 80 contacts with name, phone number and contact thumbnail image (bitmap). I'm running the following snippet inside doInBackground() of an AsyncTask instance:

Cursor cursor = null;
try {
    String[] projection = {
            ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
            ContactsContract.CommonDataKinds.Phone.NUMBER,
            ContactsContract.CommonDataKinds.Phone.PHOTO_URI };

    cursor = getBaseContext().getContentResolver().query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            projection, null, null, null);

    int nameIdx = cursor.getColumnIndex(Phone.DISPLAY_NAME);
    int phoneNumberIdx = cursor.getColumnIndex(Phone.NUMBER);

    if(cursor.moveToFirst()) {
        do {
            String name = cursor.getString(nameIdx);
            String phoneNumber = cursor.getString(phoneNumberIdx);
            long contactId=getContactIDFromNumber(phoneNumber, getBaseContext());
            Bitmap bmp=loadContactPhoto(getBaseContext().getContentResolver(), contactId);

            item.add(new ContactObject(name, phoneNumber, null, null, bmp, contactId));

        } while (cursor.moveToNext());
    }

} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (cursor != null) {
        cursor.close();
    }
}

And here are the methods to obtain contact ID from phone number and to decode bitmap stream:

public static long getContactIDFromNumber(String contactNumber,Context context)
{
    contactNumber = Uri.encode(contactNumber);
    int phoneContactID = new Random().nextInt();
    Cursor contactLookupCursor = context.getContentResolver().query(Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, contactNumber),new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup._ID}, null, null, null);
    while(contactLookupCursor.moveToNext()){
        phoneContactID = contactLookupCursor.getInt(contactLookupCursor.getColumnIndexOrThrow(PhoneLookup._ID));
    }
    contactLookupCursor.close();

    return phoneContactID;
}

public Bitmap loadContactPhoto(ContentResolver cr, long id) {
    Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
    InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri);
    if (input == null) {
        return BitmapFactory.decodeResource(getBaseContext().getResources(), R.drawable.ic_launcher);
    }
    return BitmapFactory.decodeStream(input);
}      

The program works fine but I was wondering, is there any other way to obtain contact details with above mentioned fields? I know, the program is slow due to getContactIDFromNumber() method which is running a sub-query to obtain contactId. I'm using this to retrieve contact image thumbnail. Can anyone please suggest a better way to do this? Perhaps a method by which this sub-query could be eliminated completely?

EDIT:

long contactId = Long.parseLong(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)));

Getting the bitmap:

Uri contactPhotoUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
                    InputStream is=ContactsContract.Contacts.openContactPhotoInputStream(getBaseContext().getContentResolver(), contactPhotoUri);
                    Bitmap bitmap=null;
                    if(is!=null){
                        bitmap = BitmapFactory.decodeStream(is);
                    }
Vinit Shandilya
  • 1,643
  • 5
  • 24
  • 44

1 Answers1

1

Perhaps a method by which this sub-query could be eliminated completely?

Include ContactsContract.Contacts._ID in your projection. The ContactsContract provider does a join and can give you this information in your initial query.

In this sample app, I retrieve the following three columns at once:

private static final String[] PROJECTION_NUMBERS=new String[] {
  ContactsContract.Contacts._ID,
  ContactsContract.Contacts.DISPLAY_NAME,
  ContactsContract.CommonDataKinds.Phone.NUMBER
};

for a query against ContactsContract.CommonDataKinds.Phone.CONTENT_URI.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks a lot!! Could you please explain how it can be used to retrieve contact thumbnails? – Vinit Shandilya May 02 '15 at 18:12
  • @VinitShandilya: How *what* can be used to retrieve contact thumbnails? You already have some code for that, given the contact ID. – CommonsWare May 02 '15 at 18:38
  • Please refer to the EDIT section. I tried to retrieve contact thumbnails using the contact ID. I also tried this contact ID in my original Bitmap decoding method. Unfortunately, I'm unable to obtain thumbnail bitmap. – Vinit Shandilya May 02 '15 at 18:52
  • @VinitShandilya: I have never tried loading a contact photo, so I do not know off the top of my head how to do that given a contact ID. A Google search `android contactcontracts bitmap id` turns up many links, such as http://stackoverflow.com/questions/2383580/how-do-i-load-a-contact-photo and http://stackoverflow.com/questions/13863879/load-contact-image-into-bitmap that may help you. – CommonsWare May 02 '15 at 18:55