Android external storage - android

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.

Related

Android get all folders that contain at least one media file like photo / video

I just need the path of folders that contain at least one file that ends with eg. .mp4 or .jpg . I already checked this thread: Android: how to get all folders with photos? but it's too slow for my use case. Is there a faster way to do that?
So I finally found a solution which is way faster than the mentioned above. I got all directories with images within ~100-150ms (around 3k files). In the example below all image files stored either on the internal or external storage gets checked and the parent directory is added to the array list. I excluded .gif and .giff files.
This method also works with videos therefore a few steps are required:
change queryUri to MediaStore.Video.Media.EXTERNAL_CONTENT_URI
change projection to MediaStore.Video.Media.DATA
change 'image/%' in includeImages to 'video/%'
delete + excludeGif from selection
public static ArrayList<String> getImageDirectories(Context mContext) {
ArrayList<String> directories = new ArrayList<>();
ContentResolver contentResolver = mContext.getContentResolver();
Uri queryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = new String[]{
MediaStore.Images.Media.DATA
};
String includeImages = MediaStore.Images.Media.MIME_TYPE + " LIKE 'image/%' ";
String excludeGif = " AND " + MediaStore.Images.Media.MIME_TYPE + " != 'image/gif' " + " AND " + MediaStore.Images.Media.MIME_TYPE + " != 'image/giff' ";
String selection = includeImages + excludeGif;
Cursor cursor = contentResolver.query(queryUri, projection, selection, null, null);
if (cursor != null && cursor.moveToFirst()) {
do {
String photoUri = cursor.getString(cursor.getColumnIndex(projection[0]));
if(!directories.contains(new File(photoUri).getParent())){
directories.add(new File(photoUri).getParent());
}
} while (cursor.moveToNext());
}
return directories;
}

Android - Image files in external storage are not included in ContentResolver results

I have an application that writes jpg image files to a directory structure in the app's external storage.
I was planning to use ContentResolver to scan through the directory structure so I can search both a specific folder or all folders. However, the ContentResolver query I wrote does not return any of the files written by the app (it does return other files in the phone though).
Here is the code:
// Create Content Resolver
ContentResolver resolver = getContentResolver();
// List of fields we want to include in the query
String[] projection = new String[] { BaseColumns._ID,
MediaStore.MediaColumns.DISPLAY_NAME,
MediaStore.MediaColumns.SIZE };
// Run the query and return a crusor
cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
// URI = Uniform Resource Identifier
projection, // which fields
null , // selection criteria
null, // selection arguments
MediaStore.MediaColumns.SIZE + " DESC");
if ((cursor != null) && (cursor.moveToFirst()))
{
do // loop through the items in the list of results, using the cursor
{
long id = cursor.getLong(0);
String name = cursor.getString(1);
long size = cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns.SIZE));
Log.i(TAG, "Image: id = " + id + " name = " + name
+ " size = " + size);
} while (cursor.moveToNext());
} else {
Log.w(TAG, "System media store is empty.");
}
I tried restarting the phone (so the ContentProvider will be updated), I tried on several different devices and emulators. Nothing helped.
What am I doing wrong?
While we are at it, could you please guide me how to filter the results by the directory name (e.g. show only the files in a specific sub-directory, or all the files under the app's external storage directory).
Thank you!
Yossi

MediaStore show files after deleted

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.

Access All Media Files on Internal Storage

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?

Android ContentResolver.query always returns same data

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());
}

Categories

Resources