Android 升级安装APK兼容Android7.0,解决FileUriExposedException
我们在开发app时避免不了需要添加应用内升级功能。当app启动时,如果检测到最新版本,将apk安装包从服务器下载下来,执行安装。
安装apk的代码一般写法如下,网上随处可以搜到
public static void installApk(Context context, File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.fromFile(file);
intent.setDataAndType(data, "application/vnd.android.package-archive");
context.startActivity(intent);
}
然而,当我们在Android7.0手机中执行时,会发现报如下错误日志
Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/net.csdn.blog.ruancoder/cache/test.apk exposed beyond app through Intent.getData()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:)
at android.net.Uri.checkFileUriExposed(Uri.java:)
at android.content.Intent.prepareToLeaveProcess(Intent.java:)
at android.content.Intent.prepareToLeaveProcess(Intent.java:)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:)
at android.app.Activity.startActivityForResult(Activity.java:)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:)
at android.app.Activity.startActivityForResult(Activity.java:)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:)
at android.app.Activity.startActivity(Activity.java:)
at android.app.Activity.startActivity(Activity.java:)
我们来看一下FileUriExposedException官方文档
https://developer.android.google.cn/reference/android/os/FileUriExposedException.html
从Android 7.0开始,不再允许在app中把file:// Uri暴露给其他app,否则应用会抛出FileUriExposedException。原因在于,Google认为使用file:// Uri存在一定的风险。比如,文件是私有的,其他app无法访问该文件,或者其他app没有申请READ_EXTERNAL_STORAGE运行时权限。解决方案是,使用FileProvider生成content:// Uri来替代file:// Uri。
FileProvider官方文档:
https://developer.android.google.cn/reference/android/support/v4/content/FileProvider.html
下面我们使用FileProvider解决上述异常。
1.声明FileProvider
首先在清单文件中申明FileProvider。
<manifest>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="net.csdn.blog.ruancoder.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
...
</application>
</manifest>
其中
android:name是固定写法。
android:authorities可自定义,是用来标识该provider的唯一标识,建议结合包名来保证authority的唯一性。
android:exported必须设置成 false,否则运行时会报错java.lang.SecurityException: Provider must not be exported 。
android:grantUriPermissions用来控制共享文件的访问权限。
<meta-data>节点中的android:resource指定了共享文件的路径。此处的file_paths即是该Provider对外提供文件的目录的配置文件,存放在res/xml/下。
2.添加file_paths.xml文件
文件格式如下
<paths>
<files-path name="name" path="path"/>
...
</paths>
其中根元素<paths>是固定的,内部元素可以是以下节点:
<files-path name="name" path="path" /> 对应getFilesDir()。
<cache-path name="name" path="path" /> 对应getCacheDir()。
<external-path name="name" path="path" /> 对应Environment.getExternalStorageDirectory()。
<external-files-path name="name" path="path" /> 对应getExternalFilesDir()。
<external-cache-path name="name" path="path" /> 对应getExternalCacheDir()。
此处,我们将下载的apk文件存放到sdcard中的Android/data/<package>/cache/download中,file_paths.xml文件如下。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-cache-path name="cache_download" path="download"/>
</paths>
3.在Java代码中使用FileProvider
public static void installApk(Context context, File file) {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data;
// 判断版本大于等于7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
// "net.csdn.blog.ruancoder.fileprovider"即是在清单文件中配置的authorities
data = FileProvider.getUriForFile(context, "net.csdn.blog.ruancoder.fileprovider", file);
// 给目标应用一个临时授权
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
data = Uri.fromFile(file);
}
intent.setDataAndType(data, "application/vnd.android.package-archive");
context.startActivity(intent);
}
Android 升级安装APK兼容Android7.0,解决FileUriExposedException的更多相关文章
- 升级安装APK兼容Android7.0,解决FileUriExposedException
见http://blog.csdn.net/ruancoder/article/details/67639621?utm_source=itdadao&utm_medium=referral
- 下载安装APK(兼容Android7.0)
我们使用手机的时候经常会看到应用程序提示升级,大部分应用内部都需要实现升级提醒和应用程序文件(APK文件)下载. 一般写法都差不多,比如在启动app的时候,通过api接口获得服务器最新的版本号,然后和 ...
- FileProvider N 7.0 升级 安装APK 选择文件 拍照 临时权限 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 安装office2010提示要安装MSXML6.10.1129.0解决方法
系统win7 32位 安装office2010出现了错误,提示要安装MSXML6.10.1129.0解决方法 1.下载MSXML6.10.1129.0进行安装 2.若本机已安装过不管用: a.在运行里 ...
- Android N安装apk报错:android.os.FileUriExposedException
StackOverflow: http://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-s ...
- android intent安装apk
/** * 安装apk * * @param context * @param apkPath */ public static void installApk(Context context, St ...
- mysql 安装流程 兼容8.0.0以上版本 解决修改密码规则问题
背景介绍: 第一次安装mysql服务端,版本8.0.6 遇到了问题:1:不知道流程:2:8.0以上版本密码加密规则修改的解决方案: 1:下载mysql 服务端 https://dev.mysql. ...
- Android Studio安装apk失败
可能的情况 手机上已经安装了应用或者应用卸载不彻底 解决办法: adb uninstall yourpackagename 如果uninstall失败,可以考虑 clean一下Android Stud ...
- 关于部分Android手机安装apk,无法获取正常的logo
最近出现过类似的问题,主要出现是在,MediaPad X1 7.0和MediaPad M1 8.0. 发布应用的时候明明配置好了图标的,但是始终找不到原因,郁闷了好几个小时,也浪费了好几个小时. 如果 ...
随机推荐
- 2018.5.7每天一题面试题----final, finally, finalize 的区别
1.final修饰符(关键字).被final修饰的类,就意味着不能再派生出新的子类,不能作为父类而被子类继承. 因此一个类不能既被abstract声明,又被final声明.将变量或方法声明为final ...
- RabbitMQ-linux安装rabbitmq(二)
说明 本地装了个虚拟机模拟集群 所以记下安装步骤 安装Erlang 安装类库 yum -y install ncurses-devel yum -y install openssl-devel yum ...
- [K/3Cloud]如何解决K3Cloud 2.0审批流提交时报“队列不存在,或您没有足够的权限执行该操……
按照图上的操作即可解决不可提交的问题,但如果应用服务器是部署在域环境下,应该不会出错,这是微软support上说的
- 史上超全面的Neo4j使用指南
Create by yster@foxmail.com 2018-7-10 我的博客:https://blog.csdn.net/yueshutong123 W3Cschool文档:https://w ...
- angularjs中比较实用的multipleselect选择框
一. HTML HTML中比较多逻辑代码,修改的时候要注意修改很多绑值的地方. <div class="form-group"> <label class=&qu ...
- open redis port for remote connections
edit /etc/redis.conf Add below line after bind 127.0.0.1, then try redis-cli -h xxx.xxx.xxx.xxx ping ...
- MYSQL利用Navicat对含有Bold字段表进行导入导出
MYSQL中含有Blob字段是一件挺麻烦的事情,导出导入不方便.我介绍我是怎么做的. 1.在MYSQL的my.ini最后中加入一行配置max_allowed_packet = 100M,重新启动MYS ...
- Javascript中双等号(==)隐性转换机制 JS里charCodeAt()和fromCharCode()方法拓展应用:加密与解密
Javascript中双等号(==)隐性转换机制 在Javascript中判断相等关系有双等号(==)和三等号(===)两种.其中双等号(==)是值相等,而三等号(===)是严格相等(值及类型是否 ...
- bzoj2243【SDOI2011】染色
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 4537 Solved: 1702 [id=2243" ...
- linux系统下用到的小知识点积累
preface:在ubuntu下做事情,在终端下执行一些命令.或者在vim里面做一些操作.自然而然须要用到一些小知识点,没有怎么系统地看<鸟哥的菜>,基本上是遇到了什么问题想要实现什么功能 ...