Android - Contact photo from connection - android

When a contact has a connection, like Whatsapp or Skype, and that contact hasn't a photo, the Whatsapp or Skype photo appears.
How obtain the connection photo if the contact photo hasn't a photo?
public byte[] getPhoto(String contactId) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.valueOf(contactId));
Uri photoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
try
{
Cursor c = getContentResolver().query(photoUri,
new String[] {ContactsContract.Contacts.Photo.PHOTO}, null, null, null);
try {
if (c.moveToFirst()) {
final byte[] image = c.getBlob(0);
final Bitmap bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
c.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return new byte[0];
}
SOLVED
This method works correctly. The problem was in another part of the program. Sorry for the inconvenience and thank you to all.

First, note that a Whatsapp photo does not appear in your Contacts app, it only appears within the Whatsapp app, that's because it's a proprietary photo stored locally in the Whatsapp app and is not accessible to 3rd party apps.
I'm not sure about Skype, but if you do see a photo in the Contacts app, you should be able to access it via the API.
The code you've posted accessed the thumbnail-sized photo of the contact, it's possible that the contact has only a high-res photo and no thumbnail.
Try this code using ContactsContract.DisplayPhoto:
public InputStream openDisplayPhoto(long photoFileId) {
Uri displayPhotoUri = ContentUris.withAppendedId(DisplayPhoto.CONTENT_URI, photoKey);
try {
AssetFileDescriptor fd = getContentResolver().openAssetFileDescriptor(
displayPhotoUri, "r");
return fd.createInputStream();
} catch (IOException e) {
return null;
}
}
Also, this code will show you all photos stored for a contact, along with their RawContact ID source:
String[] projection = new String[] { CommonDataKinds.Photo.PHOTO_FILE_ID, CommonDataKinds.Photo.PHOTO, CommonDataKinds.Photo.RAW_CONTACT_ID };
String selection = Data.MIMETYPE + "='" + CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "' AND " + Data.CONTACT_ID + "=" + contactId;
Cursor c = resolver.query(Data.CONTENT_URI, projection, selection, null, null);
while (c != null && c.moveToNext()) {
Long photoId = c.getLong(0);
boolean hasPhoto = c.isNull(1);
Long rawContactId = c.getLong(2);
Log.d(TAG, "found photo: " + photoId + ", " + rawContactId + ", " + hasPhoto);
}

Related

load actual photo of contact in android 2.3.*

Still facing with problem of loading actual contact's photos in android 2.3.*... Tried many different ways but can't to get latest photo from phonebook. My last code:
Uri uri = getPhotoUri(context, contact.getPhoneBookContactId());
Picasso.with(context).load(uri).error( R.drawable.contact_icon ).into(imageViewLowGB);
where getPhotoUri:
public static Uri getPhotoUri(Context context,final int contactId) {
try {
Cursor cur = context.getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.CONTACT_ID + "=" + contactId + " 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) {
Log.e( ImageManager.class.getSimpleName(), "error getPhotoUri" +e.getMessage() );
return null;
}
Uri person = ContentUris.withAppendedId( ContactsContract.Contacts.CONTENT_URI,contactId );
return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
}
This code give me photo, but if change photo, old photo loading again and again ((
Please, someone help me...This problem only on 2.3.* versions(

Get contact photo by URI [duplicate]

Alright, I'm just trying to learn about using Contact information, but I'm a bit stuck. I would like to be able to display a picture for the contact. Using the following code that I have, how would I be able to put the photo for the contact in the ImageView in contact_entry?
ListView contacts_list = (ListView) findViewById(R.id.contacts_list);
// Gets the URI of the db
Uri uri = ContactsContract.Contacts.CONTENT_URI;
// What to grab from the db
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_ID
};
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor cursor = managedQuery(uri, projection, null, null, sortOrder);
String[] fields = new String[] {
ContactsContract.Data.DISPLAY_NAME
};
int[] values = {
R.id.contactEntryText
};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor,
fields, values);
contacts_list.setAdapter(adapter);
contact_entry.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="54px">
<ImageView
android:id="#+id/contactPhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_contact_picture_3"/>
<TextView
android:text="#+id/contactEntryText"
android:id="#+id/contactEntryText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Probably this will help you(contact is identified by getId()):
/**
* #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);
}
Usage is:
Uri u = objItem.getPhotoUri();
if (u != null) {
mPhotoView.setImageURI(u);
} else {
mPhotoView.setImageResource(R.drawable.ic_contact_picture_2);
}
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;
}
For contactId you can use:
public static long getContactIDFromNumber(String contactNumber, Context context) {
String UriContactNumber = Uri.encode(contactNumber);
long phoneContactID = new Random().nextInt();
Cursor contactLookupCursor = context.getContentResolver().query(Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, UriContactNumber),
new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup._ID}, null, null, null);
while (contactLookupCursor.moveToNext()) {
phoneContactID = contactLookupCursor.getLong(contactLookupCursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
}
contactLookupCursor.close();
return phoneContactID;
}
Source: https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo.html
Don't know why but this works on 2.2 and 4.1:
Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, Long.parseLong(photoId));
imageView.setImageURI(photoUri);
The photo Uri has the following form: content://com.android.contacts/data/3345, where the number is the photoId.
This code will take an image from a contact and then will display in your imageView, it is so easy and it works perfect, in this case I am getting image from a contact and display if, if there is still query then post a comment
ImageView profile = (ImageView)findViewById(R.id.imageView1);
Uri my_contact_Uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(Contact_Id));
InputStream photo_stream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), my_contact_Uri);
BufferedInputStream buf = new BufferedInputStream(photo_stream);
Bitmap my_btmp = BitmapFactory.decodeStream(buf);
profile.setImageBitmap(my_btmp);
According to Android Developers' documentation:
A read-only sub-directory of a single contact that contains the contact's primary photo. The photo may be stored in up to two ways - the default "photo" is a thumbnail-sized image stored directly in the data row, while the "display photo", if present, is a larger version stored as a file.
https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo
You can use the following method to get thumbnail version of contact photo:
#Nullable
public Bitmap getContactPhotoThumbnail(Context context, long contactId) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), contactUri);
return BitmapFactory.decodeStream(is);
}
You can use the following method to the full sized contact photo:
#Nullable
public Bitmap getContactPhoto(Context context, long contactId) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
Uri displayPhotoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
try {
AssetFileDescriptor fd =
context.getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
return BitmapFactory.decodeStream(fd.createInputStream());
} catch (IOException e) {
return null;
}
}
For future readers, loading all contacts with images takes too much time and memory if you load the images with full size. From experience, on Nexus 5 it takes up to 3 seconds to load ~500 contacts. Because of this intensity, we need to avoid fetching contacts in UI thread.
This is mainly because the thumbnail photos are in an other table, which forces us to query more. If you don't need to load any image, it takes ~400ms in the case mentioned above.
I have created a gist that fetches all contacts, with their respective thumbnail references in ~500-700ms for 500 contacts;
https://gist.github.com/bugraoral/a4d36d79621455fa3dd860ff994ae796
The key point is to query and get all thumbnail references once, load them to memory, and use the memory for querying images of contacts individually.
You need to use permission like this in your manifest file
<uses-permission android:name="android.permission.READ_CONTACTS" />
I know it is a very old question but so are some of the answers here as few things here have now been deprecated. As the question showed up in searches while I was looking for similar solution, I though I will add my two cents here...
I have created a simple contacts list with their names and photos from ContactsContract. Please check my answer at...
https://stackoverflow.com/a/37710199/1209544
Here is the method to get all the contacts, if a contact has image it will load image in the imageview else no image will be shown in the imageview.
#SuppressLint("Range") public static void readContacts(Context context) {
if (context == null)
return;
ContentResolver contentResolver = context.getContentResolver();
if (contentResolver == null)
return;
String[] fieldListProjection = {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.PHOTO_URI
,ContactsContract.Contacts.STARRED
};
String sort = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " ASC";
Cursor phones = contentResolver
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI
, fieldListProjection, null, null, sort);
HashSet<String> normalizedNumbersAlreadyFound = new HashSet<>();
if (phones != null && phones.getCount() > 0) {
while (phones.moveToNext()) {
String normalizedNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
if (Integer.parseInt(phones.getString(phones.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
if (normalizedNumbersAlreadyFound.add(normalizedNumber)) {
int id = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
int fav = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.STARRED));
boolean isFav;
isFav= fav == 1;
String uri = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
if(uri!=null){
contactList.add(new FavContact(id,isFav,uri,name,phoneNumber));
}
else{
contactList.add(new FavContact(id,isFav,name,phoneNumber));
}
}
}
}
phones.close();
}
}
In Adapter (onBindViewHolder)
if(obj.getImage()==null){
//Image not found then load any random image (whatever you like)
Picasso.get().load(R.drawable.ic_circle_fav_no_dp).fit().into(holder.img_contact);
}
else{
//Here it will load contact image in the imageview.
Bitmap bp;
try {
bp = MediaStore.Images.Media
.getBitmap(context.getContentResolver(),
Uri.parse(obj.getImage()));
Glide.with(context).load(bp).centerInside().into(holder.img_contact);
} catch (IOException e) {
e.printStackTrace();
Picasso.get().load(R.drawable.ic_circle_fav_no_dp).fit().into(holder.img_contact);
}
}

Convert a Uri into a non-Uri android

I have a path like this:
content://media/external/audio/media/7181
That was obtained like this String mSelectedPath = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + "/";
and then I append the song id to this.
I want to convert it into a path such as /mnt/sdcard/..
How do I do this?
Android's media database stores the path to files in the DATA column. You can read that via
long id = 7181;
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
ContentResolver cr = getContentResolver();
String[] projection = { MediaColumns.DATA };
String selection = null;
String[] selectionArgs = null;
String sortOrder = null;
Cursor c = cr.query(uri, projection, selection, selectionArgs, sortOrder);
String path = null;
if (c != null) {
if (c.moveToFirst()) {
path = c.getString(0);
}
c.close();
}
Log.d("XYZ", "Path of " + id + " is:" + path);
But like #CommonsWare said it's possible that (especially on future android versions) there is no file you can access or even no path at all, meaning the path you get might be worthless.
Luckily ContentProvider allows you to read data with IO streams if the provider has that feature implemented (IIRC this one does). So you could read the data represented by that Uri like in below example.
long id = 7181;
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
ContentResolver cr = getContentResolver();
InputStream is = null;
try {
is = cr.openInputStream(uri);
is.read(); // replace with useful code.
} catch (FileNotFoundException e) {
Log.w("XYZ", e);
} catch (IOException e) {
Log.w("XYZ", e);
} finally {
if (is != null)
try {
is.close();
} catch (IOException e) {
// ignored
}
}
You don't. It is possible that there is no file (e.g., bytes are stored in a BLOB column in a database, the content represents a stream), or the file is in a location that is inaccessible by your process.

Why can't I get the URI of profile pic from a contact number?

I have a custom incoming call screen that can current show the name and phone number of an incoming call. If the contact has a profile pic set (on your own phone), that image should display in the ImageView I've created. Any number that not on the phone will show the Android icon.
After testing the code, no matter if the phone number is stored on the phone (emulator) or not, I get the Android icon. Here is the code to retrieve the contact photo of the caller if one is available:
public Uri getPhotoUri(long contactId) { //contactId takes the phone number.
ContentResolver contentResolver = getContentResolver();
try {
Cursor cursor = contentResolver
.query(ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.Data.CONTACT_ID
+ "="
+ contactId
+ " AND "
+ ContactsContract.Data.MIMETYPE
+ "='"
+ ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE
+ "'", null, null);
if (cursor != null) {
if (!cursor.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, contactId);
return Uri.withAppendedPath(person,
ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
}
This method calls the above method, and assigns the picture to the ImageView. The problem is that the else statement is always executed:
IncomingCallListener.getId(getID))); is the actual phone number used to get the corresponding profile picture.
public void showContactPhoto(){
Uri u = getPhotoUri(IncomingCallListener.getId(getID()));
if (u != null) {
qcbContactPic.setImageURI(u);
Log.d("PHOTO", "ID launched");
} else {
qcbContactPic.setImageResource(R.drawable.ic_launcher);
Log.d("PHOTO", "Default launched");
}
}
Does anyone have any ideas as to why "u" is remaining null?
NOTE: The contact picture is stored in the media gallery.
Try this
Uri uri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, longId);
ContentResolver cr = getContentResolver();
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(cr, uri);
if (input == null) {
return null;
} else
return BitmapFactory.decodeStream(input);
Use setImageBitmap() method of ImageView.

Getting a Photo from a Contact

Alright, I'm just trying to learn about using Contact information, but I'm a bit stuck. I would like to be able to display a picture for the contact. Using the following code that I have, how would I be able to put the photo for the contact in the ImageView in contact_entry?
ListView contacts_list = (ListView) findViewById(R.id.contacts_list);
// Gets the URI of the db
Uri uri = ContactsContract.Contacts.CONTENT_URI;
// What to grab from the db
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_ID
};
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
Cursor cursor = managedQuery(uri, projection, null, null, sortOrder);
String[] fields = new String[] {
ContactsContract.Data.DISPLAY_NAME
};
int[] values = {
R.id.contactEntryText
};
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_entry, cursor,
fields, values);
contacts_list.setAdapter(adapter);
contact_entry.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="54px">
<ImageView
android:id="#+id/contactPhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_contact_picture_3"/>
<TextView
android:text="#+id/contactEntryText"
android:id="#+id/contactEntryText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Probably this will help you(contact is identified by getId()):
/**
* #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);
}
Usage is:
Uri u = objItem.getPhotoUri();
if (u != null) {
mPhotoView.setImageURI(u);
} else {
mPhotoView.setImageResource(R.drawable.ic_contact_picture_2);
}
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;
}
For contactId you can use:
public static long getContactIDFromNumber(String contactNumber, Context context) {
String UriContactNumber = Uri.encode(contactNumber);
long phoneContactID = new Random().nextInt();
Cursor contactLookupCursor = context.getContentResolver().query(Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, UriContactNumber),
new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME, ContactsContract.PhoneLookup._ID}, null, null, null);
while (contactLookupCursor.moveToNext()) {
phoneContactID = contactLookupCursor.getLong(contactLookupCursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
}
contactLookupCursor.close();
return phoneContactID;
}
Source: https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo.html
Don't know why but this works on 2.2 and 4.1:
Uri photoUri = ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, Long.parseLong(photoId));
imageView.setImageURI(photoUri);
The photo Uri has the following form: content://com.android.contacts/data/3345, where the number is the photoId.
This code will take an image from a contact and then will display in your imageView, it is so easy and it works perfect, in this case I am getting image from a contact and display if, if there is still query then post a comment
ImageView profile = (ImageView)findViewById(R.id.imageView1);
Uri my_contact_Uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(Contact_Id));
InputStream photo_stream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), my_contact_Uri);
BufferedInputStream buf = new BufferedInputStream(photo_stream);
Bitmap my_btmp = BitmapFactory.decodeStream(buf);
profile.setImageBitmap(my_btmp);
According to Android Developers' documentation:
A read-only sub-directory of a single contact that contains the contact's primary photo. The photo may be stored in up to two ways - the default "photo" is a thumbnail-sized image stored directly in the data row, while the "display photo", if present, is a larger version stored as a file.
https://developer.android.com/reference/android/provider/ContactsContract.Contacts.Photo
You can use the following method to get thumbnail version of contact photo:
#Nullable
public Bitmap getContactPhotoThumbnail(Context context, long contactId) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), contactUri);
return BitmapFactory.decodeStream(is);
}
You can use the following method to the full sized contact photo:
#Nullable
public Bitmap getContactPhoto(Context context, long contactId) {
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
Uri displayPhotoUri = Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
try {
AssetFileDescriptor fd =
context.getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
return BitmapFactory.decodeStream(fd.createInputStream());
} catch (IOException e) {
return null;
}
}
For future readers, loading all contacts with images takes too much time and memory if you load the images with full size. From experience, on Nexus 5 it takes up to 3 seconds to load ~500 contacts. Because of this intensity, we need to avoid fetching contacts in UI thread.
This is mainly because the thumbnail photos are in an other table, which forces us to query more. If you don't need to load any image, it takes ~400ms in the case mentioned above.
I have created a gist that fetches all contacts, with their respective thumbnail references in ~500-700ms for 500 contacts;
https://gist.github.com/bugraoral/a4d36d79621455fa3dd860ff994ae796
The key point is to query and get all thumbnail references once, load them to memory, and use the memory for querying images of contacts individually.
You need to use permission like this in your manifest file
<uses-permission android:name="android.permission.READ_CONTACTS" />
I know it is a very old question but so are some of the answers here as few things here have now been deprecated. As the question showed up in searches while I was looking for similar solution, I though I will add my two cents here...
I have created a simple contacts list with their names and photos from ContactsContract. Please check my answer at...
https://stackoverflow.com/a/37710199/1209544
Here is the method to get all the contacts, if a contact has image it will load image in the imageview else no image will be shown in the imageview.
#SuppressLint("Range") public static void readContacts(Context context) {
if (context == null)
return;
ContentResolver contentResolver = context.getContentResolver();
if (contentResolver == null)
return;
String[] fieldListProjection = {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER,
ContactsContract.Contacts.HAS_PHONE_NUMBER,
ContactsContract.Contacts.PHOTO_URI
,ContactsContract.Contacts.STARRED
};
String sort = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY + " ASC";
Cursor phones = contentResolver
.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI
, fieldListProjection, null, null, sort);
HashSet<String> normalizedNumbersAlreadyFound = new HashSet<>();
if (phones != null && phones.getCount() > 0) {
while (phones.moveToNext()) {
String normalizedNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
if (Integer.parseInt(phones.getString(phones.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
if (normalizedNumbersAlreadyFound.add(normalizedNumber)) {
int id = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
int fav = phones.getInt(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.STARRED));
boolean isFav;
isFav= fav == 1;
String uri = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
if(uri!=null){
contactList.add(new FavContact(id,isFav,uri,name,phoneNumber));
}
else{
contactList.add(new FavContact(id,isFav,name,phoneNumber));
}
}
}
}
phones.close();
}
}
In Adapter (onBindViewHolder)
if(obj.getImage()==null){
//Image not found then load any random image (whatever you like)
Picasso.get().load(R.drawable.ic_circle_fav_no_dp).fit().into(holder.img_contact);
}
else{
//Here it will load contact image in the imageview.
Bitmap bp;
try {
bp = MediaStore.Images.Media
.getBitmap(context.getContentResolver(),
Uri.parse(obj.getImage()));
Glide.with(context).load(bp).centerInside().into(holder.img_contact);
} catch (IOException e) {
e.printStackTrace();
Picasso.get().load(R.drawable.ic_circle_fav_no_dp).fit().into(holder.img_contact);
}
}

Categories

Resources