美文网首页大前端开发工作生活
Android 7.0 调用系统相机并裁剪图片问题

Android 7.0 调用系统相机并裁剪图片问题

作者: liangbf | 来源:发表于2019-07-26 13:52 被阅读7次

    前言

    最近测试那边报了个bug,手机拍照时出现crash,这么常用而且很久没动的一个功能咋就出错了。经过跟测试人员确认,是在7.0手机上出现的。果然,7.0以下版本没有这个问题,那肯定就是兼容性问题了。下面带大家一步步来解决问题。

    1.注册内容提供者FileProvider

    从7.0开始,Android不允许直接调用本地路径,那样被认为是不安全的,即使用 content://代替了 file:///。FileProvider是一种特殊的内容提供器,作为四大组件之一,我们要使用它得先在AndroidManifest文件中进行声明。

    <provider
                android:name="android.support.v4.content.FileProvider"
                android:authorities="com.test.bf"
                android:exported="false"
                android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths" />
            </provider>
    

    我们需要创建一个共享路径xml文件file_paths

    <?xml version="1.0" encoding="utf-8"?>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
        <external-path
            name="my_images"
            path="test" />
        <!--code below fix the 'failed to find configured root that contains xxx' exception-->
        <root-path
            name="root_path"
            path="." />
    </paths>
    

    name属性的值可以随便写,path属性的值表示共享的具体位置

    2.调用系统相机

    因为6.0以上安卓增加了权限管理,在打开相机前得检查相应权限是否打开。因app在一开始便申请了权限,在这里就不贴出相应代码。

    if (Build.VERSION.SDK_INT >= 24) {
                //调用系统相机
                Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                //临时添加权限
                takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                    File photoFile = null;
                    try {
                        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
                        PHOTO_PATH = storageDir.getPath();
                        photoFile = File.createTempFile("head_image", ".png", storageDir);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
    
                    if (photoFile != null) {
                        //获取uri,注意:路径跟上面FileProvider声明的时候一致
                        photoURI = FileProvider.getUriForFile(this, "com.test.bf", photoFile);
                        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                        startActivityForResult(takePictureIntent, PHOTO_REQUEST_CAREMA);
                    }
                }
            } else {/**code below is not work for version 7.0 or later*/
                try {
                    File file = new File(PHOTO_PATH);
                    if (!file.exists()) {
                        boolean success = file.mkdirs();// 创建文件夹
                        if (!success) {
                            ToastUtil.showShort(getString(R.string.create_album_fail));
                        }
                    }
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    photoURI =Uri.fromFile(new File(PHOTO_PATH, PHOTO_NAME));
                    intent.putExtra(MediaStore.EXTRA_OUTPUT,
                            photoURI);
                    startActivityForResult(intent, PHOTO_REQUEST_CAREMA);// 采用ForResult打开
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    

    3.裁剪图片(也需要做7.0适配)

       public void cropPhoto(Uri uri, int outputX, int outputY) {
            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", outputX);
            intent.putExtra("outputY", outputY);
            intent.putExtra("return-data", true);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                //开启临时权限
                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                //重点:针对7.0以上的操作
                intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, uri));
                uritempFile = uri;
            } else {
                uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "small.jpg");
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
            startActivityForResult(intent, PHOTO_CROP);
        }
    

    相关文章

      网友评论

        本文标题:Android 7.0 调用系统相机并裁剪图片问题

        本文链接:https://www.haomeiwen.com/subject/yatlhctx.html