WdBly Blog

懂事、有趣、保持理智

WdBly Blog

懂事、有趣、保持理智

周维 | Jim

603927378@qq.com

code push系列之-客户端检查更新

code push客户端检查更新的几种模式分析,相关更新方法和属性整理

Code Push系列之 - 环境安装

Code Push系列之 - 发布更新

Code Push系列之 - 更新流程

当我们的项目集成Code Push后,应该考虑如何在用户的App中更新到最新版本,这篇文章的主要内容就是Code Push客户端提供的js API讲解和对比。

简单方式

code-push的最简单的检查更新如下:

// 普通方式 import CodePush from "react-native-code-push"; class App extends React.Component {} export default CodePush(App); // ES7 装饰器的方式加载 @CodePush class App extends React.Component {} export default App;

使用CodePush高阶函数包裹根组件, 这样会在每次启动App时检查,下载,安装App。 使用高阶组件可以实现App自动更新。

CodePush也可以接受一个检查更新相关的配置对象CodePushOptions,使用如下:

import CodePush from "react-native-code-push"; class App extends React.Component {} export default CodePush(CodePushOptions)(App);

CodePushOptions对象

CodePushOptions配置对象有如下属性:

一、deploymentKey

指定要查询更新的部署密钥。一般来说code-push会从info.plist或者MainActivity.java文件中获取,但是我们可以使用此属性覆盖文件中的key值。

二、checkFrequency

指定检查更新的时间,可取值如下:

  1. codePush.CheckFrequency.ON_APP_START:启动时检查
  2. codePush.CheckFrequency.ON_APP_RESUME:从后台返回时检查
  3. codePush.CheckFrequency.MANUAL:禁用自动检查更新,仅在调用sync方法时检查

三、installMode

installMode表示应用程序应该何时安装更新(此更新未被标记为必需更新), 取值有以下四种

  1. codePush.InstallMode.IMMEDIATE, 表示马上安装更新并重启应用程序,此模式通常使用在提示用户更新时, 因为用户在点击更新后往往希望马上看到更新, 也常用于强制更新。
  2. codePush.InstallMode.ON_NEXT_RESTART, 表示你要安装更新但不重启应用程序, 当程序下次启动时会自然更新。
  3. codePush.InstallMode.ON_NEXT_RESUME, 表示你要安装更新但不重启应用程序, 当程序从后台恢复后自然更新(也就是常用的resume事件),当应用程序在后台超过minimumBackgroundDuration秒后恢复到前台,其实会相当于重启codePush.restartApp方法
  4. codePush.InstallMode.ON_NEXT_SUSPEND, 表示应用程序需要在后台minimumBackgroundDuration秒后才开始安装更新, minimumBackgroundDuration默认为0;

四、mandatoryInstallMode

当code-push服务器上的一项更新被标记为必需更新时,指定此更新的安装时机,默认为codePush.InstallMode.IMMEDIATE, 其他值参考installMode

五、minimumBackgroundDuration

表示应用程序需要在后台minimumBackgroundDuration秒后才开始安装更新,当installMode的值为codePush.InstallMode.ON_NEXT_RESUME或者codePush.InstallMode.ON_NEXT_SUSPEND时生效。

六、updateDialog

当updateDialog为一个真值时, 如果有可用更新, 向用户展示一个确认更新对话框, 默认为null(不展示对话框)。

根据地区和平台不同,各大应用市场对更新确认框有不同限制,目前只有google play需要更新确认提示, app store和中国大陆应用市场不允许弹更新确认框。

updateDialog属性可以配置对话框的部分属性, 包括一些话术, 这里就不说了, 一般如果需要做弹框提醒更新,往往会自定义弹框样式,不会使用原本的弹框, 在启动app时调用codePush.checkForUpdate()方法,在有更新时提醒更新, 如确实需要请自行查阅官方文档。

常用方法

除了使用高阶组件的方式检查安装更新,我们也可以使用调用方法的方式检查更新, codePush上关于检查更新有如下方法:

一、codePush.sync(option, statusDidChange, downloadDidProgress)

codePush.sync方法是检测更新, 下载更新, 安装更新为一体方法, 它接收三个参数, option为配置对象,statusDidChange为更新过程状态改变的回调函数, statusDidChange参数是从code-push服务器下载更新时定时调用的回调函数,通常可以用于向用户展示进度。 调用该方法即可自动更新

option对象配置如下和CodePushOptions一致, 只是没有checkFrequency指定检查时间方法, 这是因为在调用sync方法后马上就会去检查更新。

codePush.sync()的后两个回调参数如下:

1、statusDidChange ((syncStatus: Number) => void)

statusDidChange回调会返回app的安装更新情况, 每个阶段都会触发,syncStatus一共有如下情况

  1. codePush.SyncStatus.UP_TO_DATE:应用程序与配置的部署完全一致。
  2. codePush.SyncStatus.UPDATE_INSTALLED:已安装可用更新,将在此函数返回后立即运行,或者在下次应用程序恢复/重新启动时运行,具体取决于installMode的值。
  3. codePush.SyncStatus.UPDATE_IGNORED:应用程序有一个可选的更新,最终用户选择忽略。(仅在updateDialog使用时适用)
  4. codePush.SyncStatus.UNKNOWN_ERROR:同步操作遇到未知错误
  5. codePush.SyncStatus.CHECKING_FOR_UPDATE:正在查询code-push服务器以进行更新。
  6. codePush.SyncStatus.AWAITING_USER_ACTION:有可用更新,并向最终用户显示确认对话框。(仅在updateDialog使用时适用)。
  7. codePush.SyncStatus.DOWNLOADING_PACKAGE:正在从服务器下载可用更新。
  8. codePush.SyncStatus.INSTALLING_UPDATE:已下载更新,即将安装。
