How to delete specific contact from phonebook [duplicate] - android

This question already has answers here:
How to delete a particular contact using contact id?
(4 answers)
Closed 5 years ago.
Uri contactUri = Uri.withAppendedPath(ContactsContract.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(ContactsContract.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);
}
} while (cur.moveToNext());
}
} catch (Exception e) {
System.out.println(e.getStackTrace());
} finally {
cur.close();
}

Try the following method:
private static final Uri CONTACT_CONTENT_URI = ContactsContract.Contacts.CONTENT_URI;
public static boolean deleteContact(final Context context, final String contactId) {
if (null != context) {
final Uri uri = Uri.withAppendedPath(CONTACT_CONTENT_URI, contactId);
final ContentResolver contentResolver = context.getContentResolver();
try {
final int deletedRowCount = contentResolver.delete(uri, null, null);
return deletedRowCount > 0;
} catch (final Exception e) {
Log.e(TAG, e.toString());
}
}
return false;
}

Related

How to combine multiple Uri from Images

I have this function that queries the gallery images
public void getImagesFromGallary(Context context) {
List<Uri> imagesUri = new ArrayList<>();
List<Uri> imageOrientationUri = new ArrayList<>();
Cursor imageCursor = null;
try {
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.ImageColumns.ORIENTATION};
final String orderBy = MediaStore.Images.Media.DATE_ADDED + " DESC";
imageCursor = context.getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy);
while (imageCursor.moveToNext()) {
Uri uri = Uri.parse(imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA)));
Uri uriOrientation = Uri.parse(imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION)));
imagesUri.add(uri);
imageOrientationUri.add(uriOrientation);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (imageCursor != null && !imageCursor.isClosed()) {
imageCursor.close();
}
}
}
Do I have to have two Uri list for this, for instance I have a
imagesUri list and a imageOrientationUri list.
What if I want more information from the Image do I have to parse another Uri from the cursor?
You can create an object for the image like:
public class ImageDetails {
private URI imageURI;
private URI imageOrientationURI;
public URI getImageURI() {
return imageURI;
}
public void setImageURI(URI imageURI) {
this.imageURI = imageURI;
}
public URI getImageOrientationURI() {
return imageOrientationURI;
}
public void setImageOrientationURI(URI imageOrientationURI) {
this.imageOrientationURI = imageOrientationURI;
}
}
And you create a single list and add details to it like:
public void getImagesFromGallary(Context context) {
List<ImageDetails> imageDetails = new ArrayList<>();
Cursor imageCursor = null;
try {
final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.ImageColumns.ORIENTATION};
final String orderBy = MediaStore.Images.Media.DATE_ADDED + " DESC";
imageCursor = context.getApplicationContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy);
while (imageCursor.moveToNext()) {
ImageDetails tmp = new ImageDetails();
tmp.setImageURI(Uri.parse(imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION))));
tmp.setImageOrientationURI(Uri.parse(imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA))));
imageDetails.add(tmp);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (imageCursor != null && !imageCursor.isClosed()) {
imageCursor.close();
}
}
So for each new property now, you can create a new variable in the class along with the getters and setters

java.lang.IllegalArgumentException: URI: content://com.android.contacts/contacts/-166733728/photo

I've seen many answers, have tried many of them, but none with luck, sometimes I get file not found or
java.lang.IllegalArgumentException: URI: content://com.android.contacts/contacts/-166733728/photo, calling user:
Tried the following methods:
public static long getContactIDFromNumber(String contactNumber)
{ contactNumber = Uri.encode(contactNumber);
long phoneContactID = new Random().nextInt();
Cursor contactLookupCursor = myContext.getContentResolver().query(Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,Uri.encode(contactNumber)),new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup._ID}, null, null, null);
while(contactLookupCursor.moveToNext()){
phoneContactID = contactLookupCursor.getInt(contactLookupCursor.getColumnIndexOrThrow(PhoneLookup._ID));
}
contactLookupCursor.close();
return phoneContactID;
}
public InputStream openThumbContact(long contactId) {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = myContext.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;
}
public InputStream openDisplayPhotoContact(long contactId) {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO);
try {
AssetFileDescriptor fd =
myContext.getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
return fd.createInputStream();
} catch (IOException e) {
return null;
}
}
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);
}
Ideally I would like to show the thumb in the contacts or the one facebook has stored, does anyone have a working method? The contact photo is available in the contact list, but I can't get it to load.

Is that possible to delete the phone contact from my application

I fetched all contacts from phone and listed in list view.i am able to remove the local contact in my listview as well as database now i want to remove the phone contact is that possible. For removing purpose i am using the following code.
if (position == 1) {
db.deleteContact(item_position + 1);
from.remove(item_position);
note.notifyDataSetChanged();
}
get the selected item name and assign it to the name then try the following code.
ContentResolver cr = getContentResolver();
String where = ContactsContract.Data.DISPLAY_NAME + " = ? ";
String[] params = new String[] {name};
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
.withSelection(where, params)
.build());
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();
}
Toast.makeText(getApplicationContext(), "Deleted the contact with name '" + name +"'", Toast.LENGTH_SHORT).show();
from.remove(item_position);
note.notifyDataSetChanged();
It may be same as deleting a particular log from the mobile, not sure of how far it can be done.
The code for deleting a particular call log is as follows:
public void DeleteNumFromCallLog(ContentResolver resolver, String strNum) {
try {
String strUriCalls = "content://call_log/calls";
Uri UriCalls = Uri.parse(strUriCalls);
if (null != resolver) {
resolver.delete(UriCalls, CallLog.Calls._ID + "=?",
new String[] { strNum });
}
} catch (Exception e) {
e.getMessage();
}
}
This is all we need. To delete Contact with phone number and name given
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;
}
And remind to add read/write contact permission
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
if you need to delete contact from Contact Uri
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
1.Get all contact from device and store into one container
while (phones.moveToNext())
{
String name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
phones.close();
2.Select the contact from container`
then pass selected value for performe delete operation
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;
}

how to get contact name by sending contact number in android?

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.

How do I load a contact Photo?

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;
}

Categories

Resources