How to get albums from mediastore in Android Q? - android

I am trying to get Images and videos from Media store (album wise).It is working properly in devices having OS version < 10. In Android Q i am getting an syntax error.
System.err: android.database.sqlite.SQLiteException: near "GROUP": syntax error (code 1 SQLITE_ERROR): , while compiling: SELECT _id, _data, date_modified, bucket_display_name, media_type FROM files WHERE ((is_pending=0) AND (is_trashed=0) AND (volume_name IN ( 'external_primary' ))) AND ((media_type=1 OR media_type=3) GROUP BY (bucket_display_name)) ORDER BY bucket_display_name ASC
I am using below code to get data.
Uri queryUri = MediaStore.Files.getContentUri("external");
Uri intqueryUri = MediaStore.Files.getContentUri("internal");
String[] projection = {MediaStore.Images.Media._ID,
MediaStore.MediaColumns.DATA,
MediaStore.MediaColumns.DATE_MODIFIED,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Files.FileColumns.MEDIA_TYPE};
// Return only video and image metadata.
String selection;
selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
+ " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
Cursor cursorExternal,cursorInternal;
cursorExternal = getContentResolver().query(queryUri, projection, selection+") GROUP BY (bucket_display_name",
null, MediaStore.Images.Media.BUCKET_DISPLAY_NAME+" ASC");
cursorInternal = getContentResolver().query(intqueryUri, projection, selection+") GROUP BY (bucket_display_name",
null, MediaStore.Images.Media.BUCKET_DISPLAY_NAME+" ASC");
Cursor cursor = new MergeCursor(new Cursor[]{cursorExternal, cursorInternal});
while (cursor.moveToNext()) {
path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA));
album = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
Log.w( "album:** ",album+"" );
HashMap<String, String> listData = Function.mappingInboxAlbum(album, path, countPhoto);
if (!albumList.contains(listData)) {
albumList.add(listData);
}
}
cursor.close();
I googled it but not getting any solution.
Please help...

Add this line in AndroidManifest :
android:requestLegacyExternalStorage="true"

Here is my approach:
first you will need the album_id
Uri path = Uri
.parse("content://media/external/audio/albumart");
Bitmap bmp = Album.getAlbumart(getActivity(), Long.parseLong(album_id), path);
then
public Bitmap getAlbumart(Context context, long album_id, Uri sArtworkUri) {
Bitmap bm = null;
try {
Uri uri = ContentUris.withAppendedId(sArtworkUri, album_id);
ParcelFileDescriptor pfd = context.getContentResolver()
.openFileDescriptor(uri, "r");
if (pfd != null) {
FileDescriptor fd = pfd.getFileDescriptor();
bm = BitmapFactory.decodeFileDescriptor(fd);
}
} catch (Exception e) {
}
return bm;
}
finally to display use Glide library
try {
Glide.with(mContext)
.load(uri)
.asbitmap
.error(Glide.with(ivcircle).load(R.drawable.playlist))
.into(ivcircle);
} catch (Exception e) {
e.printStackTrace();
}

you can use this method
public static ArrayList<Album> loadAlbum(Context context) {
ContentResolver contentResolver = context.getContentResolver();
ArrayList<Album> albumList = new ArrayList<>();
Uri uri = MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI;
String[] projection = new String[]
{
MediaStore.Audio.Albums.ALBUM,
MediaStore.Audio.Albums.ARTIST,
MediaStore.Audio.Albums.NUMBER_OF_SONGS
};
//String sortOrder = MediaStore.Audio.Albums.ALBUM + " ASC";
Cursor cursor = contentResolver.query(uri, projection, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ARTIST));
int numberOfSongs = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Albums.NUMBER_OF_SONGS));
// Save to albumList
albumList.add(new Album(title, artist, numberOfSongs));
}
}
assert cursor != null;
cursor.close();
return albumList;
}

Related

Load high quality image from Contacts

I found that my users got several images under the same contact id. I can access those images by running the next script:
private void loadImages(Context context, int contactId) {
String[] selectionArgs = {String.valueOf(contactId)};
String selection = ContactsContract.Data.CONTACT_ID + "=? and " +
ContactsContract.Contacts.Photo.PHOTO + " is not null";
String[] projection = {ContactsContract.Contacts.Photo.PHOTO};
Uri contentUri = ContactsContract.Data.CONTENT_URI;
Cursor cursor = context.getContentResolver().query(
contentUri,
projection,
selection, selectionArgs,
null);
if (cursor == null) {
return;
}
while (cursor.moveToNext()) {
byte[] blob = cursor.getBlob(0);
Bitmap bitmap = BitmapFactory.decodeByteArray(blob, 0, blob.length);
saveToFile(context, bitmap);
bitmap.recycle();
}
}
But those just thumbnails. To get the full image file, I need to do some thing like that(Taken from android docs):
public InputStream openDisplayPhoto(long contactId) {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri displayPhotoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.DISPLAY_PHOTO);
try {
AssetFileDescriptor fd =
getContentResolver().openAssetFileDescriptor(displayPhotoUri, "r");
return fd.createInputStream();
} catch (IOException e) {
return null;
}
}
Any ideas how to get full size images by Contacts.DATA._ID?

Android, media scan doesn't generate thumbnails?

