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开发者们能带来一定的帮助,如果有疑问大家可以留言交流。