美文网首页
Android7.0调用相机崩溃

Android7.0调用相机崩溃

作者: 南城的人 | 来源:发表于2019-05-27 16:31 被阅读0次

1、崩溃场景**

  • 当用户使用android7.0系统的手机调用相机
  • 或者打开相册、读取写入文件时崩溃

2、崩溃的描述

  • android.os.FileUriExposedException这个错误提示
  • 针对于权限部分,Android7.0是google推出的对权限做了一个更新即不允许出现以file://的形式调用隐式APP系统,也就是说以前呢,Uri的获取方式是以file://xxx的样式来,那么我们也就是通过Uri.fromFile()来获取如今放在7.0及以上系统呢,这样子就不行啦;
  • 如今的解决关键在哪里呢,需要在应用间共享文件,也就是需要发送一项content://URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用FileProvider类。

3、解决方案

1、(推荐)7.0之后你的app就算有权限,给出一个URI之后手机也认为你没有权限。
不用修改原有代码,在Application的oncreate方法中:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
       StrictMode.VmPolicy.Builder builder = new 
       StrictMode.VmPolicy.Builder();
       StrictMode.setVmPolicy(builder.build());
}

2、在调用相机的时候添加7.0系统的判断然后读取相册

/*获取当前系统的android版本号*/
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
Log.e("currentapiVersion","currentapiVersion====>"+currentapiVersion);
if (currentapiVersion<24){
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(pathFile));
    startActivityForResult(intent, TAKE_PICTURE);
}else {
    ContentValues contentValues = new ContentValues(1);
    contentValues.put(MediaStore.Images.Media.DATA, pathFile.getAbsolutePath());
    Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    startActivityForResult(intent, TAKE_PICTURE);
}

①在mainfest标签里加入以下该权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

②在application下加入该provider

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

在这里我们需要注意一下其中设置的各种属性的含义:

  • authorities:是该项目的包名+provider
  • grantUriPermissions:必须是true,表示授予 URI 临时访问权限
  • exported:必须是false
  • resource:中的@xml/file_paths是我们接下来要在资源文件目录下添加的文件

③在res目录下创建xml文件夹,在里面新建filepaths.xml文件,代码如下

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

需要注意的是:

  • path:需要临时授权访问的路径(.代表在相机调用时候访问的是所有路径,而文件写入时访问的路径是Android/data/com.ijuyin.prints.news/)
  • name: 是你为设置的这个访问路径起的名字

④接下来便是修改适配Android 7.0及以上系统的代码

//拍照
 Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                //适配android7.0 手机拍照取uri的处理
                if(Build.VERSION.SDK_INT<24){
                    uri = Uri.fromFile(imgFile);//7.0这里会闪退,imgfile是图片文件路径

                    camera.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                }else{
                    uri=FileProvider.getUriForFile(SellerAffiliate.this,"com.test.fileprovider",imgFile);
                    camera.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                    camera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION );//添加这一句表示对目标应用临时授权该Uri所代表的文件
                }
 startActivityForResult(camera, FLAG_CHOOSE_CAMERA);

//跳转相册
  Intent   intent = new Intent();
                intent.setAction(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent, FLAG_CHOOSE_IMG);

然后在onactivityresult拍照回调中

if (data != null) {
                String filepath="";
                //拍照返回
                if(getPhotoType.equals("0")){
                    if(uri.getScheme()!=null && "content".equalsIgnoreCase(uri.getScheme())){
                        filepath=imgFile.getAbsolutePath();
                    }else{
                        filepath=uri.getPath();
                    }
                }//相册返回
                else{
                    if (data != null) {
                         filepath =pathStr;
                    }
                }
//                pathStr=path;
                //将图片进行双重压缩后再上传
//                String filepath=BitmapComPressUtils.getRealFilePath(SellerAffiliate.this,uri);
                Bitmap imgBitmap= BitmapComPressUtils.getDecordeImage(SellerAffiliate.this,filepath,800f,480f);
                if(imgBitmap==null){
                    return;
                }
                String imgpath=BitmapComPressUtils.saveBitmap(SellerAffiliate.this,imgBitmap);
                pathStr=imgpath;

相关文章

网友评论

      本文标题:Android7.0调用相机崩溃

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