2010-03-04 2 views
43

У меня возникли проблемы с загрузкой фотографии для контакта в Android. Я искал ответ на этот вопрос, но до сих пор пришел пустым. Есть ли у кого-нибудь пример запроса для контакта, а затем загрузка фотографии?Как загрузить контакт Фото?

Таким образом, учитывая contactUri, который исходит от результата деятельности называется использованием

startActivityForResult(new Intent(Intent.ACTION_PICK,ContactsContract.CommonDataKinds.Phone.CONTENT_URI),PICK_CONTACT_REQUEST) 

является:

содержание: //com.android.contacts/data/1557

НагрузкаКонтакт (..) работает нормально. Однако, когда я вызываю метод getPhoto (...), я получаю значение null для фото InputStream. Это также сбивает с толку, потому что значения URI различны. ContactPhotoUri имеет значение: содержание

: //com.android.contacts/contacts/1557

Смотрите комментарии инлайн в коде ниже.

class ContactAccessor { 

    /** 
    * Retrieves the contact information. 
    */ 
    public ContactInfo loadContact(ContentResolver contentResolver, Uri contactUri) { 

     //contactUri --> content://com.android.contacts/data/1557 

     ContactInfo contactInfo = new ContactInfo(); 

     // Load the display name for the specified person 
     Cursor cursor = contentResolver.query(contactUri, 
              new String[]{Contacts._ID, 
                 Contacts.DISPLAY_NAME, 
                 Phone.NUMBER, 
                 Contacts.PHOTO_ID}, null, null, null); 
     try { 
      if (cursor.moveToFirst()) { 
       contactInfo.setId(cursor.getLong(0)); 
       contactInfo.setDisplayName(cursor.getString(1)); 
       contactInfo.setPhoneNumber(cursor.getString(2)); 
      } 
     } finally { 
      cursor.close(); 
     }   
     return contactInfo; // <-- returns info for contact 
    } 

    public Bitmap getPhoto(ContentResolver contentResolver, Long contactId) { 
     Uri contactPhotoUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 

     // contactPhotoUri --> content://com.android.contacts/contacts/1557 

     InputStream photoDataStream = Contacts.openContactPhotoInputStream(contentResolver,contactPhotoUri); // <-- always null 
     Bitmap photo = BitmapFactory.decodeStream(photoDataStream); 
     return photo; 
    } 

    public class ContactInfo { 

     private long id; 
     private String displayName; 
     private String phoneNumber; 
     private Uri photoUri; 

     public void setDisplayName(String displayName) { 
      this.displayName = displayName; 
     } 

     public String getDisplayName() { 
      return displayName; 
     } 

     public void setPhoneNumber(String phoneNumber) { 
      this.phoneNumber = phoneNumber; 
     } 

     public String getPhoneNumber() { 
      return phoneNumber; 
     } 

     public Uri getPhotoUri() { 
      return this.photoUri; 
     } 

     public void setPhotoUri(Uri photoUri) { 
      this.photoUri = photoUri; 
     } 

     public long getId() { 
      return this.id; 
     } 

     public void setId(long id) { 
      this.id = id; 
     } 

    } 
} 

Очевидно, что я здесь что-то не так, но я не могу понять, в чем проблема. Благодарю.

+0

Так нет ли приемлемого решения? Если контакты используют фотографии в facebook, мы SOL? –

+1

Мне не удалось найти способ загрузки фотографий с facebook. Я не знаю, изменилось ли это во Фройо или нет. – PaulH

+0

Сыворотка вы не используете Contacts.PHOTO_ID после чтения из курсора? –

ответ

30

Отсканировав множество вопросов и ответов на проблему с отображением миниатюры, я подумал, что отправлю свое решение на эту конкретную загадку, поскольку я мог найти только пару, которая работала вообще, и ни одна из них не обеспечила хорошее консервированное решение для ленивый разработчик.

