我在Android中为联系人加载照片时遇到问题.我已经google了一个答案,但到目前为止已经空了.有没有人有查询联系人,然后加载照片的例子?
因此,给定一个来自一个名为using的Activity结果的contactUri
startActivityForResult(new Intent(Intent.ACTION_PICK,ContactsContract.CommonDataKinds.Phone.CONTENT_URI),PICK_CONTACT_REQUEST)
是:
内容://com.android.contacts/data/1557
loadContact(..)工作正常.但是,当我调用getPhoto(...)方法时,我得到了照片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; } } }
显然,我在这里做错了,但我似乎无法弄清问题是什么.谢谢.
这对我有用:
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); }
在扫描了显示缩略图问题的许多问题和答案之后,我想我会将我的解决方案发布到这个特定的难题,因为我只能找到一对完全没有工作且没有为懒惰的开发人员提供良好的固定解决方案.
下面的类采用Context,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上进行了测试.
伙计们,我花了很多时间试图解决这个问题.这是我创建的一种方法,可以通过电话号码(无破折号)获取您的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; }
在经过大量的调试之后,我发现最好的方法是使用它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设备上测试的代码似乎有效.
这些方法都不适合我.工作是什么:
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; }