Android 7.0 拍照 FileUriExposedException

来源:互联网 发布:龙发装修 知乎 编辑:程序博客网 时间:2024/05/21 12:45

最近开发项目遇到7.0 拍照崩溃记录此问题

这个异常只会在Android 7.0+ 上会出现此问题,当app使用file:// url 共享给其他app时, 会抛出这个异常
官方推荐使用FileProvider 来解决此问题

  • 第一步在manifest.xml文件添加provider,相机,读写文件权限
  • 第二步在appliction 节点中插入代码,注意 android:authorities 里面的值,在后面使用的getUriForFile(Context, String, File) 中, 第二个参数就是这个里面的值,请务必填写正确。

    <provider     android:name="android.support.v4.content.FileProvider"     android:authorities="com.example.android.fileprovider"     android:exported="false"     android:grantUriPermissions="true">     <meta-data         android:name="android.support.FILE_PROVIDER_PATHS"         android:resource="@xml/provider_paths"></meta-data>  </provider>
  • 第三步在res节点下创建xml包并添加provider_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>

paths 可配置选项

<files-path name="name" path="path" /> //相当 Context.getFilesDir() + path, name是分享url的一部分<cache-path name="name" path="path" /> //getCacheDir()<external-path name="name" path="path" /> //Environment.getExternalStorageDirectory()<external-files-path name="name" path="path" />//getExternalFilesDir(String) Context.getExternalFilesDir(null)<external-cache-path name="name" path="path" /> //Context.getExternalCacheDir()
  • 第4步在activity中调用拍照版本高于或等于android 7.0使用FileProvider.getUriForFile 否则使用Uri.fromFile(file);
 /**     * 打开系统相机     */    private void openCamera() {        File file = new FileStorage().createIconFile();        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            //通过FileProvider创建一个content类型的Uri ,和清单文件保持一致            imageUri = FileProvider.getUriForFile(this, "com.example.android.fileprovider", file);        } else {            imageUri = Uri.fromFile(file);        }        Intent intent = new Intent();        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件        }        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI        startActivityForResult(intent, REQUEST_CAPTURE);    } public File createIconFile() {        String fileName = "";        if (iconDir != null) {            fileName = UUID.randomUUID().toString() + ".png";        }        return new File(iconDir, fileName);    }
  • File file = new FileStorage().createIconFile();
    创建文件
public class FileStorage {    private File cropIconDir;    private File iconDir;    public FileStorage() {        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {            File external = Environment.getExternalStorageDirectory();            String rootDir = "/" + "image";            cropIconDir = new File(external, rootDir + "/crop");            if (!cropIconDir.exists()) {                cropIconDir.mkdirs();            }            iconDir = new File(external, rootDir + "/icon");            if (!iconDir.exists()) {                iconDir.mkdirs();            }        }    }    public File createCropFile() {        String fileName = "";        if (cropIconDir != null) {            fileName = UUID.randomUUID().toString() + ".png";        }        return new File(cropIconDir, fileName);    }    public File createIconFile() {        String fileName = "";        if (iconDir != null) {            fileName = UUID.randomUUID().toString() + ".png";        }        return new File(iconDir, fileName);    }}
  • 裁剪
 /**     * 裁剪     */    private void cropPhoto() {        File file = new FileStorage().createCropFile();        Uri outputUri = Uri.fromFile(file);//缩略图保存地址        Intent intent = new Intent("com.android.camera.action.CROP");        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);        }        intent.setDataAndType(imageUri, "image/*");        intent.putExtra("crop", "true");        intent.putExtra("aspectX", 1);        intent.putExtra("aspectY", 1);        intent.putExtra("scale", true);        intent.putExtra("return-data", false);        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());        intent.putExtra("noFaceDetection", true);        startActivityForResult(intent, REQUEST_PICTURE_CUT);    }
  • 第5步 activity

    @Override  protected void onActivityResult(int requestCode, int resultCode, Intent data) {      //此处为系统拍照截图返回      cameraProxy.onResult(requestCode, resultCode, data);      switch (requestCode) {          case REQUEST_CAPTURE://拍照              if (resultCode == RESULT_OK) {                  cropPhoto();              }              break;          case REQUEST_PICTURE_CUT://裁剪完成              spUtil.setUserHead(imageUri.getPath());              break;      }  }
 
阅读全文
0 0
原创粉丝点击