So I am making this app, in which I am fetching all audio files of the device.
private fun getAudioFiles() {
val songs = mutableListOf<SongEntity>()
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
// IS_MUSIC : Non-zero if the audio file is music
val selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0"
// Sort the musics
val sortOrder = MediaStore.Audio.Media.TITLE + " ASC"
//val sortOrder = MediaStore.Audio.Media.TITLE + " DESC
val contentResolver1 = ContextWrapper(applicationContext).contentResolver
val cursor = contentResolver1!!.query(
uri,
null,
selection,
null,
sortOrder
)
//looping through all rows and adding to list
if (cursor != null && cursor.moveToFirst()) {
do {
val songName = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE))
val artistName =
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST))
val duration =
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION))
val url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))//.replace("\","\\\"")
//val url = File(resolver.openFileDescriptor(uri, "r"))
val songEntity =
SongEntity(songs.size + 1, songName, artistName, parseLong(duration), url, -1)
Log.i("FetchCheck", songEntity.toString())
songs.add(songEntity)
//insert song one by one
//WORKING!!!
//mAllSongsViewModel.insertSong(songEntity)
} while (cursor.moveToNext())
}
//TODO - To send songs list to DB
//TODO set shared preferences for isLoaded
//fetch and initialize db with all songs at once
//WORKING!!! TO INSERT MULTIPLE SONGS AT ONCE
mAllSongsViewModel.insertSongs(songs)
//finally set shared pref
sharedPreferences.edit().putBoolean("songLoaded", true).apply()
}
Next I have to load all the details of song in any fragment which is fine. But I am unable to load cover photo for songs.
This is code of an adapter which needs to show recent tracks by their cover photos.
override fun onBindViewHolder(holder: RecentTrackViewHolder, position: Int) {
if (songs != null) {
val image=getAlbumCover(songs!![position].albumCover)
if (image != null) {
holder.imgSingleRecentTrack.setImageBitmap(BitmapFactory.decodeByteArray(image,0,image.size))
}
else{
holder.imgSingleRecentTrack.setImageResource(R.drawable.drawable_cover)
}
}
This is getAlbumCover method's code.
private fun getAlbumCover(url:String?): ByteArray? {
if(url==null)
return null
val mmr = MediaMetadataRetriever()
try {
mmr.setDataSource(url);
Log.e("IMAGE","path OBTAINED for this song")
return mmr.getEmbeddedPicture();
}
catch(e:Exception) {
Log.e("IMAGE", e.message+e.stackTrace.toString()+"for path "+url)
return null
}
Now which I can ascertain is that all audio files are fetched properly and stored in database too. But when I try to load image from url of the audio file, I get this exception thrown. I have attached screenshots of respective log messages.
According to log messages, I am assuming, it is setDataSource(url) which is throwing illegalArgumentException (as mentioned in it's documentation) here.
Now I don't know how to resolve this. I have tried this :
url.replace("\","\\\"")
Did not work. Please suggest me what should I do? Is there any other way? Or this error is solvable?
EDIT: Question title has been updated and question has been answered. Please refer to accepted answer.
Problem was use of deprecated method for fetching url. It will work fine upto android 9 right now.
val url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))
To target higher version, use this:
val albumArtColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)
val durationColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)
val artistColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)
val titleColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)
val idColumn = cursor.getColumnIndex(MediaStore.Audio.Media._ID)