加载 MediaStore.Audio.Media.DATA 不适用于 android 10 及以上?

Loading MediaStore.Audio.Media.DATA not working for android 10 and above?

所以我正在制作这个应用程序,我正在其中获取设备的所有音频文件。

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

接下来我必须在任何片段中加载歌曲的所有细节,这很好。但是我无法加载歌曲的封面照片。

这是一个适配器的代码,需要通过封面照片显示最近的曲目。

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

这是 getAlbumCover 方法的代码。

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
    }

现在我可以确定的是,所有音频文件都已正确提取并存储在数据库中。 但是当我尝试从音频文件的 url 加载图像时,我抛出了这个异常。我附上了各个日志消息的屏幕截图。

根据日志消息,我假设是 setDataSource(url) 抛出 illegalArgumentException(如其文档中所述)here.

现在我不知道如何解决这个问题。我试过这个:

url.replace("\","\\"")

没有成功。请建议我该怎么办? 还有别的办法吗?或者这个错误是可以解决的?

编辑:问题标题已更新,问题已得到解答。请参考已接受的答案。

问题是使用了已弃用的方法来获取 url。它现在可以正常工作到 android 9。

val url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))

要定位更高版本,请使用:

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)