最近在使用蓝牙进行文件分享时,出现了一个奇怪的问题。同样的代码在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. Linux必知必会--vmstat

    视野.格局.胸怀.魄力 ---无 参考资料:https://man.linuxde.net/vmstat http://www.ha97.com/4512.html vmstat命令的含义为显示虚拟内 ...

  2. rn 环境搭建

    https://reactnative.cn/docs/next/getting-started.html 搭建开发环境 欢迎使用 React Native!这篇文档会帮助你搭建基本的 React N ...

  3. 第五篇 -- Xml序列化

    XML序列化是将对象的公共属性和字段转换为XML格式,以便存储或传输的过程.反序列化则是从XML输出中重新创建原始状态的对象.XML序列化中最主要的类是XmlSerializer类.它的最重要的方法是 ...

  4. selenium入门知识

    自动化测试 重复测试.性能测试.压力测试 快速.可靠.可重复.可程序化.广泛的 自动化测试适合场合 回归测试.更多更频繁的测试.手工测试无法实现的工作.跨平台产品的测试.重复性很强的操作 不适合场合 ...

  5. 用户体验报告(Echo)

    班级:软件工程1916|W 作业:项目Beta冲刺(团队) 团队名称:Echo 团队博客汇总 队员学号 队员姓名 个人博客地址 备注 221600136 张至锋 https://www.cnblogs ...

  6. 配置/更改vue项目中的资源路径

    打开 build/webpack.base.conf.js  ,在module.exports .resolve.alias下自定义: alias: { 'vue$': 'vue/dist/vue.e ...

  7. PLSQL 美化规则文件详解

    PL/SQL中有个代码优化的功能,里面可以定义规则,挺好用的,跟大家分享下: 1.首先新建一个my.br文件,在文件中复制以下内容 Version=1 RightMargin=90 Indent=4 ...

  8. 证明StringBuffer线程安全,StringBuilder线程不安全

    证明StringBuffer线程安全,StringBuilder线程不安全证明StringBuffer线程安全StringBuilder线程不安全测试思想测试代码结果源码分析测试思想分别用1000个线 ...

  9. 9-网页,网站,微信公众号基础入门(使用PHP实现微信token验证)

    https://www.cnblogs.com/yangfengwu/p/11062422.html 这一节看怎么用PHP实现上一节的功能 关掉上一节的 学了这么久,忘了告诉大家怎么关闭程序了.... ...

  10. LOJ#6229. 这是一道简单的数学题(莫比乌斯反演+杜教筛)

    题目链接 \(Description\) 求\[\sum_{i=1}^n\sum_{j=1}^i\frac{lcm(i,j)}{gcd(i,j)}\] 答案对\(10^9+7\)取模. \(n< ...