概述
android7.0中有一些新的变化,(官方文档),例如多窗口的支持,FileProvider等等,今天我们只对FileProvider做讲解,这也是我们在开发过程中必须要做的适配。
在7.0以上系统的手机上,Android框架执行的StrictMode API政策禁止在应用外部公开file//URI;传递file://URI会报出FileUriExposedException异常。如果要在应用间共享文件,应发送一项content//URI,最简单的方式就是使用FileProvider类。
使用方法
1,在ManiFest中的
的节点中注册一个FileProvider,因为FileProvider是ContentProvider的子类;
2,
配置可分享的文件的路径
name:是固定的,
resource:需要在res目录下新建xml文件夹,这里指向xml文件夹下的provider_paths文件,此文件的根节点为paths;
paths 标签内,必须配置最少一个 xxx-path 标签
//path=""---------表示为当前指定目录 如下:
<paths>
<root-path name="root" path="" /> //root-path:表示根目录,『/』。
<files-path name="files" path="" /> //files-path:表示 content.getFileDir() 获取到的目录。
<cache-path name="cache" path="" /> //files-path:表示 content.getFileDir() 获取到的目录。
<external-path name="external" path="" /> //files-path:表示 content.getFileDir() 获取到的目录。
<external-files-path name="name" path="" /> //files-path:表示 content.getFileDir() 获取到的目录。
<external-cache-path name="name" path="" /> //external-cache-path:表示 ContextCompat.getExternalCacheDirs() 获取到的目录
</paths>
3,使用content:// 调用FileProvider.getUriForFile()
/** @param context 上下文对象
* @param authority 这里是前面在 AndroidManifest.xml 中 配置的 android:authorities 。
* @param file 要获取URI的file对象
*/
Fileprovider.getUriForFile(Context context,String authority,File file)
// 调用此方法,会自动得到一个 file:// 转换成 content:// 的 一个 Uri 对象,可以供我们直接使用。
生成的 Content URI 是这样的
content://com.example.demo.customName/*****
host 部分为 元素的 authorities 属性值(applicationId + customname),
path 片段为 res/xml 文件中指定的子目录别名
4,授予临时读写的权限
在配置 provider 标签的时候,有一个属性 android:grantUriPermissions=”true” ,它表示允许它授予 Uri 临时的权限。
当我们生成出一个 content:// 的 Uri 对象之后,其实也无法对其直接使用,还需要对这个 Uri 接收的 App 赋予对应的权限才可以。
授权类型的常量,被定义在 Intent 类中。
授权的方式分为两种:
/****
*
* @param toPackage 表示授予权限的 App 的包名。
* @param uri 授予权限的 content:// 的 Uri。
* @param modeFlags 读写权限。
*/
@Override
public void grantUriPermission(String toPackage, Uri uri, int modeFlags) {
super.grantUriPermission(toPackage, uri, modeFlags);
}
//这种情况下,授权的有效期限,从授权一刻开始,截止于设备重启或者手动调用 Context.revokeUriPermission() 方法,才会收回对此 Uri 的授权。
配合 Intent.addFlags() 授权。 setFlags() == addflags()
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
示例代码:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
Uri data;
// 判断版本大于等于7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
data = FileProvider.getUriForFile(context,"com.example.demo.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} else {
data = Uri.fromFile(file);
}
一旦授权,直到该 App 被完全退出,这段时间内,该 App 享有对此 Uri 指向的文件的对应权限,我们无法再主动收回此权限
常见使用场景
1,自动安装文件
2,调用系统相机拍照
3,调用系统裁剪
总结:终于完成了第一篇技术博客,发现真心不容易,在这里向各位坚持写博客的大佬致敬,本人也会坚持写下去,努力提升自己的水平,不拖android开发工程师的后腿。
由于本人水平有限,代码可能会出现超出本人认知范围的Bug,欢迎各位大佬批评指正。