Нижеприведенный класс содержит контекст, QuickContactBadge и номер телефона и прикрепляет локально сохраненное изображение к значку, если для указанного номера телефона имеется один доступный.

Вот класс:

public final class QuickContactHelper { 

private static final String[] PHOTO_ID_PROJECTION = new String[] { 
    ContactsContract.Contacts.PHOTO_ID 
}; 

private static final String[] PHOTO_BITMAP_PROJECTION = new String[] { 
    ContactsContract.CommonDataKinds.Photo.PHOTO 
}; 

private final QuickContactBadge badge; 

private final String phoneNumber; 

private final ContentResolver contentResolver; 

public QuickContactHelper(final Context context, final QuickContactBadge badge, final String phoneNumber) { 

    this.badge = badge; 
    this.phoneNumber = phoneNumber; 
    contentResolver = context.getContentResolver(); 

} 

public void addThumbnail() { 

    final Integer thumbnailId = fetchThumbnailId(); 
    if (thumbnailId != null) { 
     final Bitmap thumbnail = fetchThumbnail(thumbnailId); 
     if (thumbnail != null) { 
      badge.setImageBitmap(thumbnail); 
     } 
    } 

} 

private Integer fetchThumbnailId() { 

    final Uri uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); 
    final Cursor cursor = contentResolver.query(uri, PHOTO_ID_PROJECTION, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC"); 

    try { 
     Integer thumbnailId = null; 
     if (cursor.moveToFirst()) { 
      thumbnailId = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID)); 
     } 
     return thumbnailId; 
    } 
    finally { 
     cursor.close(); 
    } 

} 

final Bitmap fetchThumbnail(final int thumbnailId) { 

    final Uri uri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, thumbnailId); 
    final Cursor cursor = contentResolver.query(uri, PHOTO_BITMAP_PROJECTION, null, null, null); 

    try { 
     Bitmap thumbnail = null; 
     if (cursor.moveToFirst()) { 
      final byte[] thumbnailBytes = cursor.getBlob(0); 
      if (thumbnailBytes != null) { 
       thumbnail = BitmapFactory.decodeByteArray(thumbnailBytes, 0, thumbnailBytes.length); 
      } 
     } 
     return thumbnail; 
    } 
    finally { 
     cursor.close(); 
    } 

} 

} 

А вот типичный случай внутри деятельности:

String phoneNumber = "..."; 
QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.friend); 
new QuickContactHelper(this, badge, phoneNumber).addThumbnail(); 

В фрагменте будет немного отличаться:

String phoneNumber = "..."; 
QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.friend); 
new QuickContactHelper(getActivity(), badge, phoneNumber).addThumbnail(); 

Теперь являются более эффективными способами - например, если вы создаете временную шкалу сообщений, которую хотите повторно использовать один и тот же бит объект карты для каждого экземпляра значка для заданного номера телефона, а не постоянно создавать новые экземпляры вспомогательного класса и повторно извлекать растровое изображение, но моя цель заключалась в том, чтобы опубликовать решение, которое было разрешено до абсолютного минимума для ясности, в то же время предоставляя полное и полезное решение из коробки. Это решение было построено и протестировано на Andriod 4.0, а также протестировано на 4.1.

+0

@ DídacPrere вопрос: «Кто-нибудь есть пример запроса контакта, а затем загрузки фотографии» - это именно то, что делает мое решение. Он запрашивает номер телефона, а затем загружает фотографию. Вы можете видеть это из примера использования. Фотография загружается в QuickContactBadge, ее можно легко модифицировать для загрузки в другой компонент, например изображение. – Phil

+2

@ DídacPérez мой ответ выглядит несколько странным теперь, когда вы удалили свой комментарий (который сказал, что я не рассматривал исходный вопрос). – Phil

2

Похоже, что моя проблема заключалась в том, что контакты на моем устройстве были синхронизированы с facebook, и поэтому фотография недоступна.

http://groups.google.com/group/android-developers/msg/be8d0cf3928e4b7f

