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);
}