Android || FileProvider 控件的使用

1 FileProvider 概述

FileProvider 是ContentProvider 的子类。 ContentProvider 用于应用间的数据共享,FileProvider 用于不用应用间的文件共享。

FileProvider 的共享流程

  • 与ContentProvider 相似:
    当一个 请求文件的 client app 想要向共享了文件的 Server app 发送请求来获取文件,大多数情况,该请求第一个会开启一个分享的文件列表的 Activity(该 Activity隶属于Server app,目的是为了让用户选择先要获取的文件,因为他可能分享了不止一个文件)。
    用户选择文件之后,Server app返回文件的 Uri 和权限给 client app。client app根据 Uri 去找文件,有了权限也就能对该文件进行读写操作了。

为什么选择使用 Uri

  • 如果直接将文件传输为 client app:当该文件非常大时,十分消耗资源。
    如果将文件的地址传给 client app:这样相当于把自身的app的文件共享地址暴露出来。这是非常危险的,我们无法估计其他app拿到这个地址之后的操作。如果这个地址下也有其他的共享文件,就不能保证他们的安全。

  • 因此,app共享文件以一种提供content Uri的形式提供一个对文件的安全操作:android 中的 FileProvider 组件通过 getUriForFile 方法为 File 生成一个 Content Uri。

2 FileProvider 的使用流程


2.1 注册 FileProvider

和 ContentProvider一样,需要在Manifest 文件中等记,在manifest 中指定 authority属性用来生成 content Uri。
额外的,必须指定一个分享 xml 文件的目录,所以分享的 xml 文件都在该目录下。

<provider
   android:name="androidx.core.content.FileProvider"
   android:authorities="${applicationId}.fileprovider"
   android:exported="false"
   android:grantUriPermissions="true">
   <meta-data
       android:name="android.support.FILE_PROVIDER_PATHS"
       android:resource="@xml/file_paths" />
</provider>
  • name 一般固定为android.support.v4.content.FileProvider。如果开发者继承了FileProvider,则可以写上其绝对路径。
  • authorities 字段的值是一个由 build.gradle 文件中的 applicationId 值和自定义的名称 组成的 Uri 字符串(这样写是约定俗成的)。用来表明使用的使用者,在FileProvider的函数getUriForFile需要传入该参数。
  • exported 的值为false,表示该FileProvider只能本应用使用,不是public的。
  • grantUriPermissions 的值为true,表示允许赋予临时权限。
  • <meta-data> resourece 属性指向 res/xml/file_paths 文件,在这个文件中存放的是想要分享的目录。

2.2 添加共享目录

在 res/xml/file_paths.xml 文件,指名目录

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <files-path name="my_images" path="images/"/>
</resources>
  • 元素必须包含一到多个子元素,这些子元素用于指定共享文件的目录路径:
    <file-path>:内部存储空间应用私有目录下的 files/ 目录,即 Content.getFilesDir() 所获得的的路径
    <cache-path>:内部存储空间应用私有目录下的 cache/ 目录,即 Content.getCacheDir() 所获得的的路径
    <external-path>:外部存储空间根目录,即 Environment.getExternalStorageDirectory() 所获得的的路径
    <external-file-path>:外部存储空间应用私有目录下的 files/ 目录,即 Context.getExternalFilesDir(null) 所获得的的路径
    <external-cache-path>:外部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getExternalCacheDir()
  • 上面的5种基本涵盖内外存储空间所有目录路径,包含应用私有目录。其中,都会有 name 和path 两个属性
    path:用于指定当前子元素所代表目录下需要共享的子目录名称。注意:path属性值不能直接使用具体的独立文件名,只能是目录名
    name:用于给path 属性所指定的子目录名称取一个别名。后续生成 content:// URI 时,会使用这个别名替代真实目录名。可以提供安全性。

2.3 生成 Content URI

在 Android 7.0 出现之前,通常使用 Uri.fromFile() 方式生成一个 File URI。现在这里,使用 FileProvider 类提供的公有静态方法 getUriForFile 生成 Content URI。

Uri contentUri = FileProvider.getUriForFile(this, 
        BuildConfig.APPLICATION_ID + " myprovider", myFile);

其中,第2个参数是 Manifest 文件中注册 FileProvider 时设置的 authority 属性值;第3个参数是要共享的文件,并且这个文件一定位于第二步在 path 文件中添加的子目录中。

String filePath = Environment.getExternalStorageDirectory() + "/images/"+System.currentTimeMillis()+".jpg"; 
File outputFile = new File(filePath); 
if (!outputFile.getParentFile().exists()) { 
   outputFile.getParentFile().mkdir(); 
} 
Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".myprovider", outputFile);

