欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android——android.os.FileUriExposedException: xxx.apk exposed beyond app through Intent.getData()解决办法

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

【问题】:Android APP实现升级apk安装时,会出现这样的错误:android.os.FileUriExposedException: xxx.apk exposed beyond app through Intent.getData()。

Android——android.os.FileUriExposedException: xxx.apk exposed beyond app through Intent.getData()解决办法

【原实现代码】:

private void installAPK() {
        String fileName = xxxx;
        String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
        File apkFile = new File(directory+fileName);
        if (!apkFile.exists()){
            Toast.makeText(MyApplication.getContext(),"安装包文件不存在",Toast.LENGTH_SHORT).show();
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);
        //安装完成后,启动app
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
        startActivity(intent);
    }

【问题根因】:FileUriExposedException,文件Uri暴露异常。实际上,以上代码在Android7.0版本以下仍然是好用的,但是到了7.0以上的版本就不行了,这也是Google在安全性方面的考虑。当你的应用把file:// Uri暴露给其他App的时候就会出现这种异常,因为接收方可能不具备访问该共享资源的权限,所以应该用content:// Url来拓展临时权限。

【解决办法】:使用FileProvider

1)在AndroidManifest.xml文件的application中添加

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="包名.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

2)在res的xml包中创建provider_paths.xml文件

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

其中paths下的子节点含义:

子节点 含义
<root-path> 设备的根目录 new File("/")
<files-path> Context.getFileDir()
<catch-path> Context.getCatchDir()
<external-path> Environment.getExternalStorageDirectory()
<external-files-path> Context.getExternalFilesDirs()
<external-catch-path> Context.getExternalCatchDirs()

以上xml文件,代表可以使用你所声明的sd卡根目录当前文件夹以及其子文件夹。

3)使用FileProvider解决高于Android7.0版本的兼容性问题

 private void installAPK() {
        String fileName = xxx;
        String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
        File apkFile = new File(directory+fileName);
        if (!apkFile.exists()){
            Toast.makeText(MyApplication.getContext(),"安装包文件不存在",Toast.LENGTH_SHORT).show();
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);
        //安装完成后,启动app
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri uri = FileProvider.getUriForFile(this, this.getPackageName() + ".fileprovider", apkFile);
            intent.setDataAndType(uri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
        }
        startActivity(intent);
    }

注意,兼容前后都不要忘了在AndroidManifest.xml文件中添加必要的权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

———————————————————————————————————————

本文为博主原创文章,转载请注明出处!

若本文对您有些许帮助,轻抬您发财的小手,关注/评论/点赞/收藏,就是对我最大的支持!

祝君升职加薪,鹏程万里!

本文地址:https://blog.csdn.net/w464960660/article/details/107188214