+1

и почему приложение-контакт по умолчанию показывает фотографию в facebook? – krtek

+1

, потому что facebook предоставляет право доступа к контактной фотографии в контактное приложение, но не к другим неизвестным приложениям. – Janusz

+2

Я также разрабатываю приложение sms и все еще имею проблему с загрузкой фотографий контактов facebook. Я думаю, что есть решение наверняка, потому что Handcent SMS может отображать все эти фотографии. @PaulH: Вы нашли какое-либо решение? – hungson175

32

Это работает для меня:

public static 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 null; 
    } 
    return BitmapFactory.decodeStream(input); 
} 
+2

Не работает для меня только для контактов FB-synced-only. –

+2

Люди продолжают говорить об альтернативных методах работы. Но я не видел одной работы на складе (я думаю, что адаптер синхронизации HTC работает по-другому). Может ли кто-нибудь подтвердить, что у пользователя с контактом в Google и с Facebook (но только с контактом facebook есть фотография) можно получить фотографию, которая появится на телефоне, на котором установлен адаптер синхронизации приложений Facebook? – Eric

+11

Эй. Здесь в функции вы прошли идентификатор. Это идентификатор фото или идентификатор контакта? –

16

Ребята, я провел много часов, пытаясь понять это. Вот метод, который я создал, и вы получите свою фотографию в facebook по номеру телефона (без тире). Вы можете, конечно, изменить его соответствующим образом:

public Bitmap getFacebookPhoto(String phoneNumber) { 
    Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); 
    Uri photoUri = null; 
    ContentResolver cr = this.getContentResolver(); 
    Cursor contact = cr.query(phoneUri, 
      new String[] { ContactsContract.Contacts._ID }, null, null, null); 

    if (contact.moveToFirst()) { 
     long userId = contact.getLong(contact.getColumnIndex(ContactsContract.Contacts._ID)); 
     photoUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, userId); 

    } 
    else { 
     Bitmap defaultPhoto = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_report_image); 
     return defaultPhoto; 
    } 
    if (photoUri != null) { 
     InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(
       cr, photoUri); 
     if (input != null) { 
      return BitmapFactory.decodeStream(input); 
     } 
    } else { 
     Bitmap defaultPhoto = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_report_image); 
     return defaultPhoto; 
    } 
    Bitmap defaultPhoto = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_report_image); 
    return defaultPhoto; 
} 
+2

Я пробовал свой код, но он не работает на моем HTC Sensation (Sense 3.0). IMHO, я думаю, что ваш код также ничего не делает, как получить contactId, а затем передать его openContactPhotoInputStream - он не отличается от кода от @ wrongmissle. На самом деле результат двух решений на моем телефоне одинаковый. – hungson175

+1

Это работает мой HTC Desire HD. Однако, если у меня есть массив контактов из более чем 261 контактов, он заставляет закрывать. Я петлю бросаю массив: photoarray [a] = getFacebookPhoto (storage [a] [0]); где [a] [0] - номер телефона. Поэтому, если storage.length> 261, он закроется. Есть идеи? Массив объявляется как photoarray = new Bitmap [storage.length]; – erdomester

+1

@erdomester Это может быть связано с тем, что требуется много времени, и вы, похоже, блокируете процессор. Вы должны сделать это в фоновом потоке, который не будет блокировать поток основного/пользовательского интерфейса! – JPuge

5

Ни один из этих подходов не работал для меня. Что работа:

String[] projection = new String[] { 
       ContactsContract.Contacts.PHOTO_ID,     ///< the correct ID for photo retrieval in loadLocalContactPhotoBytes() 
//    ContactsContract.Contacts._ID, 
       ContactsContract.Contacts.DISPLAY_NAME, 
       ContactsContract.CommonDataKinds.Phone.NUMBER, 
//    ContactsContract.CommonDataKinds.Photo.PHOTO 
     }; 

     ContentResolver cr = ctx.getContentResolver(); 

     Cursor cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
       //  Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, 
       //    new String[] {RawContacts._ID, RawContacts.ACCOUNT_TYPE, RawContacts.ACCOUNT_NAME}, 
       //    new String[] {Contacts._ID}, 
       projection, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC"); 

