Android7.0 FileProvider-程序员宅基地

技术标签: fileprovider  

一、前言

Android 7.0有很多的变化,和我们开发者关联最大的,或者说必须要适配的就是去除项目中传递 file:// 类似格式的 Uri 了。

要应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用 FileProvider 类,

FileProvider 实际上是 ContentProvider 的一个子类,它的作用也比较明显,file://Uri 不给用,那么换个 Uri 为 content:// 来替代。

二、使用步骤

1、在AndroidManifest.xml中注册

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.developerhaoz.androidtrainingdemo.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths"
                />
        </provider>
        ...
    </application>
</manifest>

FileProvider 是 ContentProvider 的子类,所以要声明

2、指定文件的分享路径

FileProvider 只能为指定的目录中的文件生成内容 URI。要指定目录,就必须使用 <paths> 元素的子元素在 XML 中指定其存储区域和路径,我们先创建一个名为 res/xml/file_paths.xml 的新文件:

在 file_paths.xml 文件中,便可以指定文件存储的区域和路径。例如,以下路径元素告诉 FileProvider,你打算为私有文件区域的 images/ 子目录 请求内容 URI:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="myimages" path="images/"/>
    ...
</paths>

<paths> 必须包含以下元素中一个或者多个子元素:

<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="name" path="path" />
    <external-cache-path name="name" path="path" />
</paths>

2019-04-25 13:59:48.032 13704-13704/? D/dongjiejie: getFileDir----/data/user/0/packagename/files
2019-04-25 13:59:48.033 13704-13704/? D/dongjiejie: getCacheDir----/data/user/0/packagename/cache
2019-04-25 13:59:48.037 13704-13704/? D/dongjiejie: getExternalStorageDirectory---/storage/emulated/0
2019-04-25 13:59:48.040 13704-13704/? D/dongjiejie: getExternalFilesDirs-----/storage/emulated/0/Android/data/packagename/files
2019-04-25 13:59:48.042 13704-13704/? D/dongjiejie: getExternalCacheDirs-----/storage/emulated/0/Android/data/packagename/cache

每个节点都有两个属性:name、path

<external-path name="external" path="pictures"/>

代表的目录即为:Environment.getExternalStorageDirectory()/pictures, 当这么声明以后,代码可以使用你所声明的当前文件夹以及其子文件夹

3、配置工作已经全部完成了,后面就需要将之前传递的 file:// 替换成 FileProvoider 需要用到的 content://,这就需要用到 FileProvider.getUriForFile() 方法了

public static Uri getUriForFile(Context context, String authority, File file) {
        final PathStrategy strategy = getPathStrategy(context, authority);
        return strategy.getUriForFile(file);
    }

可以看到 getUriForFile(),需要传入 一个
authority 的参数,这正是我们前面在 AndroidManifest.xml 文件中配置的 android:authorities 参数,调用这个方法会自动得到一个 file:// 转换成 content:// 的一个 Uri 对象,可以供我们直接使用

4、给Uri授予临时权限

例如:7.0上调用安装界面:

private void installApk(String apkName) {
        FileUtils mFileUtils = new FileUtils();
        Uri mUri;
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        //7.0系统开始认为直接使用本地Uri是不安全的 所以以FileProvider共享给外部提高安全性
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            mUri = FileProvider.getUriForFile(this, "com.manager.carmanager.fileProvider", mFileUtils.getApksFile(apkName));
        } else {
            mUri = Uri.fromFile(mFileUtils.getApksFile(apkName));
        }
        //添加这一句表示对目标应用临时授权该Uri所代表的文件
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(mUri,
                "application/vnd.android.package-archive");
        startActivityForResult(intent, 10025);
    }

 

总结:

