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

相关文章

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

python如何调用java的jar包

《python如何调用java的jar包》这篇文章主要为大家详细介绍了python如何调用java的jar包,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录一、安装包二、使用步骤三、代码演示四、自己写一个jar包五、打包步骤六、方法补充一、安装包pip3 install

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET