Android file_paths.xml配置 FileProvider文件共享XML设置

1次阅读

fileprovider 的 file_paths.xml 必须置于 res/xml/ 目录下且命名严格匹配 android:Resource 引用;android 10+ 需用 替代 以规避分区存储限制,路径匹配基于前缀且须用正斜杠。

Android file_paths.xml配置 FileProvider文件共享XML设置

FileProvider 的 file_paths.xml 必须放在 res/xml/ 下,且文件名要完全匹配 android:resource 引用

Android 构建系统不会自动识别任意路径下的 XML 文件。如果你把 file_paths.xml 放在 assets/raw/ 或根 res/ 下,FileProvider 启动时会直接抛 IllegalArgumentException: Missing android:resource Attribute 或更隐蔽的 NULLPointerException(因找不到资源 ID)。

  • res/xml/file_paths.xml 是唯一被 AndroidManifest 中 @xml/file_paths 正确解析的位置
  • 文件名必须小写、无空格、不带扩展名以外的点(比如 file_paths_v2.xml 不行)
  • 如果改了名字,Manifest 里 android:resource="@xml/xxx"xxx 必须同步更新

<external-files-path></external-files-path><external-path></external-path> 的区别决定你能否在 Android 10+ 上正常分享文件

Android 10(API 29)起强制启用分区存储(Scoped Storage),<external-path></external-path> 指向整个外部存储根目录(如 /sdcard/),即使你声明了 READ_EXTERNAL_STORAGEFileProvider 也会拒绝解析该路径下的 URI —— 表现为 SecurityException: Permission Denial

  • 想共享 App 自己创建的文件(如下载到 getExternalFilesDir() 的 PDF),用 <external-files-path></external-files-path>,它不受分区存储限制
  • 想共享公共目录(如 DCIM/Camera/)里的文件?别用 FileProvider 直接暴露路径 —— 改用 MediaStore 插入后获取 content:// URI
  • <files-path></files-path> 对应 getFilesDir(),纯内部路径,无需权限,但其他 App 默认无法访问(除非 android:grantUriPermissions="true" + Intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

path 属性值不是真实路径,而是“路径前缀匹配规则”,末尾斜杠影响匹配结果

<external-files-path path="images/" name="my_images"></external-files-path> 并不表示只允许 images/ 这个文件夹 —— 它实际匹配所有以 images/ 开头的子路径,比如 images/avatar.jpgimages/cache/temp.png 都可以;但 images.jpg(无斜杠)或 my_images/ 就不匹配。

  • 如果写成 path=""(空字符串),则匹配该目录下所有文件和子目录
  • 如果写成 path=".",反而不生效 —— FileProvider 内部会忽略当前目录符号
  • windows 开发者注意:path 值必须用正斜杠 /,不能用反斜杠 ,否则运行时报 XmlPullParserException

targetSdkVersion ≥ 30 时,android:requestLegacyExternalStorage="true"FileProvider 无效

这个 flag 只影响 getExternalStorageDirectory() 等传统 API 的行为,不影响 FileProvider 的 XML 路径解析逻辑。很多开发者误以为加了它就能继续用 <external-path></external-path>,结果在 Android 11 设备上点击分享直接崩溃。

  • 真要兼容旧路径逻辑?只能降 targetSdkVersion 到 29(不推荐)
  • 更稳妥的做法:把待分享文件先拷贝到 getExternalFilesDir(),再用 <external-files-path></external-files-path> 暴露
  • 别忘了在 AndroidManifest.xmlFileProvider <meta-data></meta-data> 中指定正确的 android:resource,拼错一个字母就白配

最常被跳过的一步是:生成 URI 时没检查 File 对象是否为 null 或路径是否真实存在 —— FileProvider.getUriForFile() 遇到非法 File 会直接抛 IllegalArgumentException,而不是返回 null。

text=ZqhQzanResources