I'm modifying my app to store information on contacts using LOOKUP_KEY instead of _ID as suggested by the API docs. The only problem I'm having is that I'm no longer able to load the contact's photo.
The problematic code is this one:
InputStream s = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), contactUri);
This is returning the following error: java.lang.IllegalArgumentException: URI: content://com.android.contacts/contacts/lookup/1424i118.2312i1220228108/photo
The contactUri that I am using as argument is acquired by the following: Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, contact_key);
and in this example, contact_key is 1424i118.2312i1220228108
Based on the API docs, this helper method should work with both CONTENT_URI or CONTENT_LOOKUP_URI, which I am using.
Any ideas? Thanks.
For anyone with a similar problem, this did the trick for me:
public Bitmap getPhoto(Uri uri){
Bitmap photoBitmap = null;
String[] projection = new String[] { ContactsContract.Contacts.PHOTO_ID };
Cursor cc = getContentResolver().query(uri, projection, null, null, null);
if(cc.moveToFirst()) {
final String photoId = cc.getString(cc.getColumnIndex(ContactsContract.Contacts.PHOTO_ID));
if(photoId != null) {
final Cursor photo = managedQuery(
Data.CONTENT_URI,
new String[] {Photo.PHOTO},
Data._ID + "=?",
new String[] {photoId},
null
);
// Convert photo blob to a bitmap
if(photo.moveToFirst()) {
byte[] photoBlob = photo.getBlob(photo.getColumnIndex(Photo.PHOTO));
photoBitmap = BitmapFactory.decodeByteArray(photoBlob, 0, photoBlob.length);
}
photo.close();
}
}
cc.close();
return photoBitmap;
}
Related
I have a custom folder in the Pictures directory, like this Pictures/MyFolder. It has images in MyFolder. Here is how to share the images using ContentResolver on MyFolder only. Or is any alternative ways to share the image. It is on android 11.
I queried images using the following snippets
String[] projection = new String[]{
MediaStore.Images.Media.DATA,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DATE_TAKEN};
Uri images = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
final String orderBy = MediaStore.Images.Media.DATE_TAKEN;
Cursor cur = context.getContentResolver().query(images,
projection, // Which
// columns
// to return
null, // Which rows to return (all rows)
null, // Selection arguments (none)
orderBy + " DESC" // Ordering
);
int bucketColumn = cur.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
int dateColumn = cur.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN);
do {
bucket = cur.getString(bucketColumn);
if (bucket.equals(context.getString(R.string.app_name))) {
date = cur.getString(dateColumn);
imagePath = listImageByFolder.get(bucket);
if (imagePath == null) {
imagePath = new ArrayList<String>();
}
imagePath.add(cur.getString(cur.getColumnIndex(MediaStore.Images.Media.DATA)));
Uri x = Uri.withAppendedPath(MediaStore.Images.Media.INTERNAL_CONTENT_URI, String.valueOf(cur.getString(cur.getColumnIndex(MediaStore.Images.Media.DATA))));
listImageByFolder.put(bucket, imagePath);
} ;
} while (cur.moveToNext());
While I try to share the image, Getting android.os.FileUriExposedException: file:///storage/emulated/0/Pictures/WhatsTouch/1628090801008.jpg exposed beyond app through ClipData.Item.getUri() exception. Is any way to correct it or is any alternative way?
I am new to android. I want get cursor to one file only. But how? I tried this but doesn't work and gives error.
private void getallaudioFromMySpecialFolder() {
String[] star = { "*" };
String Dir_recordedAudios= Environment.getExternalStorageDirectory()+File.separator+"My Audios"+File.separator;
File Directory=new File(Dir_recordedAudios);
Uri u=Uri.fromFile(Directory);
Uri uri = Uri.parse(u.toString());
Cursor musiccursor = managedQuery(uri, star,null, null, null);
if (musiccursor!= null) {
if (musiccursor.moveToFirst()) {
do {
String duration = musiccursor.getString(musiccursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
String str_duration=CalTotalTime(Integer.valueOf(duration));
String path= musiccursor.getString(musiccursor.getColumnIndex(MediaStore.Audio.Media.DATA));
Log.d("************", "**************");
Log.d("path",path);
Log.d("totalTime", str_duration);
} while (musiccursor.moveToNext());
}
musiccursor.close();
}
}
I finally Find my question solving . If we want cursor to a special file,first in Projection array determine aour fileds for projection. And we must define aur file which want fetching its info.
We use of a statement with "LIKE" word for selection. Code is here. Too,I learned that using from CursorLoader is better.because managedQuery method is deprecated.
Code is here:
String name="";
String duration="";
String path="";
Log.d("Loading file: " + filepath,"");
// This returns us content://media/external/videos/media (or something like that)
// I pass in "external" because that's the MediaStore's name for the external
// storage on my device (the other possibility is "internal")
Uri audiosUri = MediaStore.Audio.Media.getContentUri("external");
Log.d("audiosUri = " + audiosUri.toString(),"");
String[] projection = {MediaStore.Audio.Media.DATA,MediaStore.Audio.Media.DISPLAY_NAME,MediaStore.Audio.Media.DURATION};
// TODO This will break if we have no matching item in the MediaStore.
Cursor cursor = managedQuery(audiosUri, projection, MediaStore.Audio.Media.DATA + " LIKE ?", new String[] { filepath }, null);
cursor.moveToFirst();
path =cursor.getString( cursor.getColumnIndex(projection[0]));
name=cursor.getString( cursor.getColumnIndex(projection[1]));
int iduration = cursor.getColumnIndex(projection[2]);
duration=CalTotalTime(Integer.valueOf(iduration));
Log.d("pathhhhhhhhhhhhhhhhhh", path);
Log.d("nameeeeeeeeeeeeeeeeeeeeeee", name);
Log.d("duration", duration);
cursor.close();
And this is a formal of CursorLoader .May be helps you.
private String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Audio.Media.DATA };
CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index = cursor.getColumnIndexOrThrow(proj[0]);
cursor.moveToFirst();
return cursor.getString(column_index);
}
my app creates new contacts with ContentProviderOperation. The problem is, I need a reference to the new contact because I need some information of it to display it in a listview and go with intent into the contact app to the contact.
The best thing would be the ID, but I´ve read that it might change during operations on the database, which won´t be helpful to me.
Now I thought, the Uri might be the best thing, because I could later retrieve the contactID or lookup key.
How do I get the Uri directly after calling applyBatch() ?
EDIT:
Here is a solution, but not really a good one.
He is putting a randomly generated token into each contact, then he makes a new query with it.
I want neither put some extra data into the contacts, nor starting a second query. But if there is no other possibility I´ll do it that way.
simply call
private String retrieveContactId(String phoneNo) {
try {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNo));
String[] projection = new String[] { ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME };
String selection = null;
String[] selectionArgs = null;
String sortOrder = ContactsContract.PhoneLookup.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
ContentResolver cr = getApplicationContext().getApplicationContext().getContentResolver();
String contactId = null;
if (cr != null) {
Cursor resultCur = cr.query(uri, projection, selection, selectionArgs, sortOrder);
if (resultCur != null) {
while (resultCur.moveToNext()) {
contactId = resultCur.getString(resultCur.getColumnIndex(ContactsContract.PhoneLookup._ID));
Log.e("Info Incoming", "Contact Id : " + contactId);
return contactId;
}
resultCur.close();
}
}
} catch (Exception sfg) {
Log.e("Error", "Error in loadContactRecord : " + sfg.toString());
}
return null;
}
and for the uri
Uri contactUri = Contacts.getLookupUri(
Integer.valueOf(rawContactId), clookup);
I am trying to get imagepath based on thumbail path , i have already tried solution from
android-getting-path-to-image-from-thumbnail, but it is based on gridview position, i am only retrieving specific images. Also i found one sample code from SO, the code is
private String getImagePathFromThumbPath(String thumbPath)
{
String imgPath=null;
// String[] projection = new String[] {MediaStore.Images.Thumbnails._ID, MediaStore.Images.Thumbnails.IMAGE_ID};
String[] imagesDataPath={ MediaStore.Images.Media.DATA ,MediaStore.Images.Media._ID};
//mResolver.query() requires android API 16
Cursor thumbnails = mResolver.query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, imagesDataPath,MediaStore.Images.Thumbnails.DATA+"=?",new String[]{thumbPath}, null, null);
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor imageCursor = mResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, filePathColumn, MediaStore.Images.Media._ID + "=?", new String[] {thumbId}, null);
if (imageCursor != null && imageCursor.moveToFirst()) {
// Your file-path will be here
imgPath= imageCursor.getString(imageCursor.getColumnIndex(filePathColumn[0]));
}
return imgPath;
}
The above method is bit modified to suit my needs and it returns nothing on Toasting, please tell how to retrieve imagepath using thumbnail path?
After a long time and relentless try, the solution is here
1. You need to find the image id which is image unique id from images table in thumbnail table, query to thumbnail provider (MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI) if you do not understand it, refer here , specifically IMAGE_ID,
Step 1 is to get retrievedImageId.
retrievedImageId = Long.parseLong(cursor.getString(imageIdInImages));
2. Now using the retrievedImageId get the image path, by again querying the content provider, only this time query the Images media provider (MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
String getImagePathFromThumbPath(String thumbPath)
{
String imagePath = null;
if(thumbPath != null )
{
String[] columns_to_return = {MediaStore.Images.Thumbnails.IMAGE_ID};
String where = MediaStore.Images.Thumbnails.DATA+" LIKE ?";
long retrievedImageId = -1;
String valuesAre[] = {"%"+thumbPath};
Cursor cursor = getContentResolver().query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, columns_to_return, where, valuesAre, null);
if(cursor != null)
{
int imageIdInImages = cursor.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID);
for (cursor.moveToFirst();!cursor.isAfterLast(); cursor.moveToNext())
{
//STEP 1 to retrieve image ID
retrievedImageId = Long.parseLong(cursor.getString(imageIdInImages));
}
if(retrievedImageId != -1)
{
// STEP 2 Now
Log.i(TAG, "imageId-" + retrievedImageId);
String[] columnsReturn = {MediaStore.Images.Media.DATA};
String whereimageId = MediaStore.Images.Media._ID+" LIKE ?";
String valuesIs[] = {"%" + retrievedImageId};
Cursor mCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columnsReturn, whereimageId, valuesIs, null);
int rawDataPath= mCursor.getColumnIndex(MediaStore.Images.Media.DATA);
for (mCursor.moveToFirst();!mCursor.isAfterLast(); mCursor.moveToNext())
{
imagePath = mCursor.getString(rawDataPath);
}
}
}
}
return imagePath;
}
If you still have doubt or error/exception, leave comment!
I am having a problem getting a contact photo, the kind you see in the messaging app and new gmail notification. I have looked at a few example codes but nothing has worked for me, this is what I currently have
this should get the photo uri and turn it into a bitmap image to use or at least it seems
public static Bitmap getContactImage(long id,Context context){
InputStream input = getPhoto(id,context);
if(input == null){
return null;
}
return BitmapFactory.decodeStream(input);
}
public static InputStream getPhoto(long contactId,Context context){
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
InputStream in = null;
try{
in = context.getContentResolver().openInputStream(photoUri);
}catch(FileNotFoundException e){
Log.d(TAG, e.toString());
}
return in;
}
and this is how I call
long contactID = 0;
Bitmap image = BitmapFactory.decodeResource(context.getResources(),R.drawable.ic_contact_picture);
Cursor contact = context.getContentResolver().query(Data.CONTENT_URI,new String[] {Data.CONTACT_ID},Email.ADDRESS + "='" + from + "'",null,null);
if(contact.moveToFirst() && contact != null){
contactID = contact.getLong(0);
image = getContactImage(contactID,context);
}
I get the contact id fine (checked by searching the number for the person querying against) but then it does not find the contact photo. I know there is a photo because I am testing it against myself to make sure and I have a contact photo so I dont know what else I should do.
I always find navigating the contact provider very troublesome because there is so much to it.
I got it, I did a query against the RAW_CONTACT_ID with the MIMETYPE and that gave me the photo I was looking for
Cursor p = context.getContentResolver().query(Data.CONTENT_URI,new String[] {Photo.PHOTO},
Data.RAW_CONTACT_ID + "=" + contactId + " AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE+"'"
,null,null);
You're doing it wrong.
First, get an ID of the photo from the PHOTO_ID column of ContactsContract.Contacts table. Next, retrieve a byte array from PHOTO column (which is actually alias to DATA15) from ContactsContract.Data by ID you got in previous step. And, finally, decode that byte array using BitmapFactory to get a bitmap.
Here are docs about this.
This works for me.
//Querying for all contacts(Apply selection parameter in query to get a specific contact)
Uri contacts = ContactsContract.Contacts.CONTENT_URI;
cur = null;
cur = Main.context.getContentResolver().query(contacts, null, null,
null, null);
int contactIdIndex = cur.getColumnIndex(ContactsContract.PhoneLookup._ID);
int contactId = cur.getInt(contactIdIndex);
// Photo
Uri contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, contactId);
Uri photoUri = Uri.withAppendedPath(contactUri,
ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
Cursor cursor = cr
.query(
photoUri,
new String[] { ContactsContract.CommonDataKinds.Photo.PHOTO },
null, null, null);
if (cursor != null && cursor.moveToFirst()) {
byte[] data = cursor.getBlob(0);
_conEntry.setPhoto(data);
//Data is the photo bytes for you
}
if (cursor != null)
cursor.close();