android 7 post,Android7.0行为变更:适配File Provider

两个小解释:

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:

//清单文件中

android:name="android.support.v4.content.FileProvider"//固定

android:authorities="${applicationId}.yourname"//根据您控制的域将属性设置为URI权限

android:exported="false"//FileProvider不需要公开

android:grantUriPermissions="true">//允许您授予对文件的临时访问权限

...

复制代码

第二步:指定可用文件

//新建一个xml文件用于存放应用需要共享的目录文件

//以下paths元素告诉FileProvider您打算为images/私有文件区域的子目录请求内容URI

...

复制代码

该元素必须包含一个或多个以下子元素:

//代表内部存储空间应用私有目录下的 files/ 目录,等同于 Context.getFilesDir() 所获取的目录路径;

复制代码//代表内部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getCacheDir() 所获取的目录路径;

复制代码//代表外部存储空间根目录,等同于 Environment.getExternalStorageDirectory() 所获取的目录路径;

复制代码//代表外部存储空间应用私有目录下的 files/ 目录,等同于 Context.getExternalFilesDir(null) 所获取的目录路径;

复制代码//代表外部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getExternalCacheDir();

复制代码//代表外部媒体区域根目录中的文件。等同于Context.getExternalMediaDirs()。

复制代码

这些子元素都使用两个相同的属性:

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()

复制代码

以下是一个我这边的例子:

场景:版本更新完成时打开新版本 apk 文件实现自动安装

复制代码

//在 res/xml 目录下新建一个filepath文件 并指定子目录路径信息

复制代码//Manifest 文件中注册 FileProvider 对象,并链接上面的 path 路径文件

android:name="android.support.v4.content.FileProvider"

android:authorities="com.xxx.FileProvider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/filepath"/>

复制代码//授权 打开安装管理器安装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;

}

复制代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值