关于android 7.0调用相机拍照崩溃问题
2017-11-08 15:36
323 查看
解决安卓7.0拍照,相册选择崩溃的问题(包括压缩图片在内)
因为项目需要调用相机拍照,自己的测试手机是5.0,按照正常的调用方法直接可以调用,在项目测试的时候,同事的7.0系统相机拍照就崩了,进入相册没有崩,以前就听过7.0的权限问题,今天刚好碰到了就自己试着去解决一下这个问题。顺便记录一下,同时要感谢我所转载的那篇文章的大神
1.在清单文件AndroidManifest.xml中建一个内容提供者(不用java代码创建,直接复制到清单文件下即可)
[html] view
plain copy
<!-- 适配android 7.0 拍照闪退的处理 ,其中authorities的值要和等下代码中使用的一致就行,其中resource内的文件就是拍照后的共享文件 -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
2.在res文件夹下面新建一个xml文件夹,然后在xml文件夹下面建立一个file_paths的xml文件作为provider的共享文件路径
[html] view
plain copy
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<external-path path="" name="camera_photos" />
<files-path path="" name="photos" />
</paths>
</resources>
其中name:一个引用字符串,意思就是可以随便写。
path:文件夹“相对路径”,完整路径取决于当前的标签类型。
path可以为空,表示指定目录下的所有文件、文件夹都可以被共享。
在这个文件中,为每个目录添加一个XML元素指定目录。paths 可以添加多个子路径:< files-path> 分享app内部的存储;< external-path> 分享外部的存储;< cache-path> 分享内部缓存目录。
< files-path >
代表目录为:Context.getFi
16544
lesDir()
代表目录为:Environment.getExternalStorageDirectory()
代表目录为:getCacheDir()
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果对于path不理解的可以查询资料。
3.在代码中将原来的方法做判断,新增7.0的适配方法
拍照
[java] view
plain copy
private void tackUploadingCamera() {
//创建File对象,用于存储选择的照片
File outputImage = new File(getDiskCacheDir(mContext), "test.jpg");
Log.i(tag, "拍照文件路径=============:" + outputImage.toString());
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
Log.i(tag, "拍照的照片:imageUri路径:" + imageUri);
//隐式意图启动相机,拍照后并把照片存储的url存储到intent中区
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//判断是否是7.0的系统
if (Build.VERSION.SDK_INT < 24) {
//拍照的照片路径
imageUri = Uri.fromFile(outputImage);//7.0这里会闪退,imgfile是图片文件路径
Log.i(tag, "7.0之前的系统,拍照的照片:imageUri路径:" + imageUri);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
} else {
//7.0系统的操作
imageUri = FileProvider.getUriForFile(mContext, "com.chc.photo.fileprovider", outputImage);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
Log.i(tag,"android7.0动态添加权限");
}
// 启动相机程序的Activity,Cut_PHOTO 是我项目需要进行裁剪功能,拍完后进行裁剪,这个可以根据自己需求去自己设置
startActivityForResult(intent, Cut_PHOTO);
}
注意:不要添加这个权限,我之前有这个权限的时候一直崩掉,删除就好了
[html] view
plain copy
<uses-permission android:name="android.permission.CAMERA" />-->
因为项目需要调用相机拍照,自己的测试手机是5.0,按照正常的调用方法直接可以调用,在项目测试的时候,同事的7.0系统相机拍照就崩了,进入相册没有崩,以前就听过7.0的权限问题,今天刚好碰到了就自己试着去解决一下这个问题。顺便记录一下,同时要感谢我所转载的那篇文章的大神
1.在清单文件AndroidManifest.xml中建一个内容提供者(不用java代码创建,直接复制到清单文件下即可)
[html] view
plain copy
<!-- 适配android 7.0 拍照闪退的处理 ,其中authorities的值要和等下代码中使用的一致就行,其中resource内的文件就是拍照后的共享文件 -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
2.在res文件夹下面新建一个xml文件夹,然后在xml文件夹下面建立一个file_paths的xml文件作为provider的共享文件路径
[html] view
plain copy
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<external-path path="" name="camera_photos" />
<files-path path="" name="photos" />
</paths>
</resources>
其中name:一个引用字符串,意思就是可以随便写。
path:文件夹“相对路径”,完整路径取决于当前的标签类型。
path可以为空,表示指定目录下的所有文件、文件夹都可以被共享。
在这个文件中,为每个目录添加一个XML元素指定目录。paths 可以添加多个子路径:< files-path> 分享app内部的存储;< external-path> 分享外部的存储;< cache-path> 分享内部缓存目录。
< files-path >
代表目录为:Context.getFi
16544
lesDir()
代表目录为:Environment.getExternalStorageDirectory()
代表目录为:getCacheDir()
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果对于path不理解的可以查询资料。
3.在代码中将原来的方法做判断,新增7.0的适配方法
拍照
[java] view
plain copy
private void tackUploadingCamera() {
//创建File对象,用于存储选择的照片
File outputImage = new File(getDiskCacheDir(mContext), "test.jpg");
Log.i(tag, "拍照文件路径=============:" + outputImage.toString());
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
Log.i(tag, "拍照的照片:imageUri路径:" + imageUri);
//隐式意图启动相机,拍照后并把照片存储的url存储到intent中区
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//判断是否是7.0的系统
if (Build.VERSION.SDK_INT < 24) {
//拍照的照片路径
imageUri = Uri.fromFile(outputImage);//7.0这里会闪退,imgfile是图片文件路径
Log.i(tag, "7.0之前的系统,拍照的照片:imageUri路径:" + imageUri);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
} else {
//7.0系统的操作
imageUri = FileProvider.getUriForFile(mContext, "com.chc.photo.fileprovider", outputImage);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
Log.i(tag,"android7.0动态添加权限");
}
// 启动相机程序的Activity,Cut_PHOTO 是我项目需要进行裁剪功能,拍完后进行裁剪,这个可以根据自己需求去自己设置
startActivityForResult(intent, Cut_PHOTO);
}
注意:不要添加这个权限,我之前有这个权限的时候一直崩掉,删除就好了
[html] view
plain copy
<uses-permission android:name="android.permission.CAMERA" />-->
public class PhotoUtils { private String photoType, temp = "temp.jpg", path = "/sdcard/myCert/";//sd路径 private EditMyAccountActivity activity; private SimpleDraweeView simpleDraweeView; public PhotoUtils(EditMyAccountActivity activity) { this.activity = activity; } public void takePhoto(String photoType, SimpleDraweeView simpleDraweeView) { this.photoType = photoType; this.simpleDraweeView = simpleDraweeView; // mainactivitys.setSimpleDraweeViewEnable(false);//禁止所有图片点击功能 Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri uri = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { File file = new File(Environment.getExternalStorageDirectory(), temp); uri = FileProvider.getUriForFile(activity, "com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider", file); LogUtils.debug(uri.toString()); } else { uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp)); } takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); activity.startActivityForResult(takeIntent, Constants.TAKE_PHOTO); } public void handlePhoto(int requestCode, int resultCode, Intent data) { switch (requestCode) { case Constants.TAKE_PHOTO: if (resultCode == -1) { cropPhoto(); } break; case Constants.CROP_PHOTO: LogUtils.debug("case:Crop"); if (data != null && data.getExtras() != null) { /* Bundle extras = data.getExtras(); Bitmap image = extras.getParcelable("data");*/ Bitmap image = null; try { image = BitmapFactory.decodeStream(activity.getContentResolver().openInputStream(Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp)))); } catch (FileNotFoundException e) { e.printStackTrace(); } if (image != null) { savePhoto(image, photoType);//保存在SD卡中 } } else { if (data == null) { LogUtils.debug("data==null"); } else if (data.getExtras() == null) { LogUtils.debug("data.getExtras()==null"); } // mainactivitys.setSimpleDraweeViewEnable(true); activity.showDialog("剪裁时发生错误,请重试"); } break; } } private void cropPhoto() { LogUtils.debug("cropPhoto"); Uri uri = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { File file = new File(Environment.getExternalStorageDirectory(), temp); uri = FileProvider.getUriForFile(activity, "com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider", file); } else { uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp)); } Intent intent = new Intent("com.android.camera.action.CROP"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", 1.26); intent.putExtra("aspectY", 1); // outputX outputY 是裁剪图片宽高 int width=PublicUtil.getwidthPixels(activity); int height=PublicUtil.getheightPixels(activity); intent.putExtra("outputX", 300); intent.putExtra("outputY", 300); intent.putExtra("return-data", true); //uritempFile为Uri类变量,实例化uritempFile intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), temp))); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); LogUtils.debug("CropEnd"); activity.startActivityForResult(intent, Constants.CROP_PHOTO); } private void savePhoto(Bitmap mBitmap, String imageName) { LogUtils.debug("savePhoto"); String sdStatus = Environment.getExternalStorageState(); if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 检测sd是否可用 return; } FileOutputStream jpgOut = null; File file = new File(path); file.mkdirs();// 创建文件夹 Log.e("创建文件夹", "OK!!!"); String jpgFileName = path + imageName;//图片名字 try { jpgOut = new FileOutputStream(jpgFileName); mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, jpgOut);// 把数据写入文件 //关闭流 jpgOut.flush(); jpgOut.close(); compressToTragetSize(mBitmap, jpgFileName); setPhoto(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // try { // if (jpgOut != null) { // //关闭流 // jpgOut.flush(); // jpgOut.close(); // } // compressToTragetSize(mBitmap, jpgFileName); // setPhoto(); // } catch (IOException e) { // LogUtils.debug("写入失败!"); // e.printStackTrace(); // } } } private void setPhoto() { /* LogUtils.debug("setPhoto"); File temp = new File(path + photoType); Uri photoUri = Uri.fromFile(temp);*/ /* switch (photoType) { case Constants.ID_FRONT: LogUtils.debug(photoType); *//* mFrontPhoto.setImageURI("/sdcard/myCert/" + photoType); mFrontPhoto.setImageURI(photoUri);*//* mFrontPhoto.setImageBitmap(bitmap); break; case Constants.ID_BACK: LogUtils.debug(photoType); // mBackPhoto.setImageURI(photoUri); mBackPhoto.setImageBitmap(bitmap); break; case Constants.YINGYE: LogUtils.debug(photoType); // LogUtils.debug(temp.exists() ? "yes" : "NO"); // mHandedPhoto.setImageURI(photoUri); mHandedPhoto.setImageBitmap(bitmap); break; case Constants.DIAN: break; }*/ // Bitmap bitmap = getSmallBitmap(path + photoType, 172, 252); // simpleDraweeView.setImageBitmap(bitmap); Bitmap bitmap = getSmallBitmap(path + photoType, 172, 252); Uri photoUri = Uri.parse(MediaStore.Images.Media.insertImage(activity.getContentResolver(), bitmap, null, null)); Fresco.getImagePipeline().evictFromCache(photoUri); simpleDraweeView.setImageURI(photoUri); // simpleDraweeView.setImageBitmap(getSmallBitmap(path + photoType, 172, 252)); } private void compressToTragetSize(Bitmap image, String fileName) { File file = new File(fileName); double size = file.length(); /* if (file.exists()) { FileInputStream fis = null; try { fis = new FileInputStream(file); size = fis.available(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fis != null) { fis.close(); } } catch (IOException e) { e.printStackTrace(); } } }*/ Log.e("文件字节大小", size + ""); while ((size / 1024d) > 450d) { int compressSzie = (int) (100d / ((size / 1024d) / 450d)); compressSzie = 100 - compressSzie; Log.e("kb", (size / 1024d) + ""); Log.e("倍数", ((size / 1024d) / 450d) + ""); Log.e("压缩比率", compressSzie + ""); FileOutputStream b = null; try { file.delete();//删除原文件 b = new FileOutputStream(fileName); image.compress(Bitmap.CompressFormat.JPEG, 98, b);// 把数据写入文件 } catch (FileNotFoundException e) { e.printStackTrace(); } finally { try { if (b != null) { //关闭流 b.flush(); b.close(); size = new File(fileName).length(); } } catch (IOException e) { LogUtils.debug("写入失败!"); e.printStackTrace(); } } } } /** * 计算图片的缩放值 * * @param options * @param reqWidth * @param reqHeight * @return */ private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and // width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will // guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } /** * 根据路径获得突破并压缩返回bitmap用于显示 * * @param filePath * @return */ public Bitmap getSmallBitmap(String filePath, int reqWidth, int reqHeight) { final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; //只返回图片的大小信息 BitmapFactory.decodeFile(filePath, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(filePath, options); } }
相关文章推荐
- android 7.0 调用系统相机崩溃问题
- 解决android调用系统相机拍照保存时onActivityResult中data为null的问题
- Android调用系统相机拍照像素太低以及内存溢出问题
- 关于android调用拍照不返回的问题。
- Android 7.0调用相机崩溃
- 关于Android调用系统相机的问题
- android调用系统相机和相册进行拍照裁剪处理,解决不同安卓版本存在无法加载相册的问题,处理了是否有sd卡的存在的情况
- Android7.0 调用相机拍照并裁剪及遇到的坑
- Android 调用系统相机拍照(适配7.0)、从图库选择图片、从数据库读取联系人信息、相册图片、扫描文件
- 关于Android开发调用系统相机拍照的 一些事
- Android 7.0调用相机崩溃详解及解决办法
- 关于Android调用相机拍照,完成后无法返回
- 关于调用Android相机拍摄照片返回数据过小的问题
- Android 调用系统相机,拍照,并上传图片所注意的一些问题
- 调用系统相机拍照--是配到android-7.0
- 关于android 调用系统相机后activity被销毁后 拍照数据丢失的解决 特别适用于多张拍照
- 关于android调用相机及拍照的存储和照片处理功能的全面小案例
- 调用Android相机拍照,解决了拍照时候内存溢出溢出的问题
- 关于Android 4.4(华为)调用系统相机问题
- 解决Android调用系统相机拍照后相片无法在相册中显示问题