原文首发于微信公众号:躬行之,欢迎关注交流!

开发中经常需要将某个文件向另一个应用程序传递,如图片上传到另一个应用程序、文件在不同存储路径之间的复制粘贴等都需要共享文件,可以这样理解接收文件的应用是在向提供文件的应用发送请求。

从 Android 7.0 开始,Android 执行 StrictMode 策略,禁止在应用外部公开 file://URL,如果在 Android 7.0 以上的应用不使用 FileProvider ,则会抛出 FileUriExposedException 异常,Android 7.0 以后要在应用之间共享文件要使用 content://URL 授予 URL 临时访问权限,即要使用 FileProvider 的方式来授予临时访问权限,具有临时访问权限的 URL 是安全的,这种临时的 URL 会自动过期,其中 FileProvider 提供的 getUriForFile() 用于生成文件的内容。

在所有情况下,从您的应用程序向另一个应用程序提供文件的唯一安全方法是向接收应用程序发送文件的内容URI,并授予该URI的临时访问权限。具有临时URI访问权限的内容URI是安全的,因为它们仅适用于接收URI的应用程序,并且它们会自动过期。 Android FileProvider组件提供getUriForFile()方法,用于生成文件的内容URI。

这里也会提到一个在 Android 7.0 及更高版本时经常出现的异常:FileUriExposedException,通过使用 FileProvider 就可以解决该异常,当然这也是 Android 系统在安全性上不断完善的结果。

  1. 指定FileProvider
  2. 指定文件共享路径

指定FileProvider

在 AndroidManifest 文件中指定 Provider,参考如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application
...> <!--android:authorities="${applicationId}.yourname"-->
<provider
android:name="android.support.v4.content.FileProvider"
<!--authorities属性指定要用于FileProvider生成的内容URI的URI权限,一般是applicationId.yourname"组成-->
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
...
</application>
</manifest>

指定文件共享路径

上面代码中在 meta-data 目录中指定了要共享的文件目录,文件目录在 filepathd.xml 中定义,可在相应的 xml 中定义的路径有以下几种,具体参考如下:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths> <!--表示设备的根目录(new File("/"))-->
<root-path name="root" path="" />
<!--表示context.getFileDir()-->
<files-path name="files" path="" />
<!--表示context.getCacheDir()-->
<cache-path name="cache" path="" />
<!--表示Environment.getExternalStorageDirectory()-->
<external-path name="external" path="" />
<!--表示context.getExternalFilesDirs()-->
<external-files-path name="name" path="path" />
<!--表示getExternalCacheDirs()-->
<external-cache-path name="name" path="path" /> </paths>
</resources>

在 xml 中表示某个路径需要两个属性,path 表示当前指定目录的子目录,如果不指定则表示的是当前指定目录下的根目录及子目录,name 表示会将 name 添加的 URL 后面作为该文件的访问路径,参考如下:

//表示当前要共享的文件会在 context.getFileDir() 目录下的 images 子目录下查找要共享的文件
<paths>
<files-path path="images/" name="myImage" />
</paths> //表示最终生成的共享的文件URL
content://com.example.myapp.fileprovider/myImage/image.jpg

获取Uri

最后,配置完成之后,在所有需要使用文件相关的,在获取 Url 时应该按照如下方式获取,具体如下:

public Uri getUri(File file) {
Uri uri = null;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(mContext, mContext.getPackageName() + ".youName", file);
} else {
uri = Uri.fromFile(file);
}
return uri;
}

这样就可以在 Android 7.0 以上愉快的共享文件了,这个知识点也算是开发中经常会遇到到。

