关于android 7.0调用相机拍照崩溃问题

解决安卓7.0拍照,相册选择崩溃的问题(包括压缩图片在内)

因为项目需要调用相机拍照,自己的测试手机是5.0,按照正常的调用方法直接可以调用,在项目测试的时候,同事的7.0系统相机拍照就崩了,进入相册没有崩,以前就听过7.0的权限问题,今天刚好碰到了就自己试着去解决一下这个问题。顺便记录一下,同时要感谢我所转载的那篇文章的大神

1.在清单文件AndroidManifest.xml中建一个内容提供者(不用java代码创建,直接复制到清单文件下即可)

[html]  view plain  copy
  1.   
  2.         <provider  
  3.             android:name="android.support.v4.content.FileProvider"  
  4.             android:authorities="com.mblmobileproject.liuxy.maibaole.mblpostproject.fileprovider"  
  5.             android:exported="false"  
  6.             android:grantUriPermissions="true">  
  7.             <meta-data  
  8.                 android:name="android.support.FILE_PROVIDER_PATHS"  
  9.                 android:resource="@xml/file_paths" />  
  10.         provider>  
2.在res文件夹下面新建一个xml文件夹,然后在xml文件夹下面建立一个file_paths的xml文件作为provider的共享文件路径

[html]  view plain  copy
  1. xml version="1.0" encoding="utf-8"?>  
  2. <resources xmlns:android="http://schemas.android.com/apk/res/android">  
  3.     <paths>  
  4.         <external-path path="" name="camera_photos" />  
  5.         <files-path path="" name="photos" />  
  6.     paths>  
  7. resources>  

其中name:一个引用字符串,意思就是可以随便写。 
path:文件夹“相对路径”,完整路径取决于当前的标签类型。 
path可以为空,表示指定目录下的所有文件、文件夹都可以被共享。 
在这个文件中,为每个目录添加一个XML元素指定目录。paths 可以添加多个子路径:< files-path> 分享app内部的存储;< external-path> 分享外部的存储;< cache-path> 分享内部缓存目录。

< files-path > 
代表目录为:Context.getFilesDir() 

代表目录为:Environment.getExternalStorageDirectory() 

代表目录为:getCacheDir() 
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 
如果对于path不理解的可以查询资料。

3.在代码中将原来的方法做判断,新增7.0的适配方法 
拍照

[java]  view plain  copy
  1. private void tackUploadingCamera() {  
  2.         //创建File对象,用于存储选择的照片  
  3.         File outputImage = new File(getDiskCacheDir(mContext), "test.jpg");  
  4.         Log.i(tag, "拍照文件路径=============:" + outputImage.toString());  
  5.         try {  
  6.             if (outputImage.exists()) {  
  7.                 outputImage.delete();  
  8.             }  
  9.             outputImage.createNewFile();  
  10.         } catch (Exception e) {  
  11.             e.printStackTrace();  
  12.         }  
  13.           
  14.         Log.i(tag, "拍照的照片:imageUri路径:" + imageUri);  
  15.         //隐式意图启动相机,拍照后并把照片存储的url存储到intent中区  
  16.         Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");  
  17.         //判断是否是7.0的系统  
  18.         if (Build.VERSION.SDK_INT < 24) {  
  19.             //拍照的照片路径  
  20.             imageUri = Uri.fromFile(outputImage);//7.0这里会闪退,imgfile是图片文件路径  
  21.             Log.i(tag, "7.0之前的系统,拍照的照片:imageUri路径:" + imageUri);  
  22.             intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  
  23.         } else {  
  24.             //7.0系统的操作  
  25.             imageUri = FileProvider.getUriForFile(mContext, "com.chc.photo.fileprovider", outputImage);  
  26.             intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  
  27.             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件  
  28.             Log.i(tag,"android7.0动态添加权限");  
  29.         }  
  30.         // 启动相机程序的Activity,Cut_PHOTO 是我项目需要进行裁剪功能,拍完后进行裁剪,这个可以根据自己需求去自己设置  
  31.         startActivityForResult(intent, Cut_PHOTO);  
  32.     }  

注意:不要添加这个权限,我之前有这个权限的时候一直崩掉,删除就好了

[html]  view plain  copy
  1. <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调用相机拍照崩溃问题)