I'm using the following example to try to load saved images and video on an android device into a customized gallery activity:
Access ordered images and video in same Cursor
While this works for images and video created using the default Android camera app, it doesn't seem to find media files that are saved locally in a folder specifically for the app (located in Pictures/Name_of_app)
How can I fetch all media files that are on the device?
private String[] projection = {
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.TITLE
}; // used for query ContentResolver for mediafiles
private String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE
+ " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO; // used to select images and videos from contentResolver
private Uri queryUri = MediaStore.Files.getContentUri("external");
cl = new CursorLoader(CustomizedGallery.this, queryUri, projection, selection, null, MediaStore.Files.FileColumns.DATE_ADDED + " DESC");
It sounds like the files haven't been added to the MediaStore database yet. You can check this by checking the gallery app - if they don't show up there they aren't in the DB yet.
Simply creating them does not automatically add them to the database - scans happen at regular trigger points(such as on reboot or remount of the external storage) or you can manually request a rescan.
To request a scan of a particular file you can call:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(newFile)));
More information here:
How can I refresh MediaStore on Android?
Related
I use MediaStore to get all video files from Android device. Then I delete some of these videos. Followed I use MediaStore again, and I get all deleted files.
Why MediaStore returns files that are no longer are on the device?
Delete File:
File file = new File(filePath);
file.delete();
Get all video files from device:
public static List<String> getVideoFiles(Context context) {
String[] projection = { MediaStore.Video.Media.DATA };
Cursor cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, null,
null, null);
List<String> videoList = new ArrayList<String>();
while (cursor.moveToNext()) {
videoList.add(cursor.getString(0));
}
Log.i(Constants.LOG_TAG, "get video files, load: " + videoList.size() + " "
+ videoList.toString());
return videoList;
}
MediaStore updates the list of media is not in real time. It needed time to test the relevance of its database. Try to make a call MediaStore after some time.
Or report manually about updating content.
I have an app which uses cursors to load thumbnails (into a gridview) from the mediastore:
CursorLoader cursorLoader = null;
if (Integer.valueOf(android.os.Build.VERSION.SDK_INT) >= android.os.Build.VERSION_CODES.HONEYCOMB) {
String[] from = { MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.MEDIA_TYPE,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.TITLE };
projection = from;
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE + " OR "
+ MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
Uri queryUri = MediaStore.Files.getContentUri("external");
cursorLoader = new CursorLoader(this, queryUri, projection,
selection, null, MediaStore.Files.FileColumns.DATE_ADDED
+ " DESC");
} else {
String[] from = { MediaStore.MediaColumns.DATE_ADDED };
projection = from;
Uri sourceImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
cursorLoader = new CursorLoader(this, sourceImageUri, null, null,
null, MediaStore.MediaColumns.DATE_ADDED + " DESC");
}
Cursor cursor = null;
if (cursorLoader != null) {
cursor = cursorLoader.loadInBackground();
mGalleryAdapter = new GalleryAdapter(this,
android.R.layout.simple_list_item_1, cursor, projection,
to, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
gallery.setAdapter(mGalleryAdapter);
gallery.setOnItemClickListener(myOnItemClickListener);
}
However, some newer images are loaded without thumbnails, which is rather silly. The thumbnails are only generated when I open the gallery app (Photos) on my phone.
How can I refresh all the thumbnails programatically on the device so there are no images left blank without a thumbnail?
I would like this to work on all Android version, including 4.4. Thanks in advance :)
You should be able to trigger a rescan with this:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
You may need to alter the path to suit your needs.
Found here
And if you wanted to wait for the scan to complete before moving forward you will need to register a receiver for the ACTION_MEDIA_SCANNER_FINISHED intent.
Details and discussion on that here/RdvA7y4MqfE
kaiwid23 suggests this doesn't work for 4.4+. In that case you can manually control the scanner with a MediaScannerConnection.
You will want to use the MediaConnection.scanFile() method. I don't know if it works recursively if supplied a directory or whether it just accepts single paths though.
In this case you pass an OnScanCompletedListener in the constructor so monitoring for the scan to complete is actually much easier.
Edit:
Use MediaStore.Images.Thumbnails.getThumbnail() or MediaStore.Video.Thumbnails.getThumbnail() - it's a blocking class and generates a new bitmap if it doesn't find one. Much simpler.
You simply need the MediaStore ID of the file, which I assume you have, and you can use the standard getContentResolver() in your Activity or through a context. This method also allows for you to get a Bitmap directly in MINI or MICRO sizes.
More on this here.
Old answer:
As indivisible says, you can use
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://"
+ Environment.getExternalStorageDirectory())));
However, that will not work on Android 4.4 (I think), so consider using the MediaScanner class for API 19+.
I create a method that upload and save the video in "/download" folder in external storage in the android phone, if i use MediaStore.Video.Media.EXTERNAL_CONTENT_URI all video files will be included, i want to know how to get the exact path of the "/download" folder in the phone storage?
because if i use this
private static final Uri sourceUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
videoCursorTitle = getContentResolver().query(sourceUri, projection,
null, null, orderByTITLE);
if i use that it gets all the video from the external storage, how to get video in a specific folder? folder name is "/download"
String selection=MediaStore.Video.Media.DATA +" like?";
String[] selectionArgs=new String[]{"%FolderName%"};
videocursor = managedQuery(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
parameters, selection, selectionArgs, MediaStore.Video.Media.DATE_TAKEN + " DESC");
I'm using method Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) to get the default directory my Android device saves its music to.
The directory returned by this method exists(something like sdcard/music), but it doesn't have any music files. When I checked my sdcard I found all the music files are instead stored in another directory named by one of my applications(sdcard/qqmusic/song), which cannot be found using the getExternalStoragePublicDirectory method.
In such case(different devices store music in different locations), is there any good ways to get the paths regardless of the differences among devices?
As we discussed in comments, I'll show how Android Music application find all music files.
Android Music application simply query the MediaProvider to get all musics on external storage, i.e. sdcard.
And the databases is filled by MediaScannerService. The MediaScannerService call the MediaScanner.scanDirectories to search all files under those directories. Fetch metadata if it is audio file and put it into database(MediaProvider).
if (MediaProvider.INTERNAL_VOLUME.equals(volume)) {
// scan internal media storage
directories = new String[] {
Environment.getRootDirectory() + "/media",
};
}else if (MediaProvider.EXTERNAL_VOLUME.equals(volume)) {
// scan external storage volumes
directories = mExternalStoragePaths;
}
if (directories != null) {
scan(directories, volume);
}
So my answer is the MediaProvider already contains the music files on the external storage, so you can directly query the provider to get all music files.
Check MediaStore first.
You can use the following code to get all music files.
//Some audio may be explicitly marked as not being music
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
String[] projection = {
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.DURATION
};
cursor = this.managedQuery(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
projection,
selection,
null,
null);
private List<String> songs = new ArrayList<String>();
while(cursor.moveToNext()){
songs.add(cursor.getString(0) + "||" + cursor.getString(1) + "||" + cursor.getString(2) + "||" + cursor.getString(3) + "||" + cursor.getString(4) + "||" + cursor.getString(5));
}
The MediaStore.Audio.Media.DATA column contains the full path to that music file.
I have videoplayer app with filebrowser listing all videos on SD card
Code inspired by i want get audio files in sd card
Using ContentResolver, works as expected, but it does not update if the files on card change. I do not mean automatically, but after view/app restart. Not even reinstalling the application helped, still shows the same files. The deleted video file is not visible via PC nor it is possible to play it (This video cannot be played (translation)).
I dumped the data and the problem is not in view caching or elsewhere. I do not implement any caching of my own and failed to find anything on the matter. Thank you
Code:
// acquisition
String[] projection = {
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.DATA
};
ContentResolver resolver = getActivity().getContentResolver();
Cursor videoCursor = resolver.query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
projection,
null,
null,
null
);
// extraction
while(cursor.moveToNext()) {
cursorIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
filepath = cursor.getString(cursorIndex);
cursorIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
filename = cursor.getString(cursorIndex);
cursorIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION);
duration = cursor.getString(cursorIndex);
result[ index++ ] = new VideoFileMetadata(filename, duration, filepath);
}
Edit 1 [14-03-2013]:
I tried adding number + " = " + number to ORDER or WHERE clause to act as a potential query caching buster, but it had no effect (although it's possible it was removed by an optimizer as a useless clause). This time I had reinstalled the application from a different machine using different certificate, but the query result remained the same, listing currently non-existing files.
You should first call cursor.moveToFirst() .
So, your cursor iteration loop should look like
if (cursor.moveToFirst()) {
do {
// cursorIndex = cursor.getColumnIndexOrThrow, etc...
} while (cursor.moveToNext());
}