还望支持个人博客站:http://www.enjoytoday.cn

概述

Android 7.0的新特性规定,对于android 7.0应用(仅仅对于android 7.0版本的sdk而言,若是编译版本低于25仍然不会受到影响),android框架使用StrictMode Api禁止我们的应用对外部(跨越应用分享)公开file://,若使用file://格式共享文件则会报FileUriExposedException异常,android 7.0应用间的文件共享需要使用content://类型的URI分享,并且需要为其提供临时的文件访问权限
(Intent.FLAG_GRANT_READ_URI_PERMISSION和Intent.FLAG_GRANT_WRITE_URI_PERMISSION),对此,官方给我们的建议是使用FileProvider类进行分享.目前,我已经在华为mate系列最新Android 7.0系统测试验证证实。下面主要看下FileProvider的使用方法,我会结合官网给的资料和FileProvider 25.0.1的源代码进行分析。

FileProvider

简介

获取是因为v4包的版本问题,导致我发现FileProvider原代码和android官网的介绍有些许差异或者说是接入的某些细节和我在使用的v4包所能作的工作不符合。我使用的v4包是23.0.1,下面我就以我这个版本的v4来介绍FileProvider的使用。

使用

注册
FileProvider是v4包中一个继承ContentProvider的子类,位置是android.support.v4.content,他可以通过File创建一个content://类型的Uri而不是file://类型的Uri.所以我们在使用的使用首先需要在清单文件中注册一个provider,如下所示:

 <manifest>...<application>...<providerandroid:name="android.support.v4.content.FileProvider" //provider的类名android:authorities="com.hfcai.fileprovider" //没有特定要求,自定义android:exported="false"           //不建议设置未trueandroid:grantUriPermissions="true">  //允许你有给其赋予临时访问权限的权力<meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider>...</application>
</manifest>

这里是直接使用的v4包中的FileProvider,我们也可以直接继承FileProvider类,适当重写重载函数,但不建议如此做。下面来介绍上面的几个设置:

  • name:provider的类名,若使用默认的v4的FileProvider可使用”android.support.v4.content.FileProvider”,也可以设置为自定义的继承FileProvider的provider类;
  • authorities:一个签名认证,可以自定义,但在获取uri的时候需要保持一致;
    grantUriPermissions:使用FileProvider的使用需要我们给流出的URI赋予临时访问权限(READ和WRITE),该设置是允许我们行使该项权力;
  • meta-data:meta-data配置的是我们可以访问的文件的路径配置信息,需要使用xml文件进行配置,FileProvider会通过解析xml文件获取配置项,其中name名字不可改变为:android.support.FILE_PROVIDER_PATHS,resource为配置路径信息的配置项目。

路径配置
可访问的路径配置可以在res中建立一个xml文件下面建立一个配置文件,格式如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><!-- "/" --><root-path name="test" path="test"/><!--Context.getFilesDir().--><files-path path="images" name="images"/><!-- getCacheDir().--><cache-path name="images1" path="images" /><!-- Environment.getExternalStorageDirectory().--><external-path name="images2" path="images" /><!--Context#getExternalFilesDir(String) Context.getExternalFilesDir(null).   --><external-files-path name="images3" path="images" /><!-- Context.getExternalCacheDir().  --><external-cache-path name="images4" path="images" />
</paths>

这里需要注意的是,如上的配置是25.0.1版本的配置信息,各个版本或许有点不同,具体的可选配置可以在原码中查看,关于配置文件的解析部分在FileProvider的parsePathStrategy方法里,相关的代码如下:

private static PathStrategy parsePathStrategy(Context context, String authority)throws IOException, XmlPullParserException {final SimplePathStrategy strat = new SimplePathStrategy(authority);final ProviderInfo info = context.getPackageManager().resolveContentProvider(authority, PackageManager.GET_META_DATA);final XmlResourceParser in = info.loadXmlMetaData(context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS);if (in == null) {throw new IllegalArgumentException("Missing " + META_DATA_FILE_PROVIDER_PATHS + " meta-data");}int type;while ((type = in.next()) != END_DOCUMENT) {if (type == START_TAG) {final String tag = in.getName();final String name = in.getAttributeValue(null, ATTR_NAME);String path = in.getAttributeValue(null, ATTR_PATH);File target = null;if (TAG_ROOT_PATH.equals(tag)) {target = DEVICE_ROOT;} else if (TAG_FILES_PATH.equals(tag)) {target = context.getFilesDir();} else if (TAG_CACHE_PATH.equals(tag)) {target = context.getCacheDir();} else if (TAG_EXTERNAL.equals(tag)) {target = Environment.getExternalStorageDirectory();} else if (TAG_EXTERNAL_FILES.equals(tag)) {File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);if (externalFilesDirs.length > 0) {target = externalFilesDirs[0];}} else if (TAG_EXTERNAL_CACHE.equals(tag)) {File[] externalCacheDirs = ContextCompat.getExternalCacheDirs(context);if (externalCacheDirs.length > 0) {target = externalCacheDirs[0];}}if (target != null) {strat.addRoot(name, buildPath(target, path));}}}return strat;
}

查看FileProvider不难发现,这里有几点坑需要注意一下:

  1. 配置可以添加多条路径信息,这是最容易看出来的;
  2. 每条路径信息中的name是必须的,不能未空,且不可重复(可以自定义),路径信息中的name,path解析后被一个HashMap作为Key和value保存,若name重复则会导致path数据被覆盖;
  3. path的设置必须是一个目录名,不可为一个文件名,可以选择添加或不添加file的分割符,因为FileProvider会自动帮我们补充。

使用方法

