如何在Android设备上查找m4b文件以用于ExoPlayer播放
查找m4b文件的最佳方案
核心问题原因
Android 的MediaStore.Audio.Media.IS_MUSIC字段是基于文件是否包含音乐类元数据(如专辑、艺术家标签)判定的,而 m4b 作为有声书格式,通常没有这类元数据,因此会被过滤掉。直接用扩展名筛选不够灵活,最佳方式是通过MIME类型结合音频属性来查询,同时覆盖常规音频和 m4b 文件。
方案一:扩展MediaStore.Audio查询范围
不需要切换到 MediaStore.Files,只需在MediaStore.Audio的查询中补充 m4b 对应的 MIME 类型条件,同时保留对常规音频的支持:
val projection = arrayOf( MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.MIME_TYPE ) // 筛选条件:包含常规音频(IS_MUSIC=1) 或者 MIME类型为audio/m4b val selection = "${MediaStore.Audio.Media.IS_MUSIC} = ? OR ${MediaStore.Audio.Media.MIME_TYPE} = ?" val selectionArgs = arrayOf("1", "audio/m4b") val cursor = contentResolver.query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null )
这种方式既可以拿到系统识别为音乐的文件,也能捕获所有 m4b 格式的有声书文件,避免遗漏。
方案二:基于MediaStore.Files的通用音频查询
如果需要覆盖所有音频类型(包括系统未归类的格式),可以用MediaStore.Files,但通过 MIME 类型而非扩展名筛选,更可靠:
val projection = arrayOf( MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DISPLAY_NAME, MediaStore.Files.FileColumns.DATA, MediaStore.Files.FileColumns.MIME_TYPE ) // 筛选所有音频类型(MIME以audio/开头) val selection = "${MediaStore.Files.FileColumns.MIME_TYPE} LIKE ?" val selectionArgs = arrayOf("audio/%") val cursor = contentResolver.query( MediaStore.Files.getContentUri("external"), projection, selection, selectionArgs, null )
这个查询会返回所有 MIME 类型为 audio 开头的文件,自然包含 m4b(audio/m4b),同时也覆盖 mp3、flac 等常规音频格式,不需要硬编码任何扩展名。
注意事项
- 权限:Android 12 及以下需要申请
READ_EXTERNAL_STORAGE权限;Android 13 及以上需申请READ_MEDIA_AUDIO权限。 - 元数据补充:如果希望 m4b 文件被
IS_MUSIC识别,可以给文件添加音乐类元数据(如通过第三方标签编辑工具),但这不是必要操作。
内容的提问来源于stack exchange,提问作者Alejandro Gomez
相关产品推荐
相关产品推荐

