Related
Please give me a solution for loading all images from internal and external storage of android phone?
My method below returns only wallpapers and lockscreen images. For testing, I'm using mi redmi note 3 with android v6.0 os and No External storage inserted.
Please give me the latest solution. I'm a beginner to android.
public ArrayList<String> getImagePaths() {
ArrayList<String> resultIAV = new ArrayList<String>();
URI u = MediaStore.Images.Media.INTERNAL_CONTENT_URI;
Cursor c = getContentResolver().query(u, projection, null,
null, null);
column_index_data = c.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
while (c.moveToNext()) {
absolutePathOfImage = c.getString(column_index_data);
resultIAV.add(absolutePathOfImage);
}
return resultIAV;
}
Use this to get all images from internal and External storage and do not forget to add
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
permission in your manifest file.
int dataColumnIndex;
int bucketColumnIndex;
int displayNameColumnIndex;
String GalleryThumbnail_Path;
String bucket;
String displayName;
int imageCounter = 0;
Thread getImages = new Thread(new Runnable() {
#Override
public void run() {
String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_TAKEN,
MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.BUCKET_DISPLAY_NAME
};
String orderBy = MediaStore.Images.Media.DATE_TAKEN;
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
try {
Cursor cursor = context.getContentResolver().query(uri, columns, null, null, orderBy);
assert cursor != null;
int mCount = cursor.getCount();
for (int i = mCount - 1; i >= 0; i--) {
if (imageCounter <= 370) {
cursor.moveToPosition(i);
dataColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
bucketColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
displayNameColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME);
GalleryThumbnail_Path = cursor.getString(dataColumnIndex);
bucket = cursor.getString(bucketColumnIndex);
displayName = cursor.getString(displayNameColumnIndex);
myimagesPath.add(GalleryThumbnail_Path);
myStorage.add(bucket + "-->" + displayName);
imageCounter++;
Log.e("Recents " + i + "-->>", "Added to bucket");
} else {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
This works in Android 7.1.2 also (My OnePlus One-which i use for development)
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);
}
}
I use the following code to get thumbnail and fill them in gridView.
I guess that the image's information such as BUCKET_DISPLAY_NAME,MediaStore.Images.Media.DATA and MediaStore.Images.Media._ID are stored in a database,
and the thumbnail of the image are stored in another database.
So if I want to delete a image, I need to delete three parts, the one is physical file, the two is the record of the image's information in a database, and the three is the recodr of thumbnail in another database, right?
The following code is only to delete two parts, the one is physical file, the two is the record of the image's information in a database. How can I delete the record of thumbnail? Thanks!
BTW, the code
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
is not very good, because it's asynchronous, I need to get the latest thumbnails at once after I delete a image.
And more, will
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())))
update both the image's information database and thumbnails database ?
private void FillImageAndThumb() {
this.count = curPublic.getCount();
this.thumbnails = new Bitmap[this.count];
this.arrPath = new String[this.count];
this.thumbnailsselection = new boolean[this.count];
this.myID=new int[this.count];
for (int i = 0; i < this.count; i++) {
curPublic.moveToPosition(i);
int id = curPublic.getInt(curPublic.getColumnIndex(MediaStore.Images.Media._ID));
int dataColumnIndex =curPublic.getColumnIndex(MediaStore.Images.Media.DATA);
myID[i]=id;
thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(
getApplicationContext().getContentResolver(),
id,
MediaStore.Images.Thumbnails.MICRO_KIND,
null);
arrPath[i] = curPublic.getString(dataColumnIndex);
}
}
private void SetCurPublic(AdapterView<?> arg0,int index){
String[] projection = new String[]{
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATA
};
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
if (index==0){
curPublic = getContentResolver().query(
images,
projection,
"",
null,
""
);
}else{
String s=arg0.getSelectedItem().toString();
curPublic= getContentResolver().query(
images,
projection,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME+"=?",
new String[]{s},
"" // Ordering
);
}
}
public void DeleteSelected() {
for (int i = 0; i < thumbnailsselection.length; i++) {
if (thumbnailsselection[i]) {
File fdelete = new File(arrPath[i]);
if (fdelete.exists()) {
if (fdelete.delete()) {
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String mSelectionClause = MediaStore.Images.Media._ID
+ "=?";
String[] mSelectionArgs = { String.valueOf(myID[i]) };
getContentResolver().delete(
images,
mSelectionClause,
mSelectionArgs
);
}
}
}
}
}
I am trying to convert the image paths of selected images in my grid view to uris, so that I can then pass those onto my photo editor, and edit from there.
if (cb.isChecked()) {
String paths = imagePaths.get(i);
Uri uri = Uri.parse(paths);
editImagesUri[count] = uri;
count++;
}
That is my code where I am getting my NullPointerException, and I just can't seem to figure out what the problem is.
I have changed around the content in the if statement a few times so that it essentially does the same thing, but the error is still the same.
This is the value of paths:
imagePaths = new ArrayList<String>();
imagePaths = getPathOfAllImages(getActivity());
This is the value of uri:
private static Uri[] editImagesUri;
getPathOfAllImages is a method I found on this website as an answer. Here is the code for it:
public static ArrayList<String> getPathOfAllImages(Activity activity) {
ArrayList<String> absolutePathOfImageList = new ArrayList<String>();
String absolutePathOfImage = null;
String nameOfFile = null;
String absolutePathOfFileWithoutFileName = null;
Uri uri;
Cursor cursor;
int column_index;
int column_displayname;
int lastIndex;
int counter = 0;
// absolutePathOfImages.clear();
uri = android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = { MediaColumns.DATA,
MediaColumns.DISPLAY_NAME };
cursor = activity.managedQuery(uri, projection, null, null, null);
column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
column_displayname = cursor
.getColumnIndexOrThrow(MediaColumns.DISPLAY_NAME);
// cursor.moveToFirst();
while (cursor.moveToNext()) {
// for(int i=0; i<cursor.getColumnCount();i++){
// Log.i(TAG,cursor.getColumnName(i)+".....Data Present ...."+cursor.getString(i));
// }
// Log.i(TAG,"=====================================");
absolutePathOfImage = cursor.getString(column_index);
nameOfFile = cursor.getString(column_displayname);
lastIndex = absolutePathOfImage.lastIndexOf(nameOfFile);
lastIndex = lastIndex >= 0 ? lastIndex
: nameOfFile.length() - 1;
absolutePathOfFileWithoutFileName = absolutePathOfImage
.substring(0, lastIndex);
if (absolutePathOfImage != null) {
absolutePathOfImageList.add(absolutePathOfImage);
}
}
// Log.i(TAG,"........Detected images for Grid....."
// + absolutePathOfImageList);
return absolutePathOfImageList;
}
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);
}
}