FileUriExposedException

在给app做版本升级的时候,先从服务器下载新版本的apk文件到sdcard路径,然后调用安装apk的代码,一般写法如下:

private void openAPK(String fileSavePath){
File file=new File(fileSavePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.fromFile(file);
intent.setDataAndType(data, "application/vnd.android.package-archive");
startActivity(intent);
}

这样的写法在Android7.0版本之前是没有任何问题,只要给一个apk文件路径就能打开安装。但是在Android7.0版本上会报错:

 android.os.FileUriExposedException:
file:///storage/emulated/0/Download/FileProvider.apk
exposed beyond app through Intent.getData()

从Android 7.0开始,一个应用提供自身文件给其它应用使用时,如果给出一个file://格式的URI的话,应用会抛出FileUriExposedException。这是由于谷歌认为目标app可能不具有文件权限,会造成潜在的问题。所以让这一行为快速失败。

FileProvider方式解决

这是谷歌官方推荐的解决方案。即使用FileProvider来生成一个content://格式的URI。

1.在Manifest.xml中声明一个provider。

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

android:name值是固定的,android:authorities随便写但是必须得保证唯一性,我这边用的是包名+"fileprovider",android:grantUriPermission跟android:exported固定值。

里面包含一个meta-data标签,这个标签的name属性固定写法,android:resource对应的是一个xml文件。我们在res文件夹下新建一个xml文件夹,在xml文件夹下新建file_paths.xml文件。内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="name" path="Download"/>
</paths>

name表示生成URI时的别名,path是指相对路径。

paths标签下的子元素一共有以下几种:

files-path 对应  Context.getFilesDir()
cache-path 对应 Context.getCacheDir()
external-path 对应 Environment.getExternalStorageDirectory()
external-files-path 对应 Context.getExternalFilesDir()
external-cache-path 对应 Context.getExternalCacheDir()

2.当然我们还需要修改打开apk文件的代码

首先判断下版本号,如果手机操作系统版本号大于等于7.0就通过FileProvider.getUriForFile方法生成一个Uri对象。

private void openAPK(String fileSavePath){
File file=new File(fileSavePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//判断版本大于等于7.0
// "com.ansen.fileprovider.fileprovider"即是在清单文件中配置的authorities
// 通过FileProvider创建一个content类型的Uri
data = FileProvider.getUriForFile(this, "com.ansen.fileprovider.fileprovider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);// 给目标应用一个临时授权
} else {
data = Uri.fromFile(file);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
startActivity(intent);
}

源码下载

如果你想第一时间看我的后期文章,扫码关注公众号,每周不定期推送Android开发实战教程文章...

      Android开发666 - 安卓开发技术分享
扫描二维码加关注

FileProvider解决FileUriExposedException的更多相关文章

  1. Android 升级安装APK兼容Android7.0,解决FileUriExposedException

    我们在开发app时避免不了需要添加应用内升级功能.当app启动时,如果检测到最新版本,将apk安装包从服务器下载下来,执行安装.安装apk的代码一般写法如下,网上随处可以搜到 public stati ...

  2. 升级安装APK兼容Android7.0,解决FileUriExposedException

    见http://blog.csdn.net/ruancoder/article/details/67639621?utm_source=itdadao&utm_medium=referral

  3. 7.0不通过FileProvider解决调用相机给uri问题异常

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//严格模式 StrictMode.VmPolicy.Builder builder = ...

  4. Android 7.0 调取系统相机崩溃解决android.os.FileUriExposedException

    一.写在前面 最近由于廖子尧忙于自己公司的事情和OkGo(一款专注于让网络请求更简单的网络框架) ,故让LZ 接替维护ImagePicker(一款支持单.多选.旋转和裁剪的图片选择器),也是处理了诸多 ...

  5. 【适配整理】Android 7.0 调取系统相机崩溃解决android.os.FileUriExposedException

    一.写在前面 最近由于廖子尧忙于自己公司的事情和 OkGo (一款专注于让网络请求更简单的网络框架) ,故让LZ 接替维护 ImagePicker(一款支持单.多选.旋转和裁剪的图片选择器),也是处理 ...

  6. 拍照、本地图片工具类(兼容至Android7.0)

    拍照.本地图片工具类:解决了4.4以上剪裁会提示"找不到文件"和6.0动态授予权限,及7.0报FileUriExposedException异常问题. package com.hb ...

  7. Android ContentProvider 基本原理和使用详解

    ContentProvider(内容提供者)是 Android 的四大组件之一,管理 Android 以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他 ...

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

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

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

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

随机推荐

  1. mysql-python 安装

    [root@localhost ~]# [root@localhost ~]# [root@localhost ~]# gcc -v    查看是否安装gcc 若报错则未安装 [root@localh ...

  2. 生成二维码的js以及调用打印插件

    插件: qrcode.js 插件下载网址:http://code.ciaoca.com/javascript/qrcode/ 用法实例: <script type="text/java ...

  3. hdu--5351--MZL's Border

    表示看这篇博客后找到了思路: http://blog.csdn.net/queuelovestack/article/details/47291195 补充一下数据,方便观察规律 m  LBorder ...

  4. TestNG的组测试和组中组测试

    在编写测试的过程中,我们经常遇到只想执行个别或者某一部分/某一类型的测试用例,这时我们可以使用TestNG的分组测试方法 分组测试在配置时,TestNG执行的原则是:只保留最小集合进行执行 看代码: ...

  5. 前端到后台ThinkPHP开发整站(6)

    今天终于把整个后台管理系统弄好了,其实没什么难点,只是作为一个Thinphp学习的练手项目,这个项目,现在还只能算是做了一半,还有前台展示方面的功能没有完成.先过一遍后台的功能吧! 1.首页 2.菜单 ...

  6. Java 特殊字符的String.split的分割(. \ * | \\)

    特殊字符 分割的时候使用: 关于点的问题是用 : String.split("[.]");   String..split("\\.") ; 关于竖线的问题用 ...

  7. Orleans简介

    Orleans简介. Orleans是微软开源的分布式actor模型框架.actor模型的原理网络上有很多文章.有许多理论性的文章,深刻地我都不知道怎么应用.在这里我就不赘述了.既然是博客,就说说自己 ...

  8. python标准数据类型

    Python3 中有六个标准的数据类型: Number(数字) String(字符串) List(列表) Tuple(元组) Sets(集合) Dictionary(字典) Python 中的变量不需 ...

  9. shell脚本报错:"[: =: unary operator expected"

    shell脚本报错:"[: =: unary operator expected" 在匹配字符串相等时,我用了类似这样的语句: if [ $STATUS == "OK&q ...

  10. sqlite数据库之简单操作

    一 sqlite介绍 Sqlite是一种嵌入式数据库,类似于一个文件系统,是跟程序在一起的.跟mysql等数据库程序跟数据分离是不一样的. 应用场景:常用于保存本地配置,类似于本地文件系统,因此他内嵌 ...