最近在应用中开发调用系统相机拍照的时候,遇到一个问题,就是在安卓7.0及以上机型使用,按照往常写法Uri.fromFile(imgFile)回抛出异常FileUriExposedException导致程序崩溃。通过上网查看知道了安卓7.0及以上的特殊问题。因此整理了其他的人的处理方法,我也根据自身的项目需要进行了整改,特此奉上,供学习交流!
1.在清单文件里添加provider如下:
...>
"android.support.v4.content.FileProvider"
android:authorities="包名.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
"android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
2.在res目录下新建xml文件夹,并新建一个file_paths.xml文件,内容如下
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
paths>
具体什么意思,自行百度吧。我就是这么一个不求甚解的人。。。
3.配置算是完成,进入应用阶段。调用相机的方法:
private void startCarmera(){
File file = new File(getExternalCacheDir(), "img.jpg");
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
intent.putExtra(MediaStore.EXTRA_OUTPUT,
FileProvider.getUriForFile(this,"包名.fileprovider", file));
}else {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
}
startActivityForResult(intent, TAKEPHOTO);
}
然后是获取返回值:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKEPHOTO && resultCode == RESULT_OK) {
//设置文件保存路径这里放在跟目录下
File picture = new File(getExternalCacheDir() + "/img.jpg");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
Uri uri = FileProvider.getUriForFile(this, "包名.fileprovider", picture);
//裁剪照片
startPhotoZoom(uri);
}else {
//裁剪照片
startPhotoZoom(Uri.fromFile(picture));
}
}
// 裁剪照片的处理结果,看完后面的代码再看这里
if (requestCode == PHOTORESULT) {
Bundle extras = data.getExtras();
File file = new File(getExternalCacheDir() + "/head.jpg");
if (extras != null) {
Bitmap photo = extras.getParcelable("data");
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
photo.compress(Bitmap.CompressFormat.JPEG, 70, bos);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
imgView.setImageBitmap(photo);
}
super.onActivityResult(requestCode, resultCode, data);
}
}
一般拍完照片后我们会有一步裁剪的操作,在代码中我也添加了。因为针对安卓7.0及以上系统版本,也和过往系统不大一样。看代码:
// 剪裁图片
public void startPhotoZoom(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
//这段代码判断,在安卓7.0以前版本是不需要的。特此注意。不然这里也会抛出异常
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setDataAndType(uri, IMAGE_UNSPECIFIED);
intent.putExtra("circleCrop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectY", 1);
intent.putExtra("aspectX", 1);
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX", 50);
intent.putExtra("outputY", 50);
// intent.putExtra("scale",true);//自由截取
intent.putExtra("return-data", true);
startActivityForResult(intent, PHOTORESULT);
}
好了。具体就是这样了。由此我完美解决了安卓7.0及以上调用相机拍照导致程序崩溃的问题。另外,在安卓6.0及以上需要相机功能时,也是需要动态获取相应权限的,在此不再赘述。
仅供学习参考,欢迎交流指正!