how can I get contact photo from a contact's address (phone number)?
public static 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.drawable.default_image);
try {
if(contactId != null) {
InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(),
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, new Long(contactId)));
if (inputStream != null) {
photo = BitmapFactory.decodeStream(inputStream);
}
assert inputStream != null;
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return photo;
}
I think this vesion works better in all android versions :
public Bitmap getContactsDetails(String address) {
Bitmap bp = BitmapFactory.decodeResource(context.getResources(),
R.drawable.contact_default_picture);
Uri contactUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address));
// querying contact data store
Cursor phones = context.getContentResolver().query(contactUri, null, null, null, null);
while (phones.moveToNext()) {
String image_uri = phones.getString(phones.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
if (image_uri != null) {
try {
bp = MediaStore.Images.Media
.getBitmap(context.getContentResolver(),
Uri.parse(image_uri));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return bp;
}
Call this method to get all contact information.
public void readContacts() {
StringBuffer sb = new StringBuffer();
sb.append("......Contact Details.....");
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,
null, null, null);
String phone = null;
String emailContact = null;
String emailType = null;
String image_uri = "";
Bitmap bitmap = null;
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur
.getColumnIndex(ContactsContract.Contacts._ID));
String name = cur
.getString(cur
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
image_uri = cur
.getString(cur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
if (Integer
.parseInt(cur.getString(cur
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
System.out.println("name : " + name + ", ID : " + id);
sb.append("\n Contact Name:" + name);
Cursor pCur = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = ?", new String[] { id }, null);
while (pCur.moveToNext()) {
phone = pCur
.getString(pCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
sb.append("\n Phone number:" + phone);
System.out.println("phone" + phone);
}
pCur.close();
Cursor emailCur = cr.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID
+ " = ?", new String[] { id }, null);
while (emailCur.moveToNext()) {
emailContact = emailCur
.getString(emailCur
.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
emailType = emailCur
.getString(emailCur
.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
sb.append("\nEmail:" + emailContact + "Email type:" + emailType);
System.out.println("Email " + emailContact
+ " Email Type : " + emailType);
}
emailCur.close();
}
if (image_uri != null) {
System.out.println(Uri.parse(image_uri));
try {
bitmap = MediaStore.Images.Media
.getBitmap(this.getContentResolver(),
Uri.parse(image_uri));
sb.append("\n Image in Bitmap:" + bitmap);
System.out.println(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
sb.append("\n........................................");
}
textDetail.setText(sb);
}
}
You can use the column below to get the contacts photo uri, ContactsContract.CommonDataKinds.Phone.PHOTO_URI.
This is the function:
public static Bitmap getContactsDetails(String address) {
Bitmap bp = BitmapFactory.decodeResource(context.getResources(),
R.drawable.default_contact_photo);
String selection = ContactsContract.CommonDataKinds.Phone.NUMBER + " = '" + address + "'";
Cursor phones = context.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, selection,
null, null);
while (phones.moveToNext()) {
String image_uri = phones.getString(phones.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
if (image_uri != null) {
try {
bp = MediaStore.Images.Media
.getBitmap(context.getContentResolver(),
Uri.parse(image_uri));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return bp;
}
You can make some changes if you want to get Retrieving the larger photo
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;
}
for Retrieving the thumbnail-sized photo
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;
}
for more detail:
Click Here
I am calling intent to pick a contact using this code.
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
((Activity) mContext).startActivityForResult(intent, PICK_CONTACT);
#Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
if (reqCode == PICK_CONTACT) {
if (resultCode == Activity.RESULT_OK) {
Uri uri= data.getData();
}
Here I want to fetch three information of contact such as Name, Phone number, and contact Image.
I am able to fetch name and number but not able to fetch Image. any help would be appreciated.
use following function:
private String retrieveContactPhoto(String contactID) {
// Bitmap photo = null;
/*
* if (inputStream != null) { photo =
* BitmapFactory.decodeStream(inputStream); ImageView imageView =
* (ImageView) findViewById(R.id.img_contact);
* imageView.setImageBitmap(photo); }
*/
Uri photoUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI,
Long.parseLong(contactID));
final Cursor image = getContentResolver().query(photoUri,
PHOTO_ID_PROJECTION, null, null,
ContactsContract.Contacts._ID + " ASC");
try {
Integer thumbnailId = null;
if (image.moveToFirst()) {
thumbnailId = image.getInt(image
.getColumnIndex(ContactsContract.Contacts.PHOTO_ID));
Uri uri = ContentUris.withAppendedId(
ContactsContract.Data.CONTENT_URI, thumbnailId);
image.close();
if (uri.toString().equals("content://com.android.contacts/data/0"))
return null;
return uri.toString();
}
} finally {
image.close();
}
return null;
and for showing image use following code
if (entries.get(position).getphoto() != null
&& entries.get(position).getphoto() != "content:////com.android.contacts//data//0") {
try {
holder.photo.setImageURI(Uri.parse(entries.get(position)
.getphoto()));
} catch (Exception e) {
holder.photo.setImageResource(R.drawable.abc); //use default image
}
} else
holder.photo.setImageResource(R.drawable.abc); //use default image
Try following
InputStream photo_stream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(),uri);
BufferedInputStream buf =new BufferedInputStream(photo_stream);
Bitmap my_btmp = BitmapFactory.decodeStream(buf);
Use this:
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(this.getContentResolver(), uri);
BufferedInputStream buffer =new BufferedInputStream(input);
Bitmap bitmap = BitmapFactory.decodeStream(buffer);
Check the below code which will help you to get the Contact Name,Number and contact Image as well. Call the below code on click of a button.
public void onClickSelectContact(View btnSelectContact) {
// using native contacts selection
// Intent.ACTION_PICK = Pick an item from the data, returning what was selected.
startActivityForResult(new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI), REQUEST_CODE_PICK_CONTACTS);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_PICK_CONTACTS && resultCode == RESULT_OK) {
Log.d(TAG, "Response: " + data.toString());
uriContact = data.getData();
retrieveContactName();
retrieveContactNumber();
retrieveContactPhoto();
}
}
//To get the Contact Image
private void retrieveContactPhoto() {
Bitmap photo = null;
try {
InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(),
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, new Long(contactID)));
if (inputStream != null) {
photo = BitmapFactory.decodeStream(inputStream);
ImageView imageView = (ImageView) findViewById(R.id.img_contact);
imageView.setImageBitmap(photo);
}
assert inputStream != null;
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//To get Contact Number.
private void retrieveContactNumber() {
String contactNumber = null;
// getting contacts ID
Cursor cursorID = getContentResolver().query(uriContact,
new String[]{ContactsContract.Contacts._ID},
null, null, null);
if (cursorID.moveToFirst()) {
contactID = cursorID.getString(cursorID.getColumnIndex(ContactsContract.Contacts._ID));
}
cursorID.close();
Log.d(TAG, "Contact ID: " + contactID);
// Using the contact ID now we will get contact phone number
Cursor cursorPhone = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ? AND " +
ContactsContract.CommonDataKinds.Phone.TYPE + " = " +
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE,
new String[]{contactID},
null);
if (cursorPhone.moveToFirst()) {
contactNumber = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
cursorPhone.close();
Log.d(TAG, "Contact Phone Number: " + contactNumber);
}
//To get Contact Name.
private void retrieveContactName() {
String contactName = null;
// querying contact data store
Cursor cursor = getContentResolver().query(uriContact, null, null, null, null);
if (cursor.moveToFirst()) {
// DISPLAY_NAME = The display name for the contact.
// HAS_PHONE_NUMBER = An indicator of whether this contact has at least one phone number.
contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
cursor.close();
Log.d(TAG, "Contact Name: " + contactName);
}
}
Also to get all the phone numbers + email address try as below:
ContentResolver contactResolver = context.getContentResolver();
Cursor cursor = contactResolver.query(Uri.parse(aContact.getLookupUri()), null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String photoUri = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.PHOTO_THUMBNAIL_URI));
String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0)
{
Cursor pCur = contactResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { contactId }, null);
while (pCur.moveToNext())
{
String phone = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String type = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
String s = (String) ContactsContract.CommonDataKinds.Phone.getTypeLabel(context.getResources(), Integer.parseInt(type), "");
Log.d("TAG", s + " phone: " + phone);
}
pCur.close();
}
Cursor emailCursor = contactResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[] { contactId }, null);
while (emailCursor.moveToNext())
{
String phone = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
int type = emailCursor.getInt(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE));
String s = (String) ContactsContract.CommonDataKinds.Email.getTypeLabel(context.getResources(), type, "");
Log.d("TAG", s + " email: " + phone);
}
emailCursor.close();
cursor.close();
}
How to edit firstname,surname,mobilenumber,photo,email,address in native contact in android programmatically using contact id. Please help me. Thanks in advance.
on Button click do the following:
Intent in = new Intent(Intent.ACTION_INSERT_OR_EDIT);
in.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
startActivityForResult(in,EDIT_CONTACT);
and in onActivityResult Function do this:
case EDIT_CONTACT:
if (resultCode == RESULT_OK) {
Uri contactData = data.getData();
Cursor cur = managedQuery(contactData, null, null, null, null);
ContentResolver contect_resolver = getContentResolver();
if (cur.moveToFirst()) {
String id = cur.getString(cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
String name = "";
String no = "";
String key = cur.getString(cur.getColumnIndexOrThrow(ContactsContract.Contacts.LOOKUP_KEY));
String where = ContactsContract.Data.DISPLAY_NAME + " = ? AND " +
ContactsContract.Data.MIMETYPE + " = ? AND " +
String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE) + " = ? ";
String[] params = new String[] {name,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_HOME)};
Cursor phoneCur = contect_resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);
if (phoneCur.moveToFirst()) {
name = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
no = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
key = phoneCur.getString(phoneCur.getColumnIndexOrThrow(ContactsContract.Contacts.LOOKUP_KEY));
System.out.println("EDITIDDDDDDDDDD"+name);
System.out.println("EDITIDDDDDDDDDD"+no);
System.out.println("EDITIDDDDDDDDDD"+key);
/*ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
if ( (null == phoneCur) ) {
// createContact(name, phone);
} else {
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(where, params)
.withValue(ContactsContract.CommonDataKinds.Phone.DATA, no)
.build());
}
phoneCur.close();
try {
cr.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
id = null;
name = null;
no = null;
phoneCur = null;
key = null;
contect_resolver = null;
cur = null;
}
}
}
break;
I'm trying to get a contact image using its lookup URI.
I succeed getting the DISPLAY_NAME using this code:
Cursor c = context.getContentResolver().query(contactLookupUri,
new String[] { ContactsContract.Contacts.DISPLAY_NAME }, null,
null, null);
But I didn't find a way to get the photo. The Photo.PHOTO option is not valid for the API I'm using, and trying to get it using an inputStream didn't work as well (perhaps I did something wrong there):
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(context.getContentResolver(),
contactUri);
Thanks,
Yoel
Eventually I solved it by getting the contact ID and using an inputStream:
public static Uri getContactLookupUri(String contactLookupKey) {
return Uri.withAppendedPath(
ContactsContract.Contacts.CONTENT_LOOKUP_URI, contactLookupKey);
}
public static Bitmap getContactImage(Context context, String contactLookupKey) {
long contactId;
try {
Uri contactLookupUri = getContactLookupUri(contactLookupKey);
Cursor c = context.getContentResolver().query(contactLookupUri,
new String[] { ContactsContract.Contacts._ID }, null, null,
null);
try {
if (c == null || c.moveToFirst() == false) {
return null;
}
contactId = c.getLong(0);
} finally {
c.close();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
Uri contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, contactId);
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(context.getContentResolver(),
contactUri);
if (input != null) {
return BitmapFactory.decodeStream(input);
} else {
return null;
}
}
The below function return the image uri of your contact_id
/**
* #return the photo URI
*/
public Uri getPhotoUri() {
try {
Cursor cur = this.ctx.getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.CONTACT_ID + "=" + this.getId() + " AND "
+ ContactsContract.Data.MIMETYPE + "='"
+ ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'", null,
null);
if (cur != null) {
if (!cur.moveToFirst()) {
return null; // no photo
}
} else {
return null; // error in cursor process
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long
.parseLong(getId()));
return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
}
Also refer this LINK
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?
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)
is:
content://com.android.contacts/data/1557
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
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.
This works for me:
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);
}
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.
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.
Here's the class:
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();
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.
After a lot of debugging nights I discover that the best approach is to use the contact id and if it fails to use the 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;
}
the code tested on emulator and Nexus S device and seems to work.
Guys, I spent many hours attempting to figure this out. Here is a method I created that will get you your facebook photo by phone number (no dashes). You can, of course, modify it accordingly:
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;
}
None of these approaches worked for me. What did work was:
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");
....
//the 'cursor' above got passed as an argument below
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;
}
Just for kicks I copied most of the answers here into a single class to see if any of them would succeed in getting the Facebook thumbnail. They didn't.... But, here is what I did to perhaps save you doing the same.
It shows the results in a dialog for ease.
Please be aware - it's not optimised and you'll need to catch errors and close cursors etc:
To start the contact picker intent:
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();
}
The callback:
#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 attempts....
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;
}
}
If any of the methods work for you, please upvote the answer I've copied and pasted the code from!
Check this link for the Android Developers suggested way
Good luck
It seems that my problem was because the contacts in my device were synced from facebook, and the photo therefore is not available.
http://groups.google.com/group/android-developers/msg/be8d0cf3928e4b7f
Android documentation says, that we should do it in this way.
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 stands for:
getString(c.getColumnIndex(ContactsContract.Contacts._ID))
source: https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo.html
After some research I found the solution at: Displaying the Quick Contact Badge
My code with some minor modifications, works fine for me
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;
}