解决安卓7.0拍照,相册选择崩溃的问题(包括压缩图片在内)
因为项目需要调用相机拍照,自己的测试手机是5.0,按照正常的调用方法直接可以调用,在项目测试的时候,同事的7.0系统相机拍照就崩了,进入相册没有崩,以前就听过7.0的权限问题,今天刚好碰到了就自己试着去解决一下这个问题。顺便记录一下,同时要感谢我所转载的那篇文章的大神
1.在清单文件AndroidManifest.xml中建一个内容提供者(不用java代码创建,直接复制到清单文件下即可)
其中name:一个引用字符串,意思就是可以随便写。
path:文件夹“相对路径”,完整路径取决于当前的标签类型。
path可以为空,表示指定目录下的所有文件、文件夹都可以被共享。
在这个文件中,为每个目录添加一个XML元素指定目录。paths 可以添加多个子路径:< files-path> 分享app内部的存储;< external-path> 分享外部的存储;< cache-path> 分享内部缓存目录。
< files-path >
代表目录为:Context.getFilesDir()
代表目录为:Environment.getExternalStorageDirectory()
代表目录为:getCacheDir()
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
如果对于path不理解的可以查询资料。
3.在代码中将原来的方法做判断,新增7.0的适配方法
拍照
注意:不要添加这个权限,我之前有这个权限的时候一直崩掉,删除就好了
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); } }