使用JS控制Cordava热更新过程[cordova-hot-code-push-plugin]

雾绡重载
• 阅读 3346

概要

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

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这