移動端APP應用版本升級更新方案:整包更新及資源在線升級(熱更新)


  App端的升級,又分為整包更新和資源熱更新兩種:

1、整包更新,即常規的整個App安裝包重新下載安裝。

2、資源熱更新,即App不重新安裝,里面的js等前端代碼進行更新。

一、整包更新方案

1、IOS更新

  一般iOS Appstore的安裝包,無法直接更新。App啟動后檢查有新版本,只能跳轉到Appstore,然后用戶在Appstore的詳情頁點擊更新按鈕。

2、Android更新

  而Android App,可以直接下載新的apk,只要包名和證書不變,就可以覆蓋安裝。

  注意:

(1)App的升級檢測代碼必須使用條件編譯,否則在非App環境由於不存在plus相關API,將會報錯。

(2)升級地址URL,如果是自行托管的App,就提供自己的包地址。如果是打開應用市場,那URL如下:

if (plus.os.name=="Android") { appurl = "market://details?id=io.dcloud.hellouniapp"; 
  //這個是通用應用市場,如果想指定某個應用商店,需要單獨查這個應用商店的包名或scheme及參數 } else { appurl = "itms-apps://itunes.apple.com/cn/app/hello-uni-app/id1417078253"; }

(3)版本檢測需要打包app,真機運行基座無法測試。因為真機運行的plus.runtime.version是固定值。

  關於升級,比較省事的就是跳轉到瀏覽器下載apk包,下載完成之后安裝。另外可以在應用內下載,下載完成之后調用plus.runtime.install安裝。具體代碼如下:

// 在index.vue 中的onload方法里面或者app.vue中的onLaunch中添加如下部分:
update() { var _this = this; uni.request({ url: `${this.$store.state.apiBaseUrl}/users/versions`,  //請求接口
    method: 'POST', success: result => { if (result.data.code == 1) { plus.runtime.getProperty(plus.runtime.appid, function(inf) { if(inf.version != result.data.data.versions){ uni.showModal({ title: "發現新版本", content: "確認下載更新", success: (res) => { if (res.confirm == true) {//當用戶確定更新,執行更新
 _this.doUpData(); } } }) } }); } }, }) }, doUpData() { uni.showLoading({ title: '更新中……' }) uni.downloadFile({//執行下載
        url: '***', //下載地址
        success: downloadResult => {//下載成功
 uni.hideLoading(); if (downloadResult.statusCode == 200) { uni.showModal({ title: '', content: '更新成功,確定現在重啟嗎?', confirmText: '重啟', confirmColor: '#EE8F57', success: function(res) { if (res.confirm == true) { plus.runtime.install(//安裝
 downloadResult.tempFilePath, { force: true }, function(res) { utils.showToast('更新成功,重啟中'); plus.runtime.restart(); } ); } } }); } } }); }

二、資源在線升級(熱更新)

  HBuilderX 1.6.5 起,uni-app 支持生成 App 資源升級包。

1、生成 App 資源升級包

(1)修改版本號:

  首先,更新 manifest.json 中的版本號。比如之前是 1.0.0,那么新版本應該是 1.0.1 或 1.1.0 這樣。

(2)發行:

  然后,在 HBuilderX 中生成wgt的升級包(wgt):菜單->發行->原生App-制作移動App資源升級包

  生成結束會在控制台告知升級包的輸出位置。

2、安裝資源升級包

  應用的升級需要服務端與客戶端配合完成,下面以本地測試過程中的操作舉例說明:

(1)存放資源

  將 %appid%.wgt 文件存放在服務器的 static 目錄下,如即 http://www.example.com/static/UNI832D722.wgt。

(2)服務端接口

  約定檢測升級的接口,如地址為:http://www.example.com/update/

(3)傳入參數

參數名 類型 默認值 說明
name String '' 客戶端讀取到的應用名稱,定義這個參數可以方便多個應用復用接口。
version String '' 客戶端讀取到的版本號信息

(4)返回參數

參數名 類型 默認值 說明
update Boolean false 是否有更新
wgtUrl String '' wgt 包的下載地址,用於 wgt 方式更新。
pkgUrl String '' apk/ipa 包的下載地址或 AppStore 地址,用於整包升級的方式。

(5)代碼示例

  下面是一個簡單的服務端判定的示例,僅做參考,實際開發中根據自身業務需求處理。

var express = require('express'); var router = express.Router(); var db = require('./db'); // TODO 查詢配置文件或者數據庫信息來確認是否有更新 
function checkUpdate(params, callback) { db.query('一段SQL', function(error, result) { // 這里簡單判定下,不相等就是有更新。 
        var currentVersions = params.appVersion.split('.'); var resultVersions = result.appVersion.split('.'); if (currentVersions[0] < resultVersions[0]) { // 說明有大版本更新 
 callback({ update: true, wgtUrl: '', pkgUrl: result.pkgUrl }) } else { // 其它情況均認為是小版本更新 
 callback({ update: true, wgtUrl: result.wgtUrl, pkgUrl: '' }) } }); } router.get('/update/', function(req, res) { var appName = req.query.name; var appVersion = req.query.version; checkUpdate({ appName: appName, appVersion: appVersion }, function(error, result) { if (error) { throw error; } res.json(result); }); });

  注意事項

  • 以上約定,僅做參考。
  • 服務端的具體判定邏輯,請根據自身的業務邏輯靈活處理。
  • 應用中的路徑盡量不要包含特殊符號

3、客戶端檢測升級

  在 App.vue 的 onLaunch 中檢測升級,代碼如下:

// #ifdef APP-PLUS 
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) { uni.request({ url: 'http://www.example.com/update/', data: { version: widgetInfo.version, name: widgetInfo.name }, success: (result) => { var data = result.data; if (data.update && data.wgtUrl) { uni.downloadFile({ url: data.wgtUrl, success: (downloadResult) => { if (downloadResult.statusCode === 200) { plus.runtime.install(downloadResult.tempFilePath, { force: false }, function() { console.log('install success...'); plus.runtime.restart(); }, function(e) { console.error('install fail...'); }); } } }); } } }); }); // #endif