.... 

// «курсор» выше был передан в качестве аргумента ниже

private byte[] loadLocalContactPhotoBytes(ContentResolver cr, Cursor cursor, byte[] defaultPhotoBytes) 
    { 
     byte[] photoBytes = null;// = cursor.getBlob(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO)); 

//  int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID)); 
     int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID)); 
//  Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id); 
//  Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY); 
     Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, id); 

     Cursor c = cr.query(photoUri, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); 

     try 
     { 
      if (c.moveToFirst()) 
       photoBytes = c.getBlob(0); 

     } catch (Exception e) { 
      // TODO: handle exception 
      Log.w(_TAG, e.toString()); 

     } finally { 

      c.close(); 
     }   

     photoBytes = photoBytes == null ? defaultPhotoBytes : photoBytes; 
     return photoBytes; 
    } 
16

После долгих отладочных ночей я обнаруживаю, что наилучший подход заключается в использовании contact id и если он не использует photo id.

public static Bitmap loadContactPhoto(ContentResolver cr, long id,long photo_id) 
{ 

    Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id); 
    InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, uri); 
    if (input != null) 
    { 
     return BitmapFactory.decodeStream(input); 
    } 
    else 
    { 
     Log.d("PHOTO","first try failed to load photo"); 

    } 

    byte[] photoBytes = null; 

    Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, photo_id); 

    Cursor c = cr.query(photoUri, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null); 

    try 
    { 
     if (c.moveToFirst()) 
      photoBytes = c.getBlob(0); 

    } catch (Exception e) { 
     // TODO: handle exception 
     e.printStackTrace(); 

    } finally { 

     c.close(); 
    }   

    if (photoBytes != null) 
     return BitmapFactory.decodeByteArray(photoBytes,0,photoBytes.length); 
    else 
     Log.d("PHOTO","second try also failed"); 
    return null; 
} 

код, протестированный на эмуляторе и устройстве Nexus S, и, похоже, работает.

+0

Это единственный фрагмент кода, который я нашел, фактически работая со всеми типами фотографий. +1 обновление: к сожалению, он не работает на Samsung Galaxy S2, на котором работает последний Gingerbread Stock rom. :/ –

+0

Запуск ICS и JellyBean, это единственная рутина, которую мне удалось запустить. Посмотрите, как это работает в Gingerbread, и посмотрите, есть ли способ заставить его работать повсюду. – hnilsen

3

Только для пинок Я скопировал большую часть ответов здесь в один класс, чтобы узнать, удастся ли кому-нибудь из них получить миниатюру Facebook. Они этого не сделали ... Но вот что я сделал, чтобы спасти вас от этого.

Он отображает результаты в диалоговом окне для удобства.

Пожалуйста, обратите внимание - это не оптимизирована, и вы должны поймать ошибок и близких курсоры и т.д.:

Чтобы начать контакт сборщика намерение:

private static final int SELECT_CONTACT = 1468; 

Intent contactPickerIntent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); 
contactPickerIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 

try { 
    startActivityForResult(contactPickerIntent, SELECT_CONTACT); 
} catch (ActivityNotFoundException e) { 
    e.printStackTrace(); 
} 

Обратный вызов:

