Android7.0 调用相机拍照并裁剪及遇到的坑
2017-03-11 15:11
387 查看
之前用的几年的选择头像上传中的拍照上传报错无法使用,错误懒得再重现,大概错误过程如下:
① 代码中无法直接使用imageUri = Uri.fromFile(f);
会报FileUriExposedException,因为在android 6.0 权限需要在运行时候检查, 其他app可能没有读写文件的权限, 所以在android 7.0的时候加上了这个限制。上网查了一下需要使用 FileProvider 解决这个问题。
解决方案:在mainfest.xml中配置如下代码:
其中内容提供器的grantUriPermissions属性被设置为true,表示权限能够被授予内容提供器范围内的任何数据。但是,如果grantUriPermission属性被设置为false,那么权限就只能授予这个元素所指定的数据子集。一个内容提供器能够包含任意多个个元素。每个都只能指定一个路径(三个可能属性中的一个)。
另外权限不要忘了:
file_paths文件内容如下:
然后拍照代码改为:
拍照可以了,可是返回执行裁剪操作时又提示toast“无法加载此图片”。着实郁闷,找了找网上的说法,没特别对应的,只好下了个demo,对照排查,发现了错误:
② File f =getCreateFile(); 这个文件已经不能随便找个目录创建了。
原来出错的getCreateFile()方法如下:
更改为:
不太清楚之前的创建路径有什么问题,但是改成下面的代码,在裁剪的时候正常运行了,剪切在sdk24以上需要加上intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
否则会提示toast 无法加载该图片。
① 代码中无法直接使用imageUri = Uri.fromFile(f);
会报FileUriExposedException,因为在android 6.0 权限需要在运行时候检查, 其他app可能没有读写文件的权限, 所以在android 7.0的时候加上了这个限制。上网查了一下需要使用 FileProvider 解决这个问题。
/** * 拍照 */ private void takePhoto() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); try { //错误② File f = getCreateFile(); //错误① imageUri = Uri.fromFile(f); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(takePictureIntent, PHOTO_REQUEST_TAKEPHOTO); } catch (Exception e) { e.printStackTrace(); } }
解决方案:在mainfest.xml中配置如下代码:
</application> <provider android:authorities="应用包名.fileprovider" android:name="android.support.v4.content.FileProvider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/> </provider> </application>
其中内容提供器的grantUriPermissions属性被设置为true,表示权限能够被授予内容提供器范围内的任何数据。但是,如果grantUriPermission属性被设置为false,那么权限就只能授予这个元素所指定的数据子集。一个内容提供器能够包含任意多个个元素。每个都只能指定一个路径(三个可能属性中的一个)。
另外权限不要忘了:
file_paths文件内容如下:
<?xml version="1.0" encoding="utf-8"?> <paths> <!-- external-path:sd ;path:你的应用保存文件的根目录;name随便定义--> <!-- root-path 手机存储根目录 --> <root-path path="" name="robot" /> </paths>
然后拍照代码改为:
/** * 拍照 */ private void takePhoto() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); try { // 指定存放拍摄照片的位置 // File f =getCreateFile(); if (Build.VERSION.SDK_INT >= 24) { takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); imageUri = FileProvider.getUriForFile(getApplicationContext(), _context.getPackageName()+".fileprovider", f); } else { imageUri = Uri.fromFile(f); } imageUri = uri; takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri ); startActivityForResult(takePictureIntent, PHOTO_REQUEST_TAKEPHOTO); } catch (Exception e) { e.printStackTrace(); } }
拍照可以了,可是返回执行裁剪操作时又提示toast“无法加载此图片”。着实郁闷,找了找网上的说法,没特别对应的,只好下了个demo,对照排查,发现了错误:
② File f =getCreateFile(); 这个文件已经不能随便找个目录创建了。
原来出错的getCreateFile()方法如下:
/** * 把程序拍摄的照片放到 SD卡的 Pictures目录中 robot 文件夹中 * 照片的命名规则为:robot_20131106_093721.jpg * * @return * @throws IOException */ @SuppressLint("SimpleDateFormat") private File getCreateFile() throws IOException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss"); String timeStamp = format.format(new Date()); imageFileName = "robot_" + timeStamp + ".png"; File image = new File(PictureUtil.getAlbumDir(), imageFileName); mCurrentPhotoPath = image.getAbsolutePath(); return image; }
更改为:
private File getCreateFile() { String cachePath = null; if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) { cachePath = _context.getExternalCacheDir().getPath(); } else { cachePath = _context.getCacheDir().getPath(); } File dir = new File(cachePath); SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HHmmss"); String timeStamp = format.format(new Date()); String fileName = "robot_" + timeStamp + ".png"; File file = new File(dir, fileName); if (file.exists()) { file.delete(); } try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } mCurrentPhotoPath = file.getAbsolutePath(); return file; }
不太清楚之前的创建路径有什么问题,但是改成下面的代码,在裁剪的时候正常运行了,剪切在sdk24以上需要加上intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
否则会提示toast 无法加载该图片。
相关文章推荐
- Android 7.0 调用系统相机拍照、裁剪相片
- Android调用系统相机拍照并且裁剪指定大小
- 总结Android调用系统相机拍照遇到的坑
- Android 调用系统相机拍照(适配7.0)、从图库选择图片、从数据库读取联系人信息、相册图片、扫描文件
- android调用系统相机拍照后对相片进行裁剪[先存,明天看]
- Android拍照及图片裁剪、调用系统相册(兼容6.0以上权限处理及7.0以上文件管理)
- Android调用相册或相机拍照选取照片并裁剪
- Android 调用系统相机拍照并且显示在相册中,以及中间可能会遇到的一些问题的解决
- Android手机调用系统相机拍照、裁剪以及获取Url上传图片
- Android调用相机实现拍照并裁剪图片,调用手机中的相冊图片并裁剪图片
- android选择系统相机拍照和系统相册,裁剪图片并保存和设置头像,适配至7.0
- Android调用系统相机拍照、裁剪,并保存到手机SD卡中,展示到界面
- Android调用相机实现拍照并裁剪图片,调用手机中的相册图片并裁剪图片
- Android编程实现调用相册、相机及拍照后直接裁剪的方法
- Android调用系统相机、图库、裁剪图片并压缩上传(适配7.0)
- android调用系统相机和相册进行拍照裁剪处理,解决不同安卓版本存在无法加载相册的问题,处理了是否有sd卡的存在的情况
- 调用系统相机拍照--是配到android-7.0
- Android 7.0调用相机,相册,裁剪的相关改进
- android调用系统相机拍照后对相片进行裁剪
- [置顶] Android 7.0实际开发中调用系统相机和获取相册照片遇到的坑具备向下兼容