Android 调用自带相机抛FileUriExposedException异常

2023-10-29 02:40

本文主要是介绍Android 调用自带相机抛FileUriExposedException异常,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

     最近公司业务需求,做一个类似淘宝,京东的拍照搜索商品的功能,这里搜索引擎使用的是百度的AI搜图,效果整体还不错。服务端接口接收的参数是一个图片文件,这里就需要使用到Android自带相机,按照常规的用法写完后在某些手机上报错,查看log FileUriExposedException,抛出这样一个异常.

  上网查阅了资料后得知在Android 7.0以后的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。

   解决办法:

   Google给出的解决办法使用FileProvider ,FileProvider是v4包中一个继承ContentProvider的子类,位置是android.support.v4.content,他可以通过File创建一个content://类型的Uri而不是file://类型的Uri.

使用步骤:

1.manifest中申明FileProvider


android:name:provider你可以使用v4包提供的FileProvider,或者自定义您自己的,只需要在name申明就好了,一般使用系统的就足够了。
android:authorities:类似schema,命名空间之类,后面会用到。
android:exported:false表示我们的provider不需要对外开放。
android:grantUriPermissions:申明为true,你才能获取临时共享权限

2.res/xml中定义对外暴露的文件夹路径

在res文件夹下创建名为xml的文件夹,然后再xml文件夹下创建名为file_paths.xml(注:在manifest android:resource="@xml/file_paths"处引用此文件
)


name:一个引用字符串。

path:文件夹“相对路径”,完整路径取决于当前的标签类型。


paths节点下有很多取值:

<files-path name="name" path="path" /> 物理路径相当于Context.getFilesDir() + /path/。
<cache-path name="name" path="path" /> 物理路径相当于Context.getCacheDir() + /path/。
<external-path name="name" path="path" /> 物理路径相当于Environment.getExternalStorageDirectory() + /path/。
<external-files-path name="name" path="path" /> 物理路径相当于**Context.getExternalFilesDir(String) **+ /path/。
<external-cache-path name="name" path="path" />物理路径相当于Context.getExternalCacheDir() + /path/。

<root-path name="name" path="path" /> 物理路径相当于/path/。

3.生成content://类型的Uri

平常我们写法是这样的,在7.0后就会抛出FileUriExposedException:

File picFile = xxx;
Uri picUri = Uri.fromFile(picFile);

所以我们需要使用content来生成URL

Url  uri = FileProvider.getUriForFile(fragment.getActivity(), "com.jiemeihome.internal", getFile());


4.给Uri授予临时权限

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);  
Intent.FLAG_GRANT_READ_URI_PERMISSION //表示可读
Intent.FLAG_GRANT_WRITE_URI_PERMISSION//表示可写

权限的添加视项目需求而定.

5.使用Intent传递Uri

项目中需要使用到相机和相册代码如下:

public static void startCarmera(Fragment fragment) {Uri uri;
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        uri = FileProvider.getUriForFile(fragment.getActivity(), "com.jiemeihome.internal", getFile());
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    } else {intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getFile()));
    }fragment.startActivityForResult(intent, RESULT_CAMERA);
}
public static void startGallery(Activity activity) {Intent intentGallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    activity.startActivityForResult(intentGallery, RESULT_GALLERY);
}

public static File getFile() {File newFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/images/" + System.currentTimeMillis() + ".jpg");
    if (!newFile.exists()) {newFile.getParentFile().mkdirs();
    }mCurrentPhotoPath = newFile.getAbsolutePath();
    return newFile;
}

然后再onActivityResult()中处理接收返回的图片:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {if (requestCode == RESULT_CAMERA) {upload(CarmeraUtil.mCurrentPhotoPath);
        } else if (requestCode == RESULT_GALLERY && data != null) {//处理来自图库的照片
            Uri selectedImage = data.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(selectedImage,
                    filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String picturePath = cursor.getString(columnIndex);
            cursor.close();
            upload(picturePath);
        }}
}
 

 

这篇关于Android 调用自带相机抛FileUriExposedException异常的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/297711

相关文章

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

C#文件复制异常:"未能找到文件"的解决方案与预防措施

《C#文件复制异常:未能找到文件的解决方案与预防措施》在C#开发中,文件操作是基础中的基础,但有时最基础的File.Copy()方法也会抛出令人困惑的异常,当targetFilePath设置为D:2... 目录一个看似简单的文件操作问题问题重现与错误分析错误代码示例错误信息根本原因分析全面解决方案1. 确保

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Java利用@SneakyThrows注解提升异常处理效率详解

《Java利用@SneakyThrows注解提升异常处理效率详解》这篇文章将深度剖析@SneakyThrows的原理,用法,适用场景以及隐藏的陷阱,看看它如何让Java异常处理效率飙升50%,感兴趣的... 目录前言一、检查型异常的“诅咒”:为什么Java开发者讨厌它1.1 检查型异常的痛点1.2 为什么说

Java调用Python脚本实现HelloWorld的示例详解

《Java调用Python脚本实现HelloWorld的示例详解》作为程序员,我们经常会遇到需要在Java项目中调用Python脚本的场景,下面我们来看看如何从基础到进阶,一步步实现Java与Pyth... 目录一、环境准备二、基础调用:使用 Runtime.exec()2.1 实现步骤2.2 代码解析三、

Python如何调用另一个类的方法和属性

《Python如何调用另一个类的方法和属性》在Python面向对象编程中,类与类之间的交互是非常常见的场景,本文将详细介绍在Python中一个类如何调用另一个类的方法和属性,大家可以根据需要进行选择... 目录一、前言二、基本调用方式通过实例化调用通过类继承调用三、高级调用方式通过组合方式调用通过类方法/静

Java异常捕获及处理方式详解

《Java异常捕获及处理方式详解》异常处理是Java编程中非常重要的一部分,它允许我们在程序运行时捕获并处理错误或不预期的行为,而不是让程序直接崩溃,本文将介绍Java中如何捕获异常,以及常用的异常处... 目录前言什么是异常?Java异常的基本语法解释:1. 捕获异常并处理示例1:捕获并处理单个异常解释:

C#控制台程序同步调用WebApi实现方式

《C#控制台程序同步调用WebApi实现方式》控制台程序作为Job时,需同步调用WebApi以确保获取返回结果后执行后续操作,否则会引发TaskCanceledException异常,同步处理可避免异... 目录同步调用WebApi方法Cls001类里面的写法总结控制台程序一般当作Job使用,有时候需要控制

Python用Flask封装API及调用详解

《Python用Flask封装API及调用详解》本文介绍Flask的优势(轻量、灵活、易扩展),对比GET/POST表单/JSON请求方式,涵盖错误处理、开发建议及生产环境部署注意事项... 目录一、Flask的优势一、基础设置二、GET请求方式服务端代码客户端调用三、POST表单方式服务端代码客户端调用四