@Override 
    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { 
     super.onActivityResult(requestCode, resultCode, data); 

    if (data != null && resultCode == Activity.RESULT_OK) { 

     switch (requestCode) { 

     case SELECT_CONTACT: 

      Uri contactURI = data.getData(); 

      if (contactURI != null) { 

       String contactID = data.getData().getLastPathSegment().trim(); 

       String contactName = ContactThumb.getDisplayName(getActivity(), contactURI); 

       if (contactName != null && !contactName.isEmpty() && contactID != null && !contactID.isEmpty()) { 

        final int THUMBNAIL_SIZE = 100; 

        Bitmap contactThumb = ContactThumb.loadContactPhoto(getActivity(), Long.valueOf(contactID)); 

        if (contactThumb != null) { 

         final AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); 

         final int width = contactThumb.getWidth(); 
         final int height = contactThumb.getHeight(); 
         final int ratio = width/height; 

         final Bitmap resized = ThumbnailUtils.extractThumbnail(contactThumb, (THUMBNAIL_SIZE * ratio), 
           THUMBNAIL_SIZE); 

         Drawable icon = new BitmapDrawable(getActivity().getResources(), resized); 

         alert.setIcon(icon); 

         alert.setTitle("Contact details"); 

         final TextView homeTV = new TextView(getActivity()); 

         homeTV.setText(contactName + " : " + contactID); 
         homeTV.setTextSize(12); 

         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { 
          homeTV.setTextColor(Color.WHITE); 
         } 

         homeTV.setPadding(30, 2, 20, 10); 
         homeTV.setMovementMethod(LinkMovementMethod.getInstance()); 

         alert.setView(homeTV); 
         alert.show(); 

        } else { 
         Toast.makeText(getActivity(), "Photo null", Toast.LENGTH_SHORT).show(); 
        } 
       } 

      } 

      break; 
     } 
    } else { 
     // cancelled or error 
    } 
} 

The ContactThumb попытки ....

import java.io.InputStream; 
import android.content.ContentResolver; 
import android.content.ContentUris; 
import android.content.Context; 
import android.database.Cursor; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.net.Uri; 
import android.provider.ContactsContract; 
import android.provider.ContactsContract.Contacts; 
import android.provider.ContactsContract.PhoneLookup; 
import android.provider.ContactsContract.CommonDataKinds.Phone; 
import android.util.Log; 

public class ContactThumb { 

private static final String TAG = "THUMB"; 

public static String getDisplayName(final Context ctx, final Uri contactURI) { 

    String cname = null; 

    try { 

     final String[] projection = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; 
     final Cursor cursor = ctx.getContentResolver().query(contactURI, projection, null, null, null); 

     if (cursor != null) { 

      try { 

       if (cursor.moveToFirst()) { 
        cname = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); 
       } 

      } finally { 
       cursor.close(); 
      } 

     } 

    } catch (final Exception e) { 
     e.printStackTrace(); 
    } 

    return cname; 
} 

public static Bitmap loadContactPhoto(final Context ctx, final long contactId) { 

    final Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId); 

    final InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(ctx.getContentResolver(), contactUri); 

    if (input != null) { 
     Log.i(TAG, "loadContactPhoto: input"); 

     return BitmapFactory.decodeStream(input); 

    } else { 

     byte[] photoBytes = null; 

     Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); 

     final Cursor c = ctx.getContentResolver().query(photoUri, 
       new String[] { ContactsContract.CommonDataKinds.Photo.PHOTO }, null, null, null); 

     try { 

      if (c.moveToFirst()) { 
       photoBytes = c.getBlob(0); 
      } 

     } catch (final Exception e) { 
      e.printStackTrace(); 

     } finally { 
      c.close(); 
     } 

     if (photoBytes != null) { 

      Log.i(TAG, "loadContactPhoto: photoBytes"); 

      return BitmapFactory.decodeByteArray(photoBytes, 0, photoBytes.length); 

     } else { 

      Bitmap another = finalAttempt(ctx, contactId); 

      if (another != null) { 

       Log.i(TAG, "loadContactPhoto: another"); 

       return another; 
      } else { 

       Log.i(TAG, "loadContactPhoto: might be returning default"); 

       return getFacebookPhoto(ctx, getContactNumber(ctx, String.valueOf(contactId))); 
      } 
     } 
    } 
} 

