乐趣区

关于javascript:使用JS控制Cordava热更新过程cordovahotcodepushplugin

概要

cordova-hot-code-push-plugin(以下简称 chcp)自身曾经反对主动查看更新、下载、装置,具体内容能够搜寻“cordova 热更新”,或查看官网 wiki。本文次要介绍如何应用 chcp 提供的 JS API 管制整个热更新过程,包含其中一些注意事项。本文仅针对安卓,iOS 暂未验证。

需要背景

  1. 显示更新内容(弹窗)
  2. 可手动查看更新(点击按钮)

存在的问题

chcp 提供的 API 根本能满足大部分性能,但为了满足需要还须要解决以下问题:

  1. 官网没有提供显示更新内容的办法
  2. 查看更新时,如果有更新,会等到下载实现才执行回调函数,导致操作长时间没有反馈;另一方面,如果有 error(正在更新等),回调函数又会立刻执行

思路

针对问题 1:在配置文件 chcp.json 中新增字段示意更新内容,并通过间接申请或调用 API 获取,比方"message":"1. bug 修复...",并在具体流程中展现弹窗(本文是在更新内容下载实现后,也能够在查看到有更新的时候)

针对问题 2:独自申请服务端的 chcp.json,并跟本地的版本比拟,不同就认为有更新,能够立刻反馈给用户

API 验证

getVersionInfo((err, data) => {…}) 获取版本信息

data.currentWebVersion 对应 www/chcp.json 中的 release,本地配置,就是比拟版本要用到的
data.readyToInstallWebVersion 本次要装置的版本,为空可能是没有获取到服务端配置,或者已是最新版
data.previousWebVersion 更新后的上一个版本,为空阐明还没有更新过
data.appVersion 版本号,对应 config.xml 中的 widget 的 version,本地配置
data.buildVersion 构建版本号,本地配置

理论测试,只有服务端的 release 字段和本地的 currentWebVersion 不同,chcp 就认为须要更新,而不会查看 appVersion 或者 buildVersion 是否雷同(chcp.json 中也没有这两个字段)。

fetchUpdate((err, data) => {…}, options) 获取更新

如果有更新,fetchUpdate只有在下载实现所有更新后才执行回调函数。如果正在下载更新,回调函数会立刻执行,err.code为 -17。为了辨别上述两种状况且只有一次提醒,首次查看到有更新时,提醒能够应用 setTimeout 延时,回调函数执行时,先clearTimeout,再执行有 error 时的提醒。

须要留神的是,下载胜利后,回调函数中 data 的内容如下:

{config: '"release":"xxx",...'}

其实就是把 chcp.json 的内容作为字符串作为 config 属性的值。如果要获取外面的值,须要做一次 JSON 解析。

isUpdateAvailableForInstallation((err, data) => {…}) 查看本地是否有可供装置的更新

如果没有调用过fetchUpdate,或者曾经是最新版,则 error 存在,示意没有能够装置的更新,须要获取更新,具体参见官网示例。

installUpdate((err) => {…}) 执行装置

整体流程

  1. 比拟本地和服务端版本,版本不同 -> 2
  2. 查看本地是否有可装置的更新,没有 -> 3,有 -> 4
  3. 从服务端下载更新,会有以下几种状况:
    a. 没有更新(个别不会呈现,除非 1 到 3 之间,server 版本回退了 …)
    b. 正在下载更新中(没下载实现的时候,点击“查看更新”)
    c. 不能应用热更新,须要更新包(原生代码有批改的时候,热更新曾经不能向后兼容)
    d. 其余谬误
    e. 失常下载实现 -> 4
  4. 弹窗显示更新内容,用户点击“立刻体验”后,装置更新,装置成后会间接刷新,目测是跳转到 index

另外,最好将主动下载和主动装置敞开,避免抵触:

config.xml
<chcp>
  <auto-download enabled="false" />
  <auto-install enabled="false" />
</chcp>

具体代码

// 获取本地的 currentWebVersion,并和服务端的 release 比拟
function compareVersion(serverVersion) {return new Promise((resolve, reject) => {window.chcp.getVersionInfo((error, data) => {console.log('getVersionInfo', data);
      if (error) {reject(error)
      } else {resolve(data.currentWebVersion === serverVersion);
      }
    });
  });
}
// 申请服务端 chcp.json
function checkUpdate() {
  const url = "https://yourserver/chcp.json";
  fetch(url).then(res => res.json()).then(data => compareVersion(data.release)).then(isEqual => {if (isEqual) {toast('已是最新版');
    } else {
      // 流程 2,查看是否有可装置更新
      checkAvalilable();}
  }).catch((error) => {console.log('checkUpdate failed', error)
  });
}
// 查看是否有可装置的更新
function checkAvalilable() {console.log('checkAvalilable');
  window.chcp.isUpdateAvailableForInstallation((error, data) => {if (error) {console.log('isUpdateAvailableForInstallation error', error);
      checkHotUpdate();
      return;
    }
    // 已有可装置版本
    beforeInstallAlert();});
}
// 获取更新
function checkHotUpdate() {console.log('checkHotUpdate');
  const waitingId = setTimeout(() => {toast('有新版,开始更新');
  }, 200);
  window.chcp.fetchUpdate((error, data) => {if (error) {console.log('fetchUpdate error', error);
      clearTimeout(waitingId);
      if (error.code == 2) {toast('已是最新版');
      } else if (error.code == -17) {toast('正在下载更新中...');
      } else if (error.code == -2) {// 须要下载 apk} else {toast(` 出错了: ${error.code}`);
      }
      return;
    }
    // 服务器版本信息
    console.log('fetchUpdate data', data);
    // JSON 解析 config
    const config = data && data.config && JSON.parse(data.config);
    console.log('fetchUpdate config', config);
    // 下载实现,message 为自定义字段,示意更新内容
    beforeInstallAlert(config && config.message);
  });
}

function beforeInstallAlert(message) {// 弹窗逻辑,点击“立刻体验”调用 installUpdate()
}

function installUpdate() {console.log('installUpdate');
  window.chcp.installUpdate((error) => {if (error) {console.log('installUpdate error', error);
      toast(` 装置失败: ${error.code}`);
      return;
    }
    console.log('installUpdate done');
  });
}

其余

err.code 参见 Error codes

退出移动版