使用FileProvider与其他共享文件的方法的唯一区别就是生成URI的方式,将之前使用Uri.formFile(File file)或者直接加上”file://”通过Uri.parse(String str)转化的方式改为FileProvider.getUriForFile(Context context,String auth,File file)方法获取。当然还需要给该uri添加临时访问权限,代码如下:

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "test.png");
Uri contentUri = FileProvider.getUriForFile(getContext(), "com.hfcai.fileprovider", newFile);
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(contentUri,"image/*");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivity(intent);

这样就可以通过系统的相册或其他可查看图片的应用打开我们所创建的图片文件了,下面给了一个FileProvider使用的Demo原码,可供参考,不喜勿喷。

FileProvider 示例:FileProviderDemo

转载于:https://www.cnblogs.com/amiko/p/7906237.html

FileProvider的使用相关推荐

  1. android 7.0拷贝文件,Android 7.0应用间共享文件----FileProvider

    应用间经常需要将自己的私有文件共享给其他的app,如某应用想要共享图库的图片用来编辑用户的头像,或者文件管理app允许用户在不同目录下复制粘贴文件等等,但为了保护私有文件的安全性,在targetSdk ...

  2. 【错误记录】Android 文件分享 FileProvider 设置错误

    文章目录 一.报错信息 二.解决方案 一.报错信息 分享内部存储到文件到其它应用 ; 2021-05-18 16:10:23.480 31881-31881/kim.hsl.file E/DEBUG: ...

  3. androidx使用FileProvider适配安卓7

    前言 安卓7版本后,需要适配获取本地uri,否则会报错,之前用的android support库,可以参考这篇文章<点击查看> 但是现在使用了androidx后,发现清单文件中配置不一样了 ...

  4. FileProvider 在 Android N 上的应用

    作者:才华横溢的段老师 蓝田大营 一.背景 Android 从 N 开始不允许以 file:// 的方式通过 Intent 在两个 App 之间分享文件,取而代之的是通过 FileProvider 生 ...

  5. 清单文件中android support,Android FileProvider 配置

    1. 在清单文件中配置FileProvider FileProvider是ContentProvider的子类,属于四大组件之一,因此需要在清单文件中配置. android:name="an ...

  6. [转]快速使用FileProvider解决Android7.0文件权限问题

    升级到Android7.0之后,启动系统相机或者截图,传入URI的时候可能会导致程序闪退崩溃.这是因为7.0的新的文件权限导致的.下面是解决这个问题的快速解决方案. 问题代码 在7.0可能会出问题的代 ...

  7. android开发 文件分享到应用,Android开发之——7.0适配之应用之间共享文件(FileProvider)...

    前言 Android 7.0强制启用了被称作StrictMode的策略,带来的影响就是你的App对外无法暴露file://类型的URI了. 如果你使用Intent携带这样的URI去打开外部App(比如 ...

  8. ASP.NET Core 源码学习之 Logging[4]:FileProvider

    前面几章介绍了 ASP.NET Core Logging 系统的配置和使用,而对于 Provider ,微软也提供了 Console, Debug, EventSource, TraceSource ...

  9. Android用外部应用打开文件,Android N 以上使用其他应用打开文件 FileProvider

    又是好长一段时间没有写东西了,说忙到没有时间写东西,这个说法在任何时候都是借口.总的来说还是没有写,真的要写的话还是有时间来写的,不说成为一个高产的人吧,但是稍微写一些的时间还是有的,再不济也可以分开 ...

  10. .NET Core的文件系统[2]:FileProvider是个什么东西?

    在<读取并监控文件的变化>中,我们通过三个简单的实例演示从编程的角度对文件系统做了初步的体验,接下来我们继续从设计的角度来继续认识它.这个抽象的文件系统以目录的形式来组织文件,我们可以利用 ...

最新文章

  1. AI战场,李彦宏马化腾马云都在频频刷脸,周鸿祎和他的360在想啥呢?
  2. 2017 Multi-University Training Contest - Team 3 Kanade's sum hd6058
  3. 瞥一瞥AI,撩一撩算法,顺便送几本书
  4. HBase 默认配置项详细解读
  5. solr java api_solr java api
  6. 如何使用TensorFlow构建简单的图像识别系统(第2部分)
  7. linux 管道非阻塞,linux – 管道上的非阻塞读取
  8. Cookiecutter
  9. 艰苦的网购火车票,周末可以不用再秒杀余票了
  10. java游戏运行_用jar包运行带GUI的java游戏
  11. 发电机机房设计规范_柴油发电机房设计规范.docx
  12. java 同步线程方式
  13. π型滤波频率计算_π型电感滤波电路计算
  14. 【Python】使用python 画出一张机器猫doraemon
  15. sql md5或shal加密
  16. 再不学点东西我们就老了
  17. java 能实现csgo吗
  18. hive学习笔记-数据操作
  19. 小米拒绝权限_小米应用商城:我下载的是快图,打开却是天天相册,还发扣费短信...
  20. HTML图片和文字一行时的对齐方式

热门文章

  1. 第十七:如何搭建Pytest+Allure2环境(重点非常详细)
  2. 字段 密码有效期_你知道Linux中用户们的密码藏在哪儿吗?
  3. 谷歌浏览器怎么长截图怎么截_Chrome浏览器如何完美实现滚动截图技巧
  4. 研华数据采集卡如何采集压力信号转化为数字信号_我所了解的数据-数据分析-数据产品...
  5. java题1_java面试题1
  6. Spring Boot+Vaadin 14项目初始化
  7. linux运行库,Linux C 静态库 共享库 运行库
  8. mysql查询问题解答_mysql查询问题
  9. Linux中Docker的yum源与镜像加速器
  10. 烟台大学计算机学院宋宜斌教授,宋宜斌