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

MAUI Android应用打开Downloads目录文件时触发Android.OS.FileUriExposedException异常的问题求助

MAUI Android应用打开Downloads目录文件时触发Android.OS.FileUriExposedException异常的问题求助

嗨,我来帮你搞定这个头疼的问题!这个FileUriExposedException是Android 7.0(API 24)及以上版本的安全限制导致的——直接用file://格式的Uri分享文件/文件夹会被系统拦截,因为这种方式会暴露文件的绝对路径,存在安全风险。下面给你几个可行的解决方案,优先推荐第一种官方合规的方式:

方案一:使用FileProvider生成Content Uri(推荐)

这是Android官方推荐的安全方式,通过FileProvider把文件路径转换成content://格式的Uri,避免直接暴露文件路径。

步骤1:在AndroidManifest.xml中配置FileProvider

打开Platforms/Android/AndroidManifest.xml,在<application>标签内部添加以下FileProvider配置:

<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/file_paths" />
</provider>

注意:${applicationId}会自动替换成你的应用包名,不用手动修改。

步骤2:创建file_paths.xml配置文件

在Platforms/Android/Resources目录下新建一个xml文件夹(如果没有的话),然后在里面创建file_paths.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 配置允许访问公共Downloads目录 -->
    <external-path name="downloads" path="Download/" />
</paths>

这个配置是告诉FileProvider,你的应用可以访问设备公共Downloads目录下的内容。

步骤3:修改MAUI代码生成合规的Uri

把你原来的Uri生成和打开逻辑替换成以下代码(仅针对Android平台做修改,Windows逻辑保持不变):

#if ANDROID
string dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
string folderName = rework.ServiceOrder.ServiceOrderNo;
string folderPath = Path.Combine(dir, folderName);

Java.IO.File targetFolder = new Java.IO.File(folderPath);

// 使用FileProvider生成Content格式的Uri
Android.Net.Uri contentUri = AndroidX.Core.Content.FileProvider.GetUriForFile(
    Android.App.Application.Context,
    Android.App.Application.Context.PackageName + ".fileprovider",
    targetFolder);

// 创建打开文件夹的Intent,并授予临时读取权限
Intent openFolderIntent = new Intent(Intent.ActionView);
// 针对文件夹的MIME类型,部分设备可能需要调整为"*/*"
openFolderIntent.SetDataAndType(contentUri, "resource/folder");
// 授予临时权限给目标应用(比如文件管理器)
openFolderIntent.AddFlags(Android.Content.ActivityFlags.GrantReadUriPermission);
openFolderIntent.AddFlags(Android.Content.ActivityFlags.NewTask);

// 启动Intent打开文件夹
Android.App.Application.Context.StartActivity(openFolderIntent);
#else
// Windows平台原有逻辑保持不变
string dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads");
string folderName = rework.ServiceOrder.ServiceOrderNo;
string folderPath = Path.Combine(dir, folderName);
var uri = new Uri(folderPath).AbsoluteUri;
await Launcher.Default.OpenAsync(uri);
#endif

如果是打开单个文件而非文件夹,只需要把"resource/folder"改成对应文件的MIME类型(比如PDF文件用"application/pdf",图片用"image/*")即可。

方案二:临时降低目标SDK版本(不推荐)

如果只是临时测试,可以把Android的目标SDK版本降到23以下(Android 6.0及以下),这样系统不会触发FileUriExposedException。但这只是权宜之计,不符合现代Android的安全规范,绝对不建议用于正式发布的应用。

补充说明

  • 你之前添加的WRITE_EXTERNAL_STORAGE和MANAGE_EXTERNAL_STORAGE权限,在Android 10及以上版本,访问公共Downloads目录其实不需要这些权限(因为Downloads是系统开放的公共目录),如果你的应用不需要访问其他私有目录,可以考虑移除这些权限。
  • 不要再用Launcher.Default.OpenAsync直接打开file://格式的Uri,在Android 7+版本上必然会触发异常,改用FileProvider的方式才是长期可行的解决方案。

备注:内容来源于stack exchange,提问作者Dragon Slayer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 10:29:30