最近在使用蓝牙进行文件分享时,出现了一个奇怪的问题。同样的代码在android5.1上可以顺利运行,但是在android7.0上就运行失败。出现如下的错误:

Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/bluetooth/data.txt exposed beyond app through ClipData.Item.getUri()

出现这个问题的时候我立刻意识到这是一个兼容的问题,于是在网上找了一些方法,并解决了这个问题,我受到启发的网址是:

​ 出现FileUriExposedException这样的异常,原因是Andorid7.0的“私有目录被限制访问”,“StrictMode API 政策”。
由于从Android7.0开始,直接使用真实的路径的Uri会被认为是不安全的,会抛出一个FileUriExposedException这样的异常。需要使用FileProvider,选择性地将封装过的Uri共享到外部。

即以前的共享代码是这样写的:

Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("*/*");
sharingIntent.setComponent(new ComponentName("com.android.bluetooth","com.android.bluetooth.opp.BluetoothOppLauncherActivity"));
sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path)));
startActivity(sharingIntent);

在android7.0版本以上时,不使用Uri.fromFile(),使用以下的代码:

Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("*/*");
sharingIntent.setComponent(new ComponentName("com.android.bluetooth","com.android.bluetooth.opp.BluetoothOppLauncherActivity"));
sharingIntent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(BluetoothChat.this,"你的包名" + ".fileprovider", new File(path)));
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(sharingIntent);

​ 如果是Andorid7.0或以上,则不再使用Uri.fromFile()方法获取文件的Uri,而是通过使用FileProvider(support.v4提供的类)的getUriForFile()。同时要添加多这么一行代码

sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

由于FileProvider是继承ContentProvider,属于四大组件之一,需要在AndroidManifest.xml中配置,配置如下:

    <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_provider_paths"/>
</provider>

其中android:resource="@xml/file_provider_paths"的内容你可以在res目录下新建一个xml文件夹,在文件夹中新建一个file_provider_paths.xml文件即可,如下图所示

<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path path="" name="myFile"></external-path>
</paths>
</resources>

  上述代码中path=” “,是有特殊意义的,它代码根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了,如果你将path设为path=”pictures”, 那么它代表着根目录下的pictures目录(eg:/storage/emulated/0/pictures),如果你向其它应用分享pictures目录范围之外的文件是不行的。

分享文件代码如下:

    // 調用系統方法分享文件
public static void shareFile(Context context, File file) {
try{
if (null != file && file.exists()) {
Log.w("ppp-params", file.getPath());
Intent share = new Intent(Intent.ACTION_SEND);
share.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(context,"app.zhaohangwuliu.com.appada" + ".fileprovider", file));
share.setType("*/*");//此处可发送多种文件
share.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(share, "分享文件"));
} else {
//Toast.makeText(context, "分享文件不存在", Toast.LENGTH_SHORT).show();
}
}catch (Exception ex){
Log.w("ppp-params", ex);
} }

转: https://blog.csdn.net/kabuto_hui/article/details/78907572

android文件分享在android7.0以上版本报错的解决方案的更多相关文章

  1. appium desktop v1.2.7在android7.0上运行报错“Error: Error executing adbExec”

    1.参考下面链接,https://stackoverflow.com/questions/42283921/unable-to-run-appium-tests-on-android-7-0:得知需要 ...

  2. ve2.0 v-for循环报错的解决方案

    <li v-for="(item,index) in mokeData" class="page" :key="index"> ...

  3. Appium适配Android7.0以上版本

    Appium适配Android7.0以上版本 测试机型: 华为荣耀V9 安卓版本: Android7.0 appium版本: 1.65 说明: 公司新采购了一批安卓机器,拿了其中一台华为荣耀V9跑之前 ...

  4. centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'

    centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'的解决办法 3.7版本需要一个新的包libffi-de ...

  5. 【原创】大叔问题定位分享(20)hdfs文件create写入正常,append写入报错

    最近在hdfs写文件的时候发现一个问题,create写入正常,append写入报错,每次都能重现,代码示例如下: FileSystem fs = FileSystem.get(conf); Outpu ...

  6. 0.4 IDEA报错以及解决方式

    0.4 IDEA报错以及解决方式一.端口被占用 [WARNING] FAILED SelectChannelConnector@0.0.0.0:8080: java.net.BindException ...

  7. iOS-C文件添加到iOS项目中,运行报错

    iOS-C文件添加到iOS项目中,运行报错 问题: 往项目中添加一个空的c文件, 编译运行; 出现2,30个编译错误. 原因: 由于在项目中添加了Pch文件,在文件中所有代码还没有开始运行之前, pc ...

  8. 【spring boot】整合LCN,启动spring boot2.0.3 启动报错:Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.

    spring boot 2.0.3启动报错: Error starting ApplicationContext. To display the conditions report re-run yo ...

  9. ubuntu 16.04 anaconda 4.2.0 安装tensorflow 报错

    ubuntu 16.04 anaconda 4.2.0 安装tensorflow 报错. 安装pyenv后,在pyenv环境内安装 anaconda,然后再安装tensorflow不再报错,比较奇怪, ...

随机推荐

  1. ShareSDK For Unity集成

    Mob ShareSDK Android - V2.7.10 iOS - V3.5.0 Mob下载:https://github.com/MobClub/New-Unity-For-ShareSDK ...

  2. sklearn---DBSCAN

    参考文献: [1]用scikit-learn学习DBSCAN聚类

  3. es6 | 新增语法 | 总结

    电梯 原文 https://www.jianshu.com/p/5f40c43c6f85 重点: 遍历map结构 正则扩展 at相当于charAt() ,可以识别中文normarize()includ ...

  4. ECMAScript规范解读this

    在<JavaScript深入之执行上下文栈>中讲到,当JavaScript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution conte ...

  5. Go语言 - 结构体 | 方法

    自定义类型和类型别名 自定义类型 在Go语言中有一些基本的数据类型,如string.整型.浮点型.布尔等数据类型, Go语言中可以使用type关键字来定义自定义类型. 自定义类型是定义了一个全新的类型 ...

  6. Vant 实现 上拉加载更多

    Vant 的List 组件 默认支持 瀑布流滚动加载.官方的示例是用定时器模拟的数据.我们在项目实战中,肯定是结合ajax请求处理的.那么我们该如何实现这个效果呢? Vant 的 List组件 使用方 ...

  7. ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: ORA-02291: 违反完整约束条件 (SSM.SYS_C0011830) - 未找到父项关键字

    在向Oracle数据库里面插入数据时发生了以下错误 ; ]; ORA-: 违反完整约束条件 (SSM.SYS_C0011830) - 未找到父项关键字 ; nested exception : 违反完 ...

  8. Django3 的服务器搭建

    进入python虚拟环境 执行以下 命令 source env/bin/active 激活并切换虚拟环境 安装 pip3 install django 创建django项目 django-admin ...

  9. UFUN函数 UF_CSYS函数 UF_MTX函数(如何创建坐标系);

    // (题目不够长,写在这了) // 函数有 // UF_MTX3_initialize,UF_CSYS_create_matrix,UF_CSYS_create_csys,UF_CSYS_ask_c ...

  10. MYSQL中group_concat( )函数中参数的排序方法

    使用mysql中的group_concat( )函数连接指定字段时,可以先对该字段进行排序. PS:是因为二刷mysql的51道题的第12题遇到的:查询和" 01 "号同学学习的课 ...