I am populating a gridview with MICRO_KIND thumbnails using the following:
/* Find images of interest */
imagecursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CON TENT_URI,
columns,
MediaStore.Images.Media.DATA + " like ? ",
new String[]{"%/houseTab" + currentHouseNumber + "/%"},
null);
/* Retrieve MICRO_KIND Thumbnails */
int id = imagecursor.getInt(image_column_index);
thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(
getActivity().getApplicationContext().getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
The retrieve process works perfectly; the issue happen when I delete the actual image files I can not delete the MICRO_KIND Thumbnails. This is what I am using right now and the files images gets deleted but the MICRO_KIND does not get deleted and still visible in the gridview even after a refresh. To get rid of the thumbnail I have to turn off the device or do a unmount/mount of the sdcard.
int count = imagecursor.getCount();
int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
ContentResolver cr = getActivity().getApplicationContext().getContentResolver();
for (int i = 0; i < count; i++) {
new File(arrPath[i]).delete(); // Delete the actual image file
imagecursor.moveToPosition(i);
long id = imagecursor.getInt(image_column_index);
/* Delete the thumbnails ???? Not working */
cr.delete(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, MediaStore.Images.Thumbnails.IMAGE_ID +
"= ?",new String[]{"" + id});
By the way arrPath is retrieve from the mediastore using the following:
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
arrPath[i] = imagecursor.getString(dataColumnIndex);
I also try to following to delete the thumbnails but also without any success.
MediaScannerConnection.scanFile(
getActivity().getApplicationContext(),
new String[]{arrPath[i]},
null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
refreshImages();
}
});
So how do I remove this entry from the database so the when the imagecursor is refreshed after the file deletion the imagecursor is empty and no MICRO_KIND or any data for that matter is returned???
Any help would be appreciated.
Hopefully this will help others. I manage to delete the entry from the mediastore hence the MICRO_KIND thumbnails using the following:
Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
id);
cr.delete(uri,null,null);
I'm having this same problem, I couldn't find any way to delete the MICRO_KIND thumbnails no matter what I did, so I peeked through the MediaStore source code and saw that there were references to the /sdcard/DCIM/.thumbnails/.thumbdata3--##### file, and it looks like thats where the MICRO_KIND thumbnails are stored.
The MediaStore database holds records that point to the thumbnail files in the /sdcard/DCIM/.thumbnails folder, so when you delete a thumbnail from MediaStore, it also deletes the file under that folder (which appear to be the MINI_KIND thumbnails since they are considerably larger than MICRO_KIND).
When I deleted the /sdcard/DCIM/.thumbnails/.thumbdata--BLAHBLAH file through ADB, it fixed my problem, the correct thumbnails loaded and I noticed the file instantly was recreated.
I also noticed when I deleted the file throught he ContentResolver like you did, and then queried the MINI_KIND thumbnails, they always loaded correctly.
So my answer (which seems more like a workaround than an answer) was to query the MINI_KIND thumbnails from the MediaStore, and extract a thumbnail from that:
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 3;
Bitmap out = MediaStore.Images.Thumbnails.getThumbnail(contentResolver, imageId, MediaStore.Images.Thumbnails.MINI_KIND, opts);
out = ThumbnailUtils.extractThumbnail(out, 96, 96);
And delete the thumbnail using user2553585's answer
Hope this helps
Related
I am trying to get the image of mp3 file on my phone. I've been struggling a few days and now I know;
Firstly, I use a content provider with this code
` Uri allSongsUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
String[] projection = {
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ALBUM_ID,
MediaStore.Audio.Media.ALBUM_KEY,
MediaStore.Audio.Media.DATE_MODIFIED
};
String sortOrder = MediaStore.Video.Media.DATE_MODIFIED + " DESC";
And I create my cursor like this;
Cursor cursor = ctx.getContentResolver().query(allSongsUri, projection, null, null, sortOrder);
In there I have all my mp3 files. That's ok. Now I want to get their's cover image.
If I use MediaMetadataRetriver's getEmbeddedPicture method like this
mediaMetadataRetriever.setDataSource(localeMusic.getPath());
localeMusic.setImage(mediaMetadataRetriever.getEmbeddedPicture());
it took about 6-7 seconds with nearly 40-50 file. Because getEmbeddedPicture() is too slow!.
Also tried to get album_id and query another cursor to MediaStore.Audio.Albums and I saw all album id is the same because all of them is the same folder. I don't want to show their Album image. I want to show the file's cover image.
I tried this like here But in there, we are getting file's albums image. That is not I ask.
Where can I find the file's image path? Where can the MetadataRetriever class get it with getEmbeddedPicture? Where is that embedded picture?
Thanks. Best regards
mediaMetadataRetriever.getEmbeddedPicture() is a native method and every native method call has a price because JNI calls takes time. So, if you iterate such calls, you may lost a lot of time. You may try to call this method asynchronously on demand and cache the result. Try to combine with glide
This will solve two of your problem at the same time, glide calls is naturally asnyc, so you don't need to implement an AsyncTask class also it caches your images.
This is the basic glide usage:
Glide.with(context).load(mediaMetadataRetriever.getEmbeddedPicture());
I encourage you to read glide documents. It has lots of other features.
Hope this helps.
You can get the album art as mentioned here
https://stackoverflow.com/a/17574629/3825975
Basically,
Cursor cursor = getContentResolver().query(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
new String[] {MediaStore.Audio.Albums._ID, MediaStore.Audio.Albums.ALBUM_ART},
MediaStore.Audio.Albums._ID+ "=?",
new String[] {String.valueOf(albumId)},
null);
if (cursor.moveToFirst()) {
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Albums.ALBUM_ART));
// do whatever you need to do
}
But to get individual song art, this is how I remember doing it. Hope it helps.
float ht_px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());
float wt_px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics());
Bitmap artwork, bitmap2 = null;
MediaMetadataRetriever mmr = new MediaMetadataRetriever();
byte[] rawArt;
BitmapFactory.Options bfo = new BitmapFactory.Options();
try {
mmr.setDataSource(songUri); //songUri is the uri of the song. You need to extract this from the song id
rawArt = mmr.getEmbeddedPicture();
if (rawArt != null)
bitmap2 = BitmapFactory.decodeByteArray(rawArt, 0, rawArt.length, bfo);
if (bitmap2 == null)
bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.def_icon);
artwork = Bitmap.createScaledBitmap(bitmap2, (int) ht_px, (int) wt_px, true); //This is the bitmap you need
} catch (Exception e) {
//Exception handling
}
}
Hi I am trying to save an image to the .thumbnails folder as shown below:
bitmap = ThumbnailUtils.extractThumbnail
(BitmapFactory.decodeFile(actualImagePath,options), 120, 120);
bitmapGenerated = true;
File file = new File(Environment.getExternalStorageDirectory()
.toString()+"/"+"DCIM/.thumbnails/"+id+".jpg");
boolean bcc =file.createNewFile();
boolean success = bitmap.compress(Bitmap.CompressFormat.PNG,60,new
FileOutputStream
(file));
The 'id' is actually the id of the particular image that I am trying to save and is obtained from a cursor as shown:
image_column_index = mCursor.getColumnIndex(MediaStore.Images.Media._ID);
id = mCursor.getLong(image_column_index);
The image gets saved in the '.thumbnails' , however, as I try to access the image thumbnail that I just created, it is not read.
I think it was because of the name I gave to the thumbnail image.
So my question is it okay to save to '.thumbnails' folder and if so in what name should we save the file?
Help is really appreciated,
Thank You.
I found out that to generate a thumbnail we don't need to explicitly create a thumbnail image file and put it in the .thumbnials folder.
There is a method called getThumbnail in MediaStore.Images.Media that we can use for our purpose. Code is as shown:
Cursor mCursor;
mCursor = mContext.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null,
null, null, null);
int image_column_index = mCursor.getColumnIndex(MediaStore.Images.Media._ID);
long id = mCursor.getLong(image_column_index);
MediaStore.Images.Thumbnails.getThumbnail(mContext
.getContentResolver(), id, MediaStore.Images.Thumbnails.MINI_KIND, null);
The above code will generate a thumbnail for the associated imageid , first we have to make sure that the thumbnail doesn't exist and create a new one only if one doesn't exist.
For my application, I need to refresh thumbnail image of gallery.
Because whenever I update my image content that thing don't reflected on thumbnail. The thumbnail image show first time image creation data not the present one.
But actual image contain new data so I need to reflect it into thumbnail also.
After wandering this forum I found following code snipper to delete current thumbnail but I can't able to call this function because I don't able to get photoId.
private static void removeThumbnails(ContentResolver contentResolver, long photoId) {
Cursor thumbnails = contentResolver.query(Thumbnails.EXTERNAL_CONTENT_URI, null, Thumbnails.IMAGE_ID + "=?", new String[]{String.valueOf(photoId)}, null);
for (thumbnails.moveToFirst(); !thumbnails.isAfterLast(); thumbnails.moveToNext()) {
long thumbnailId = thumbnails.getLong(thumbnails.getColumnIndex(Thumbnails._ID));
String path = thumbnails.getString(thumbnails.getColumnIndex(Thumbnails.DATA));
File file = new File(path);
if (file.delete()) {
contentResolver.delete(Thumbnails.EXTERNAL_CONTENT_URI, Thumbnails._ID + "=?", new String[]{String.valueOf(thumbnailId)});
}
}
At present I was calling this function as
removeThumbnails(pexelMimics.getContentResolver(),
ContentUris.parseId(uri));
I think this trick will work for me. But this is my guess. If you guys have better solution for this problem then please help me.
At the time of image saving, I have to provide following code to delete image content.
activity.getContentResolver().delete(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
MediaColumns.DATA
+ "='"
+ GameManager.getInstance().getSavedImageFilePath()
.replaceAll("'", "''") + "'", null);
After this I got new content in thumbnail icon.
You don't mention what class and inheritance you have; if you are in a class the inherits BaseAdapter, then you can do
notifyDataSetChanged();
after you change the thumbs.
I am trying to rename an image in Gallery taken from Camera to give a new name. When I renamed the file the original image disappears showing 2 black squares . Can any one help me in sorting this issue by telling me procedure to rename Gallery Image.
Path is as follows : /mnt/sdcard/DCIM/Camera
I tried to update the Image title through content provider as below:
ContentValues val = new ContentValues();
val.put(Images.Media.TITLE, "ImageTitle23");
getContentResolver().update(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, val, null, null);
The image title is changed in Gallery.
But when I try to query the updated image as below I am getting the name same as previous one :
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, MediaStore.Images.Media._ID+"="+id, null, imageOrderBy);
if(imageCursor.moveToFirst()){
int idd = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
String fullPath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
Can anyone help me in sorting out this issue?
The MediaStore looks for changes in your pictures BUT it will not react to all changes in real time. Each time you do such a modification, you should ask the MediaScanner to scan this file:
MediaScannerConnection.scanFile(
getApplicationContext(),
new String[]{file.getAbsolutePath()},
null,
new OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Log.v("grokkingandroid",
"file " + path + " was scanned seccessfully: " + uri);
}
});
Also, you should check this blog post that gives a lot of useful informations on this usecase.
The Gallery is interacting with the MediaStore content provider. If you change the name of the image file you probably need to update the field in the content provider.
You can read up on it in the MediaStore reference : http://developer.android.com/reference/android/provider/MediaStore.Images.Media.html
Potentially you can just trigger a refresh of the MediaStore. Look at this thread : How can I refresh MediaStore on Android?
I am having urls of images.
I am creating .JPEG files of it and saving in a directory of SD card.
After downloading all images (creating bitmaps and compressing in JPEG), i am calling another intent, which is supposed to show all images downloaded in that directory.
but I am seeing blank.
I cheecked DDMS, and found jpeg of correct sizes have got downloaded in my desired directory. But my intent is not showing.
To my surprise, when I close emulator , restart it, re run program with another set of image links, now my intent is showing previously downloaded images ! (not the images which r downloaded in this run of program).
Following is code i use for showing downloaded images:
Can anybody help me with this ?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.imagechooser);
Bundle bundle = this.getIntent().getExtras();
thumbNailsLnkdhs = (LinkedHashSet<String>) bundle.getSerializable("keyThumbNails");
Toast.makeText(getApplicationContext(),
"ThumbNailsLnkdhs size in new intent: "+thumbNailsLnkdhs.size(), Toast.LENGTH_LONG).show();
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor=managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
columns,
MediaStore.Images.Media.DATA + " like ? ",
new String[] {"%myDesiredDirectory%"},
null);
Log.d(LOGGER, "cursor made");
int colcount=imagecursor.getColumnCount();
//.d(LOGGER, "cursor column count is: "+colcount);
int count =imagecursor.getCount();
//Log.d(LOGGER, "count is: "+count);
String colnAME=imagecursor.getColumnName(0);
//Log.d(LOGGER, "COL NAME FOR 0TH COLUMN="+colnAME);
String colnAME_1=imagecursor.getColumnName(1);
//Log.d(LOGGER, "COL NAME FOR 1st COLUMN="+colnAME_1);
int image_column_index = imagecursor.getColumnIndex(imagecursor.getColumnName(1));
//Log.d(LOGGER, "image_column_index="+image_column_index);
//Log.d(LOGGER, "ThumbNailsLnkdhs size: "+ThumbNailsLnkdhs.size());
//int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
this.count = imagecursor.getCount();
//Log.d(LOGGER, "this.count="+this.count);
this.thumbnails = new Bitmap[this.count];
this.arrPath = new String[this.count];
this.thumbnailsselection = new boolean[this.count];
for (int i = 0; i < this.count; i++) {
imagecursor.moveToPosition(i);
int id = imagecursor.getInt(image_column_index);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
//Log.d(LOGGER, "dataColumnIndex="+dataColumnIndex);
thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(
getApplicationContext().getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
arrPath[i]= imagecursor.getString(dataColumnIndex);
}
GridView imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
imageAdapter = new ImageAdapter();
imagegrid.setAdapter(imageAdapter);
imagecursor.close();
}
ok, so as per suggestion of below ansr,
I found I need to insert image in gallery after I create its physical file.
I tried
MediaStore.Images.Media.insertImage(getContentResolver(), bitmapimage,
imgname+ ".jpg Card Image", "imgDescription"
+ ".jpg Card Image");
but couldnt use getcontentresolver as im in a class which downloads,creates physical file and not inn activity.
So I tried
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
+Environment.getExternalStorageDirectory()
+ "/myDesiredDirectory/")))
in my activity which displays previously downloaded images ... but it didnt helped me to show newly downloaded images...
so tried
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"
+ Environment.getExternalStorageDirectory()+)));
this also not showing new images :(
Can anyone help me with this ?
when you put Image manually in AVD through DDMS, you need to scan media from settings right?
same problem here
After download you need to scan media via coding and close the image cursor before set adapter.
You are creating a new ImageAdapter and then attaching the GridView to that 'new' adapter. In other words your GridView is bound to be empty as it is attached to a new blank adapter.
Where are you connecting the Bitmaps/Cursor to the Adapter/View?