I understand how to query "music files" from MediaStore with cursor loader.
I also do not see problem to query specific Album, Genre, Artist for songs. But I have no idea how to query MediaStore for song according to the directory in which they are located.
final Uri sourceUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
CursorLoader cursorLoader = new CursorLoader(
context,
sourceUri,
null,
null,
null,
MediaStore.Audio.Media.TITLE);
Also if you can help me to get number of songs in album, genre, etc. in same query it would be great.
Thank you for any help in advance.
Michal, your question and example are confusing. You ask about music, yet your code is about Images.
Anyway, to get the song directory
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
final String path = MediaStore.Audio.Media.DATA;
so when you have a cursor say c which returns _DATA,
String strpath = (c.getString(c.getColumnIndex(MediaStore.Audio.Media._DATA)));
this will return the full path including the song title itself.
To get number of tracks of an album (where c is the cursor returned)
String strnosongs = (c.getString(c
.getColumnIndex(MediaStore.Audio.Albums.NUMBER_OF_SONGS)));
I hope this helps.
For current API (18) there is no way to do it with in-build tools. This requires to build something (like own database) to help with this query or use other approach (like use "file browser").
Related
To get all local Music-Files on an android-Device I'm working with a ContentResolver, getting Data from MediaStore.Audio.
Here's an example on how I load all titles + their artist:
ContentResolver musicResolver = act.getContentResolver();
Uri musicUri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor musicCursor = musicResolver.query(musicUri, null, selection, null, sortOrder);
if(musicCursor!=null && musicCursor.moveToFirst()){
int titleColumn = musicCursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
int artistColumn = musicCursor.getColumnIndex(android.provider.MediaStore.Audio.Media.ARTIST);
do {
String thisTitle = musicCursor.getString(titleColumn);
String thisArtist = musicCursor.getString(artistColumn);
//save them somewhere
}while (musicCursor.moveToNext());
}
So this code is working for about 75% of all the music I have.
But there are tracks, where artist (and some other values like artistKey, Track, Cover,...) return null. But the title, album_name and artistId are loading correctly.
The Tags should be right (shown right on the Computer and other Music-Apps). Also the format isn't different to the tracks that are working.
Have anyone of you had the same problem some day and solved this?
All those missing Meta-Tags are not even loading with a MediaMetadataRetriever. I can't explain what's the problem with some of my Files and why other apps can load them correctly.
If needed, I can upload a working and a not-working Music-File somewhere.
Managed how to do it.
Some albums have only stored the most information (aristname, albumcover) in one (mostly the first or last) of the tracks, not all.
This is not very common, but about 20% of my albums had this, even they were bought.
So, if you are loading/displaying one of these albums, you need to go through all album-tracks until you find the one, where the information you are missing on the others is stored.
I made it a bit different because of my other code, but I think this is the most understandable way to do it.
I'm using code below to get all songs from folder, but it's not working because it will only work with such paths: /sdcard/test.mp3, but i need to get songs from folder- eg /sdcard/
How can i do this without getting all songs?
public Playlist getSongsByPath(String name){
String where = MediaStore.Audio.Media.DATA
+ "=?";
String whereVal[] = { name };
String orderBy = MediaStore.Audio.Media.TITLE;
Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
ContentResolver resolver = mContext.getContentResolver();
Cursor cursor = resolver.query(media, Song.FILLED_PROJECTION, where, whereVal, orderBy);
Playlist result = new Playlist();
while(cursor.moveToNext()){
result.addSong(new Song(cursor));
}
return result;
}
By using the Mediastore, you will find all music on your device. The media scanning process maintains the android music database. The _DATA attribute holds the fully qualified pathname so could have differing paths. Eg /mnt/sdcard, /sdcard or wherever you have placed your music etc.
If you want to search the filesystem then mediastore is probably not the correct way to do it.
Ps. Your question is a little confusing? Perhaps you mean something else than "get songs from folder eg /sdcard/"
In the class MediaStore.Files class, its mentioned that,
Media provider table containing an index of all files in the media storage, including non-media files.
I'm interested in querying for non-media files like PDF.
I'm using CursorLoader to query the database. The second parameter for the constructor requires an Uri argument which is easy to get for the media types Audio, Images and Video as each of them have a EXTERNAL_CONTENT_URI and INTERNAL_CONTENT_URI constant defined for them.
For MediaStore.Files there is no such defined constant. I tried using the getContentUri() method but couldn't figure out the argument value for volumeName. I tried giving "/mnt/sdcard" and also the volume name that appears when I connect the device to my system but in vain.
I saw a similar question on Google Groups but that is not resolved.
EDIT: I also tried using Uri.fromFile(new File("/mnt/sdcard/")) and Uri.parse(new File("/mnt/sdcard").toString()) but that didn't work out either.
It is "external" or "internal" although internal (system files) is probably not useful here.
ContentResolver cr = context.getContentResolver();
Uri uri = MediaStore.Files.getContentUri("external");
// every column, although that is huge waste, you probably need
// BaseColumns.DATA (the path) only.
String[] projection = null;
// exclude media files, they would be here also.
String selection = MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;
String[] selectionArgs = null; // there is no ? in selection so null here
String sortOrder = null; // unordered
Cursor allNonMediaFiles = cr.query(uri, projection, selection, selectionArgs, sortOrder);
If you want .pdf only you could check the mimetype
// only pdf
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + "=?";
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf");
String[] selectionArgsPdf = new String[]{ mimeType };
Cursor allPdfFiles = cr.query(uri, projection, selectionMimeType, selectionArgsPdf, sortOrder);
Gah, another scenario here something that should be simple is proving to be very time-consuming and painful.
I'm using this to query the contacts provider:
private Cursor getContacts(){
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_ID
};
......
return managedQuery(uri, projection, selection, selectionArgs, sortOrder);
}
This works fine and retrieves contact names, and on a handful of contacts it shows a numeric ID for the PHOTO_ID field, which I assume is the PHOTO_ID I'm requesting. But then I push that ID into this method to extract the bitmap, it fails on every contact and the stream is null every time. I'm testing against a set of contacts that includes some with Android contact photos (I know there are some issues extracting photos from Facebook contacts).
private Bitmap loadContactPhoto(long id) {
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, id);
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, uri);
if (input == null) return null;
Bitmap bitmap = BitmapFactory.decodeStream(input);
return bitmap;
}
What have I missed?
openContactPhotoInputStream() takes the uri of the contact, try calling it with the ContactsContract.Contacts._ID column instead of the PHOTO_ID column and you should see better results.
There's a bunch of relevant discussion here with some code to check out:
How do I load a contact Photo?
Note that in some cases you'll see a photo in the native contacts app which won't load through the content resolver. Some sync info, like Facebook for example, is flagged to be used only by the contacts app itself and doesn't get exported to other apps :-(
However, using the contactUri should take care of at least some of your issues.
Much like the music app does I want to access the name of the song (not the name of the file) or the artist or album. For example, I want to populate a listview with the names of all the songs on the phone.
There are two approaches to this, one to read the meta tags from the music files themselves and one to use the MediaStore content provider. MediaStore is essentially a public database that you may query for all media related information on the phone.
Using MediaStore is very simple and can be found in the docs here.
Here is a simple example from one of my applications:
String[] proj = { MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Artists.ARTIST };
tempCursor = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
proj, null, null, null);
tempCursor.moveToFirst(); //reset the cursor
int col_index=-1;
int numSongs=tempCursor.getCount();
int currentNum=0;
do{
col_index = tempCursor.getColumnIndexOrThrow(MediaStore.Audio.Artists.ARTIST);
artist = tempCursor.getString(col_index);
//do something with artist name here
//we can also move into different columns to fetch the other values
}
currentNum++;
}while(tempCursor.moveToNext());