// 用法如下: codePush.sync({ ... }, this.codePushStatusDidChange ) codePushStatusDidChange = syncStatus => { switch(syncStatus) { case CodePush.SyncStatus.CHECKING_FOR_UPDATE: consloe.log("Checking for update."); } ... }
2、downloadDidProgress((progress: DownloadProgress) => void)

下载更新过程中定时调用此回调函数, DownloadProgress参数是返回的进度,其中包含了两个属性:

  • totalBytes: 此次更新的从字节数
  • receivedBytes: 当前已经接收的字节数
codePush.sync({ ... }, this.codePushStatusDidChange, this.codePushDownloadDidProgress ) codePushDownloadDidProgress = progress => { console.log(progress) }

在使用高阶函数包裹根组件的方式中,也会有这两个回调, 只不过是以生命周期函数出现的, 用发是在App根组件中添加两个生命周期方法, 用法如下。

import CodePush from "react-native-code-push"; class App extends React.Component { codePushStatusDidChange(state){ ... } codePushDownloadDidProgress(progress){ ... } } export default CodePush(App);

一般来说,我们使用高阶函数或者sync方法配合一些配置已经可以完成检查更新的大部份需求, 但有时我们需要手动去控制整个过程(检查更新, 下载更新, 安装更新), 这时我们可能会用到下面的一些高级方法,为了对code-push有一个更清晰的了解,我们还是需要了解这些方法的用处用法, 下面我会一一介绍。

二、codePush.disallowRestart()方法

由于安装了更新, 在下次启动时安装的更新会被应用。 在这期间(安装了更新但还未重启), 调用codePush.disallowRestart()可以禁止通过程序重启App.

什么时候会用到此方法呢?
当installMode的值为IMMEDIATE,或ON_NEXT_RESUME,或者手动调用codePush.restart()方法时。
也可以理解为codePush.disallowRestart()方法阻止codePush.restart()的调用。

在调用codePush.disallowRestart()方法后,任然可以获取和安装更新, 但必须等待allowRestart方法被调用后才会重启。

三、codePush.allowRestart()方法

如果调用了disallowRestart方法,而导致更新被挂起(未重启),那么调用allowRestart方法将立即重启程序。

否则将会有以下四种情况

  1. 这期间没有更新,所以无需重启
  2. installMode为ON_NEXT_RESTART(下次启动更新), 所以无需重启
  3. installMode为ON_NEXT_RESUME,但程序一直在前台,所以无需重启
  4. 这期间没有调用过restartApp方法

使用

class App extends Component { componentWillMount(){ // 组件活动状态不允许重启 codePush.disallowRestart(); } componentWillUnmount(){ // 组件卸载时可以运行重启更新了 codePush.allowRestart(); } ... }

四、codePush.checkForUpdate(deploymentKey, handleBinaryVersionMismatchCallback)

checkForUpdate用于查询code-push服务器是否有可用更新, 它接收两个参数,第一个是deploymentKey可用于覆盖配置文件中的key, 第二个为查询的回调函数。

handleBinaryVersionMismatchCallback返回一个promise表示查询结果, 有两种情况:

  1. null
  2. 可用的更新实例RemotePackage

返回结果为null表示无更新 可能是如下几种情况造成的:

  1. 服务器上该部署还没有任何版本
  2. 配置部署的二进制版本和当前用户版本不一致(二进制版本更新需重新上传应用商店)
  3. 已经是最新版本
  4. 部署中的版本被标记为禁用
  5. 部署中的最新版本是活动部署状态,当前用户不在百分百范围内(也就是灰度发布)

否则返回一个可用的更新实例RemotePackage(远端包的实例)

这个实例中包含了一些包的基础信息和下载信息, 另外提供了一个下载方法,用于我们调用此方法下载更新。具体如下

  1. appVersion: 二进制包的版本号
  2. deploymentKey: 秘钥
  3. packageSize: 包的大小
  4. downloadUrl: 包的地址
  5. download(downCallBack ? function) : Promise, 下载的回调, 下载完成后会返回一个 LocalPackage本地包的实例。
  6. 其他的属性不说了…

使用

codePush.checkForUpdate().then(update => { if (!update) { console.log("上面那五种失败情况之一"); } else { console.log("有可用更新"); // 下载远端的包到本地 update.download(this.downCallBack); } });

将远端的包下载到本地后,可以拿到LocalPackage本地包的实例,本地包实例包含了和LocalPackage包相似的属性方法, 另外提供了一个install方法用于安装更新。

五、codePush.notifyAppReady()

调用此方法通知codePush服务器新的安装已经成功,此方法用在手动下载更新时,如果没有调用此方法通知,那么在下一次启动app时,code-push服务器会任务上一次安装失败了,然后会回滚更新。 在使用sync方法或者高阶函数时不需要调用此方法。

六、codePush.getUpdateMetadata(UpdateState)

获取用户当前已安装的二进制文件信息

七、codePush.restartApp

立即重启应用程序, 但有可能被阻止。

总结

在客户端检查更新的方式有很多中,具体选泽哪种更新方案需要根据具体需求+平台规定考虑决定。

通常使用自动检查下载安装更新可以更加方便简单,但若是有特殊需求,也可以自己控制着整个过程。