React Native热修复CodePush以及react-native-update

对于RN开发而言,最方便的就是热修复了,我们公司项目集成的热修复是:react-native-update,但是我们的用户主要针对尼日利亚用户,而国内的react-native-update补丁包是放在国内七牛上的,因此访问巨慢,加上尼日利亚那边基本都是3G,综合考虑该换微软的:CodePush.

对于CodePush而言,东西是真的多,覆盖问题真的全,因此我们需要摘出我们需要的东西——根据需求找需要。

需求:

  1. 由于项目是跟金钱挂钩的,所以首先,可能发现重大漏洞,就要求所有用户必须更新,并且期间不能使用APP,更新完之后再使用APP。此时对于开发而言就是说:需要有一个弹框,然后显示下载进度。并且这个弹框是不能够回退关闭的。
  2. 可能发现一些“小”BUG,比如:视觉UI显示错误,这些可能对于用户而言,不是必须的。因此我们可以让用户默默下载,然后下次启动的时候释放补丁包。也就是:无感更新。

综上所需: 我们得出两点:

  1. 强制更新,弹窗显示进度
  2. 无感更新。

进入正题,首先是安装CodePush脚手架:

npm install -g appcenter-cli

然后安装CodePush :

npm install --save react-native-code-push

接着就是配置Android和IOS环境:
Android IOS配置链接

配置成功之后,我们需要先在项目根目录登录codePush:

appcenter login

登录成功之后会显示owner-name 需要记一下。

创建应用(Android):

appcenter apps create -d TestCodePush -o Android -p React-Native

其中TestCodePush 是你自己的项目名。

然后创建分支:开发分支,还有线上分支,当然了你也可以创建测试分支以及灰度分支:

appcenter codepush deployment add -a / Staging
appcenter codepush deployment add -a / Production

上述命令行,创建成功之后都会显示一个key, 这个key就是配置Android项目中的key。
当然了可以运行

appcenter codepush deployment list -a / --displayKeys

查看key。

至此,我们的环境就算基本搭建完成了。

在此我想说个问题就是:按照官网的说啊,需要发不到Google市场,这个一直挺困扰我的,刚开始我的配置出了问题,让我误以为是没有发布到Google市场的缘故。在此我想说的是:你不发布到Google市场也是可以的。官网说的发不到google市场是因为:在老外的眼里,你不发布到Google市场,用户怎么下载你的app呢?

好,现在在分析一遍我们的需求:

  1. 需要时刻准备检测更新,并且是我们有发布的时候,再时刻更新,没发布的话,我们就不检测更新。思路:网络拦截器里,拦截response,然后判断我们定义的version和服务器返回的头部的version比较,如果符合条件,那么我们就说明需要检查更新了。
  2. 需要判断是否是大更新:是否需要到Google应用市场下载。猜测:应该是有字段的,或者我们创建一个字段,用户区分是否是大更新还是小更新
  3. 需要区分是强势更新还是无感更新,猜测这个时候按理说应该有一个字段的。
  4. 需要下载进度,这样的话,是有两种做法,第一种:我们可以模拟一个假的进度条,比如到了百分之九十,就不再增长,一直到下载完成,比如react-native-update是不支持的获取下载进度的,所以只能这种做法;第二种做法是CodePush支持的,也就是获取下载进度以及补丁包总大小,这时候我们判断:应该是有一个进度回调函数的!

流程图如下:
React Native热修复CodePush以及react-native-update_第1张图片
**

是否需要检测更新

**
此时客户端和服务端比对version,如果客户端的version小于服务端的version,说明这是我们已经发布了新版本,此时需要检测看看是大更新还是小更新。
**

检查热更新版本

**
此时需要检测是否是大版本还是小版本更新:

import codePush from "react-native-code-push";
    codePush.checkForUpdate()
      .then((update) => {
        if (!update) {
          console.log("The app is up to date!");
        } else {
          console.log("An update is available! Should we download it?");
          console.log("更新:" + JSON.stringify(update));
          console.log("----" + JSON.parse(update.description));
          codePush.sync(
            {updateDialog: false, installMode: codePush.InstallMode.ON_NEXT_RESUME},
            this.codePushStatusDidChange.bind(this),
            this.codePushDownloadDidProgress.bind(this)
          );
      }
    });

此时我们需要从update取出数据,

从上述JSON可以看出我们可以从description取出我们想要的数据。 至于怎么设置该字段,后面再说。

**

判断是否是大更新

**
我们可以从Update对象中获取,一个字段是:是否是大更新。如果是:跳转Google市场。
如果是小更新,那么下一步:

**

判断是否是需要强制更新

**
跟上步骤一样,可以在description的JSON中添加一个字段:是否需要强制更新

**

下载补丁包