Android 7.0 禁止在应用外部公开 file:// URI,所以我们必须使用 content:// 替代 file://,这时主要需要 FileProvider 的支持,而因为 FileProvider 是 ContentProvider 的子类,所以需要在 AndroidManifest.xml 文件中进行注册,而又因为需要对真实的 filepath 进行映射,所以需要编写一个 xml 文档,用于描述可使用的文件夹目录,以及通过 name 去映射该文件夹目录。当我们生成一个 content:// 的 Uri 对象之后,还需要对这个 Uri 接收的 App 赋予对应的权限

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/helloworld19870427/article/details/89514956

智能推荐

LTE CAT1问题记录一_4g cat.1有啥问题-程序员宅基地

文章浏览阅读1.3k次。一、硬件问题1.电源由于2G模块出现电源电平跳变,导致模块出现不工作,死机,等各种异常问题在CAT1上将基带和模块的电源分开,并且滤波电容的选取要合适,此处选择官方提供的电容并且电源供电要采取星形走线的规则。下图为走线对比。具体文章参考:电源星形走线的分析及其注意事项这篇文章说的非常详细,理解深刻如果道不同,一开始就不要为谋,不要最后一刻才来分道扬镳。这句话写得非常好。虽然在BGA的IC上才能体现出来,但是为了预防一切问题,就按照标准的星形走线方式走线2.器件布局1)首先电源器件布局_4g cat.1有啥问题

NBU 异机恢复Oracle操作步骤_nbu恢复oracle-程序员宅基地

文章浏览阅读5.8k次,点赞4次,收藏17次。一、 准备工作1. DB侧恢复服务器安装与原库相同版本的操作系统、数据库软件、NBU客户端 双向开通到NBU备份服务器的1556、13724、13720、13782、13790端口的防火墙策略(应该只要1556和13724,但为避免还原时出现其他异常,建议都开) /etc/hosts文件添加NBU备份服务器主机名及原库主机名,ping主机名测试能否解析成功 确保恢复服务器磁盘空间足够2. NBU侧/etc/hosts文件添加待恢复服务器主机名,ping主机名测试能否解析成功,若不成..._nbu恢复oracle

TensorFlow2学习四、Keras 保存和加载模型_best_model_weights.hdf5-程序员宅基地

文章浏览阅读856次。1. 权重保存和加载# 保存为TensorFlow checkpoint格式model.save_weights('./my_model')# 保存为TensorFlow HDF5格式model.save_weights('model.h5', save_format='h5')# 加载model.load_weights('my_model')2. 保存和加载网络结构保存一个..._best_model_weights.hdf5

扩展Smack Message-程序员宅基地

文章浏览阅读56次。XMPP是一种基于标准通用标记语言的子集XML的协议,它继承了在XML环境中灵活的发展性。 Smack是一个开源的用 java 写的XMPP(jabber)客户端代码库 因为XMPP是XML,所以进行扩展十分方便。而Smack也提供了对Message扩展的支持。 Smack对..._smack message 扩展

最大子矩阵和问题_最大和问题-程序员宅基地

文章浏览阅读1.4k次。最大子矩阵和问题Description: 描述: In this article, we would see how to convert a recursion into dynamic programming to solve the maximum sum problem? This can be featured in any interview coding round. 在本文中..._最大子矩阵和问题

sql 统计每月入职离职人数_Excel – 统计全年员工入职离职变化,用数据透视表就够了...-程序员宅基地

文章浏览阅读4k次。俗话说:流水的营盘,铁打的兵。公司每个月总有人离职,也总会有新人不断加入。人生就是这样,不断地遇见,又逐一地失去。不用太记挂,世界那么小,相信总有一天会再度相遇。有点扯远了,说回 Excel。如果公司员工很多,比如上万,那要按月快速统计出入职、离职人员名单,以及各部门尚缺几个 head count 等等,就是一项很费时的工作。有没有简单的方法可以快速又一目了然地得知以上信息呢?其实不需要什么复杂公..._每个月入职与离职统计

随便推点

Ubuntu 20.10 groovy 更换国内源_ubuntu20.10的各种国内源-程序员宅基地

