MAUI FilePicker在Android平台返回缓存文件地址问题咨询
解决MAUI FilePicker在Android返回缓存路径的问题
问题原因
在Android平台上,由于**分区存储(Scoped Storage)**的限制,应用无法直接访问其他应用或公共存储中的原始文件。MAUI的FilePicker为了让应用能正常读取选中的文件,会自动将用户选择的文件复制到应用的私有缓存目录,然后返回这个副本的路径。这是Android平台权限机制导致的设计行为,并非Bug。
解决方案
方案1:通过OpenReadAsync()读取文件内容(推荐)
无需依赖文件路径,直接使用FileResult提供的OpenReadAsync()方法获取文件流,这种方式跨平台兼容,能避开路径相关的权限问题:
private async void bExecute_Clicked(object sender, EventArgs e) { FilePickerFileType customFileType = new FilePickerFileType( new Dictionary<DevicePlatform, IEnumerable<string>> { { DevicePlatform.iOS, new[] { "public.audio" } }, { DevicePlatform.Android, new[] { "audio/*" } }, { DevicePlatform.WinUI, new[] { ".mp3", ".wav", ".wma", ".m4a", ".flac" } }, { DevicePlatform.Tizen, new[] { "*/*" } }, { DevicePlatform.macOS, new[] { ".mp3", ".wav", ".wma", ".m4a", ".flac" } }, }); PickOptions options = new() { PickerTitle = "Please select audio file's", FileTypes = customFileType }; var fileResult = await FilePicker.Default.PickMultipleAsync(options); foreach (FileResult file in fileResult) { // 通过OpenReadAsync获取文件流 using var stream = await file.OpenReadAsync(); // 将流传入TagLib处理 var tfile = TagLib.File.Create(new TagLib.StreamFileAbstraction(file.FileName, stream, null)); // 后续业务逻辑... } }
方案2:获取原始文件的Uri(针对必须使用原路径的场景)
如果确实需要获取原始文件的Uri而非缓存副本,可通过自定义Android平台代码,利用存储访问框架(SAF)实现:
- 在Android项目中调用
ACTION_OPEN_DOCUMENT意图唤起文件选择器 - 处理返回的Uri,通过
ContentResolver操作文件(Android 10+无法直接获取真实文件路径,只能通过Uri操作)
示例简化代码(Android项目内):
// 在MainActivity中添加方法 public async Task<List<string>> PickAudioFilesAsync() { var intent = new Intent(Intent.ActionOpenDocument); intent.AddCategory(Intent.CategoryOpenable); intent.SetType("audio/*"); intent.PutExtra(Intent.ExtraAllowMultiple, true); var result = await StartActivityForResultAsync(intent, 100); var uris = new List<string>(); if (result.ResultCode == Result.Ok && result.Data != null) { if (result.Data.ClipData != null) { for (int i = 0; i < result.Data.ClipData.ItemCount; i++) { uris.Add(result.Data.ClipData.GetItemAt(i).Uri.ToString()); } } else if (result.Data.Data != null) { uris.Add(result.Data.Data.ToString()); } } return uris; }
之后在MAUI共享代码中通过依赖服务调用该方法,再通过ContentResolver处理Uri对应的文件。
注意事项
- 避免直接依赖
FullPath属性,在Android、iOS平台该属性可能指向非原始文件路径,或存在访问权限限制 - 跨平台开发优先使用
OpenReadAsync()等FileResult提供的抽象方法,保障代码兼容性
内容的提问来源于stack exchange,提问作者Alireza Mirabedini
相关产品推荐
相关产品推荐

