Android7.0异常:FileUriExposedException

来源:互联网 发布:怎么在淘宝客上推广 编辑:程序博客网 时间:2024/06/01 09:13

参考:http://www.jianshu.com/p/a1eb3ad79ef6?mType=Group
又遇到android兼容问题,差点哭晕在厕所。。。
错误描述:7.0拍照调用:intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));报异常FileUriExposedException,看了一下各种解释,好头晕。。。

尤其是那个路径,真的不知道怎么配置,后面调试放在源码里才知道配置方式。
记录一下:

方法1

<application ...><provider        android:name="android.support.v4.content.FileProvider"        android:authorities="Authorities名,一般包含包名,例如com.A.B"        android:exported="false"        android:grantUriPermissions="true">        <meta-data            android:name="android.support.FILE_PROVIDER_PATHS"            android:resource="@xml/file_paths"/>    </provider>    <meta-data        android:name="android.support.FILE_PROVIDER_PATHS"        android:resource="@xml/file_paths"/></application>

然后再res文件夹创建文件夹xml,里面放置一个xml,命名为file_paths.xml

<?xml version="1.0" encoding="utf-8"?><paths xmlns:android="http://schemas.android.com/apk/res/android">    <!--注意后面的名字images,等一下有个配置必须和这个一致,否则报错-->    <files-path name="my_images" path="images"/></paths>

拍照方法:

private void takePhoto() {        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);        if (takePictureIntent.resolveActivity(getPackageManager())!=null){            //这里必须和前面的images一致,这两个是相同的            //源码逻辑会将这里的路径和前面xml配置的路径尝试匹配            //即tempFile的路径必须以前面配置的路径中至少一个匹配            File imagePath = new File(getFilesDir(),"images");            tempFile = new File(imagePath, System.currentTimeMillis() + ".jpg");                FileUtils.createFile(tempFile);            if (tempFile!=null){                Uri photoURI = FileProvider.getUriForFile(this,"Authorities名,一般包含包名,例如com.A.B,和前面provider中配置相同",tempFile);                List<ResolveInfo> resInfoList= getPackageManager().queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);                for (ResolveInfo resolveInfo : resInfoList) {                    String packageName = resolveInfo.activityInfo.packageName;                    grantUriPermission(packageName, photoURI,                            Intent.FLAG_GRANT_WRITE_URI_PERMISSION);                }                if(AppUtil.getApiVersion()>=24){                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,photoURI);                }else{                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));                }             takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION);                this.startActivityForResult(takePictureIntent, TAKE_PICTURE);            }        }    }

这里有两个地方要求一致性
(1)manifest的provider中android:authorities=”此处”
和 Uri photoURI = FileProvider.getUriForFile(this,”此处”,tempFile);
“此处”的替换字符串必须相同
(2)file_paths.xml中配置的路径和File imagePath = new File(getFilesDir(),”images”);中imagePath的路径必须相同,这里有个转换问题,直接参看上面的参考url了:

<files-path name="name" path="path" />Context.getFilesDir()<cache-path name="name" path="path" />Context.getCacheDir()<external-path name="name" path="path" />Environment.getExternalStorageDirectory()<external-files-path name="name" path="path" />Context#getExternalFilesDir(String) Context.getExternalFilesDir(null).<external-cache-path name="name" path="path" />Context.getExternalCacheDir()

这里是说,file-path.xml中配置的路径例如第一条

<file-path name="my_img" path="path"/>

意思就是

File file = new File(getFilesDir(),path);String path = file.getAbsolutePath();

总之是getXXDir()+path,如果需要加分割“/”则添加
这样一个路径。

方法2

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();            StrictMode.setVmPolicy(builder.build());        }

方法3

改低targetVersion为25以下的任何版本

总结:方法二方法三虽然更容易,但是毕竟不是最终解决办法,存在隐患,当然读者如果急着改,可以先用,事后再改为1的方式。
方法2:哪天谷歌看你不爽不开放这个方法了,你咋办?呵呵。不过目前来看,这是一个好且简便方法。
方法3:难道targetVersion每个版本出兼容问题都往低了改么?如果不是开发库如此且非开源或不能改进,那还ok,否则尽量别这样写,宁可多改bug,现在更新太快,如果跟不上,以后要补充的东西可能很多。

阅读全文
0 0
原创粉丝点击