两个小解释:
FileProvider是ContentProvider特殊的子类,ContentProvider通过创建content:// Uri来替代file:/// Uri。
在Android 7.0的以上的系统中,尝试传递file://URI可能会触发FileUriExposedException
FileProvider的这个概述包括以下主题:
1.定义FileProvider
2.指定可用文件
3.检索文件的Content URI
4.授予URI的临时权限
5.将内容URI提供给其他应用程序
第一步:定义FileProvider:
//清单文件中 <provider android:name="android.support.v4.content.FileProvider"//固定 android:authorities="${applicationId}.yourname"//根据您控制的域将属性设置为URI权限 android:exported="false"//FileProvider不需要公开 android:grantUriPermissions="true">//允许您授予对文件的临时访问权限 ... </provider>
第二步:指定可用文件
//新建一个xml文件用于存放应用需要共享的目录文件 //以下paths元素告诉FileProvider您打算为images/私有文件区域的子目录请求内容URI <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path name="my_images" path="images/"/> ... </paths>
该元素必须包含一个或多个以下子元素:
//代表内部存储空间应用私有目录下的 files/ 目录,等同于 Context.getFilesDir() 所获取的目录路径; <files-path name = “ name ” path = “ path ” /> //代表内部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getCacheDir() 所获取的目录路径; <cache-path name = “ name ” path = “ path ” /> //代表外部存储空间根目录,等同于 Environment.getExternalStorageDirectory() 所获取的目录路径; <external-path name = “ name ” path = “ path ” /> //代表外部存储空间应用私有目录下的 files/ 目录,等同于 Context.getExternalFilesDir(null) 所获取的目录路径; <external-files-path name = “ name ” path = “ path ” /> //代表外部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getExternalCacheDir(); <external-cache-path name = “ name ” path = “ path ” /> //代表外部媒体区域根目录中的文件。等同于Context.getExternalMediaDirs()。 <external-media-path name = “ name ” path = “ path ” />
这些子元素都使用两个相同的属性:
name="name"
一个URI路径段。 用于给 path 属性所指定的子目录名称取一个别名 为了提高安全性,此值将隐藏您要共享的子目录的名称。该值的子目录名称包含在该 path属性中。
path="path"
你正在分享的子目录。虽然该name属性是一个URI路径段,但该path值是实际的子目录名称。请注意,该值是指一个子目录,而不是独立文件名。您无法通过文件名共享单个文件,也无法使用通配符指定文件的子集。
第三步:检索文件的 Content URI
//使用 FileProvider 类提供的公有静态方法 getUriForFile 生成 Content URI //第一个参数:context上下文 //第二个参数: Manifest 文件中注册 FileProvider 时设置的 authorities 属性值 //第三个参数:要共享的文件,并且这个文件一定位于第二步我们在 path 文件中添加的子目录里面 Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".myprovider", myFile);
第四步:授予URI的临时权限
授权方式有两种:
第一种方式:
//调用方法: //参数1:授权访问 URI 对象的其他应用包名 //参数2:授权访问的 Uri 对象 //参数3:授权类型FLAG_GRANT_READ_URI_PERMISSION 或者 FLAG_GRANT_WRITE_URI_PERMISSION (或者二者同时授权。这种形式的授权方式,权限有效期截止至发生设备重启或者手动调用 revokeUriPermission() 方法撤销授权时) grantUriPermission(package, Uri, mode_flags)
第二种方式:
//配合intent使用 //权限有效期截止至其它应用所处的堆栈销毁,并且一旦授权给某一个组件后,该应用的其它组件拥有相同的访问权限。 Intent.setFlags() 或者 Intent.addFlags() Intent.setData(Uri uri);
第五步:将内容URI提供给其他应用程序
//通过以下方法启动其他应用并传递授权过的 Content URI 数据。当然,也有其他方式提供服务。 startActivity()
或者
startActivityResult()
或者
setResult()
官方原文(需要自备梯子,想自己搭的教程点击这里): Google Develpers - FileProvider
以下是一个我这边的例子:
场景:版本更新完成时打开新版本 apk 文件实现自动安装
//在 res/xml 目录下新建一个filepath文件 并指定子目录路径信息 <?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="external_path" path="."/> <cache-path name="cache_path" path="."/> </paths>
//Manifest 文件中注册 FileProvider 对象,并链接上面的 path 路径文件 <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.xxx.FileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepath"/> </provider>
//授权 打开安装管理器安装apk包 Intent intent = new Intent(Intent.ACTION_VIEW); intent.addCategory("android.intent.category.DEFAULT"); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri uri = UriUtil.getUriForFile(BitZApplication.mContext.get(), new File((String) msg.obj)); intent.setDataAndType(uri, "application/vnd.android.package-archive"); startActivity(intent); //UriUtil工具类: public static Uri getUriForFile(Context context, File file) { if (context == null || file == null) { throw new NullPointerException(); } Uri uri; if (Build.VERSION.SDK_INT >= 24) { uri = FileProvider.getUriForFile(context, "com.xxx.FileProvider", file); } else { uri = Uri.fromFile(file); } return uri; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍适配android7.0获取文件的Uri的方法,包括了适配android7.0获取文件的Uri的方法的使用技巧和注意事项,需要的朋友参考一下 前言# Android 7.0已经发布很久了,虽然市场份额还不是很高,但是流行起来都是早晚的事,所以适配Android 7.0刻不容缓。 Android 7.0 对系统进行了很多的优化:例如文件访问权限,省电,网络,后台等等,其中最突出的就是应
本文向大家介绍Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0),包括了Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)的使用技巧和注意事项,需要的朋友参考一下 Feature: 点击选择拍照或者打开相册,选取图片进行裁剪最后设置为圆形头像。 Problem: 拍好照片,点击裁剪,弹Toast“无法加载此图片”。 Sol
问题内容: 关于数据库,我是一个相对新手。我们正在使用MySQL,而我目前正在尝试加速似乎需要一段时间才能运行的SQL语句。我四处寻找类似问题,但没有找到。 目的是删除表A中表B中具有匹配ID的所有行。 我目前正在执行以下操作: 表a中约有10万行,表b中有约22k行。列“ id”是两个表的PK。 在我的测试箱上运行此语句大约需要3分钟-Pentium D,XP SP3、2GB内存,MySQL 5
本文向大家介绍解决Android7.0更新后无法安装的问题,包括了解决Android7.0更新后无法安装的问题的使用技巧和注意事项,需要的朋友参考一下 最近在我们的应用中加入更新功能,按照往常一样加入代码 在测试机上一运行,妥妥的能安装,就此完事,然后我把它打包后发到我自己的手机上(Android7.1.1)上,下载安装,居然报错了,然后我的同事就说你看看7.0以上的文件,好像加了限制了,于是上百
如果我创建一个SFTP入站通道适配器,并使用在SFTP中配置为channel属性的通道发送一些文件。文件将传输到SFTP远程目录本地目录,还是直接从通道流到本地目录
在我的主要活动中,我有三个循环利用的观点。 其中一个在底部工作表中,它是主要的(默认情况下,底部工作表是打开以显示这个),在其适配器的onbind方法中,我做了一个onClickListener,以便当用户单击其中的项目时,我想要, 我想回到主活动类来设置To Start一个方法,它的滚动是关闭底表并为下一个回收视图设置数据(当底表关闭时会出现) ......这里的问题是如何从onBind方法的L