如何加载一个联系人的照片?加载、联系人、照片

2023-09-11 12:05:17 作者:只剩寒暄

我无法加载在Android的联系人的照片。我GOOGLE了一个答案,但至今都拿出了空。有没有人有查询联系人,然后加载图片的例子吗?

I'm having trouble loading a photo for a contact in Android. I've googled for an answer, but so far have come up empty. Does anyone have an example of querying for a Contact, then loading the Photo?

所以,对于一个contactUri其中来自使用称为活动结果

So, given a contactUri which comes from an Activity result called using

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

是:

内容://com.android.contacts/data/1557

content://com.android.contacts/data/1557

在loadContact(..)正常工作。然而,当我打电话getPhoto(...)方法,我得到的照片的InputStream空值。这也是令人困惑,因为URI值是不同的。该contactPhotoUri计算结果为:

The loadContact(..) works fine. However when I call the getPhoto(...) method, I get a null value for the photo InputStream. It is also confusing because the URI values are different. The contactPhotoUri evaluates to:

内容://com.android.contacts/contacts/1557

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

查看评论内嵌在下面的code。

See the comments inline in the code below.

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

}

}

显然,我在这里做得不对,但我似乎无法弄清楚的问题是什么。谢谢你。

Clearly, I'm doing something wrong here, but I can't seem to figure out what the problem is. Thanks.

推荐答案

已经扫描了许多的问题和答案,以显示缩略图我想我会后我的解决方案,以这种特殊的难题,我只能找到一对夫妇的问题供职于一切,没有一个规定的懒惰开发一个很好的罐头的解决方案。

Having scanned the many questions and answers to the problem of displaying a thumbnail I thought I would post my solution to this particular conundrum as I could only find a couple that worked at all and none that provided a good canned solution for the lazy developer.

类下面需要一个上下文,QuickContactBadge和电话号码和将附加本地存储的图像到徽章,如果有一个可用的特定的电话号码。

The class below takes a Context, QuickContactBadge and a telephone number and will attach a locally stored image to the badge if there is one available for the specified phone number.

下面是类:

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

}

}

这是一个典型的用例的活动里面的:

And here's a typical use case inside an activity:

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

在一个片段也将略有不同:

In a fragment it will be slightly different:

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

现在有一些方法可以更有效率 - 例如,如果你正在呈现你想要重新使用的每一个徽章例如相同的位图对象,对于给定的电话号码的消息时间表,而不是不断创造新的辅助类实例并重新检索位图 - 但这里我的目的是要张贴被剥离下来的绝对最小为了清楚起见而在同一时间提供一个完整的,可使用的溶液的开箱的溶液。该解决方案已建成和在安卓4.0进行测试,并在4.1以及测试。

Now there are ways to be more efficient - for example if you are rendering a message timeline you'd want to re-use the same bitmap object for every badge instance for a given phone number instead of constantly creating new helper class instances and re-retrieving the bitmap - but my purpose here was to post a solution that is stripped down to the absolute minimum for clarity whilst at the same time providing a complete and usable solution out of the box. This solution has been built and tested on Andriod 4.0, and tested on 4.1 as well.