一.概述

Android 7.0后,提供了很多新特性,其中最主要的是禁止了通过file://URI直接在文件操作共享文件(该操作会触发FileUriExposedException),而是通过content://URI来实现共享。

FileRrovider是ContentProvider的子类,用于不同应用间的文件共享。

二 使用

1.在Mainfest文件中声明provider。

 <provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>

2.编写资源文件provider_paths。

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name = "root" path = ""/> <files-path
name="files"
path=""/> <cache-path
name="cache"
path=""/> <external-path
name="external"
path=""/> <external-files-path
name="external-file"
path=""/> <external-cache-path
name="external-cache"
path=""/>
</paths>

在paths节点内部支持以下几个子节点,分别为:

  • <root-path/> 代表设备的根目录new File("/");
  • <files-path/> 代表context.getFilesDir()
  • <cache-path/> 代表context.getCacheDir()
  • <external-path/> 代表Environment.getExternalStorageDirectory()
  • <external-files-path>代表context.getExternalFilesDirs()
  • <external-cache-path>代表getExternalCacheDirs()

path代表目录下的子目录,如:

<cache-path
name = "cache"
path = "path
/>

代表context.getChcheDir()/path目录,如果path为空,代表直接使用该根目录。

既然要使用content://URI替代file://URI,那么我们需要一个虚拟路径对真实文件路径进行映射。通过编写xml文件,其中path路径确定了可访问的文件目录,name属性映射了真实文件路径。

3.使用fileProvider API 安装APK

我们一般编写安装APK操作时,是这么写的。

  private void installAPK() {
File file = new File(Environment.getExternalStorageDirectory(),"test.apk"); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
startActivity(intent); }

拿着在7.0上的手机跑一下,果不其然会报android.os.FileUriExposedException。

简单修改下URI的获取方式。

    private void installAPK() {
File file = new File(Environment.getExternalStorageDirectory(),"test.apk"); Intent intent = new Intent(Intent.ACTION_VIEW);
Uri fileUri = null;
if(Build.VERSION.SDK_INT >= 24){
//输出 content://com.example.fanggao.fgtextdemo/external/test.apk
fileUri = FileProvider.getUriForFile(this,BuildConfig.APPLICATION_ID+".fileProvider",file);
}else {
fileUri = Uri.fromFile(file);
}
intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivity(intent); }

这样就可以正常运行了。注意,我们还需要加上权限,否则会报Permission Denial异常。

那么问题来了,当我们直接使用fileProvider时,在5.0以下的手机也会报Permission Denial异常,是不是也可以使用addFlags()方法添加权限呢?

答案是不行的,但addFlags只是使用与setData,setDataandType以及setClipData,而且该方法在5.0以下是无效的,需要使用grantUrlPermission()方法,获取所有符合授权的应用,全部授权。

三 小结

7.0后使用fileProvider来实现文件共享,主要目的是隐藏真实的文件目录,因为fileProvider是ContentProvider的子类,所以需要在AndroidManifest.xml文件中注册;并且需要编写xml文件描述可使用的文件夹目录,通过name 去映射文件真实目录,实现访问的安全性。

另外获取授权的方式有2种,

1.通过addFlags()来获取,仅使用setData,setDataandType以及setClipData方法传递uri时支持。

2.通过grantUrlPermission()方式,具体参考下文博客。

更多参考博客:

https://blog.csdn.net/lmj623565791/article/details/72859156