文章浏览阅读9.9k次,点赞24次,收藏28次。南湖秋水夜无烟,耐可乘流直上天。且就洞庭赊月色,将船买酒白云边。—李白《游洞庭湖五首其二》Ubuntu 的软件源配置文件是 /etc/apt/sources.list。将系统自带的该文件做个备份,将该文件替换为下面内容,即可使用国内的软件源镜像。一定要备份,一定要备份,一定要备份,重要的事情说三遍。1.备份原始源文件source.listsudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2.修改源文件sources.l._ubuntu20.10的各种国内源

SpringBoot下使用FreeMarker导出world,下载功能_springboot 下载freemarker-程序员宅基地

文章浏览阅读3.5k次,点赞5次,收藏7次。SpringBoot下使用FreeMarker导出world,下载功能Java中导出World文档,最早之前使用的是POI,由于比较繁琐,这次改用FreeMarker模板来进行操作,比较方便。 直奔主题吧1.准备要导出的模板文档2.将其另存为xml格式3.将该xml文件后缀改成.ftl,然后拷贝到项目中进行格式化之后就是这个样子4.编写工具类首先在添加FreeMarker的jar..._springboot 下载freemarker

ST-LINK V2.1 制作(含源码及其原理图)(type-c接口)可以配合robomaster 开发板下载口或者直接用杜邦线连接下载,支持串口调试_stlink原理图-程序员宅基地

文章浏览阅读7.8k次,点赞12次,收藏70次。标题ST-LINK V2.1 制作(含源码及其原理图)(type-c接口)可以配合robomaster 开发板下载口或者直接用杜邦线连接下载,支持串口调试基于电子爱好者,下载器是必不可少的工具,做一个自己喜欢的下载器,还是可以的,主要是便宜且简单。ST-LINK V2.1 支持SW调试 以及下载程序 ,bin文件直接拖动下载,还可以虚拟串口使用,简直不要太方便直接放图片体积只有30mmX30mm,非常小巧。支持串口和调试下载以及bin文件拖拽下载。接口也很方便,可以与robomasterA版_stlink原理图

理解serialVersionUID是什么?有什么用?如何生成?_serialversionuid是不是类似class的hashcode-程序员宅基地

文章浏览阅读335次。转自:https://www.cnblogs.com/xuxinstyle/p/11394358.html如果您曾经实现过Serializable接口,则必须遇到此警告消息The serializable class xxx does not declare a static final serialVersionUID field of type long那么......什么是serialVersionUID?serialVersionUID用作Serializable类中的版本控件。如果_serialversionuid是不是类似class的hashcode

计算机应用基础课程基本要求,计算机应用基础课程标准.doc-程序员宅基地

文章浏览阅读369次。《计算机基础》课程标准(适用于高中后大专各专业)计算机应用技术的推广,信息技术对人类社会全方位的渗透,使许多领域的面貌焕然一新,而且正在形成一种新的文化形态——?信息时代的计算机文化。掌握计算机的基本知识和常用操作方法不仅是学生步入社会,为己谋生的一种工具,更是现代文明必须具备的一种素养。计算机基础教育课程既要培养学生实际的操作技能,更要培养学生利用计算机解决问题的能力和意识。一、课程性质:计算机..._普通本科新版计算机基础课程基本要求发布 2023.04.27

微信小程序获取dom元素-程序员宅基地

文章浏览阅读4w次,点赞12次,收藏38次。微信小程序不支持document.querySelect获取元素,它内置了获取元素的两种方法,第一种是通过wx.createSelectorQuery()获取dom元素,第二种时给想要使用的对象绑定事件,输出e对象,就能拿到该对象的一些信息先在页面上定义一个view标签var query = wx.createSelectorQuery(); query.select('.v1').boundingClientRect(); query.exec(function (res) {_微信小程序获取dom元素

推荐文章

热门文章

相关标签