Xamarin中如何从外部SD卡的URI获取文件路径?
嘿,我懂你现在的困境——刚上手Xamarin Android,本来用ActionOpenDocumentTree选了保存路径,结果返回的URI里存储卷是12FB-3215(SD卡的UUID)而不是内置存储的primary,原来的文件选择器代码没处理这种情况,直接卡壳了对吧?别慌,我给你梳理几个解决思路:
处理Xamarin Android中非Primary存储的DocumentTree URI
首先得明白这个URI的结构:content://com.android.externalstorage.documents/tree/12FB-3215%3ATest 里的12FB-3215是外部SD卡的唯一标识符(UUID),%3ATest是转义后的文件夹路径(冒号+Test文件夹),和内置存储的primary是不同的存储卷标识。
1. 适配UUID类型的存储卷判断
原来的代码大概率只判断了type == "primary",现在把UUID的情况也加进去就行:
// 解析返回的Tree URI var selectedTreeUri = Android.Net.Uri.Parse("content://com.android.externalstorage.documents/tree/12FB-3215%3ATest"); var docId = DocumentsContract.GetTreeDocumentId(selectedTreeUri); // 拆分出存储卷类型和相对路径 var splitParts = docId.Split(new[] { ':' }, 2); var storageType = splitParts[0]; var folderRelativePath = splitParts[1]; string storageRootPath = string.Empty; // 处理内置存储 if (storageType.Equals("primary", StringComparison.OrdinalIgnoreCase)) { storageRootPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath; } // 处理SD卡UUID的情况 else { var allStorageVolumes = Android.OS.Environment.GetExternalStorageVolumes(); foreach (var volume in allStorageVolumes) { if (volume.Uuid?.Equals(storageType, StringComparison.OrdinalIgnoreCase) == true) { storageRootPath = volume.Directory?.AbsolutePath; break; } } } // 拼接成完整的物理路径 var fullFolderPath = Path.Combine(storageRootPath, folderRelativePath);
2. 权限与更安全的文件操作方式
在Android 10及以上的分区存储模式下,直接拿物理路径可能会遇到访问权限问题,更推荐用SAF自带的DocumentFile来操作文件,不需要纠结物理路径:
// 从Tree URI获取可操作的DocumentFile var targetDirectory = DocumentFile.FromTreeUri(this, selectedTreeUri); if (targetDirectory != null && targetDirectory.IsDirectory) { // 比如在选中的目录下创建一个测试文本文件 var newTestFile = targetDirectory.CreateFile("text/plain", "MyTestFile.txt"); // 写入内容 using (var outputStream = ContentResolver.OpenOutputStream(newTestFile.Uri)) using (var streamWriter = new StreamWriter(outputStream)) { streamWriter.WriteLine("这是通过SAF写入的测试内容"); } }
这种方式不需要申请传统的WRITE_EXTERNAL_STORAGE权限,完全符合系统的权限规范,兼容性也更强。
3. 额外提示
如果你的应用需要兼容Android 9及以下版本,记得在AndroidManifest.xml中添加对应的存储权限,并且动态申请:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
内容的提问来源于stack exchange,提问作者Large
相关产品推荐
相关产品推荐

