I'm trying to access system folders on Android, /Music to be precise. What I found in documentation is that getExternalFilesDir(Environment.DIRECTORY_MUSIC) will grant access to music folder related to my app, which is part of it and eventually will be deleted once app gets removed from the device. So my question is how to access system music folder contents? Will I have the necessary permissions to grab these files and send over Bluetooth later on?
What I have done so far, yet it obviously lists app directory:
File path = getExternalFilesDir(Environment.DIRECTORY_MUSIC);
Log.d("Files", "Path: " + path);
File f = new File(path,"");
File file[] = f.listFiles();
for (int i=0; i < file.length; i++)
{
filesList.setText("FileName:" + file[i].getName());
}
To get a list of all the music on a device, you'll want to look into using Content Providers and MediaStore
Check out this code from Google's sample code for how to retrieve music from a device. It shows you exactly how to do it.
The important bit is this part...
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
// Perform a query on the content resolver. The URI we're passing specifies that we
// want to query for all audio media on external storage (e.g. SD card)
Cursor cur = mContentResolver.query(uri, null,
MediaStore.Audio.Media.IS_MUSIC + " = 1", null, null);
if (cur == null) {
// Query failed...
return;
}
if (!cur.moveToFirst()) {
// Nothing to query. There is no music on the device. How boring.
return;
}
// retrieve the indices of the columns where the ID, title, etc. of the song are
int artistColumn = cur.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int titleColumn = cur.getColumnIndex(MediaStore.Audio.Media.TITLE);
int albumColumn = cur.getColumnIndex(MediaStore.Audio.Media.ALBUM);
int durationColumn = cur.getColumnIndex(MediaStore.Audio.Media.DURATION);
int idColumn = cur.getColumnIndex(MediaStore.Audio.Media._ID);
Related
This question already has answers here:
Simple mediaplayer play mp3 from file path?
(7 answers)
Closed 5 years ago.
I have been building simple mp3 player everything is going well the code which fetches all mp3 files from storage device's works well.
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
My question i need to load mp3 files only from sdcard kalid folder. i have tried this code but its not loading mp3 files from kalid folder.
File path = new File(Environment.getExternalStorageDirectory() + "/kalid");
Uri media = Uri.fromFile(path);
i have also tired this code
File path = new File(Environment.getExternalStorageDirectory() + "/kalid");
Uri media = MediaStore.Audio.Media.getContentUriForPath(String.valueOf(path));
I think no one is understanding my question here is full source code
ContentResolver resolver = context.getContentResolver();
Uri media = MediaStore.Audio.Media.getContentUriForPath("Environment.getExternalStorageDirectory().getPath()+ kalid+");
String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0";
Cursor cursor = resolver.query(media, PROJECTION, selection, null, null);
if (cursor == null || cursor.getCount() == 0) {
Log.d(TAG, "Music List Empty");
return false;
}
mMusicList.clear(); // clear
int count = cursor.getCount();
for (int i = 0; i != count; ++i) {
if (!cursor.moveToNext()) {
break;
}
//Log.d(TAG, cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)));
// Add to ArrayList
mMusicList.add(new Music(
cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST))
));
}
cursor.close();
Finally after trying so many things i have listed mp3 files from kalid folder here is the source code.
Cursor cursor = resolver.query(media,
PROJECTION,
MediaStore.Audio.Media.DATA + " like ? ",
new String[]{"%kalid%"}, null);
Using this method of audio file retrieval from Android's external storage
Cursor cursor = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null);
can I actually find a resonable way to fetch a genre of the given song? MediaStore class seems to provide everything else - from song's title to its composer info - except for the genre field. Should I use MediaMetadataRetriever then? If so, how drastically can creating a MediaMetadataRetriever instance for every song on a device reduce app's performance?
Maybe there are some better ways to retrieve all audio files from both external and internal storages in android?
As mentioned at Developer's Site,
You can fetch the Genres of the Audio file using MediaStore.Audio.Genres
Sample Code :
private static String[] genresProj = {
MediaStore.Audio.Genres.NAME,
MediaStore.Audio.Genres._ID
};
int idIndex = cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media._ID);
while (cursor.moveToNext()){
int id = Integer.parseInt(mediaCursor.getString(idIndex));
Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", id );
genresCursor = context.getContentResolver().query(uri,
genresProj , null, null, null);
int genreIndex = genresCursor.getColumnIndexOrThrow(MediaStore.Audio.Genres.NAME);
while (genresCursor.moveToNext()) {
Log.d(TAG, "Genre = " +genresCursor.getString(genreIndex));
}
}
}
To fetch other details of the Audio file, please check here .
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
I'm using the following code to get all audio files (actually their ids so I can play them later with MediaPlayer) from a directory on my android device:
ContentResolver cr = context.getContentResolver();
Uri audioUri = MediaStore.Audio.Media.getContentUriForPath(dir.getPath()); //dir is a File object representing the dir I'm looking in
Cursor audioCursor = cr.query(audioUri, null, null, null, null);
if (audioCursor != null && audioCursor.moveToFirst()) {
int idColumn = audioCursor.getColumnIndex(MediaStore.Audio.Media._ID);
List<Long> fileIds = new ArrayList<>();
do {
long id = audioCursor.getLong(idColumn);
fileIds.add(id);
} while (audioCursor.moveToNext());
return fileIds;
} else {
return null;
}
For some reason however, it returns an array with 2904 ids for any dir I give it. I'm guessing there are 2904 audio files on my device (when I use Uri audioUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI it also returns 2904 ids). So it seems I'm using getContentUriForPath incorrectly, however the android reference doesn't give any information.
How should this work?
Some more info about what I'm trying to do (if it makes any difference in your answer): I'm still working on the code, trying out different things. Ultimately I want to play the files with MediaPlayer. I only need the audio files in that folder directly, ignoring any subfolders. They should also be ordered by filename.
You can't use getContentUriForPath with a folder, there isn't any content registered at this path. In this case getContentUriForPath return the standard EXTERNAL_CONTENT_URI, for this reason you get all the ids available.
This return all the files contained in a particular folder (e.g. /storage/emulated/0/Music/), ignoring any subfolders and ordered by filename:
Cursor audioCursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
null,
MediaStore.Audio.Media.DATA + " LIKE ? AND " + MediaStore.Audio.Media.DATA + " NOT LIKE ?",
new String[]{path + "%", path + "%/%"},
MediaStore.Audio.Media.DISPLAY_NAME + " ASC");
if (audioCursor != null && audioCursor.moveToFirst()) {
int idColumn = audioCursor.getColumnIndex(MediaStore.Audio.Media._ID);
List<Long> fileIds = new ArrayList<>();
do {
long id = audioCursor.getLong(idColumn);
fileIds.add(id);
} while (audioCursor.moveToNext());
return fileIds;
} else {
return null;
}
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());
}