Android 7.0应用之间共享文件的更多相关文章

  1. Android 7.0 通过FileProvider共享文件

    一.概述 Android 7.0后,提供了很多新特性,其中最主要的是禁止了通过file://URI直接在文件操作共享文件(该操作会触发FileUriExposedException),而是通过cont ...

  2. android 7.0以上共享文件(解决调用系统照相和图片剪切出现的FileUriExposedException崩溃问题)

    在android7.0开始试共享“file://”URI 将会导致引发 FileUriExposedException. 如果应用需要与其他应用共享私有文件,则应该使用 FileProvider, F ...

  3. 关于Android 7.0(API24)相机的问题汇总

    在开发Android项目的时候,我们会用到相机,有些时候只是开发一个普通的扫码,仅仅赋予一下 权限 就好了,但是有些时候是需要拍照和从相册中获取照片的.我们在Android 5.0以及5.0之前调用相 ...

  4. Android 7.0 行为变更

    Android 7.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更.本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更. 如果您之前发布过 Android 应用,请注意 ...

  5. Android 7.0新特性

    还望支持个人博客站:http://www.enjoytoday.cn 由于google目前不是无法直接在国内访问,故此,对于android 开发平台的7.0新特性做个保存.也可供大家查阅.原文转自an ...

  6. Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...

  7. Android 6.0 新功能及主要 API 变更

    运行时权限 这个版本中引入了新的权限模型,现在用户可以在运行时直接管理应用程序的权限.这个模型基于用户对权限控制的更多可见性,同时为应用程序的开发者提供更流畅的应用安装和自动升级.用户可以为已安装的每 ...

  8. [转]Android 5.0——Material Design详解(动画篇)

    Material Design:Google推出的一个全新的设计语言,它的特点就是拟物扁平化. Material Design包含了很多内容,今天跟大家分享一下Material新增的动画: 在Andr ...

  9. Android 6.0 Changes

    原文链接:http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html 伴随着新特性和功能,Andr ...

随机推荐

  1. 14.java设计模式之命令模式

    基本需求: 一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装app就可以控制对这些家电工作 这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个App分别控制,我们希望只要一个 ...

  2. 牛客练习赛71 数学考试 题解(dp)

    题目链接 题目大意 要你求出有多少个长度为n的排列满足m个限制条件 第i个限制条件 p[i]表示前 p[i]个数不能是1-p[i]的排列 题目思路 这个感觉是dp但是不知道怎么dp 首先就是要明白如果 ...

  3. dubbo协议之请求头编码器

    开局一张图,内容全靠XXXXX.... 如图是dubbo协议的格式 encodeRequest进来会先去channel对象中取url的Parameters的"serialization&qu ...

  4. CentOS下搭建简易iSCSI服务

    iscsi 服务器端设置 安装target包 yum install scsi-target-utils.x86_64 创建测试裸磁盘 dd if=/dev/zero of=/iSCSIdisk/20 ...

  5. python 二维数组赋值问题

    [[]]是一个含有一个空列表元素的列表,所以[[]]*3表示3个指向这个空列表元素的引用, 修改任何一个元素都会改变整个列表 所以需要用另外一种方式进行创建多维数组,以免浅拷贝 >>> ...

  6. linux下iptables原理

    原文链接:https://www.cnblogs.com/ggjucheng/archive/2012/08/19/2646466.html iptables简介 netfilter/iptables ...

  7. Java 生成有序 UUID

    UUID.randomUUID() 生成的 UUID 是无序的,如果作为数据主键,不利于索引 Hibernate 的 UUIDHexGenerator.generate() 方法可以生成有序的 UUI ...

  8. RabbitMQ Go客户端教程5——topic

    本文翻译自RabbitMQ官网的Go语言客户端系列教程,本文首发于我的个人博客:liwenzhou.com,教程共分为六篇,本文是第五篇--topic. 这些教程涵盖了使用RabbitMQ创建消息传递 ...

  9. Python中函数是否能使用全局变量?

    Python函数中的变量,既可以使用局部变量(本地名字空间的变量),也可以使用全局变量(全局名字空间的变量),函数在执行查找变量只读时,先在局部变量中查找,找不到再查到全局变量中查找.因此当局部变量和 ...

  10. PyQt(Python+Qt)学习随笔:Designer中ItemViews类部件的frameShadow属性

    老猿Python博文目录 老猿Python博客地址 frameShadow属性是从QFrame继承的属性,对应类型为QFrame.Shadow,该属性表示框架提供三维效果的阴影类型,有如下取值: 可以 ...