**
此时不管是否是强制的,都需要下载热补丁包,codepush提供了下载,安装以及获取下载进度为一体的函数:codePush.sync()

		codePush.sync(
            {updateDialog: false, installMode: codePush.InstallMode.ON_NEXT_RESUME},
            this.codePushStatusDidChange.bind(this),
            this.codePushDownloadDidProgress.bind(this)
          );

首先我们需要设置updateDialog为false,因为如果有下载弹窗,那么我们肯定要自定义啊,比如我们的是一个:大火箭弹窗=-=,炫的一笔。
至于安装模式:InstallMode.ON_NEXT_RESUME, 官网是这样定义的:

codePush.InstallMode.ON_NEXT_RESUME (2) - 表示您要安装更新,但不希望重新启动应用程序,直到最后一个用户从后台恢复它。这样,您不会中断当前会话,但是您可以更快地在它们前面获得更新,然后必须等待下一次自然重启。此值适用于可以以非侵入方式在恢复时应用的静默安装。

codePushStatusDidChange方法是获取下载,安装或者失败状态的:

  codePushStatusDidChange(syncStatus) {
    // if (this.state.immediateUpdate) {
      switch(syncStatus) {
        case codePush.SyncStatus.CHECKING_FOR_UPDATE:
          console.log('::: Checking for update');
          this.syncMessage = 'Checking for update'
          break;
        case codePush.SyncStatus.DOWNLOADING_PACKAGE:
          console.log('::: Downloading package');
          this.syncMessage = 'Downloading package'
          break;
        case codePush.SyncStatus.AWAITING_USER_ACTION:
          console.log('::: Awaiting user action');
          this.syncMessage = 'Awaiting user action'
          break;
        case codePush.SyncStatus.INSTALLING_UPDATE:
          console.log('::: Installing update');
          this.syncMessage = 'Installing update'
          break;
        case codePush.SyncStatus.UP_TO_DATE:
          console.log('::: App up to date.');
          this.syncMessage = 'App up to date.'
          break;
        case codePush.SyncStatus.UPDATE_IGNORED:
          console.log('::: Update cancelled by user');
          this.syncMessage = 'Update cancelled by user'
          break;
        case codePush.SyncStatus.UPDATE_INSTALLED:
          console.log('::: Update installed and will be applied on restart.');
          this.syncMessage = 'Update installed and will be applied on restart.'
          codePush.restartApp(true);
          break;
        case codePush.SyncStatus.UNKNOWN_ERROR:
          console.log('::: An unknown error occurred');
          this.syncMessage = 'An unknown error occurred'
          break;
      }
    // }
  }

注意:当状态为:codePush.SyncStatus.UPDATE_INSTALLED的时候,说明已经下载完成了,此时就等你是现在重启还是下次启动释放补丁包。此时就是区别是否是强制更新。如果是强制更新,讲道理肯定是需要立即重启的:codePush.restartApp(true); 如果不是强制的,那么就不调用restartApp方法。
获取进度信息:

  codePushDownloadDidProgress(progress) {
    console.log("--------::: " + JSON.stringify(progress));
  }

progress对象包含:已下载进度以及总大小。

最后注意:需要在我们的根目录用codePush包裹:

import codePush from "react-native-code-push";
let codePushOptions = {
  checkFrequency : codePush.CheckFrequency.MANUAL
}
export default codePush(codePushOptions)(App);

至于我们为什么设置为:MANUAL, 需求:我们自己控制是否检测更新,官网:
codePush.CheckFrequency.MANUAL (2) - 禁用自动检查更新,但仅检查codePush.sync()应用程序代码中何时调用。

至此我们的代码流程完了,此时就是我们发布更新,对于发布更新我们,可以执行以下命令:

appcenter codepush release-react -a 235434504-qq.com/TestCodePush -d Staging -m true  --description [{\"content\":\"aaaa\"},{\"content\":\"bbbbbbc\"}]  -t 1.0.1

235434504-qq.com : 你自己的owernName。
TestCodePush : 你自己的项目名称
Staging : 发布分支。
-m : 是否是强制更新, 在此我定义为(是否是大版本更新!)
–description: 在此自定义输入JSON字符串
-t: 我们APP打包的真正的version,如果Android版本:也就是我们的versionName.

**

react-native-update

**
对于国内的热修复方案,使用的话挺简单的,考虑的方面可能没有微软的codePush周全,但是推出react-native-update,个人感觉真的挺厉害的,毕竟别人整出来了,有本事你上啊? 哈哈。

在此我想说一下react-native-update的使用新得吧

  1. 首先不支持Debug包的热修复测试
  2. 有的手机热修复更新不下来,也就是报:NetWork error! 此时我判断可能是https的问题,此时如果你不想放弃react-native-update,因此我的做法是copy源码,将https替换为http,解决了问题。

Android交流群:
React Native热修复CodePush以及react-native-update_第2张图片

你可能感兴趣的:(React,Native)