I'm having a hard time retrieving pictures of contacts on Android. I tried to google it, but I couldn't find the relevant data. Does anyone have an example of querying a contact to retrieve a photo?
startActivityForResult(new Intent(Intent.ACTION_PICK,ContactsContract.CommonDataKinds.Phone.CONTENT_URI),PICK_CONTACT_REQUEST)
The contactUri retrieved from the activity result using the above code is as follows.
content://com.android.contacts/data/1557
The loadContact(..)
function that loads contacts works fine, but when you call the getPhoto()
function that loads pictures, a null value appears in the picture InputStream. The confusing thing is that the URI value is different. Contact PhotoUri is as follows.
content://com.android.contacts/contacts/1557
Please refer to the notes in the code below.
class ContactAccessor {
/**
* A function that retrieves contact information
*/
public ContactInfo loadContact(ContentResolver contentResolver, Uri contactUri) {
//contactUri --> content://com.android.contacts/data/1557
ContactInfo contactInfo = new ContactInfo();
// Calling up names for a specific 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; // <-- Return contact information
}
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); // <-- This part always returns 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;
}
}
}
I'm sure I made a mistake somewhere here, but I can't find the problem. Thank you.
android contactscontract
I've seen a lot of questions and answers about the thumbnail issue, but I've only seen a couple of ways to solve it, and I haven't seen a good solution.
The classes below call up Context, QuickContactBadge, and phone numbers, if any images are available for a particular phone number.
The classes are as follows.
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 below is how to use it in the activity :
String phoneNumber = "...";
QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.friend);
new QuickContactHelper(this, badge, phoneNumber).addThumbnail();
It's a little different if you use it in a fragment :
String phoneNumber = "...";
QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.friend);
new QuickContactHelper(getActivity(), badge, phoneNumber).addThumbnail();
Of course, to use this code more efficiently, you need to modify it somewhat. For example, if a questioner wants to organize a message timeline, he or she would rather reuse the same picture file on all badges that correspond to the same phone number than recall a new picture file from time to time. However, the purpose of this answer is to provide a solution that users can complete and use in an original way to make a point more clearly. This solution was built and tested in an Android 4.0 environment, and was also tested in 4.1.
© 2024 OneMinuteCode. All rights reserved.