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

Xamarin Android 如何调用系统文件管理器打开共享存储指定文件夹

你当前的实现方向是对的,出现的问题都是配置和代码细节错误,按以下步骤修复即可覆盖API 21-30的需求:

第一步 修复provider_paths资源找不到报错

  • 确认provider_paths.xml存放路径:在你的Xamarin.Android项目的Resources/xml目录下,若xml文件夹不存在请手动创建
  • 右键点击provider_paths.xml选择【属性】,将【生成操作】设置为AndroidResource,【自定义工具】项留空
  • 确认文件名全小写、无拼写错误,Android资源对大小写敏感,任何拼写或大小写错误都会导致资源找不到

第二步 修正FileProvider权限配置不匹配问题

你当前代码中FileProvider.GetUriForFile传入的授权名是Application.Context.PackageName + ".fileprovider",但Manifest中配置的android:authorities值为com.vtbuild17.demoapp.provider,两者必须完全一致才能正常工作,推荐按如下方式修正:
修改Manifest中provider节点的authorities属性,使用包名占位符避免后续包名变更导致不匹配:

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

provider_paths.xml现有内容无需修改,已经可以覆盖公共存储目录的访问需求。

第三步 修正打开文件夹的业务代码

原有代码存在两个问题:一是两次调用SetFlags会覆盖之前的Flag配置,二是resource/folder不是通用MIME类型,多数第三方文件管理器不识别,修正后代码如下:

// 先确保已经获取读写外部存储的运行时权限,API 23+需要动态申请
string location = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDocuments).AbsolutePath;
if (location.Contains("/Android")) {
    location = location.Split("/Android")[0];
}
location += "/Exports container";
if (!Directory.Exists(location)) {
    Directory.CreateDirectory(location);
}

Intent intent = new Intent(Intent.ActionView);
Java.IO.File folder = new Java.IO.File(location);
var contentURI = FileProvider.GetUriForFile(Application.Context, Application.Context.PackageName + ".fileprovider", folder);

// 适配不同文件管理器的MIME类型
intent.SetDataAndType(contentURI, DocumentsContract.Document.MimeTypeDir);
// 叠加Flag,不要用SetFlags覆盖
intent.AddFlags(ActivityFlags.NewTask);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
intent.AddFlags(ActivityFlags.GrantWriteUriPermission);

// 先判断是否有可处理该Intent的应用,避免崩溃
if (intent.ResolveActivity(PackageManager) != null) {
    StartActivity(intent);
} else {
    // 兜底方案:调用通用文件浏览Intent
    Intent fallbackIntent = new Intent(Intent.ActionGetContent);
    fallbackIntent.SetDataAndType(contentURI, "*/*");
    fallbackIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
    if (fallbackIntent.ResolveActivity(PackageManager) != null) {
        StartActivity(fallbackIntent);
    } else {
        Toast.MakeText(Application.Context, "未找到可用的文件管理器", ToastLength.Long).Show();
    }
}

补充适配注意事项

  • API 23及以上版本需要先动态申请READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE权限,权限获取成功后再调用上述打开文件夹的逻辑
  • 若后续升级到API 31及以上,只需将目标SDK版本对应升级,现有逻辑无需修改即可兼容
  • 部分国产ROM对文件管理器Intent做了定制,若出现无法定位到指定文件夹的情况,可以在生成路径时避免路径中包含空格,比如将Exports container改为ExportsContainer,兼容性更好

内容的提问来源于stack exchange,提问作者Alex A.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:24:01