public static String getContactNumber(final Context ctx, final String contactID) { 

    Cursor phones = null; 

    try { 

     phones = ctx.getContentResolver().query(Phone.CONTENT_URI, null, Phone.CONTACT_ID + " = " + contactID, null, null); 

     String cnum = null; 

     if (phones != null && phones.getCount() > 0) { 

      while (phones.moveToNext()) { 
       cnum = phones.getString(phones.getColumnIndex(Phone.NUMBER)); 

       if (cnum != null && !cnum.isEmpty() && !cnum.contains("@")) { 

        Log.i(TAG, "getContactNumbers: : cnum: " + cnum); 

        try { 
         phones.close(); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 

        return cnum; 
       } 
      } 
     } 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return null; 
} 

public static Bitmap getFacebookPhoto(final Context ctx, String phoneNumber) { 

    Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)); 
    Uri photoUri = null; 
    ContentResolver cr = ctx.getContentResolver(); 

    Cursor contact = cr.query(phoneUri, new String[] { ContactsContract.Contacts._ID }, null, null, null); 

    if (contact.moveToFirst()) { 
     long userId = contact.getLong(contact.getColumnIndex(ContactsContract.Contacts._ID)); 
     photoUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, userId); 

    } else { 
     Bitmap defaultPhoto = BitmapFactory.decodeResource(ctx.getResources(), android.R.drawable.ic_menu_report_image); 
     return defaultPhoto; 
    } 
    if (photoUri != null) { 
     InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(cr, photoUri); 
     if (input != null) { 
      return BitmapFactory.decodeStream(input); 
     } 
    } else { 
     Bitmap defaultPhoto = BitmapFactory.decodeResource(ctx.getResources(), android.R.drawable.ic_menu_report_image); 
     return defaultPhoto; 
    } 
    Bitmap defaultPhoto = BitmapFactory.decodeResource(ctx.getResources(), android.R.drawable.ic_menu_report_image); 
    return defaultPhoto; 
} 

public static Bitmap finalAttempt(final Context ctx, final long contactId) { 

    byte[] photoBytes = null; 

    String[] projection = new String[] { ContactsContract.Contacts.PHOTO_ID, ContactsContract.Contacts.DISPLAY_NAME, 
      ContactsContract.CommonDataKinds.Phone.NUMBER, }; 

    ContentResolver cr = ctx.getContentResolver(); 

    final Uri contactUri = ContentUris.withAppendedId(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, contactId); 

    Cursor cursor = cr.query(contactUri, projection, null, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC"); 

    if (cursor != null && cursor.moveToFirst()) { 

     int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_ID)); 
     Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, id); 

     Cursor c = cr.query(photoUri, new String[] { ContactsContract.CommonDataKinds.Photo.PHOTO }, null, null, null); 

     try { 
      if (c.moveToFirst()) { 
       photoBytes = c.getBlob(0); 
      } 

     } catch (Exception e) { 

     } finally { 
      cursor.close(); 
      c.close(); 
     } 

     if (photoBytes != null) { 
      return BitmapFactory.decodeByteArray(photoBytes, 0, photoBytes.length); 
     } 
    } 

    return null; 
} 

} 

Если какой-либо из методов работает для вас, пожалуйста, подтвердите ответ, который я скопировал и вставил код!

Проверить эту ссылку для Android Developers suggested way

Успехов

0

После некоторых исследований я нашел решение на: Displaying the Quick Contact Badge

Мой код с некоторыми незначительными изменениями, отлично работает для меня