4、不支持的情況

(1)SDK 部分有調整,比如新增了 Maps 模塊等,不可通過此方式升級,必須通過整包的方式升級。

(2)原生插件的增改,同樣不能使用此方式。

(3)對於老的非自定義組件編譯模式,這種模式已經被淘汰下線。但以防萬一也需要說明下,老的非自定義組件編譯模式,如果之前工程沒有 nvue 文件,但更新中新增了 nvue 文件,不能使用此方式。因為非自定義組件編譯模式如果沒有nvue文件是不會打包weex引擎進去的,原生引擎無法動態添加。自定義組件模式默認就含着weex引擎,不管工程下有沒有nvue文件。

5、注意事項

(1)條件編譯,僅在 App 平台執行此升級邏輯。

(2)appid 以及版本信息等,在 HBuilderX 真機運行開發期間,均為 HBuilder 這個應用的信息,因此需要打包自定義基座或正式包測試升級功能。

(3)plus.runtime.version 或者 uni.getSystemInfo() 讀取到的是 apk/ipa 包的版本號,而非 manifest.json 資源中的版本信息,所以這里用 plus.runtime.getProperty() 來獲取相關信息

(4)安裝 wgt 資源包成功后,必須執行 plus.runtime.restart(),否則新的內容並不會生效

(5)如果App的原生引擎不升級,只升級wgt包時需要注意測試wgt資源和原生基座的兼容性。平台默認會對不匹配的版本進行提醒,如果自測沒問題,可以在manifest中配置忽略提示,詳見https://ask.dcloud.net.cn/article/35627

6、關於熱更新是否影響應用上架

  應用市場為了防止開發者不經市場審核許可,給用戶提供違法內容,對熱更新大多持排斥態度。

  但實際上熱更新使用非常普遍,不管是原生開發中還是跨平台開發。

  Apple曾經禁止過jspatch,但沒有打擊其他的熱更新方案,包括cordovar、react native、DCloud。封殺jspatch其實是因為jspatch有嚴重安全漏洞,可以被黑客利用,造成三方黑客可篡改其他App的數據。

  使用熱更新需要注意:

  • 上架審核期間不要彈出熱更新提示
  • 熱更新內容使用https下載,避免被三方網絡劫持
  • 不要更新違法內容、不要通過熱更新破壞應用市場的利益,比如iOS的虛擬支付要老老實實給Apple分錢

  如果你的應用沒有犯這些錯誤,應用市場是不會管的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM