Android端MAUI.Audio播放外部存储音频遇System.IO.FileNotFoundException
解决Android平台MAUI.Audio播放外部存储音频的FileNotFoundException问题
1. 错误核心:用错了文件读取API
你当前调用的FileSystem.OpenAppPackageFileAsync是专门读取应用包内置资源的API,完全不适合访问外部存储文件,这就是传外部路径会报找不到文件的根本原因。
2. 正确解决步骤
步骤1:补全权限配置(适配不同Android版本)
你已有的权限配置对Android 12及以下有效,但Android 13+读取音频需要READ_MEDIA_AUDIO权限,在AndroidManifest.xml里补充:
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" android:maxSdkVersion="33" />
保留原有配置:
<application... android:requestLegacyExternalStorage="true" .../> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
步骤2:主动请求运行时权限
MAUI不会自动申请权限,播放前必须检查并请求:
using Microsoft.Maui.ApplicationModel; using Microsoft.Maui.ApplicationModel.Permissions; private async Task<bool> CheckAndRequestPermissions() { PermissionStatus status; if (DeviceInfo.Platform == DevicePlatform.Android) { // 根据Android版本选择对应权限 if (DeviceInfo.Version.Major >= 13) { status = await Permissions.CheckStatusAsync<Permissions.Media>(); } else { status = await Permissions.CheckStatusAsync<Permissions.StorageRead>(); } if (status != PermissionStatus.Granted) { status = await Permissions.RequestAsync(DeviceInfo.Version.Major >=13 ? typeof(Permissions.Media) : typeof(Permissions.StorageRead)); if (status != PermissionStatus.Granted) { // 权限被拒,可在此给用户弹提示 return false; } } } return true; }
步骤3:用正确方式读取外部存储文件
直接用File.OpenRead获取外部文件流,再创建播放器:
public IAudioPlayer? audioPlayer; public async void PlaySong() { // 先确认权限已获取 bool hasPermission = await CheckAndRequestPermissions(); if (!hasPermission) return; string audioPath = "/storage/emulated/0/Music/mymusic.mp3"; // 先判断文件是否存在 if (!File.Exists(audioPath)) { // 文件不存在,提示用户检查路径 return; } if (audioPlayer == null) { using var audioStream = File.OpenRead(audioPath); audioPlayer = AudioManager.Current.CreatePlayer(audioStream); audioPlayer.Play(); } }
3. 额外提醒
- 避免硬编码路径:
/storage/emulated/0/不是所有Android设备的通用外部存储路径,建议用媒体库API获取音乐文件路径,减少适配问题。 - 及时释放资源:播放器不再使用时,调用
audioPlayer.Dispose()释放资源,防止内存泄漏。 - Android 12+适配:
requestLegacyExternalStorage在Android 12及以上失效,若要兼容更高版本,建议使用Scoped Storage或MediaStore API访问文件。
内容的提问来源于stack exchange,提问作者Никита Черепанов
相关产品推荐
相关产品推荐