生成的 Content URI:
【content://com.yifeng.samples.myprovider/my_images/1493715330339.jpg】
其中,构成URI的【host 】部分为 <provider> 元素的 authorties 属性值(applicationId + customname);【path】片段 my_images 为 res/xml 问文件中指定的子目录别名(真实名为 images)


2.4 授予访问权限

生成 Content URI 对象后,需要对其授权访问权限。授权方式有两种:

  • 第一种方式,使用 Context 提供的 grantUriPermission(package, Uri, mode_flags) 方法向其他应用授权访问 URI 对象。三个参数分别表示授权访问 URI 对象的其他应用包名,授权访问的 Uri 对象,和授权类型。其中,授权类型为 Intent 类提供的读写类型常量:
    FLAG_GRANT_READ_URI_PERMISSION FLAG_GRANT_WRITE_URI_PERMISSION
    或者二者同时授权。这种形式的授权方式,权限有效期截止至发生设备重启或者手动调用 revokeUriPermission() 方法撤销授权时。
  • 第二种方式,配合 Intent 使用。通过 setData() 方法向 intent 对象添加 Content URI。然后使用 setFlags() 或者 addFlags() 方法设置读写权限,可选常量值同上。这种形式的授权方式,权限有效期截止至其它应用所处的堆栈销毁,并且一旦授权给某一个组件后,该应用的其它组件拥有相同的访问权限。

2.5 提供 Content URI 给其它应用

拥有授予权限的 Content URI 后,便可以通过 startActivity() 或者 setResult() 方法启动其他应用并传递授权过的 Content URI 数据。当然,也有其他方式提供服务。
如果你需要一次性传递多个 URI 对象,可以使用 intent 对象提供的 setClipData() 方法,并且 setFlags() 方法设置的权限适用于所有 Content URIs。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 是Google开发的基于Linux平台的开源手机操作系统。它包括操作系统、用户界面和应用程序—— 移动电话工作所需的全部软件,而且不存在任何以往阻碍移动产业创新的专有权障碍。 Android以Java为编程语言,使接口到功能,都有层出不穷的变化,其中Activity等同于J2ME的MIDlet,一个 Activity 类(class)负责创建视窗(window),一个活动中的Activity就是在 foreground(前景)模式,背景运行的程序叫做Service。两者之间通过由ServiceConnection和AIDL连结,达到复数程序同时运行的效果。 Android基础阶段:平台架构特性(JAVA/C) Market/应用程序组件 环境搭建与部署/打包与发布 AVD/DDMS/AAPT 调试与测试 相关资源访问/资源制作 Activity/Service/Broadcast Receiver/Content Provider/原理(生命周期)及深层实现. Android进阶初级:组件Widget/ 菜单Menu/ 布局Layout 详解 Xml解析(Pull/Dom/Sax)/JNI 解析SQL数据库原理, SQLit e /SharedPreferences/File详解 多媒体Audio/Video/Camera 详解 Android进阶高级:蓝牙/WIFI SMS/MMS 应用实现 深层次解析GPS原理,实现LocationManager/LocationProvider 进行定位/跟踪/查找/趋近警告以及Geocoder正逆向编解码等技术细节 2D图形库(Graphics/View)详解 SDCARD/传感器/手势 应用实现 《老罗Android视频教程(第一季)》的视频一共分为15个章节, 涵盖了Android入门、常用UI布局介绍、HTTP编程、 XML与Json数据解析、JDBC与Web编程、常用UI控件、 数据储存与文件操作、对话框、通知、菜单、 LoaderManager异步加载、多线程(AsyncTask与Handler)、 百度地图等十五个模块,一共102集。 本网盘分享章节编号是按照视频更新的先后顺序编号的,具体学习可参考如下章节顺序: 【第一版第一章】老罗Android开发视频--入门介绍(9集) 【第一版第二章】老罗Android开发视频--常用UI布局介绍(5集) 【第一版第三章】老罗Android开发视频--HTTP协议编程(4集) 【第一版第四章】老罗Android开发视频--解析XML数据(3集) 【第一版第五章】老罗Android开发视频--解析JSON数据(4集) 【第一版第六章】老罗Android开发视频--服务器端JDBC编程(2集) 【第一版第七章】老罗Android开发视频--服务器端Web编程(6集) 【第一版第八章】老罗Android开发视频-常用UI控件(33集) 【第一版第九章】老罗Android开发视频--存储数据和文件(7集) 【第一版第十章】老罗Android开发视频--对话框介绍(4集) 【第一版第十一章】老罗Android开发视频--通知的使用(2集) 【第一版第十二章】老罗Android开发视频--菜单的使用(4集) 【第一版第十三章】老罗Android开发视频--异步加载数据库(2集) 【第一版第十四章】老罗Android开发视频--多线程编程(7集) 【第一版第十五章】老罗Android开发视频--百度地图实战开发(10集)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值