Android 7.0中拍照和图片裁剪适配的问题详解
前言
Android7.0系统发布后,拿到能升级的nexus6P,就开始了7.0的适配。发现在Android7.0以上,在相机拍照和图片裁剪上,可能会碰到以下一些错误:
Process:com.yuyh.imgsel,PID:22995 //错误1 android.os.FileUriExposedException:file:///storage/emulated/0/Android/data/com.yuyh.imgsel/cache/1486438962645.jpgexposedbeyondappthroughClipData.Item.getUri() //错误2 android.os.FileUriExposedException:file:///storage/emulated/0/DCIM/RxGalleryFinal/IMG_20161018180127.jpgexposedbeyondappthroughIntent.getData()
主要是由于在Android7.0以后,用了ContentUri替换了原本的FileUri,故在targetSdkVersion=24的时候,部分“`Uri.fromFile()“`方法就不适用了。**FileUri与ContentUri的区别**-FileUri对应的是文件本身的存储路径-ContentUri对应的是文件在ContentProvider的路径所以在android7.0以上,我们就需要将FileUri转换为ContentUri。
具体转换方法如下:
/**
*转换content://uri
*
*@paramimageFile
*@return
*/
publicUrigetImageContentUri(FileimageFile){
StringfilePath=imageFile.getAbsolutePath();
Cursorcursor=getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
newString[]{MediaStore.Images.Media._ID},
MediaStore.Images.Media.DATA+"=?",
newString[]{filePath},null);
if(cursor!=null&&cursor.moveToFirst()){
intid=cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID));
UribaseUri=Uri.parse("content://media/external/images/media");
returnUri.withAppendedPath(baseUri,""+id);
}else{
if(imageFile.exists()){
ContentValuesvalues=newContentValues();
values.put(MediaStore.Images.Media.DATA,filePath);
returngetContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);
}else{
returnnull;
}
}
}
那么,我们在裁剪的时候,应该如下调用:
privatevoidcrop(StringimagePath){
Filefile=newFile("xxx.jpg");
cropImagePath=file.getAbsolutePath();
Intentintent=newIntent("com.android.camera.action.CROP");
intent.setDataAndType(getImageContentUri(newFile(imagePath)),"image/*");
intent.putExtra("crop","true");
intent.putExtra("aspectX",config.aspectX);
intent.putExtra("aspectY",config.aspectY);
intent.putExtra("outputX",config.outputX);
intent.putExtra("outputY",config.outputY);
intent.putExtra("scale",true);
intent.putExtra("return-data",false);
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(file));
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection",true);
startActivityForResult(intent,IMAGE_CROP_CODE);
}
这样就解决了裁剪的问题,但是!!拍照的时候就会出现以下错误:
IntentcameraIntent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
if(cameraIntent.resolveActivity(getActivity().getPackageManager())!=null){
tempFile=newFile(FileUtils.createRootPath(getActivity())+"/"+System.currentTimeMillis()+".jpg");
LogUtils.e(tempFile.getAbsolutePath());
FileUtils.createFile(tempFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(tempFile));
startActivityForResult(cameraIntent,REQUEST_CAMERA);
}
android.os.FileUriExposedException:file:///storage/emulated/0/Android/data/com.yuyh.imgsel/cache/1486438962645.jpgexposedbeyondappthroughClipData.Item.getUri()
这是因为拍照存储的文件,也需要以ContentUri的形式,故采用以下办法解决:
Step.1
修改AndroidManifest.xml
<application
...>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="{替换为你的包名}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
Step.2
在res/xml/下新建provider_paths.xml文件
<?xmlversion="1.0"encoding="utf-8"?> <pathsxmlns:android="http://schemas.android.com/apk/res/android"> <external-pathname="external_files"path="."/> </paths>
Step.3
修改拍照时的参数
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,FileProvider.getUriForFile(getActivity(),BuildConfig.APPLICATION_ID+".provider",tempFile));//Uri.fromFile(tempFile)
总结
好了,以上就是这篇文章的全部内容了,希望本文的内容对各位Android开发者们能带来一定的帮助,如果有疑问大家可以留言交流。