Xamarin Android从SD卡导入文件报错,求当前适用的新语法
Xamarin Android SD卡文件导入问题解决指南
核心问题分析
你当前的代码存在两个关键问题:
- 硬编码路径
/storage/emulated/0/LumberData/export-icsep.txt兼容性差,不同设备外部存储路径可能存在差异,且Android 10(API 29)及以上版本的Scoped Storage机制限制了直接访问根目录的权限。 - 未正确适配Android新的存储权限规则,导致即便文件存在也无法被应用检测到。
解决方案
方案一:使用存储访问框架(SAF,推荐适配Android 10+)
SAF是Android官方推荐的文件访问方式,无需硬编码路径,由用户主动选择文件,规避权限限制:
- 启动文件选择器
// 启动选择txt文件的意图 var pickFileIntent = new Intent(Intent.ActionOpenDocument); pickFileIntent.AddCategory(Intent.CategoryOpenable); pickFileIntent.SetType("text/plain"); StartActivityForResult(pickFileIntent, 100); // 100为请求码,自定义即可
- 处理选择结果
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); if (requestCode == 100 && resultCode == Result.Ok && data != null) { var fileUri = data.Data; // 通过ContentResolver读取文件内容 using (var stream = ContentResolver.OpenInputStream(fileUri)) using (var reader = new StreamReader(stream)) { string fileContent = reader.ReadToEnd(); // 在这里处理读取到的文件内容 } } }
方案二:临时兼容旧存储机制(仅适用于过渡阶段)
如果暂时不想迁移到SAF,可通过以下方式兼容Android 10+:
- 在
AndroidManifest.xml的<application>标签中添加遗留存储权限声明:
android:requestLegacyExternalStorage="true"
- 正确构建存储路径,避免硬编码:
// 拼接合法的自定义目录路径 string lumberDir = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "LumberData"); string importFile = Path.Combine(lumberDir, "export-icsep.txt"); // 先检查目录是否存在 if (!Directory.Exists(lumberDir)) { ShowErrorDialog("LumberData目录不存在", null); return; } // 再检查文件是否存在 if (!System.IO.File.Exists(importFile)) { ShowErrorDialog("导入文件未找到,请联系管理员", null); return; } // 读取文件内容 string fileContent = System.IO.File.ReadAllText(importFile);
注意:该方案在Android 11及以上版本会被逐步限制,最终仍需迁移至SAF。
调试注意事项
- 确认目标文件确实存在于设备对应路径中,可通过设备自带的文件管理器查看。
- Android 10以下版本需在
AndroidManifest.xml中添加<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />,并在运行时主动请求存储权限。
内容的提问来源于stack exchange,提问作者Mr.E
相关产品推荐
相关产品推荐

