本文对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+版本
解决方案:
- 在清单文件 application 标签下 注册
android:name是写死的。
android:authorities 是用来标识该provider的唯一标识,可以结合包名
android:exported必须设置成 false,否则运行时会报错java.lang.SecurityException: Provider must not be exported 。
android:grantUriPermissions用来控制共享文件的访问权限。
<!-- 兼容7.0+ 版本的下载安装APK -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider" />
</provider>
- 指定配置文件file_provider,需要再res下创建xml包,并新建file_provider.xml文件,名字随意
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="version"
path="Rise" />
</paths>
注意路径的配置要一致,否则会出现:
万恶的报错,找不到文件
Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Rise/rise_parent.apk
如下设置路径即可,不用去对应,
path="." 表示该标签对应的根路径下的所有文件夹
此处表示 Environment.getExternalStorageDirectory() 下的所有文件夹
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--<external-files-path-->
<!--name="external-files-path"-->
<!--path="." />-->
<external-path
name="version"
path="." />
</paths>
或者指定特定文件夹下,如 Rise,则表示:
Environment.getExternalStorageDirectory()对应的路径+ /Rise 路径下的所有文件夹
<external-path
name="version"
path="Rise" />
切记不要用错标签
根元素<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()。
最后说明
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
第一步
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
第二步 ,虽然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
网友评论