如何用Xamarin(Android)获取设备所有音频文件?现有代码无返回数据
问题根因与修复方案
核心问题1:IsMusic字段读取类型错误
MediaStore中IsMusic字段存储的是整型值,值为1代表是音乐文件,0代表非音乐文件。你原代码中用GetString()读取后再用Boolean.Parse()转换,要么会解析失败抛出异常,要么得到错误的判断结果,直接跳过了所有有效条目。
核心问题2:Android 10(API 29)媒体库未收录手动放入的文件
你手动放到模拟器「下载」文件夹的MP3文件,默认不会被系统自动同步到MediaStore媒体库,所以查询时没有对应数据。
核心问题3:分区存储适配问题
API 29引入了分区存储机制,如果你没有开启legacy兼容模式,部分目录的媒体文件查询会受到限制。
修复步骤
- 修正IsMusic的判断逻辑,改用整型读取:
string[] columns = { MediaStore.Audio.Media.InterfaceConsts.IsMusic, MediaStore.Audio.Media.InterfaceConsts.RelativePath, MediaStore.Audio.Media.InterfaceConsts.Title, // 你需要的专辑、歌手字段也可以加在这里 MediaStore.Audio.Media.InterfaceConsts.Album, MediaStore.Audio.Media.InterfaceConsts.Artist }; ICursor cursor = context?.ContentResolver?.Query(MediaStore.Audio.Media.ExternalContentUri, columns, null, null, null); if (cursor is null) { return; } // 先获取列索引,避免循环里重复查找,性能更好也更稳定 int isMusicCol = cursor.GetColumnIndexOrThrow(MediaStore.Audio.Media.InterfaceConsts.IsMusic); int pathCol = cursor.GetColumnIndexOrThrow(MediaStore.Audio.Media.InterfaceConsts.RelativePath); int titleCol = cursor.GetColumnIndexOrThrow(MediaStore.Audio.Media.InterfaceConsts.Title); int albumCol = cursor.GetColumnIndexOrThrow(MediaStore.Audio.Media.InterfaceConsts.Album); int artistCol = cursor.GetColumnIndexOrThrow(MediaStore.Audio.Media.InterfaceConsts.Artist); while (cursor.MoveToNext()) { // 直接读整型判断 if (cursor.GetInt(isMusicCol) != 1) { continue; } string trackPath = cursor.GetString(pathCol); string trackTitle = cursor.GetString(titleCol); string trackAlbum = cursor.GetString(albumCol); string trackArtist = cursor.GetString(artistCol); // 这里存到你的自定义数据结构即可 } cursor.Close();
开启分区存储兼容(API 29专用)
在你的AndroidManifest.xml的<application>节点添加属性:android:requestLegacyExternalStorage="true"
这个属性在API 30+会被忽略,后续如果要适配更高版本可以申请MANAGE_EXTERNAL_STORAGE权限,或者调整存储逻辑。手动触发媒体库扫描(测试用)
你可以调用系统媒体扫描器,把下载目录的文件同步到MediaStore:
// 扫描单个文件示例,替换成你的测试文件路径 MediaScannerConnection.ScanFile(context, new string[] { "/sdcard/Download/test.mp3" }, null, null);
或者你也可以直接在模拟器的自带音乐APP里打开一次你放的MP3,系统就会自动把文件录入媒体库。
排查校验点
- 确认权限是运行时动态申请的,不要只在Manifest里静态声明,Android 6.0以上动态权限申请通过后才能读取媒体库。
- 如果你不需要依赖媒体库的元数据,也可以直接遍历
/sdcard/Download目录读取后缀为.mp3的文件,不过要注意分区存储的权限限制。
内容的提问来源于stack exchange,提问作者Carnagion
相关产品推荐
相关产品推荐