public Bitmap loadContactPhoto(String name) { 
    String photoUri = null;  
    int thumbnailColumn;   
    ContentResolver cr = GlobalData.instance().getContext().getContentResolver(); 
    String[] projection = new String[] { ContactsContract.Contacts._ID ,ContactsContract.Contacts.PHOTO_ID, ContactsContract.Contacts.PHOTO_URI, ContactsContract.Contacts.PHOTO_THUMBNAIL_URI}; 
    Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, projection, ContactsContract.Contacts.DISPLAY_NAME + "='" + name + "'", null, null); 
    if (cursor.moveToFirst()) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
       thumbnailColumn = cursor.getColumnIndex(Contacts.PHOTO_THUMBNAIL_URI); 
      else 
       thumbnailColumn = cursor.getColumnIndex(PhoneLookup._ID); 

      photoUri = cursor.getString(thumbnailColumn); 

      if(photoUri != null) 
       return loadContactPhotoThumbnail(photoUri); 
      else 
       return null;  
    } 
    return null; 
} 
private Bitmap loadContactPhotoThumbnail(String photoData) { 
    AssetFileDescriptor afd = null; 
    try { 

     Uri thumbUri; 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
      thumbUri = Uri.parse(photoData); 
     } else { 
      final Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_URI, photoData); 
      thumbUri = Uri.withAppendedPath(contactUri, Photo.CONTENT_DIRECTORY); 
     } 
     afd = GlobalData.instance().getContext().getContentResolver().openAssetFileDescriptor(thumbUri, "r"); 
     FileDescriptor fileDescriptor = afd.getFileDescriptor(); 
     if (fileDescriptor != null) 
      return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, null); 
    } catch (FileNotFoundException e) { 
    } finally { 
     if (afd != null) { 
      try { 
       afd.close(); 
      } catch (IOException e) { 
      } 
     } 
    } 
    return null; 
} 
+0

FileNotFoundException: Нет контент-провайдера:/contacts/27/photo –

2

В документации на Android говорится, что мы должны делать это таким образом.

public Bitmap openPhoto(long contactId) { 
     Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId); 
     Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY); 
     Cursor cursor = getContentResolver().query(photoUri, 
       new String[] {ContactsContract.Contacts.Photo.PHOTO}, null, null, null); 
     if (cursor == null) { 
      return null; 
     } 
     try { 
      if (cursor.moveToFirst()) { 
       byte[] data = cursor.getBlob(0); 
       if (data != null) { 
        return BitmapFactory.decodeStream(new ByteArrayInputStream(data)); 
       } 
      } 
     } finally { 
      cursor.close(); 
     } 
     return null; 

} 

ContactId расшифровывается как:

getString(c.getColumnIndex(ContactsContract.Contacts._ID)) 

Источник: https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo.html

1

Код взят developer.android.com

public InputStream openPhoto(long contactId) { 
    Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 
    Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); 
    Cursor cursor = getContentResolver().query(photoUri, 
      new String[] {Contacts.Photo.PHOTO}, null, null, null); 
    if (cursor == null) { 
     return null; 
    } 
    try { 
     if (cursor.moveToFirst()) { 
      byte[] data = cursor.getBlob(0); 
      if (data != null) { 
       return new ByteArrayInputStream(data); 
      } 
     } 
    } finally { 
     cursor.close(); 
    } 
    return null; 
} 
0

проверить мой пост:

https://stackoverflow.com/a/41445851/1733810

public Bitmap retrieveContactPhoto(Context context, String number) { 
     ContentResolver contentResolver = context.getContentResolver(); 
     String contactId = null; 
     Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); 

     String[] projection = new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup._ID}; 

     Cursor cursor = 
       contentResolver.query(
         uri, 
         projection, 
         null, 
         null, 
         null); 

     if (cursor != null) { 
      while (cursor.moveToNext()) { 
       contactId = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID)); 
      } 
      cursor.close(); 
     } 

     Bitmap photo = BitmapFactory.decodeResource(context.getResources(), 
       R.mipmap.popup); 

     try { 

      Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.valueOf(contactId)); 
      Uri displayPhotoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO); 

       AssetFileDescriptor fd = 
         getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r"); 
       InputStream inputStream=fd.createInputStream(); 


      if (inputStream != null) { 
       photo = BitmapFactory.decodeStream(inputStream); 
      } 

      assert inputStream != null; 
      inputStream.close(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return photo; 
    }