Android Nougat设备调用相机Intent触发FileUriExposedException问题咨询
看起来你已经迈出了配置FileProvider的第一步,但还是踩了坑,大概率是配置细节或者代码处理上有遗漏。我帮你梳理下完整的解决方案,你可以逐一对照检查:
1. 确认Manifest中的FileProvider配置完整
你提到已经添加了FileProvider,但要确保android:name属性正确,且authorities要和后续代码完全匹配。完整配置示例(以AndroidX为例,用旧支持库就换成android.support.v4.content.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/filepaths" /> </provider>
划重点:android:exported必须设为false,grantUriPermissions必须是true,这两个是硬性要求,不能改。
2. 检查filepaths.xml的路径配置
这个文件决定了FileProvider允许访问哪些目录,比如你把图片存到外部存储的公共图片目录,配置应该类似这样:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 外部存储公共图片目录 --> <external-path name="public_pictures" path="Pictures/" /> <!-- 如果是应用私有外部存储目录,用这个 --> <!-- <external-files-path name="private_pictures" path="Pictures/" /> --> </paths>
name可以随便取,path要和你实际保存文件的子目录对应。比如你存文件的路径是Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)/MyApp/photo.jpg,那path写Pictures/MyApp/或者Pictures/都可以,只要能覆盖到目标路径就行。
3. 代码中正确生成Uri并启动相机Intent
核心是区分系统版本处理,并且给Intent授予临时权限:
// 假设你已经创建好要保存图片的File对象,比如photoFile Uri photoUri; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 用FileProvider生成content:// Uri photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile); Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); // 必须添加权限标志,否则相机应用无法访问你的Uri cameraIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA); } else { // 低于N版本直接用file:// Uri photoUri = Uri.fromFile(photoFile); Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA); }
注意:getPackageName() + ".fileprovider"必须和Manifest里的android:authorities完全一致,多一个少一个字符都会出问题。
4. 额外注意事项
- 如果你的targetSdkVersion >=24,必须做这个适配,没有绕开FileProvider的捷径。
- 部分小众第三方相机应用可能对content:// Uri支持不佳,但主流应用都没问题。
- 保存图片的目录要确保有读写权限,Android 10+还要注意分区存储规则,公共目录在Android 11+无需申请
WRITE_EXTERNAL_STORAGE,但旧版本兼容还是要加权限声明。
你可以对照上面的步骤排查,大概率是某个细节没做到位导致的异常~
内容的提问来源于stack exchange,提问作者Shaun F

