您的位置:首页 > 移动开发 > Android开发

Android7.0 调用相机拍照并裁剪及遇到的坑

2017-03-11 15:11 387 查看
之前用的几年的选择头像上传中的拍照上传报错无法使用,错误懒得再重现,大概错误过程如下:

① 代码中无法直接使用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 无法加载该图片。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