RK3588解决无法音乐/相册等无法同步问题

发布时间 2023-11-14 20:15:47作者: ZJHqs

RK3588解决无法音乐/相册等无法同步问题

 

背景

 

最近在做一个项目的时候发现音乐APP无法自动识别设备中的音频,这个APP是芯片厂商写的,可能由于年代久远,有这种奇怪的bug。复现步骤如下:1、使用adb push音频文件到/sdcard/Music/文件夹下或使用文件管理器从外部设备(如U盘)将音频文件复制到/sdcard/Music/文件夹中。2、打开音乐APP,发现找不到任何音频文件。

 

神奇的是,它可以识别到U盘内的音频文件,如果复制到/sdcard/Music/文件夹后重启,重启后又可以查找到/sdcard/Music/中的音频文件了。我一开始以为是APP初始化时会去扫描,因此将该APP进程kill掉,再启动发现依旧查找不到任何音频文件,这就说明是重启时有我不知道的地方帮我做了同步的功能。因此写了一个简易的demo来进行测试。

 

排查过程

 

先看一下是如何查询系统中的音乐文件的。下面是我写的一个方法,与源码方法基本一样,其中Music是一个data class

 

查询音乐代码

 

fun initMusicList(context: Context): List<Music> {
        val musicList = ArrayList<Music>()
        val cols = arrayOf(
            MediaStore.Audio.Media.DISPLAY_NAME,
            MediaStore.Audio.Media.ALBUM,
            MediaStore.Audio.Media.DURATION
        )
        val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI

        val cursor = context.contentResolver.query(
            uri,
            cols,
            null,
            null,
            MediaStore.Audio.Media.DEFAULT_SORT_ORDER
        )

        if (cursor != null && cursor.moveToFirst()) {
            do {
                val music = Music(
                    cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)),
                    cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ALBUM)),
                    cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION))
                )
                musicList.add(music)
            } while (cursor.moveToNext())
            cursor.close()
        }

        return musicList
    }

 

我用了一个简易的RecyclerView用于展示读取到的信息,/sdcard/Music/中的文件内容与RecyclerView所得到的内容如下

 

 

现在一切正常,是吧。那让我们添加一个音乐到/sdcard/Music/文件夹下看看会怎么样:

 

可以看到我已经把我们的app给kill掉了

神奇的事情来了:重新打开APP后,它依旧只有三首歌,这说明我们新添加的3.wma这首歌没有被识别到MediaStore.Audio.Media.EXTERNAL_CONTENT_URI路径中。

 

这时候我们只需要执行以下命令就可以了:

adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/Music/

不难理解,这就是一个让设备在我们所指定的文件夹/sdcard/Music/下查找媒体文件的命令,这里的/sdcard/Music/可以根据实际需要进行改变。这样我们就能把刚添加的音频文件“刷新” 到媒体库了。那么如何在代码中使用呢?可以参考下面的方法:

Java版本

private void syncMusic(Context context) {
    String path = Environment.getExternalStorageDirectory().getPath() +
            File.separator + "Music";
    context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
            Uri.fromFile(new File(path))));
}

Kotlin版本

private fun syncMusic(context: Context) {
        val path = Environment.getExternalStorageDirectory().path + File.separator + "Music"
        context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(File(path))))
    }

 

在你的Activity、Fragment等有context的地方调用,但是需要注意的是,这是一个耗时方法,因此我们最好是开一个工作线程去执行它。