android 7.0安装APK崩溃


大家都知道android7.0相册由于权限问题 需要先查询是否获得系统权限 不然就会报错

这个也是这样的原因

报错代码

android.os.FileUriExposedException: file:///XXX exposed beyond app through ClipData.Item.getUri() at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799) at android.net.Uri.checkFileUriExposed(Uri.java:2346) at android.content.ClipData.prepareToLeaveProcess(ClipData.java:832) at android.content.Intent.prepareToLeaveProcess(Intent.java:8909)

Android不再允许在app中把file://Uri暴露给其他app,包括但不局限于通过Intent或ClipData 等方法。

原因在于使用file://Uri会有一些风险,比如:

  • 文件是私有的,接收file://Uri的app无法访问该文件。
  • 在Android6.0之后引入运行时权限,如果接收file://Uri的app没有申请READ_EXTERNAL_STORAGE权限,在读取文件时会引发崩溃。

因此,google提供了FileProvider,使用它可以生成content://Uri来替代file://Uri


之前我是直接

 File apkFile = new File(file);
        if (!apkFile.exists()) {
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//        intent.setDataAndType(Uri.parse("file://" + apkFile.toString()), "application/vnd.android.package-archive");

没有做适配就报错了  然后网上找了资料   处理下 

    public void installAPK(String file) {
        File apkFile = new File(file);
        if (!apkFile.exists()) {
            return;
        }
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//        intent.setDataAndType(Uri.parse("file://" + apkFile.toString()), "application/vnd.android.package-archive");
        if (Build.VERSION.SDK_INT >= 24) {
            Uri apkUri = FileProvider.getUriForFile(getApplicationContext(), "com.wy.toy.FileProvider", apkFile);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
        } else {
            intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
        }
        startActivity(intent);
    }

在AndroidManifest.xml添加
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.wy.toy.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
            android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/rc_file_path" />

资源文件下加上
xml version="1.0" encoding="utf-8"?>


            name="files_root"
        path="/sdcard/updateAPK/" />

android:authorities
是用来标识provider的唯一标识,在同一部手机上一个"authority"串只能被一个app使用,冲突的话会导致app无法安装。
android:exported必须设置成false,后面异常会讲为什么 android:grantUriPermissions用来控制共享文件的访问权限,也可以在java代码中设置

res/xml/provider_paths.xml
这是指定路径和转换规则
中可以定义以下子节点
子节点     对应路径     例子
files-path     Context.getFilesDir()     
cache-path     Context.getCacheDir()     
external-path     Environment.getExternalStorageDirectory()     /storage/emulated/0/
external-files-path     Context.getExternalFilesDir(null)     
external-cache-path     Context.getExternalCacheDir()     

加入我要替换的目录是
/storage/emulated/0/sdcard/updateAPK/
那么配置应该写成
    path="/sdcard/updateAPK/"

我碰见的异常
Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference

com.wy.toy.FileProvider 中的FP大小写错误就一直报错了  


花了一个上午找了很多资料才解决 


最后写一个有趣的事情   我在小米手机上  低版本的覆盖高版本的会报错说下载的文件损坏无法安装  然后借用同事的手机就会直接提示 无法降级  记录下  希望大家遇见相同的错误不要走这么多弯路了 

你可能感兴趣的:(安卓开发)