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

概要

cordova-hot-code-push-plugin(如下簡稱chcp)自己已經支持自動檢查更新、下載、安裝,具體內容能夠搜索「cordova熱更新」,或查看官方wiki。本文主要介紹如何使用chcp提供的JS API控制整個熱更新過程,包括其中一些注意事項。本文僅針對安卓,iOS暫未驗證。javascript

需求背景

  1. 顯示更新內容(彈窗)
  2. 可手動檢查更新(點擊按鈕)

存在的問題

chcp提供的API基本能知足大部分功能,但爲了知足需求還須要解決如下問題:java

  1. 官方沒有提供顯示更新內容的方法
  2. 檢查更新時,若是有更新,會等到下載完成才執行回調函數,致使操做長時間沒有反饋;另外一方面,若是有error(正在更新等),回調函數又會當即執行

思路

針對問題1:在配置文件chcp.json中新增字段表示更新內容,並經過直接請求或調用API獲取,好比"message":"1. bug修復...",並在具體流程中展現彈窗(本文是在更新內容下載完成後,也能夠在檢查到有更新的時候)git

針對問題2:單獨請求服務端的chcp.json,並跟本地的版本比較,不一樣就認爲有更新,能夠當即反饋給用戶github

API驗證

getVersionInfo((err, data) => {...}) 獲取版本信息

data.currentWebVersion 對應www/chcp.json中的release,本地配置,就是比較版本要用到的
data.readyToInstallWebVersion 本次要安裝的版本,爲空多是沒有獲取到服務端配置,或者已經是最新版
data.previousWebVersion 更新後的上一個版本,爲空說明尚未更新過
data.appVersion 版本號,對應config.xml中的widget的version,本地配置
data.buildVersion 構建版本號,本地配置json

實際測試,只要服務端的release字段和本地的currentWebVersion不一樣,chcp就認爲須要更新,而不會檢查appVersion或者buildVersion是否相同(chcp.json中也沒有這兩個字段)。服務器

fetchUpdate((err, data) => {...}, options) 獲取更新

若是有更新,fetchUpdate只有在下載完成全部更新後才執行回調函數。若是正在下載更新,回調函數會當即執行,err.code爲-17。爲了區分上述兩種狀況且只有一次提示,首次檢查到有更新時,提示能夠使用setTimeout延時,回調函數執行時,先clearTimeout,再執行有error時的提示。app

須要注意的是,下載成功後,回調函數中data的內容以下:函數

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

其實就是把chcp.json的內容做爲字符串做爲config屬性的值。若是要獲取裏面的值,須要作一次JSON解析。測試

isUpdateAvailableForInstallation((err, data) => {...}) 檢查本地是否有可供安裝的更新

若是沒有調用過fetchUpdate,或者已是最新版,則error存在,表示沒有能夠安裝的更新,須要獲取更新,具體參見官方示例fetch

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

相關文章
相關標籤/搜索