多模块调起系统相机Intent触发FileProvider权限报错问题排查
Android 多模块项目系统相机调用的FileProvider权限冲突解决
问题场景
- 项目结构分为两个模块:
:app基础主模块、:camera独立功能模块 - camera模块通过
MediaStore.ACTION_IMAGE_CAPTURE动作调用系统原生相机完成拍照流程 - 运行时直接抛出权限错误:
UID 10388 does not have permission to content://com.example.android.provider/attachment_file/Android/media/com.example.android.dev/some_name.jpg [user 0] - 目前app模块的FileProvider节点配置如下:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_path" /> </provider>
- 临时验证结果:把FileProvider的authority直接硬编码成
com.example.android.provider,相机功能就能正常跑,但设备上已经装了其他同签名的构建变体应用,两个应用的FileProvider authority重了,新的应用根本装不上去。
问题本质
两边的配置没对上,完全是硬编码埋的坑:
camera模块在生成拍照输出的FileProvider Uri时,代码里直接写死了authority值为com.example.android.provider,根本没跟着app模块Manifest里的动态规则走:
- 当app模块的FileProvider authority和camera模块代码里写死的值不一致时,camera生成的Uri根本不属于当前app的FileProvider管理范围,系统相机拿到这个Uri自然没有访问权限,直接抛错
- 把app模块的authority改成和写死值一致,功能是通了,但固定写死的authority没法适配不同applicationId的构建变体,同设备上多个同签名应用用同一个authority,必然触发安装冲突
解决步骤
- 删掉camera模块里所有硬编码的authority字符串
把原来调用FileProvider.getUriForFile()时传的固定值com.example.android.provider,换成动态拼接的规则:${context.packageName}.provider,和app模块Manifest里配置的authority规则完全对齐。
错误写法参考:
// 直接写死authority,和当前app实际配置不匹配 val outputUri = FileProvider.getUriForFile(context, "com.example.android.provider", outputFile)
正确写法参考:
// 动态读取当前应用的包名拼接,和Manifest配置完全一致 val authority = "${context.packageName}.provider" val outputUri = FileProvider.getUriForFile(context, authority, outputFile)
- 启动相机Intent时补充Uri临时权限授予
不要依赖系统自动授予权限,显式给接收Intent的系统相机应用加上目标Uri的读、写临时权限,避免跨应用访问被拦截:
val captureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply { putExtra(MediaStore.EXTRA_OUTPUT, outputUri) addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) }
- 全流程验证多构建变体兼容性
分别打不同applicationId的安装包(比如dev版本包名com.example.android.dev、正式版本包名com.example.android),每个版本的FileProvider authority都会自动变成<对应包名>.provider,既不会出现同设备上的authority重复冲突,也能保证camera模块生成的Uri和当前应用的FileProvider完全匹配,不会再触发权限报错。
注意事项
- 不要图省事给FileProvider设置
android:exported="true",会导致应用私有存储的文件能被任意外部应用访问,带来严重安全风险 - 不要在多模块项目里把FileProvider的authority硬编码为固定字符串,必须配合
${applicationId}占位符适配不同构建变体
内容的提问来源于stack exchange,提问作者RusyaMed
相关产品推荐
相关产品推荐

