前言

由于公司开发的一款清理 App 中有一个功能是安装包管理,需列出所有的未安装的安装包,当用户点击安装包时会跳转到安装该 Apk 文件的页面。
经一番查阅,以此记录。

在 AndroidManifest 指定 FileProvider

1
2
3
4
5
6
7
8
9
10
<!-- Android 7.0 文件访问的兼容处理 -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_path" />
</provider>

在 res/xml/ 下面创建 xml 文件 provider_path.xml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="files-path" path="/."/>
<cache-path name="cache-path" path="/."/>
<external-path name="external-path" path="/."/>
<external-files-path name="external-files-path" path="/."/>
<external-cache-path name="external-cache-path" path="/."/>
</paths>

安装代码做兼容处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 描述: 安装 Apk
*/
fun installApk(apkPath: String, context: Context): Boolean {
try {
// 没有root权限,利用意图进行安装
val file = File(apkPath)
if (!file.exists()) {
return false
}
val intent = Intent(Intent.ACTION_VIEW)
val uri: Uri
val type = "application/vnd.android.package-archive"
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
uri = Uri.fromFile(file)
} else {
val authority = context.packageName + ".fileProvider"
uri = FileProvider.getUriForFile(context, authority, file)
intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
}
context.grantUriPermission(
context.packageName,
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
intent.setDataAndType(uri, type)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(intent)
return true
} catch (e: Throwable) {
LogUtil.e("xcy-installFail, message=" + e.message)
return false
}
}

参考文章

https://github.com/hgncxzy/InstallApk
https://blog.csdn.net/qq_31877171/article/details/114314648