项目背景

使用 cordova + vue + mintui 开发混合 app(安卓版),需要提供热更新和版本升级功能。此处热更新指的是更新 h5 代码部分,比如修改了登录的样式没必要让用户去重新下载 app;版本升级就是需要用户下载 app 覆盖安装,这一般发生在 cordova 下载了新的插件去调用手机硬件功能。

热更新配置步骤:

  1. 安装 cordova 热更新插件
cordova plugin add cordova-hot-code-push-plugin
  1. 安装 cordova 热更新工具
npm install -g cordova-hot-code-push-cli

注意:该步可能失败,一是网速较慢,二是我的 npm 版本较低,安装了最新的 nodejs 后安装成功。(我的环境:node v14.15.5,npm 6.14.11)

  1. 在服务器可访问路径下创建一个目录,比如:www。该目录存放的是 cordova 工程的 www 目录下的所有文件。注意要保证该目录以 http 方式正常访问,而且json 格式的文件,也必须同样能以 http 方式访问到。
  2. 生成热更新相关配置文件
cordova-hcp init

执行该命令后会在 cordova 项目根目录下生成 cordova-hcp.json 文件,内容如下:

{
  "name": "mobilemanage",
  "autogenerated": true, 
  "ios_identifier": "",
  "android_identifier": "",
  "update": "start",
  "content_url": "http://61.164.57.186:18890/dev/ftp/www"
}

“autogenerated”: true 这个值执行命令后是没有的需要自己手动添加,如果不添加网页内容更新将会无效。content_url 字段的值是步骤 3 中目录的地址。

cordova-hcp build

执行该命令后会在 cordova 项目的 www 目录中发现两个文件:chcp.json 和 chcp.manifest。
chcp.json 文件的内容如下:

{
  "name": "mobilemanage",
  "autogenerated": true,
  "ios_identifier": "",
  "android_identifier": "",
  "update": "start",
  "content_url": "http://61.164.57.186:18890/dev/ftp/www",
  "release": "2021.02.24-11.05.08"
}

可以发现,chcp.json 比 cordova-hcp.json 多了一行内容。release 字段用于热更新的版本比较。

  1. config.xml 文件配置(该文件位于 cordova 项目根目录下)
    在 widget 标签内加入如下代码,url 的值为 chcp.json 文件在服务器的地址。
<chcp>
  <config-file url="http://61.164.57.186:18890/dev/ftp/www/chcp.json"/>
</chcp>
  1. 测试热更新功能
    1) cordova 打包 apk 并安装至手机
cordova build android

2)修改页面内容后执行cordova-hcp build,重新生成 chcp.json 和 chcp.manifest。将 cordova 项目的 www 文件夹下的所有内容复制到步骤 3 的目录下。

3)重新启动 app ,可以看到页面被修改。注意:页面修改不一定及时,可多次重启 app 查看效果。

版本升级配置步骤:

在完成热更新配置的基础上,完成下面步骤即可实现版本升级。

  1. 在config.xml 文件中的 chcp 标签内添加如下配置:
<auto-download enabled="false" />
<auto-install enabled="false" />
<native-interface version="1" />

auto-download:是否自动下载热更新代码,默认是 true,这里改为false,因为我们想控制下载的流程
auto-install:是否自动安装热更新代码,默认是 true,这里改为false,理由同上
native-interface:当前 native side 的版本号即 app 外壳版本号

  1. 在 cordova-hcp.json 文件中添加如下配置:
"min_native_interface": 1,
"android_identifier": "http://61.164.57.186:18890/dev/ftp/app-debug.apk"

min_native_interface:在用 cordova-hcp.json 文件生成 chcp.json 文件后,(chcp.json 文件中的)该字段被用来和步骤 1 中的 native-interface 比较。两个值相同 ,不提示升级,但是网页内容可以更新。如果 xml 文件中的值大于服务器上的值,不会提醒更新,但是网页内容可以更新。小于服务上的值,提示应用需要更新升级,那么热更新将无法正常进行。
android_identifier:我们的 apk 未进驻安卓应用市场,因此该值配置的是需要下载的安装包在可访问的服务器上的路径

  1. 添加手动更新的 js 代码
    因为我用了 Vue,因此我的 js 代码写在 main.js 文件内,并且在监听设备加载完成的函数内。
chcp.fetchUpdate((error, data) => {
    if (error) {
      if (error.code === -2) {
        var dialogMessage = '发现新版本,为避免影响使用请更新';
        //调用升级提示框 点击确认会跳转对应商店升级
        chcp.requestApplicationUpdate(dialogMessage, null, null);
      }
    }
})

以上代码的功能是检查本地安装版本和服务器 apk 版本大小,-2 代表 chcp.error.APPLICATION_BUILD_VERSION_TOO_LOW 即本地版本太低,需要下载 apk。因为我们的后端不打算维护多套代码,因此这里使用强制更新即在升级提示框出现后没有取消按钮,用户只能点击立即更新。这需要去改热更新插件的源码,注释掉设置取消按钮那一段。文件是 chcp 的 view 目录下的 AppUpdateRequestDialog,注释部分如下图所示。

cordova版本更新 ios cordova热更新_json

  1. 测试版本升级功能出现的问题
    1、 测试机配置 native-interface 版本为 1 ,服务器上 chcp.json 中 min_native_interface 值为 2,弹框提示是否更新,点击确定后弹出系统下载框询问是否下载app-debug.apk 。这里用户如果选择了取消,版本升级也将失败,因此我们并未实现强制更新。
    2、不同机型和系统下载完 apk 后表现不同。华为 9.0 的手机下载完成会自动跳转到安装页面询问是否安装;小米 10.0 的手机下载完后只在消息通知栏提示,需要手动点击才能跳转到安装页面。
    3、安装最新的 apk 发现未生效,遗漏了一个重要字段的更新。config.xml 文件 widget 标签有一个属性 version,每次升级 native-interface 字段的同时也要升级 version 字段。