解决 Android 7.x 报错 Android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
过去在Android 7.x之前的手机调用拍照直接简单的唤起系统相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.fromFile(sdcardTempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
但是Android N 文件系统权限的变化(Android N == Android 7.x);
为了提高私有文件的安全性,在targetSdk版本为N或者以后版本的app中,其私有目录将会限制访问。这可以防止私有文件元数据的泄露,比如文件大小或者是文件是否存在。但这给开发者带来了很多不利的影响;
如果你的targetSdk版本为N,恭喜你
解决方案:
--- 使用FileProvider 能完美解决 ---
1、在res资源目录下新建一个xml文件夹
2、在xml目录下新建一 file_paths.xml,然后打开xml文件添加如下代码
<?xml version="1.0"encoding="utf-8"?>
<paths>
<external-path name="files_root" path="Android/data/${你的包名}/"/>
<external-path name="external_storage_root" path="."/>
</paths>
3、在AndroidManifest.xml中添加如下代码
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${ 你的包名 }.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
4、修改代码适配Android N,由于Android N对权限管理严格,所以呢要做权限处理
如下代码内容 == 如上图显示:(由于没有格式化功能,所以可以直接复制进IDE 进行格式化跳整)
public voidselectPicFromCamera() {
if(!EaseCommonUtils.isExitsSdcard()) {
showToast("SD卡不存在,不能拍照");
return;
}
if(Build.VERSION.SDK_INT>=23) {
int checkPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
if(checkPermission != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},222);
return;
}else{ openCamera(); } }else{ openCamera(); } }
@Override
public voidonRequestPermissionsResult(intrequestCode, String[] permissions,int[] grantResults) {
switch(requestCode) {
//就像onActivityResult一样这个地方就是判断你是从哪来的。
case 222:
if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openCamera(); }else{ Toast.makeText(this,"很遗憾你把相机权限禁用了。请务必开启相机权限享受我们提供的服务吧。", Toast.LENGTH_SHORT).show(); }
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
} }
//拍照
private voidopenCamera() {
cameraFile=newFile(PathUtil.getInstance().getImagePath(), EMClient.getInstance().getCurrentUser() + System.currentTimeMillis() +".jpg");
cameraFile.getParentFile().mkdirs();
Intent intent =newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
//判断是否是AndroidN以及更高的版本
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID+".fileProvider",cameraFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
}else{ intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile)); } startActivityForResult(intent, Constants.REQUEST_CODE.IMAGE_CAPTURE); }
private void showToast(String c){ Toast.makeText(this,c,Toast.LENGTH_SHORT).show(); }
亲测试完美解决
方法二:使用ContentProvider方式传递uri,