You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Xamarin(Android)获取设备所有音频文件?现有代码无返回数据

问题根因与修复方案

核心问题1:IsMusic字段读取类型错误

MediaStore中IsMusic字段存储的是整型值,值为1代表是音乐文件,0代表非音乐文件。你原代码中用GetString()读取后再用Boolean.Parse()转换,要么会解析失败抛出异常,要么得到错误的判断结果,直接跳过了所有有效条目。

核心问题2:Android 10(API 29)媒体库未收录手动放入的文件

你手动放到模拟器「下载」文件夹的MP3文件,默认不会被系统自动同步到MediaStore媒体库,所以查询时没有对应数据。

核心问题3:分区存储适配问题

API 29引入了分区存储机制,如果你没有开启legacy兼容模式,部分目录的媒体文件查询会受到限制。


修复步骤
  1. 修正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();
  1. 开启分区存储兼容(API 29专用)
    在你的AndroidManifest.xml的<application>节点添加属性:
    android:requestLegacyExternalStorage="true"
    这个属性在API 30+会被忽略,后续如果要适配更高版本可以申请MANAGE_EXTERNAL_STORAGE权限,或者调整存储逻辑。

  2. 手动触发媒体库扫描(测试用)
    你可以调用系统媒体扫描器,把下载目录的文件同步到MediaStore:

// 扫描单个文件示例,替换成你的测试文件路径
MediaScannerConnection.ScanFile(context, new string[] { "/sdcard/Download/test.mp3" }, null, null);

或者你也可以直接在模拟器的自带音乐APP里打开一次你放的MP3,系统就会自动把文件录入媒体库。


排查校验点
  • 确认权限是运行时动态申请的,不要只在Manifest里静态声明,Android 6.0以上动态权限申请通过后才能读取媒体库。
  • 如果你不需要依赖媒体库的元数据,也可以直接遍历/sdcard/Download目录读取后缀为.mp3的文件,不过要注意分区存储的权限限制。

内容的提问来源于stack exchange,提问作者Carnagion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 05:36:00