android7.0调用相机拍照的问题解决方案

最近在应用中开发调用系统相机拍照的时候,遇到一个问题,就是在安卓7.0及以上机型使用,按照往常写法Uri.fromFile(imgFile)回抛出异常FileUriExposedException导致程序崩溃。通过上网查看知道了安卓7.0及以上的特殊问题。因此整理了其他的人的处理方法,我也根据自身的项目需要进行了整改,特此奉上,供学习交流!

1.在清单文件里添加provider如下:

<application
    ...>
       <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="包名.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>
</application>

2.在res目录下新建xml文件夹,并新建一个file_paths.xml文件,内容如下

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

具体什么意思,自行百度吧。我就是这么一个不求甚解的人。。。

3.配置算是完成,进入应用阶段。调用相机的方法:

 private void startCarmera(){
        File file = new File(getExternalCacheDir(), "img.jpg");
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            intent.putExtra(MediaStore.EXTRA_OUTPUT,
                    FileProvider.getUriForFile(this,"包名.fileprovider", file));
        }else {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
        }
        startActivityForResult(intent, TAKEPHOTO);
    }

然后是获取返回值:

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == TAKEPHOTO && resultCode == RESULT_OK) {
            //设置文件保存路径这里放在跟目录下
            File picture = new File(getExternalCacheDir() + "/img.jpg");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
                Uri uri = FileProvider.getUriForFile(this, "包名.fileprovider", picture);
                //裁剪照片
                startPhotoZoom(uri);
            }else {
             //裁剪照片
                startPhotoZoom(Uri.fromFile(picture));
            }
        }

        // 裁剪照片的处理结果,看完后面的代码再看这里
        if (requestCode == PHOTORESULT) {
            Bundle extras = data.getExtras();
            File file = new File(getExternalCacheDir() + "/head.jpg");
            if (extras != null) {
                Bitmap photo = extras.getParcelable("data");
                try {
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                    photo.compress(Bitmap.CompressFormat.JPEG, 70, bos);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                imgView.setImageBitmap(photo);
            }
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

一般拍完照片后我们会有一步裁剪的操作,在代码中我也添加了。因为针对安卓7.0及以上系统版本,也和过往系统不大一样。看代码:

// 剪裁图片
    public void startPhotoZoom(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");

    //这段代码判断,在安卓7.0以前版本是不需要的。特此注意。不然这里也会抛出异常
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        intent.setDataAndType(uri, IMAGE_UNSPECIFIED);
        intent.putExtra("circleCrop", "true");
        // aspectX aspectY 是宽高的比例
        intent.putExtra("aspectY", 1);
        intent.putExtra("aspectX", 1);
        // outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 50);
        intent.putExtra("outputY", 50);
//        intent.putExtra("scale",true);//自由截取
        intent.putExtra("return-data", true);
        startActivityForResult(intent, PHOTORESULT);
    }

好了。具体就是这样了。由此我完美解决了安卓7.0及以上调用相机拍照导致程序崩溃的问题。另外,在安卓6.0及以上需要相机功能时,也是需要动态获取相应权限的,在此不再赘述。

仅供学习参考,欢迎交流指正!

展开阅读全文

没有更多推荐了,返回首页