I have image files which don't have thumbnails. (imported from my external carmera using NFC)
I want to create thumbnails for my image picker view. (has to be fast)
At this moment, I'm not even sure "MEDIA SCAN" means "generating thumbnail" or what.
I tried to scan file using mMediaScannerConnection.scanFile(mPath, null);
onScanCompleted gets called and I try to get thumbnail using the following two version of functions.
I get null thumbnailPath for both functions, I don't get why..
private String getThumbnailPath(long imageId) {
ContentResolver cr = this.mContext.getContentResolver();
Cursor c = MediaStore.Images.Thumbnails.queryMiniThumbnail(cr, imageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
try {
if (c.moveToNext()) {
int dataId = c.getColumnIndex( Images.Thumbnails.DATA);
String strThumPath = c.getString(dataId);
Log.i("ScanTest", "strThumPath = " + strThumPath );
return strThumPath;
}
} finally {
if (c != null) c.close();
}
return null;
}
private String getThumbnailPath2( long imageId ){
// http://wikicloud.blogspot.kr/2010/10/scanfile.html
ContentResolver cr = this.mContext.getContentResolver();
Cursor c = cr.query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Thumbnails.IMAGE_ID + "= ?" , new String[]{String.valueOf(imageId)}, null);
try {
if (c.moveToNext()) {
int dataId = c.getColumnIndex( Images.Thumbnails.DATA);
String strThumPath = c.getString(dataId);
Log.i("ScanTest", "strThumPath = " + strThumPath );
return strThumPath;
}
} finally {
if (c != null) c.close();
}
return null;
}
-- edit --
Here's how I try to get thumbnails.
first create a mapping from image-id to thumbnail-path.
protected Map getThumbnailPathFromDB() {
Map result = new HashMap();
Cursor thumbCursor = null;
thumbCursor = getContentResolver().query(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
null,
null,
null, null);
if (thumbCursor.moveToFirst()) {
do {
String path = thumbCursor.getString(thumbCursor
.getColumnIndex(MediaStore.MediaColumns.DATA));
long imageId = thumbCursor.getLong(thumbCursor
.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID));
result.put(new Long(imageId), path);
} while(thumbCursor.moveToNext());
}
thumbCursor.close();
return result;
next I iterate all images and try to find thumbnails from the mapping I created above
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(
Images.Media.EXTERNAL_CONTENT_URI, null,
null, null, Images.ImageColumns.DATE_MODIFIED + " DESC");
//thumbnailPathList is the mapping I created above, imageId is the id of image obtained from the cursor
String thumbnailPath = thumbnailPathList.get(new Long(imageId));
// thumbnailPath are occasionally null here!,
I tested my code on about 10 devices.
They all have images which I can't find thumbnails for.

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

how to get contact photo URI

I am working with Android Contact ContentProvider. I have a Phone Number and I need to get the URI of the Photo of the contact associated with this phone number. How can I do it???
I know I can get the raw data of the photo and build an InputStream, but I dont want the input stream, I need the URI.
EDIT: Originally I'm using following code to fetch contact info
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNo));
Cursor cursor = context.getContentResolver().query(uri, details, null, null, null);
To get the conatct id using the phone number use the following code:
import android.provider.ContactsContract.PhoneLookup;
public String fetchContactIdFromPhoneNumber(String phoneNumber) {
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phoneNumber));
Cursor cursor = this.getContentResolver().query(uri,
new String[] { PhoneLookup.DISPLAY_NAME, PhoneLookup._ID },
null, null, null);
String contactId = "";
if (cursor.moveToFirst()) {
do {
contactId = cursor.getString(cursor
.getColumnIndex(PhoneLookup._ID));
} while (cursor.moveToNext());
}
return contactId;
}
and use the contact id obtained to get the contatc photo URI. Use the following code for getting photo URI:
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
public Uri getPhotoUri(long contactId) {
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);
}
Hope this would help.
This solution demonstrates how to get an image from a user contact and then display it in an ImageView.
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);
Here's the code from Android Documentation.
Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
return Uri.withAppendedPath(contactUri, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
You can get PHOTO_URI by NUMBER just use following code also you can use _ID.
public static String getContactPhoto(Context context, String phoneNumber) {
ContentResolver cr = context.getContentResolver();
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
Cursor cursor = cr.query(uri, new String[]{ContactsContract.PhoneLookup.PHOTO_URI}, null, null, null);
if (cursor == null) {
return null;
}
String contactImage= null;
if (cursor.moveToFirst()) {
contactImage= cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.PHOTO_URI));
}
if (!cursor.isClosed()) {
cursor.close();
}
return contactImage;
}
final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
String phoneNumber = "+1 416 385 7805";
ContentResolver contentResolver = context.getContentResolver();
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.LOOKUP_KEY,
IS_HONEYCOMB ? ContactsContract.Contacts.PHOTO_THUMBNAIL_URI : ContactsContract.Contacts._ID,
};
Cursor cursor =
contentResolver.query(
uri,
projection,
null,
null,
null);
if (cursor != null && cursor.moveToNext()) {
long contactId = cursor.getLong(0);
String lookupKey = cursor.getString(1);
String thumbnailUri = cursor.getString(2);
cursor.close();
}
So now if sdk is honeycomb or higher u have thumbnail uri of the contact.
Or you can construct a lookup uri like this:
Uri uri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
P.S. If you already know contact id and/or lookup key you can construct a Uri from string:
lookup: content://com.android.contacts/contacts/lookup/{lookup key}/{contact id}
thumbnail: content://com.android.contacts/contacts/{contact id}/photo
So it's better to cache these values.

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