Получение результатов из хранилища контактов Android

Я пытался оптимизировать свой код для получения контактной информации из базы данных контактов Android. Но что бы я ни пытался, для загрузки 80 контактов с именем, номером телефона и эскизом контакта (растровым изображением) все равно требуется около 4-5 секунд. Я запускаю следующий фрагмент внутри doInBackground() экземпляра AsyncTask:

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

А вот методы получения идентификатора контакта из номера телефона и декодирования потока растровых изображений:

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

Программа работает нормально, но мне интересно, есть ли другой способ получить контактную информацию с указанными выше полями? Я знаю, что программа работает медленно из-за метода getContactIDFromNumber(), который выполняет подзапрос для получения contactId. Я использую это для получения миниатюры изображения контакта. Может ли кто-нибудь предложить лучший способ сделать это? Возможно, метод, с помощью которого этот подзапрос можно было бы полностью исключить?

РЕДАКТИРОВАТЬ:

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

Получение растрового изображения:

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

person Vinit Shandilya    schedule 02.05.2015    source источник


Ответы (1)


Возможно, метод, с помощью которого этот подзапрос можно было бы полностью исключить?

Включите ContactsContract.Contacts._ID в свой прогноз. Поставщик ContactsContract выполняет соединение и может предоставить вам эту информацию в вашем первоначальном запросе.

В этом примере приложения я одновременно извлекаю следующие три столбца. :

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

для запроса против ContactsContract.CommonDataKinds.Phone.CONTENT_URI.

person CommonsWare    schedule 02.05.2015
comment
Большое спасибо!! Не могли бы вы объяснить, как его можно использовать для получения эскизов контактов? - person Vinit Shandilya; 02.05.2015
comment
@VinitShandilya: Как что можно использовать для получения эскизов контактов? У вас уже есть код для этого, учитывая идентификатор контакта. - person CommonsWare; 02.05.2015
comment
Пожалуйста, обратитесь к разделу РЕДАКТИРОВАТЬ. Я попытался получить эскизы контактов, используя идентификатор контакта. Я также попробовал этот идентификатор контакта в своем исходном методе декодирования Bitmap. К сожалению, я не могу получить растровое изображение эскиза. - person Vinit Shandilya; 02.05.2015
comment
@VinitShandilya: я никогда не пытался загрузить фотографию контакта, поэтому я не знаю, как это сделать с идентификатором контакта. Поиск Google android contactcontracts bitmap id выдает множество ссылок, таких как stackoverflow.com/questions/2383580/ и stackoverflow.com/questions/13863879/, которое может вам помочь. - person CommonsWare; 02.05.2015