react-native install download apk file

周龙光
2023-12-01

 

由于react-native-code-pusher不适用于客户需求,花了一天时间翻找了下如何安装下载到本地的最新apk文件。

版本号: 0.12.0

推荐组件: 

rn-fetch-blob

用于访问管理文件与请求传输数据。正好存在集下载、通知与自动安装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);

 

 类似资料: