应用内更新版本apk & FileUriExposedException

本文对7.0 & 8.0分别做了兼容处理

正常解决方案报错如下:

Caused by: android.os.FileUriExposedException: file:///storage/emulated/0/Rise/rise_parent.apk exposed beyond app through Intent.getData()

需要兼容7.0+版本
解决方案:

  1. 在清单文件 application 标签下 注册

android:name是写死的。
android:authorities 是用来标识该provider的唯一标识,可以结合包名
android:exported必须设置成 false,否则运行时会报错java.lang.SecurityException: Provider must not be exported 。
android:grantUriPermissions用来控制共享文件的访问权限。

        
        
            
        
  1. 指定配置文件file_provider,需要再res下创建xml包,并新建file_provider.xml文件,名字随意


    

注意路径的配置要一致,否则会出现:

万恶的报错,找不到文件
 Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Rise/rise_parent.apk

如下设置路径即可,不用去对应,
path="." 表示该标签对应的根路径下的所有文件夹
此处表示 Environment.getExternalStorageDirectory() 下的所有文件夹



    
        
        
    

或者指定特定文件夹下,如 Rise,则表示:
Environment.getExternalStorageDirectory()对应的路径+ /Rise 路径下的所有文件夹


切记不要用错标签

根元素是固定的
 对应getFilesDir()。
 对应getCacheDir()。
 对应Environment.getExternalStorageDirectory()。
 对应getExternalFilesDir()。
 对应getExternalCacheDir()。

最后说明

7.0 以下版本安装无问题,已测试
Android 7.0 出现解析错误

配置build.gradle,关掉V2签名 >> v2SigningEnabled false

// 解析包时出现问题
// 配置build.gradle,关掉V2签名  >>  v2SigningEnabled false
  signingConfigs {
        release {
            storeFile file("key.jks")
            storePassword "1234"
            keyAlias "1234"
            keyPassword "1234"
            //  应用内更新 Android7.0 兼容
            v2SigningEnabled false
        }
    }

请看这篇文章Android 7.0解析包时出现问题 的解决方案(应用内更新)

Android 8.0 需要新添加权限 & 处理 解析包时出现问题 的bug

第一步

  

第二步 ,虽然7.0 关掉V2签名 >> v2SigningEnabled false,但是8.0仍遇到解析包出现问题的情况

解决方案

去掉 intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK 的设置即可

//  去掉这句话 去掉这句话 去掉这句话 去掉这句话
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

请看这篇文章Android 实现应用更新适配 Android O (Android 8.0)

附代码:
   private fun installApk(t: File) {
        val intent = Intent()
        intent.action = "android.intent.action.VIEW"

        var data : Uri
        // 判断版本大于等于7.0
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // "com.risecenter.parent.fileprovider"即是在清单文件中配置的authorities
            data = FileProvider.getUriForFile(context, "com.risecenter.parent.fileprovider", t)
            // 给目标应用一个临时授权
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        } else {
            data = Uri.fromFile(t)
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        }

        //显示完成和打开按钮
//        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
        intent.addCategory("android.intent.category.DEFAULT")
        intent.setDataAndType(data, "application/vnd.android.package-archive")
        mContext!!.startActivity(intent)
        android.os.Process.killProcess(android.os.Process.myPid())
    }

题外之意

你可能会说,我这边怎么只用传统解决方式就可以了,没有这么复杂。
我的 targetSdkVersion = 27 > 26

你可能感兴趣的:(应用内更新版本apk & FileUriExposedException)