解决Android7.0以上系统拍照闪退及拍照后、选取相册剪裁后闪退问题

做了一个拍照及从相册调用图片作为头像的功能:
一开始代码写好在Android6.0系统上正常运行,换了Android8.0 9.0就闪退了,那问题就是版本不兼容问题了,

一、首先在onCreate方法中加入了以下代码,判断系统大于6.0

//android 7.0系统以上解决拍照的问题
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                builder.detectFileUriExposure();
            }
        }

二、解决了这个之后,能打开相机了,但是,,,拍照完毕后以及从相册选取完照片后,不能调取剪裁,于是在onActivityResult回调方法中及剪裁方法cropPhoto中 又加了几行代码

 //处理手机不兼容问题
                    try {
                        head = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile));
                        verifyStoragePermissions(this);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
uritempFile=uri;

并且千万千万要注释掉这下面两条代码:

// head = extras.getParcelable("data");          
//intent.putExtra("return-data", true);

下面是比较完整的代码:

 protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case CROP_PHOTO1:
                if (resultCode == RESULT_OK) {
                    cropPhoto(data.getData()); //裁剪图片
                }
                break;
            case CROP_PHOTO2:
                if (resultCode == RESULT_OK) {
                    File temp = new File(Environment.getExternalStorageDirectory() +"/"+
                            spUserName+"_head.jpg");
                    cropPhoto(Uri.fromFile(temp)); //裁剪图片
                }
                break;
            case SAVE_PHOTO:
                if (data != null) {
                    Bundle extras = data.getExtras();
                  // head = extras.getParcelable("data");
                    //处理手机不兼容问题
                    try {
                        head = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile));
                        verifyStoragePermissions(this);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                    if (head != null) {
                        String fileName=setPicToView(head); //保存在SD卡中
                        //保存头像地址到数据库中
                        DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("head",
                                fileName,spUserName);
                        iv_photo.setImageBitmap(head); //用ImageView显示出来
                        //发送广播更新“我”的界面中的头像
                        Intent intent = new Intent(
                                UpdateUserInfoReceiver.ACTION.UPDATE_USERINFO);
                        intent.putExtra(
                                UpdateUserInfoReceiver.INTENT_TYPE.TYPE_NAME,
                                UpdateUserInfoReceiver.INTENT_TYPE.UPDATE_HEAD);
                        intent.putExtra("head", fileName);
                        sendBroadcast(intent);
                    }
                }
                break;
          }


 /**
     * 调用系统的裁剪功能
     */
    public void cropPhoto(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        //aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        //outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 150);
        intent.putExtra("outputY", 150);
        //intent.putExtra("return-data", true);
    //处理手机不兼容问题
        uritempFile=uri;
        startActivityForResult(intent, SAVE_PHOTO);
    }

三、运行之后,还是闪退,出现日志

java.io.FileNotFoundException: /storage/emulated/0/ (Permission denied)

查询资料后,还是权限问题,安卓7.0系统以后写入SD卡权限失败问题,添加动态权限使APP可以访问手机存储权限

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            int REQUEST_CODE_CONTACT = 101;
            String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
            //验证是否许可权限
            for (String str : permissions) {
                if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
                    //申请权限
                    this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
                }
            }
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
                builder.detectFileUriExposure();
            }
        }

三、很不幸,还没有完。如果你的手机是小米MIUI系统的话,小米miui系统调用系统裁剪图片功能camera.action.CROP后会崩溃或重新打开app
在剪裁方法cropPhoto中

//处理手机不兼容问题及小米手机不兼容问题
        if (Build.MODEL.contains("MI")) {
            uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + spUserName+"_head.jpg");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
            intent.putExtra("noFaceDetection", false); // no face detection
        }else {
            //处理手机不兼容问题
            uritempFile=uri;
        }

