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

兼容Android系统7.0升级安装apk 在app更新安装包的时候报错 FileUriExposedException如下: 报错代码: private void update() { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(Enviro 阅读详情
我们在开发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:1799)
   at android.net.Uri.checkFileUriExposed(Uri.java:2346)
   at android.content.Intent.prepareToLeaveProcess(Intent.java:8933)
   at android.content.Intent.prepareToLeaveProcess(Intent.java:8894)
   at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517)
   at android.app.Activity.startActivityForResult(Activity.java:4224)
   at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50)
   at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79)
   at android.app.Activity.startActivityForResult(Activity.java:4183)
   at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:859)
   at android.app.Activity.startActivity(Activity.java:4507)
   at android.app.Activity.startActivity(Activity.java:4475)

我们来看一下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 7.0 & 8.0 升级兼容 一、7.0 问题记录 参考 1. 安装APK报错,FileUriExposedException 2. 调取系统相机崩溃,FileUriExposedException 二、8.0 问题记录 参考 1. 未知来源应用安装权限 2. 针对通知的限制 3. 运行时权限策略变化 4. 针对顶级弹窗的限制 三、7.0 修改记录 版本: 24 环境:三星S7-API24 1. Uri.paurse(fi... 阅读详情

相关推荐

Android——安装apk升级时出现FileUriExposedException: xxx.apk exposed beyond app through Intent.getData()的解决方法

【问题】:Android APP实现升级apk安装时,会出现这样的错误:android.os.FileUriExposedException: xxx.apk exposed beyond app through Intent.getData()。 【原实现代码】: private void installAPK() { String fileName = xxxx; String directory = Environment.getExternalStorage

数字世界 万物互联 4220

Android7.0、8.0安装apk以及安装apk弹出“选择打开方式”的解决方案

目录 Android7.0安装apk导致的FileUriExposedException异常 问题描述 解决方案 Android8.0安装apk无法跳转到正常的APP安装页面 问题描述 解决方案 安装apk时弹出“选择打开方式”让用户选择而不是直接跳转到APP安装界面 问题描述 解决方案 安装apk代码示例 最近在做一款APP,做自动更新的时候,安装apk遇到了一些问题: ...

Lone_Star斌 的博客 1万+

Android-在app内安装apk

先看下android7.0以下的安装代码. Intent intent = new Intent("android.intent.action.VIEW"); intent.putExtra("name", ""); Uri data = Uri.fromFile(file); intent.set...

ccx 3702

android安装apk出现android.os.FileUriExposedException

问题描述: 解决AndroidN 上 安装Apk时报错:android.os.FileUriExposedException: file:///storage/emulated/0/download/%E5%85%A8%E5%90%8D%E7%82%B9%E6%BB%B4 exposed beyond app through Intent.getData() 解决方法: 1、在AndroidMan...

冬瓜去哪儿的博客 8011

android 7.+使用provider共享uri以及authrities冲突的解决

最近项目需要做拍照&amp;图片选择,于是把去年发现的一个仿微信图片选择库导入项目准备用,结果在安卓8.0测试时闪退,弹出 android.os.FileUriExposedException: exposed beyond app through Intent.getData() at android.os.StrictMode.onFileUriExposed(StrictMode.java...

iamlocky的博客 1362

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

我们在开发app时避免不了需要添加应用内升级功能。当app启动时,如果检测到最新版本,将apk安装包从服务器下载下来,执行安装安装apk的代码一般写法如下,网上随处可以搜到 public static void installApk(Context context, File file) { Intent intent = new Intent(Intent.ACTION_VIE...

weixin_30609287的博客 107

android7.0 apk下载完成后跳转到apk安装页面闪退的兼容处理

最近看到一个库,觉得有点意思,就下载源码编译了一下,结果发现打不开apk包,报错为: //这个库的地址是:https://github.com/bingoogolapple/BGAUpdate-Android //设置了超链接也不变色,还是直接写出来得了 Caused by: android.os.FileUriExposedException: file:///...

lizhong 1154

Android 如何安装APK

本文详细介绍了Android应用内APK安装的实现方案,重点解决Android 7.0+版本的文件权限限制问题。核心内容包括:1)提供完整的APK安装工具类实现代码;2)解析FileProvider的工作原理及必要性;3)详细说明FileProvider的配置步骤;4)使用示例和常见问题解决方案。特别针对Android 7.0+版本,采用FileProvider替代传统file://Uri方式,确保安全共享文件。同时覆盖了Android 8.0+的安装权限和Android 11+的包可见性等新特性适配问题

Jm0218Xx的博客 4332

Android 7.0系统使用Intent跳转到APK安装界面

前言 之前做过的一个功能 apk在线升级 想必大家都做过 我们公司的平板采购不同的公司 有一家公司的平板 在下载好apk后没有拉起 自动安装的弹框 就卡在100那里了 其他的平板 包括测试机 测试平板 都可以唤醒 自动安装的弹框 我去找他们硬件服务商 他们也承认 是他们的硬件问题 他们提出用他们的 主板api 来调试这个bug 解决过程 硬件提供方 说用他们的解决方案太麻烦了 并且不知道能不能行 算了,还是自己来吧 apk在下载完之后 没有唤起自动安装界面 那能不能我们手动 唤醒呢? 答案肯定是可以的

吕氏春秋i 1597

下载安装APK(兼容Android7.0)

我们使用手机的时候经常会看到应用程序提示升级,大部分应用内部都需要实现升级提醒和应用程序文件(APK文件)下载。一般写法都差不多,比如在启动app的时候,通过api接口获得服务器最新的版本号,然后和本地的版本号比较,来判断是否需要弹出提示框下载,当然也可以通过推送的自定义消息来实现。我们这里主要讨论的是应用程序下载,并在通知栏提醒下载完成。实现过程大致分为三步:创建一个service在servic

于连林 961

Android开发 android7.0安装apk文件的姿势

最近看到一个库,觉得有点意思,就下载源码编译了一下,结果发现打不开apk包,报错为: Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/cn.bingoogolapple.update.demo/files/apk/BGAUpdateDemo_v1.0.0.apk e

Good luck 1万+

Android7.0后FileProvider升级安装包导致FileUriExposedException的异常

最近在鼓捣应用升级时遇到了安装失败的问题,抛出了“apk exposed beyond app through Intent.getData()”异常,网上一顿谷歌百度后晓得了,是谷歌在Android7.0(api 24)后出的幺蛾子。 Android7.0后Uri uri=Uri.fromFile(file) ——> Uri uri=FileProvider.getUriForFile(content,authority,file)获取uri文件地址的改变,使用FileProvider可以生成co

yongli198600163的专栏 329

安装新版本的apkandroid.os.FileUriExposedException

最近在做app更新升级作者又碰到因为android 7.0 引起的兼容问题了。 在7.0以前的版本: //创建临时图片 File photoOutputFile = SDPath.getFile(“temp.jpg”, SDPath.PHOTO_FILE_STR); Uri photoOutputUri = Uri.fromFile(photoOutputFile); 这个file文件直接非常简单...

树懒的博客 1530
上一篇: TabLayout属性介绍
下一篇: 图片压缩
ruancoder
博客等级 码龄10年 42粉丝 66原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值