android文件分享在android7.0以上版本报错的解决方案
最近在使用蓝牙进行文件分享时,出现了一个奇怪的问题。同样的代码在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以上版本报错的解决方案的更多相关文章
- 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:得知需要 ...
- ve2.0 v-for循环报错的解决方案
<li v-for="(item,index) in mokeData" class="page" :key="index"> ...
- Appium适配Android7.0以上版本
Appium适配Android7.0以上版本 测试机型: 华为荣耀V9 安卓版本: Android7.0 appium版本: 1.65 说明: 公司新采购了一批安卓机器,拿了其中一台华为荣耀V9跑之前 ...
- centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'
centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'的解决办法 3.7版本需要一个新的包libffi-de ...
- 【原创】大叔问题定位分享(20)hdfs文件create写入正常,append写入报错
最近在hdfs写文件的时候发现一个问题,create写入正常,append写入报错,每次都能重现,代码示例如下: FileSystem fs = FileSystem.get(conf); Outpu ...
- 0.4 IDEA报错以及解决方式
0.4 IDEA报错以及解决方式一.端口被占用 [WARNING] FAILED SelectChannelConnector@0.0.0.0:8080: java.net.BindException ...
- iOS-C文件添加到iOS项目中,运行报错
iOS-C文件添加到iOS项目中,运行报错 问题: 往项目中添加一个空的c文件, 编译运行; 出现2,30个编译错误. 原因: 由于在项目中添加了Pch文件,在文件中所有代码还没有开始运行之前, pc ...
- 【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 ...
- ubuntu 16.04 anaconda 4.2.0 安装tensorflow 报错
ubuntu 16.04 anaconda 4.2.0 安装tensorflow 报错. 安装pyenv后,在pyenv环境内安装 anaconda,然后再安装tensorflow不再报错,比较奇怪, ...
随机推荐
- Android中UID和PID的作用和区别
PID:为Process Identifier, PID就是各进程的身份标识,程序一运行系统就会自动分配给进程一个独一无二的PID.进程中止后PID被系统回收,可能会被继续分配给新运行的程序,但是在a ...
- oVirt部署
所有前提建议: 关闭防火墙.selinux,配置hosts,计算机名使用域名 ovirt-engine部署 yum install http://resources.ovirt.org/pub/yum ...
- Spring Cloud Consul Config 知识点
Spring Cloud Consul Config 是 Config Server 和 Client的替代方案. 搭建一个配置中心,可以选择的方案: Spring Cloud Config 或者 S ...
- Spring Boot 中集成 Redis 作为数据缓存
只添加注解:@Cacheable,不配置key时,redis 中默认存的 key 是:users::SimpleKey [](1.redis-cli 中,通过命令:keys * 查看:2.key:缓存 ...
- wordpress调用指定tag的文章
前面的文章wordpress调用指定分类文章如何实现有网友回复要如何调用指定tag的文章,原理是类似的,有两种方法,随ytkah一起来看看 1.第一种 <?php $args=array( 't ...
- IMP本质上是一个通用的函数指针
IMP:通用的函数指针 /// A pointer to the function of a method implementation. #if !OBJC_OLD_DISPATCH_PROTOTY ...
- Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要
译文:https://blog.csdn.net/fangxing80/article/details/7381619 原文:http://www.atmarkit.co.jp/fdotnet/int ...
- Python3 连接各类数据库
Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口.它定义了一系列必须的对象和数据库存取方式, 以便为各种各样的底层数据库系统和多 ...
- cf1173 D. Nauuo and Circle
链接 [cf]http://codeforces.com/contest/1175/problem/F) 思路 当1在1的位置做dp[i]为i的子树所有的方案. 一条性质是i的子树所占圆上的位置一定一 ...
- .NET总结--ASP.NET工作原理
前言 前前后后写了不少关于某些技术啥的博客,一直在追新求深,而真正使用上的时候才发现了解的太少太少了,从事.net开发三年有余了不是它不行了而是我坚持不住了,如今不得不向生活低头,这个系列作为三年技术 ...