上代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            int REQUEST_CODE_CONTACT = 101;
            String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
            //验证是否许可权限
            for (String str : permissions) {
                if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
                    //申请权限
                    this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
                }
            }
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1001);
                builder.detectFileUriExposure();
            }
        }

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case CROP_PHOTO1:
                if (resultCode == RESULT_OK) {
                    cropPhoto(data.getData()); //裁剪图片
                }
                break;
            case CROP_PHOTO2:
                if (resultCode == RESULT_OK) {
                    File temp = new File(Environment.getExternalStorageDirectory().getPath()+"/"+ spUserName+"_head.jpg");
                    cropPhoto(Uri.fromFile(temp)); //裁剪图片
                }
                break;
            case SAVE_PHOTO:
                if (data != null) {
                    Bundle extras = data.getExtras();
                   // head = extras.getParcelable("data");
                    //处理手机不兼容问题及小米手机不兼容问题
                    try {
                        head = BitmapFactory.decodeStream(getContentResolver().openInputStream(uritempFile));
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                    if (head != null) {
                        String fileName=setPicToView(head); //保存在SD卡中
                        //保存头像地址到数据库中
                        DBUtils.getInstance(UserInfoActivity.this).updateUserInfo("head",
                                fileName,spUserName);
                        iv_photo.setImageBitmap(head); //用ImageView显示出来
                        //发送广播更新“我”的界面中的头像
                        Intent intent = new Intent(
                                UpdateUserInfoReceiver.ACTION.UPDATE_USERINFO);
                        intent.putExtra(
                                UpdateUserInfoReceiver.INTENT_TYPE.TYPE_NAME,
                                UpdateUserInfoReceiver.INTENT_TYPE.UPDATE_HEAD);
                        intent.putExtra("head", fileName);
                        sendBroadcast(intent);
                    }
                }
                break;
            case CHANGE_NICKNAME:  //个人资料修改界面回传过来的昵称数据
                if (data != null) {
                    new_info = data.getStringExtra("nickName");
                    if (TextUtils.isEmpty(new_info)) {
                        return;
                    }
                    tv_nickName.setText(new_info);
                    //更新数据库中的昵称字段
                    DBUtils.getInstance(UserInfoActivity.this).updateUserInfo(
                            "nickName", new_info, spUserName);
                }
                break;
            case CHANGE_SIGNATURE: //个人资料修改界面回传过来的签名数据
                if (data != null) {
                    new_info = data.getStringExtra("signature");
                    if (TextUtils.isEmpty(new_info)) {
                        return;
                    }
                    tv_signature.setText(new_info);
                    //更新数据库中的签名字段
                    DBUtils.getInstance(UserInfoActivity.this).updateUserInfo(
                            "signature", new_info, spUserName);
                }
                break;
        }
    }
    /**
     * 调用系统的裁剪功能
     */
    public void cropPhoto(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        //aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        //outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 150);
        intent.putExtra("outputY", 150);
        //intent.putExtra("return-data", true);
       //处理手机不兼容问题及小米手机不兼容问题
        if (Build.MODEL.contains("MI")) {
            uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + spUserName+"_head.jpg");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
            intent.putExtra("noFaceDetection", false); // no face detection
        }else {
            //处理手机不兼容问题
            uritempFile=uri;
        }
        startActivityForResult(intent, SAVE_PHOTO);
    }
    private String setPicToView(Bitmap mBitmap) {
        String sdStatus = Environment.getExternalStorageState();
        if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { //检测sd是否可用
            return "";
        }
        FileOutputStream b = null;
        File file = new File(path);
        file.mkdirs(); //创建文件夹
        String fileName = path + spUserName+"_head.jpg"; //图片名字
        try {
            b = new FileOutputStream(fileName);
            mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b); //把数据写入文件
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭流
                b.flush();
                b.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileName;
    }

未完待续……
在模拟器上,相册选取照片出现 editing is not supported for this image,还未解决……

你可能感兴趣的:(解决Android7.0以上系统拍照闪退及拍照后、选取相册剪裁后闪退问题)