Android 7.0 通过FileProvider共享文件的更多相关文章

  1. Android 7.0应用之间共享文件

    原文首发于微信公众号:躬行之,欢迎关注交流! 开发中经常需要将某个文件向另一个应用程序传递,如图片上传到另一个应用程序.文件在不同存储路径之间的复制粘贴等都需要共享文件,可以这样理解接收文件的应用是在 ...

  2. Android 7.0 出现 ”FileUriExposedException“ 和 ”解析包出现错误“ 异常的解决办法

    问题1 :android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.xxx.xxx.xxx.rel ...

  3. android 7.0+ FileProvider 访问隐私文件 相册、相机、安装应用的适配

    从 Android 7.0 开始,Android SDK 中的 StrictMode 策略禁止开发人员在应用外部公开 file:// URI.具体表现为,当我们在应用中使用包含 file:// URI ...

  4. android 7.0以上共享文件(解决调用系统照相和图片剪切出现的FileUriExposedException崩溃问题)

    在android7.0开始试共享“file://”URI 将会导致引发 FileUriExposedException. 如果应用需要与其他应用共享私有文件,则应该使用 FileProvider, F ...

  5. android 7.0 应用间文件共享FileProvider

    1.官方教程 Android 7.0 以后安全系数提高,应用间文件共享要使用FileProvider.原来的 file:/// Uri 替换为 content://Uri  https://devel ...

  6. Android 7.0 FileProvider 使用说明

    FileProvider FileProvider 这个组件在Android 22.0.0 (也就是 Android 5.0 ) 版本下加入进Android系统,该组件是ContentProvider ...

  7. 关于Android 7.0(API24)相机的问题汇总

    在开发Android项目的时候,我们会用到相机,有些时候只是开发一个普通的扫码,仅仅赋予一下 权限 就好了,但是有些时候是需要拍照和从相册中获取照片的.我们在Android 5.0以及5.0之前调用相 ...

  8. Android 7.0下,拍摄照片报错

    对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI.如果一项包含文件 URI 的 intent 离开 ...

  9. Android 7.0 行为变更

    Android 7.0 除了提供诸多新特性和功能外,还对系统和 API 行为做出了各种变更.本文重点介绍您应该了解并在开发应用时加以考虑的一些主要变更. 如果您之前发布过 Android 应用,请注意 ...

随机推荐

  1. caffe实现年龄及性别预测

    一.相关代码及训练好的模型 eveningglow/age-and-gender-classification: Age and Gender Classification using Convolu ...

  2. abstract class VS interface

    关于抽象类 abstract class: 1. 抽象方法必须在抽象类中 2. 抽象类和抽象方法要用abstract 关键字修饰 3. 不可以用new 来实例化一个abstract类,因为调用抽象方法 ...

  3. CentOS7.5实践快速部署LAMP+Tomcat成功运行阿里云或者腾讯云

    安装一定要按照顺序来 1 先安装JDK+TOMCAT 点击看这里 2 在安装LAMP  点击看这里 3 最关键的就是这里 LAMP+Tomcat整合 我们不用源码编译安装,而是使用yum命令来完成. ...

  4. linux tee

    tee 功能说明:读取标准输入的数据,并将其内容输出成文件. 语 法:tee [-ai][--help][--version][文件...] 补充说明:tee指令会从标准输入设备读取数据,将其内容输出 ...

  5. python3学习笔记九(if语句)

    # !/usr/bin/python3 斐波那数列,两个元素的总和确定下一个数a,b = 0,1while b < 1000: print(b,end=',') a, b = b, a+bpri ...

  6. HTML prefetch 预加载无效的记录

    在link中新增: <link rel="prefetch" href="/view/search.html" /> 预加载会将内容缓存到浏览器, ...

  7. DES加密算法—实现(C语言)

    http://www.iteye.com/topic/478024 DES(Data Encrypt Standard数据库加密标准)是迄今为止使用最广泛的加密体制. 初学信息安全的新生,一般都会被老 ...

  8. c# 观察者模式 匿名方法与Lambda

    //匿名方法 //和委托搭配使用 //方便我们快速对委托进行传参 //不需要我们去定义一个新的函数 //直接用delegate关键字代替方法名,后面跟上参数列表与方法体 //delegate(参数列表 ...

  9. 【算法习题】正整数数组中和为sum的任意个数的组合数

    1.递归实现(参考:https://blog.csdn.net/hit_lk/article/details/53967627) public class Test { @org.junit.Test ...

  10. 对象名 'dbo.__MigrationHistory' 无效 错误解决

    // 在数据库上下文的构造方法里 public GewPeAppContext() : base(ConnectionStrings.GewPeAppConnectionString) { // 添加 ...