如何加载联系人照片? [英] How do I load a contact Photo?
问题描述
我在为 Android 中的联系人加载照片时遇到问题.我在谷歌上搜索了答案,但到目前为止都是空的.有没有人有查询联系人然后加载照片的示例?
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?
因此,给定一个来自名为 using 的活动结果的 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)
是:
content://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:
content://com.android.contacts/contacts/1557
content://com.android.contacts/contacts/1557
查看下面代码中的内嵌注释.
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();
现在有一些方法可以提高效率 - 例如,如果您正在渲染消息时间线,您希望为给定电话号码的每个徽章实例重复使用相同的位图对象,而不是不断创建新的帮助程序类实例并重新检索位图 - 但我在这里的目的是发布一个解决方案,为了清晰起见,该解决方案被精简到绝对最小值,同时提供一个完整且可用的开箱即用的解决方案.此解决方案已在 Andriod 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.
这篇关于如何加载联系人照片?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!