I am trying to display a list of albums (of music mp3s stored on the sd-card) along with the album art for each album. The album art is stored in the mp3s tag (it is not a separate image on the SD card)
I can get the album details fine using:
String[] projection = new String[] { Albums._ID, Albums.ALBUM, Albums.ARTIST, Albums.ALBUM_ART, Albums.NUMBER_OF_SONGS };
String rowsToReturn = null;
String[] selectionWhere = null;
String sortOrder = Media.ALBUM + " ASC";
Cursor cursor = contentResolver.query(Albums.EXTERNAL_CONTENT_URI, projection, rowsToReturn, selectionWhere, sortOrder);
String albumArtUri = cursor.getString(cursor.getColumnIndex(Albums.ALBUM_ART));
The URI is correct, but when I try to set the URi to the src of an ImageView, I get a silent error being thrown "resolveUri failed on bad bitmap uri".
imageview.setImageURI(Uri.parse(albumArtUri));
This only happens for some albums. Some are fine and display the album art correctly.
I took a look at the URI path and checked on the SD card for the thumbnail images and found them here: /mnt/sdcard/Android/data/com.android.providers.media/albumthumbs/
I found images that work and images that dont, so the image does exist, but just cannot be read correctly. I even tried copying the images off the sd card and adding .png extension to the files - the ones that show up on the phone work, but the ones that don't are 'corrupt'
Finally I copied the mp3 files themselves back to the PC and inspected the album art embedded in the tags and they all show correctly.
It's almost as if the thumbnails that the Android system is creating form the tags are invalid or corrupt, but this can't be right.
Or maybe I need to read them differently?
i think the issue could be with Media scanning. Delete the cache folder and open the music player app.It will create album cache again for all the songs. See if this helps.
Related
I have an app in which I'd like to view a video file that I chose to share from the Gallery to be edited. For that I know I have to use the intent-filter tag in the manifest of the Activity.
So here I was, selecting a video from the Gallery app to be 'shared' into this app. When the Activity opens, I used Uri videoUri = getIntent().getParcelableExtra(Intent.EXTRA_STREAM); to retrieve the URI of the video. The URI looks like this:
content://com.google.android.apps.photos.contentprovider/-1/2/file%3A%2F%2F%2Fdata%2Fdata%2Fcom.google.android.apps.photos%2Fcache%2Fshare-cache%2Fmedia.tmp%3Ffilename%3Dimage.jpg/ORIGINAL/NONE/1804018524
I can play it just fine in MediaPlayer, but the problem comes when I have to use a library that requires a File [namely, MP4Parser], and that means a file path - this URI doesn't work.
I've parsed the file%3A%2F%2F%2Fdata%2Fdata%2Fcom.google.android.apps.photos%2Fcache%2Fshare-cache%2Fmedia.tmp%3Ffilename%3Dimage.jpg part, and it gives me:
file:///data/data/com.google.android.apps.photos/cache/share-cache/media.tmp?filename=image.jpg
The problem with this is that opening it results in an ENOENT. new File("/data/data/com.google.android.apps.photos/cache/share-cache/media.tmp").exists() returns false.
I've also queried the URI itself in the cursor via getContentResolver().query(uri, null, null, null, null) and logged all the values inside. All I got was:
_id:0
_display_name:image.jpg
_size:2183131
mime_type:video/mpeg
_data:null
orientation:0
datetaken:0
latitude:null
longitude:null
special_type_id:null
My question: Is there a way to inquire the actual path [either in file:// form or in content://media/external/videos/...] of the video shared by the Gallery app if that URI is what it sends out?
Turns out all I needed to do is to open an InputStream from said URI via the ContentResolver, write it into a FileOutputStream directed towards a temporary file (right now I have the temporary file inside my app's FilesDir), then use that as the data source instead.
I used below query to load all pictures or video from sd card and it works accordingly. But when I add some video or pictures manually into sd card at different folder then its not loading after query. Please suggest me regarding same.
final String[] columns = { MediaStore.Video.Media.DATA,
MediaStore.Video.Media._ID};
final String orderBy = MediaStore.Video.Media.DATE_TAKEN;
Uri videosuri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
Cursor imagecursor = getContentResolver().query(videosuri, columns, null, null, orderBy);
if (imagecursor != null && imagecursor.getCount() > 0) {
while (imagecursor.moveToNext()) {
int video_id=imagecursor.getInt(imagecursor.getColumnIndex(MediaStore.Video.Media._ID));
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Video.Media.DATA);
String path=imagecursor.getString(dataColumnIndex);
}
}
When you "add some video or pictures manually into sd card at different folder", the MediaStore has to be updated in order for them to be available to your query, as well as to other apps that use the MediaStore backend.
Adding them via MTP or apps like Gallery will invoke the MediaScanner (or some similar process) to add them to the MediaStore, but adding them via adb push or in your own code requires you to explicitly do so afterward.
In your code, after writing an image or video file to the SDCard, you can pass the path and MIME type of the file to the MediaScanner by implementing the MediaScannerConnectionClient interface in a class, instantiating it, then calling scan(). The MediaScanner will then open the file, collect/generate metadata, and add the file to the MediaStore
See android - dynamically add pictures to gallery widget for an example class using this approach.
possible duplicate
Refreshing the thumbnail using MediaScanner
I have a problem regarding the update of thumbnails in the android in built-in gallery. Actually I have opened, edited and saved the image which was selected in the gallery.
I open leave the gallery and open the gallery again, then the thumbnail for that image is not updated. However, I pick the image, it is the edited version indeed.
Does anybody have solution about this? I have search but I'm getting the answer about refreshing the gallery using sendBroadcast(), which does not seem to update the image previews.
Edit
I don't want to delete the existing file because suppose user want to save file with different name then that file did not affected
Two suggestions.
Try getThumbnail. From the javadoc, I would expect it to regenerate an up-to-date thumbnail.
If that doesn't update the thumbnail, try deleting the thumbnail.
I found a workaround for this problem, before you request a new thumbnail you need to delete old one. Use MediaStore and ContentResolver for this
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)});
}
}
You can get photoId from its URI, to get URI from file name just create File and parse URI from it
Uri uri = Uri.fromFile(file);
I want to show an images gallery. The problem is during the loading of them.
At the beginning, I was loading the images with :
images = new File("/sdcard/DCIM/Camera/");
if(images.listFiles().length==0)
//no images, do some other stuff...
else
//put images in the gallery and do some stuff
This code works with the emulator (Android 2.2 - API Level 8) and with a Samsung Galaxy S2 (Android 2.2.1). But I ask some friends to test this code with their own phones (HTC, LG...).
With an HTC Desire, there is a problem during this loading. The code is going into "//no images" but they have images in the album (for example from Camera...) My friend said to me that :
album is stored in the internal storage and not in the SD Card with HTC.
So i've tried to check others directory, like this :
//Get the internal content
images = new File(MediaStore.Images.Media.INTERNAL_CONTENT_URI.getPath());
if (!images.isDirectory()) {
//Get the external content
images = new File(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.getPath());
}
if (!images.isDirectory()) {
//Get the SD Card content
images = new File("/sdcard/DCIM/Camera/");
}
But still not working :( That is not the good directory :/
So, my question is : how can i get the good path for images with all android phone ? is their an Object which is able to return the path of the album ?
Thanks :)
(sorry for mistakes)
I did some checking and it looks like you are trying to access the MediaStore incorrectly. It should be accessed via a cursor and not directly as a file.
This is because as mentioned at http://developer.android.com/guide/topics/providers/content-providers.html
Content providers expose their data as a simple table on a database model, where each row is a record and each column is data of a particular type and meaning.
So basically you can't read the URI as a file. It is a table of data.
Here's an example from that same page on how to access it.
import android.provider.Contacts.People;
import android.content.ContentUris;
import android.net.Uri;
import android.database.Cursor;
// Use the ContentUris method to produce the base URI for the contact with _ID == 23.
Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
// Alternatively, use the Uri method to produce the base URI.
// It takes a string rather than an integer.
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");
// Then query for this specific record:
Cursor cur = managedQuery(myPerson, null, null, null, null);
Also, here's another Stackoverflow question that has some examples that shows how to use the cursor.
How to query Android MediaStore Content Provider, avoiding orphaned images?
Finally, based on the links above I would just use the mediastore object as a cursor on all devices and that will solve the problem you are having with different directories.
Hope this helps,
George
AFAIK accessing thumbnails for images via MediaStore.Images.Thumbnails would generate thumbnails at first attempt, and that's what I need to perform against specific location on sd card.
The question is how to make valid URI to content under specific folder?
All answers I can find use just MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI as uri to make managedQuery. And result of it is Cursor that points to all sdcard images, while none examples can be found on how to access only specific folder.
Maybe you could just list files in the directory and parse them to get thumbnails without using content provider. You can use inSampleSize option to get small bitmap not the complete image Strange out of memory issue while loading an image to a Bitmap object.
may be is to late, but for some one will be helpfull
Mihai Fonoage said...
Use something like
File imagesDir = new File(Environment.getExternalStorageDirectory().toString() + "/pathToDirectory");
File[] imageList = imagesDir.listFiles();
for (File imagePath : imageList) {
bitmap = BitmapFactory.decodeStream(imagePath.toURL().openStream());}
Here you have some great tutorial.