美文网首页大前端开发工作生活
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