Reputation: 589
I am trying to grab the genre of each song while I'm loading the songs. Currently I am using this solution:
MediaMetadataRetriever mr = new MediaMetadataRetriever();
Uri trackUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
cursor.getLong(id));
mr.setDataSource(c, trackUri);
String genre = mr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
It does work, but takes an insanely long time. On my test phone with only ~20 songs it works fast, but on my main phone with 1700+ songs it takes a really long time. If I remove that code and load just the songs it's almost instant so I know it has to be this. Is there a better/more efficient way to get the genre of a song with the song id?
Thanks in advance for any help!
Full code snippet
try {
if (cursor.moveToFirst()) {
int id = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
int title = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE);
int album = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM);
int artist = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST);
int duration = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION);
int albumId = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID);
int data = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
do {
MediaMetadataRetriever mr = new MediaMetadataRetriever();
Uri trackUri = ContentUris.withAppendedId(
android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
cursor.getLong(id));
mr.setDataSource(c, trackUri);
String genre = mr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
if (genre == null){
genre = "Not Specified";
}
genres.add(genre);
Song item = new Song(cursor.getLong(id), cursor.getString(title),
cursor.getString(artist), cursor.getString(album),
cursor.getLong(duration),
ContentUris.withAppendedId(albumArtUri, cursor.getLong(albumId)),
Uri.parse(cursor.getString(data)), "");
items.add(item);
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
Upvotes: 2
Views: 726
Reputation: 81
//This Method is Use For get LIST OF GENRES_NAME or ID Or NUMBER_OF_SONG In GENRES
public void getListofGenres(Context c) {
ArrayList<Song> songs = new ArrayList<>();
String[] projection = new String[]{
MediaStore.Audio.Genres.NAME,
MediaStore.Audio.Genres._ID
};
Cursor cursor = c.getContentResolver().query(
MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI,
projection,
null,
null,
null);
while (cursor.moveToNext()) {
songs.add(addGenres(cursor));
}
cursor.close();
}
private Song addGenres(Cursor cursor) {
Song song = new Song();
//set name of Genres
song.setAlbum(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Genres.NAME)));
//set id of Genres
song.setGenre(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Genres._ID)));
Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Genres._ID)));
String[] projection = new String[]{MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media._ID};
Cursor cur = c.getContentResolver().query(uri, projection, null, null, null);
//set Number Of songs in Genres
song.setSize("" + cur.getCount());
song.setPlaying(false);
return song;
}
//This methos is use for get availabe song in GENRES
public void getGenresdata(Context c, String genresID) {
//Arraylist for add song songDetails
ArrayList<Song> songslist = new ArrayList<>();
String[] projection = new String[]{
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.AudioColumns.SIZE,
MediaStore.Audio.AudioColumns.DURATION,
MediaStore.Audio.AudioColumns.DATE_ADDED,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ALBUM_ID
};
Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", Long.parseLong(genresID));
Cursor cursor = c.getContentResolver().query(
uri,
projection,
null,
null,
null);
while (cursor.moveToNext()) {
//get data like this and add data in model class
Song song = new Song();
song.setTitle(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)));
//Note: - We use all MediaColumns declare in projection
songslist.add(song);
}
cursor.close();
}
Upvotes: 2
Reputation: 4648
Your do-while loop is likely the cause of the bottleneck. Instead of iterating through sequentially like you are, you could try implementing code to execute the iterations of the loop in parallel.
I'm not sure what sort of data structure the cursor is iterating through, but assuming it's a data structure called allCursors, the code would look something like this:
allCursors.parallelStream().forEach(cursor -> {
// inside of loop
});
Upvotes: 1