由于react-native-code-pusher不适用于客户需求,花了一天时间翻找了下如何安装下载到本地的最新apk文件。
版本号: 0.12.0
推荐组件:
用于访问管理文件与请求传输数据。正好存在集下载、通知与自动安装apk的api。
在AndroidManifest.xml内加入安装文件权限声明:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
代码示例:
import RNFetchBlob from "rn-fetch-blob";
import { PermissionsAndroid, Platform } from "react-native";
//安卓9.0需要主动要求用户授权SD卡写入权限,否则直接权限报错导致APP奔溃
initWritePermission = async () => {
if (Platform.OS == "android") {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
this.handleUpdate();
} else {
Toast.show("您未授权存储访问权限, 无法下载更新文件");
}
} else {
this.handleUpdate();
}
};
checkUpdate = () => {
const android = RNFetchBlob.android;
//下载成功后文件所在path
const downloadDest = `${
RNFetchBlob.fs.dirs.DownloadDir
}/xxxxx.apk`;
RNFetchBlob.config({
//配置手机系统通知栏下载文件通知,下载成功后点击通知可运行apk文件
addAndroidDownloads: {
useDownloadManager: true,
title: "xxxxx.apk",
description: "An APK that will be installed",
mime: "application/vnd.android.package-archive",
path: downloadDest,
mediaScannable: true,
notification: true
}
})
.fetch(
"GET",
"https://xxxxx.apk"
)
.then(res => {
//下载成功后自动打开运行已下载apk文件
android.actionViewIntent(
res.path(),
"application/vnd.android.package-archive"
);
});
}
当前包存在一个问题, 在用户手机系统为安卓9.0或者9.0以上时,下载后自动安装会触发报错信息,弹窗提示解析包出现问题:
java.lang.SecurityException: Permission Denial: reading
这个错误找了两天的解决方法,也去包的源码里翻了,发现作者确实给了读文件的权限,但是权限不够完全,目前我测试正常,如果还有错希望大家留意评论。
这个包作者明确说明,已经不再维护了,后续如果该包出现设备兼容问题,会考虑找新的包代替或者自己写原生去处理。
解决方法:
AndroidManifest.xml内 application 加上 android:requestLegacyExternalStorage="true"
直接进npmModule下的rn-fetch-blob包内修改源代码
android/src/main/java/com/RNFetchBlob/RNFetchBlob.java 122-123行添加下列代码
this.getReactApplicationContext().grantUriPermission(this.getReactApplicationContext().getPackageName(), uriForFile, Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);