Android 7.0系统代码调用安装apk时报错FileUriExposedException完美解决

项目更新遇到问题

  Android项目开发中经常遇到下载更新的需求,以前调用系统安装器执行安装操作代码如下:

Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive");
context.startActivity(intent);

  如果Android系统为7.0及以上时则会报异常FileUriExposedException,这是由于安卓官方为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问 (0700)。此设置可防止私有文件的元数据泄漏,如它们的大小或存在性。传递file:// URI 可能给接收器留下无法访问的路径。因此,尝试传递 file:// URI 会触发 FileUriExposedException。因此需要使用 FileProvider。

Android7.0系统使用FileProvider安装apk安装步骤:

1.manifest.xml文件配置:定义一个FileProvider

    <application
        android:allowBackup="true"
        android:label="@string/app_name"
        android:icon="@mipmap/ic_launcher"
        android:theme="@style/AppTheme">

        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="packageName.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>
        </provider>
     </application>
     
2.添加可用权限的文件目录

  在项目res路径下新建名为xml的路径,在xml路径下新建名为file_paths.xml的文件,在file_paths.xml文件中增加如下内容指定分享的路径:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path path="Android/data/packageName/" name="files_root" />
</PreferenceScreen>
3.使用provider直接安装apk:
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri contentUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", new File(path));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri, context.getContentResolver().getType(contentUri));
//指定打开文件所调用的Activity,若不指定,则会弹出打开方式选择框,
intent.setClassName("com.android.packageinstaller","com.android.packageinstaller.PackageInstallerActivity");
context.startActivity(intent); 

完美适配所有系统版本进行apk安装的方式

  如上代码虽然可以在Android7.0系统中正常安装apk,但是在低于Android7.0的系统中则不起作用,所以对apk安装调用方法进行封装,完美适配所有系统版本进行apk的安装调用。

/**
     * 安装apk
     * 
     * @param context Application对象
     * @param path
     *            apk路径
     */
    public static void InstallApk(Context context, String path) {

        Intent intent = new Intent();

        if (Build.VERSION.SDK_INT >= 24) {//Android 7.0以上
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            Uri contentUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", new File(path));
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(contentUri, context.getContentResolver().getType(contentUri));
            //指定打开文件所调用的Activity
            intent.setClassName("com.android.packageinstaller", "com.android.packageinstaller.PackageInstallerActivity");
        } else {
            intent.setAction(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive");
        }
        context.startActivity(intent);
    }

注意事项:

  清单文件配置的authorities的值必须与FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", new File(path));方法中第二个参数一致。

转载于:https://www.cnblogs.com/walker-world/p/7517364.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值