To query the MediaStore, I simply create an URI with the proper "base URI" and append the IMAGE_ID (which I have from the corresponding thumbnail). Then, I simply invoke the content resolver to get a cursor:
Long IMAGE_ID = 172712; // let's say we have this IMAGE_ID
Uri baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
baseUri = Uri.withAppendedPath(baseUri, ""+ IMAGE_ID);
// let's just get this one field, description
String[] projection = {MediaStore.Images.Media.DESCRIPTION};
Cursor c = getContext().getContentResolver().query(baseUri, projection, null, null, null);
if (!c.moveToFirst()) return -1;
String description = c.getString(0); // and we're done :-)
However, what if I want to set the MediaStore.Images.Media.DESCRIPTION field? Can I, somehow, invoke the update method?
Long IMAGE_ID = 172712; // same image...
Uri baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
baseUri = Uri.withAppendedPath(baseUri, ""+ IMAGE_ID);
// create an object with the value to set
ContentValues test_values = new ContentValues();
test_values.put(MediaStore.Images.Media.DESCRIPTION, "Some image text...");
// i.e., SQL like: UPDATE MEDIASTORE SET DESCRIPTION = "Some image text..." WHERE IMAGE_ID = 172712;
String sIMAGE_ID = "" + IMAGE_ID;
int res = getContext().getContentResolver().update(baseUri, test_values, MediaStore.Images.Media._ID + "= ?", new String[]{sIMAGE_ID }); // works fine!
The above code works fine (at least in the emulator, Nexus 7 device)! update sets the DESCRIPTION "field".
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 getting audio files from specific folder and binding them on recyclerview. now i want Uri of each file so i can upload them one-by-one. i am using Cursor to get files. below is my code :
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Audio.AudioColumns.SIZE,MediaStore.Audio.AudioColumns.TITLE,android.provider.MediaStore.Audio.AudioColumns.DATA,
MediaStore.Audio.AudioColumns.DURATION,MediaStore.Audio.AudioColumns.TITLE};
Cursor c = context.getContentResolver().query(uri, projection, MediaStore.Audio.Media.DATA + " like ? ", new String[]{"%/storage/emulated/0/Call%"},null);
if (c != null ) {
for (int i = 0; i < 50 && c.moveToNext(); ++i) {
// Create a model object.
POJO audioModel = new POJO();
long id = c.getLong(4);
String SIZE = c.getString(0); // Retrieve path.
String NAME = c.getColumnName(1); // Retrieve name.
String PATH = c.getString(2); // Retrieve album name.
String DURATION = c.getString(3); // Retrieve artist name.
Uri contentUri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,id);
audioModel.setSize(SIZE);
audioModel.setName(NAME);
audioModel.setPath(PATH);
audioModel.setDuration(DURATION);
audioModel.setUri(contentUri);
Log.d("#", String.valueOf(contentUri));
arrayListFile.add(audioModel);
}
c.close();
}
return arrayListFile;
in contentUri i am getting this ( content://media/external/audio/media/0 ) . and what i want is
content://com.android.providers.media.documents/document/xyz.mp3. how can i do ??
why do not use MediaStore.Files.FileColumns.DATA ? the path can be also used to upload to server.
Please consider using (MediaStore.Audio.Media.DATA must be part of your projection):
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
Uri yourFileUri = Uri.parse(cursor.getString(column_index));
I am queryng MediaStore.Audio.Media for a song ID, using the ID to find the album art URI, and then downloading the album art if the URI is null, and finally updating MediaStore.Audio.Albums with the new image URI. I am not able to figure out the last part.
Here I am getting the cursor with GetCursor() method
private Cursor GetCursor() {
Uri contentURI = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.ALBUM_ID};
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
String order = MediaStore.Audio.Media.TITLE + " ASC";
final Cursor mCursor = getContentResolver().query(contentURI, projection, selection, null, order);// Run getContentResolver query
return mCursor;
}
Here I am adding the album art URI to songObject with GetAlbumArtURI()
String[] albumID = {mCursor.getString(5)};
songObject.albumArtURI = GetAlbumArtURI(albumID);
Here is GetAlbumArtURI() method
private String GetAlbumArtURI(String[] albumID) {
final Cursor mCursor = getContentResolver().query(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Audio.Albums.ALBUM_ART},
MediaStore.Audio.Albums._ID + "=?",
albumID,
null
);
if (mCursor.moveToFirst()) {
String var = mCursor.getString(mCursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
//DatabaseUtils.dumpCursor(mCursor);
mCursor.close();
return var;
}
else {
mCursor.close();
return null;
}
}
And here I test if the songObject.albumArtURI is null, download the image, and record the URI in the meta data
if (songObject.albumArtURI == null){
String anotherURI = downloadImageReturnURI();
ContentValues values = new ContentValues();
values.put(MediaStore.Audio.Albums.ALBUM_ART, anotherURI);
// And now I don't know what to do
}
So now, how can I add the new URI back to ALBUM_ART column? Something along these lines?
Uri uri = MediaStore.Audio.Albums.getContentUriForPath(newSoundFile.getAbsolutePath());
Uri newUri = getContentResolver().insert(uri, values);
The problem is that I am not trying to update values in MediaStore.Audio.Media but in MediaStore.Audio.Albums
From the documentation - Content Provider Basics
// Defines a new Uri object that receives the result of the insertion
Uri mNewUri;
...
// Defines an object to contain the new values to insert
ContentValues mNewValues = new ContentValues();
/*
* Sets the values of each column and inserts the word. The arguments to the "put"
* method are "column name" and "value"
*/
mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
mNewValues.put(UserDictionary.Words.WORD, "insert");
mNewValues.put(UserDictionary.Words.FREQUENCY, "100");
mNewUri = getContentResolver().insert(
UserDictionary.Word.CONTENT_URI, // the user dictionary content URI
mNewValues // the values to insert
);
And this is probably the most important take away
Many providers allow you to access a single row in a table by appending an ID value to the end of the URI. For example, to retrieve a row whose _ID is 4 from user dictionary, you can use this content URI:
Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
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 using the following intent:
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
Basically i am using ACTION_IMAGE_CAPTURE intent to invoke the camera and save the taken image into the specified uri.
It works but at the same time the image is also saved with the default name.
Thus once i have snapped the picture, it is saved twice, both in the uri and in the default path and name.
How do i ensure that it is only saved in the specified uri?
Thanks In Advance,
Perumal
You can take the ID or Absolute path of the gallery last image. And delete it.
It can be done like that:
/**
* Gets the last image id from the media store
* #return
*/
private int getLastImageId(){
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy);
if(imageCursor.moveToFirst()){
int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
String fullPath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
Log.d(TAG, "getLastImageId::id " + id);
Log.d(TAG, "getLastImageId::path " + fullPath);
imageCursor.close();
return id;
}else{
return 0;
}
}
And to remove the file:
private void removeImage(int id) {
ContentResolver cr = getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
}
This code was based on the post: Deleting a gallery image after camera intent photo taken