The problem which i'm facing is I am not able to display the fetched value, as I have used a list view to display the values are not reaching it. This is my code snippet which fetches multiple contacts from phone book. Hope any1 help me solve it.
private void chooseContact() {
Intent phonebookIntent = new Intent("intent.action.INTERACTION_TOPMENU");
phonebookIntent.putExtra("additional", "phone-multi");
phonebookIntent.putExtra("maxRecipientCount", MAX_PICK_CONTACT);
phonebookIntent.putExtra("FromMMS", true);
startActivityForResult(phonebookIntent, REQUEST_CODE_PICK_CONTACT);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == RESULT_PICK_CONTACT) {
Uri contractData = data.getData();
ContactRetriever cr = new ContactRetriever(getApplicationContext(), contractData);
Person p = cr.getPerson();
if (p == null)
Toast.makeText(this, "Phone number not found!", Toast.LENGTH_SHORT).show();
else {
PersonManager.savePerson(p, getApplicationContext());
listContacts.setAdapter(new PersonAdapter(this, PersonManager.getSavedPersons(this)));
}
}
}
}}
And the Uri value is called and used in next below class
public class ContactRetriever {
private final String TAG = "ContactRetriever";
private ContentResolver cr;
private Context context;
private Uri contractData;
private String id;
public ContactRetriever(Context context,Uri contractData ) {
this.context = context;
this.cr = context.getContentResolver();
this.contractData = contractData;
}
public Person getPerson() {
String name = getName();
String num = getNumber();
if (name != null && num != null)
return new Person(getNumber(), getName());
else return null;
}
private String getNumber() {
String ret = null;
Cursor cId = cr.query(contractData, new String[]{ContactsContract.Contacts._ID}, null, null, null);
if (cId.moveToFirst()){
id = cId.getString(cId.getColumnIndex(ContactsContract.Contacts._ID));
Log.i(TAG + " IDs: ", id);
}
cId.close();
Cursor cNum = cr.query(contractData, null, null, null, null);
if (cNum.moveToNext()){
ret = cNum.getString(cNum.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.i(ret, TAG + " NUMBERS: ");
}
return ret;
}
private String getName() {
String ret = null;
Cursor c = cr.query(contractData, null, null, null, null);
if (c.moveToFirst())
ret = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
c.close();
Log.i(TAG + "NAMES: ", ret);
return ret;
}
}
Here is my working code for mine
//enter code here
private void getAllContacts() {
List<InviteContactInfo> inviteContactList = new ArrayList();
InviteContactInfo inviteContactInfo;
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
inviteContactInfo = new InviteContactInfo();
inviteContactInfo.setContactName(name);
Cursor phoneCursor = contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id},
null);
if (phoneCursor.moveToNext()) {
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
inviteContactInfo.setContactNumber(phoneNumber);
}
phoneCursor.close();
Cursor emailCursor = contentResolver.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?",
new String[]{id}, null);
while (emailCursor.moveToNext()) {
String emailId = emailCursor.getString(emailCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
}
Bitmap photo =null;
try {
InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(),
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, new Long(id)));
if (inputStream != null) {
photo = BitmapFactory.decodeStream(inputStream);
inviteContactInfo.setContactImage(photo);
}
else
{
photo =BitmapFactory.decodeResource(getResources(), R.drawable.profilepic);;
inviteContactInfo.setContactImage(photo);
}
assert inputStream != null;
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
inviteContactList.add(inviteContactInfo);
}
}
InviteContactAdapter contactAdapter = new InviteContactAdapter(getApplicationContext(), inviteContactList);
recList.setLayoutManager(new LinearLayoutManager(this));
recList.setAdapter(contactAdapter);
}
}
The following code lets me display duplicate contacts.
And when I try to delete, it deletes the duplicated number as well as the original number.
I want it to delete only the duplicated number present in the listview.
Here is my code.
public class MainActivity extends Activity {
ListView listView;
ArrayList<String> listItems = new ArrayList<String>();
Set<String> dupesRemoved = new HashSet<String>();
String[] newList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list);
String order = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC";
Cursor curLog = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null,order);
Cursor cursor = null;
if(curLog != null) {
while(curLog.moveToNext()) {
String str = curLog.getString(curLog.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
//contactid = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
listItems.add(str);
}
}
dupesRemoved = findDuplicates(listItems);
String listString = dupesRemoved.toString();
listString = listString.substring(1,listString.length()-1);
newList = listString.split(", ");
//Arrays.sort(newList);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, newList);
listView.setAdapter(adapter);
}
public void deleteDupes(View view) {
String[] info = new String[2];
for (String s : newList) {
info = (getContactInfo(s));
updateContact(info[0],this,info[1]);
listView.invalidateViews();
}
}
public void updateContact(String contactId, Activity act, String type){
/* ASSERT: #contactId alreay has a work phone number */
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
String selectPhone = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" +
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'" + " AND " + ContactsContract.CommonDataKinds.Phone.TYPE + "=?";
String[] phoneArgs = new String[]{contactId,type /*String.valueOf(ContactsContract.CommonDataKinds.Phone.TYPE_HOME)*/};
ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
.withSelection(selectPhone, phoneArgs).build());
try {
act.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
}
public static Set<String> findDuplicates(List<String> listContainingDuplicates) {
final Set<String> setToReturn = new HashSet<String>();
final Set<String> set1 = new HashSet<String>();
for (String yourInt : listContainingDuplicates) {
if (!set1.add(yourInt)) {
setToReturn.add(yourInt);
}
}
return setToReturn;
}
private String[] getContactInfo(String number)
{
String[] contactInfo = new String[2];
ContentResolver context = getContentResolver();
/// number is the phone number
Uri lookupUri = Uri.withAppendedPath(
ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(number));
String[] mPhoneNumberProjection = { ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.NUMBER, ContactsContract.PhoneLookup.TYPE };
Cursor cur = context.query(lookupUri,mPhoneNumberProjection, null, null, null);
try
{
if (cur.moveToFirst())
{
contactInfo[0] = cur.getString(0);
contactInfo[1] = cur.getString(2);
return contactInfo;
}
}
finally
{
if (cur != null)
cur.close();
}
return contactInfo;
}
}
Use hashmap instead of arraylist to store items in key value pair as duplicate keys are not allowed in a map.
Java code for delete contact:
public static boolean deleteContact(Context ctx, String phone, String name) {
Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phone));
Cursor cur = ctx.getContentResolver().query(contactUri, null, null, null, null);
try {
if (cur.moveToFirst()) {
do {
if (cur.getString(cur.getColumnIndex(PhoneLookup.DISPLAY_NAME)).equalsIgnoreCase(name)) {
String lookupKey = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
ctx.getContentResolver().delete(uri, null, null);
return true;
}
} while (cur.moveToNext());
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
}
return false;
}
Manifest permission:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
I've tried several ways to load contact images into a listview and this class works, if there is an image set in the phone. Since that is often not the case I would like to get the facebook profile picture.
I'm using the following 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;
private final Context myContext;
public QuickContactHelper(final Context context, final QuickContactBadge badge, final String phoneNumber) {
this.badge = badge;
this.phoneNumber = phoneNumber;
contentResolver = context.getContentResolver();
myContext=context;
}
public Bitmap getFacebookPhoto() {
Uri phoneUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Uri photoUri = null;
Cursor contact = contentResolver.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(myContext.getResources(), R.drawable.ic_contact_picture);
return defaultPhoto;
}
if (photoUri != null) {
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(
contentResolver, photoUri);
if (input != null) {
return BitmapFactory.decodeStream(input);
}
} else {
Bitmap defaultPhoto = BitmapFactory.decodeResource(myContext.getResources(), R.drawable.ic_contact_picture);
return defaultPhoto;
}
Bitmap defaultPhoto = BitmapFactory.decodeResource(myContext.getResources(), R.drawable.ic_contact_picture);
return defaultPhoto;
}
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);
}
}
if (thumbnail == null){
thumbnail=getFacebookPhoto(); //error: isQmage : stream is not a Qmage file
}
return thumbnail;
}
finally {
cursor.close();
}
}
}
When trying to retrieve the bitmap with the method getFacebookPhoto(), it gives me the following error and not the profile picture:
11-20 11:16:26.591: D/(2383): DFactory start
11-20 11:16:26.591: D/(2383): isQmage : stream is not a Qmage file
How do I convert the bitmap into a Qmage file? And does this work for non samsung devices?
if there any method to get contact name by send contact number in android.if any one have idea .
private String getContactName(String string) {
String name=null;
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,null,null,null, null);
if (cur.getCount() > 0) {
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
}
}
return name;
}
I am sending contact number to these method.How to get contact name.
use following method to get contact, from contact provider:
Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, Uri.encode(string));
Cursor cursor = mContext.getContentResolver().query(contactUri, null, null, null, null);
This cursor will have resultset having number same as string.
I got it by do like these.
public static String getContactName(final String phoneNumber,Context context) {
Uri uri;
String[] projection;
Uri mBaseUri = Contacts.Phones.CONTENT_FILTER_URL;
projection = new String[] { android.provider.Contacts.People.NAME };
try {
Class<?> c = Class
.forName("android.provider.ContactsContract$PhoneLookup");
mBaseUri = (Uri) c.getField("CONTENT_FILTER_URI").get(mBaseUri);
projection = new String[] { "display_name" };
} catch (Exception e) {
}
uri = Uri.withAppendedPath(mBaseUri, Uri.encode(phoneNumber));
Cursor cursor = context.getContentResolver().query(uri, projection, null,
null, null);
String contactName = "";
if (cursor.moveToFirst()) {
contactName = cursor.getString(0);
}
cursor.close();
cursor = null;
return contactName;
}
Try
Uri uri;
String[] projection;
Uri baseUri = Contacts.Phones.CONTENT_FILTER_URL;
projection = new String[] { android.provider.Contacts.People.NAME };
try {
Class<?> c = Class.forName("android.provider.ContactsContract$PhoneLookup");
baseUri = (Uri) c.getField("CONTENT_FILTER_URI").get(baseUri);
projection = new String[] { "display_name" };
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
uri = Uri.withAppendedPath(baseUri, Uri.encode(Uri
.encode(phoneNumber)));
Cursor cursor =mContext.getContentResolver().query(uri,
projection, null, null, null) ;
String fromDisplayName = null;
if (cursor != null) {
if (cursor.moveToFirst()){
fromDisplayName = cursor.getString(0);
}
else{
fromDisplayName="";
}
cursor.close();
} else {
fromDisplayName="";
}
return fromDisplayName;
The Uri android.provider.Contacts.People.NAME is deprecated. But android.provider.ContactsContract$PhoneLookup is available from API level 5 only. Hence it is better to use reflections to support all phones.
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;
}