"use strict"; cc._RF.push(module, 'ccd99idFVNMI4Kh//YC0YYp', 'update.mod'); // Scripts/mod/login/update/update.mod.js "use strict"; /******************************************************************************* * * 版本热更新 * * * * 2020.08.31 ******************************************************************************/ var MOD = require("nx.mod"); var HotUpdater = cc.Class({ "extends": MOD, name: "HotUpdater", // 初始化 initialize: function initialize(_args) { // USPER this._super(_args); // 访问接口(设置) nx.bridge.updater = this; // 准备工作 this.doReady(); return true; }, // 销毁 uninitialize: function uninitialize() { // 监听关闭 if (this._am) { this._am.setEventCallback(null); } // 访问接口(关闭) nx.bridge.updater = null; // USPER return this._super(); }, // 准备工作 doReady: function doReady() { nx.debug("$Updater:开始准备工作"); // 存储路径 this._storagePath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'fc-remote-asset'; nx.debug("$Updater:存储路径:", this._storagePath); // 实例化更新器 this._am = new jsb.AssetsManager('', this._storagePath, function (_v1, _v2) { nx.debug("$Updater:版本比较:%s, %s", _v1, _v2); var vA = _v1.split('.'); var vB = _v2.split('.'); for (var i = 0; i < vA.length; ++i) { var a = parseInt(vA[i]); var b = parseInt(vB[i] || 0); if (a === b) { continue; } else { return a - b; } } if (vB.length > vA.length) { return -1; } else { return 0; } }); // 安卓 if (cc.sys.os === cc.sys.OS_ANDROID) { this._am.setMaxConcurrentTask(2); } }, // 绑定本地清单 bindManifest: function bindManifest(_asset) { this.manifestUrl = _asset; }, // ====================================================================== // 检查更新 // ====================================================================== // 检查更新 checkUpdate: function checkUpdate(_cb) { nx.debug("$Updater:更新检查"); if (this._updating) { nx.warn("$Updater:正在更新,重复检查忽略"); nx.dt.fnInvoke(_cb, false, "UpdateCheckFailed", 99); return; } // 清单载入 if (this._am.getState() === jsb.AssetsManager.State.UNINITED) { var url = this.manifestUrl.nativeUrl; if (cc.loader.md5Pipe) { url = cc.loader.md5Pipe.transformURL(url); } this._am.loadLocalManifest(url); } // 清单载入失败 if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) { nx.error("$Updater:Failed to load local manifest ..."); nx.dt.fnInvoke(_cb, false, "UpdateCheckFailed", jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST); return; } this._updating = true; this._checkListener = _cb; this._am.setEventCallback(this.checkCb.bind(this)); this._am.checkUpdate(); }, // 检查事件 checkCb: function checkCb(event) { nx.debug("$Updater:Code:", event.getEventCode()); var EAM = jsb.EventAssetsManager; switch (event.getEventCode()) { case EAM.ERROR_NO_LOCAL_MANIFEST: nx.error("$Updater:No local manifest file found, hot update skipped."); nx.dt.fnInvoke(this._checkListener, false, "UpdateCheckFailed", event.getEventCode()); break; case EAM.ERROR_DOWNLOAD_MANIFEST: case EAM.ERROR_PARSE_MANIFEST: nx.error("$Updater:Fail to download manifest file, hot update skipped."); nx.dt.fnInvoke(this._checkListener, false, "UpdateCheckFailed", event.getEventCode()); break; case EAM.ALREADY_UP_TO_DATE: nx.debug("$Updater:无需更新."); nx.dt.fnInvoke(this._checkListener, true, 0); break; case EAM.NEW_VERSION_FOUND: nx.debug("$Updater:发现新版本,字节数(%s),文件数(%s)", this._am.getTotalBytes(), this._am.getTotalFiles()); nx.dt.fnInvoke(this._checkListener, true, this._am.getTotalBytes()); break; default: return; } this._updating = false; this._checkListener = null; this._am.setEventCallback(null); }, // ====================================================================== // 资源更新 // ====================================================================== // 更新 doUpdate: function doUpdate(_cb) { nx.debug("$Updater:更新"); if (this._updating) { nx.warn("$Updater:正在更新,重复更新忽略"); nx.dt.fnInvoke(_cb, false, "UpdateFailed", 99); return; } // 清单载入 if (this._am.getState() === jsb.AssetsManager.State.UNINITED) { var url = this.manifestUrl.nativeUrl; if (cc.loader.md5Pipe) { url = cc.loader.md5Pipe.transformURL(url); } this._am.loadLocalManifest(url); } this._failCount = 0; this._updating = true; this._updateListener = _cb; this._am.setEventCallback(this.updateCb.bind(this)); this._am.update(); }, // 更新事件 updateCb: function updateCb(event) { var failed = false; var needRestart = false; var EAM = jsb.EventAssetsManager; switch (event.getEventCode()) { case EAM.ERROR_NO_LOCAL_MANIFEST: nx.error("$Updater:No local manifest file found, hot update skipped. "); failed = true; break; case EAM.UPDATE_PROGRESSION: nx.dt.fnInvoke(this._updateListener, true, { size: { percent: event.getPercent(), cur: event.getDownloadedBytes(), total: event.getTotalBytes() }, files: { percent: event.getPercentByFile(), cur: event.getDownloadedFiles(), total: event.getTotalFiles() } }); var msg = event.getMessage(); if (msg) { nx.debug("$Updater:Updated file:", msg); // cc.log(event.getPercent()/100 + '% : ' + msg); } break; case EAM.ERROR_DOWNLOAD_MANIFEST: case EAM.ERROR_PARSE_MANIFEST: nx.error("$Updater:Fail to download manifest file, hot update skipped. "); failed = true; break; case EAM.ALREADY_UP_TO_DATE: nx.error("$Updater:Already up to date with the latest remote version. "); failed = true; break; case EAM.UPDATE_FINISHED: nx.debug("$Updater:Update finished.", event.getMessage()); needRestart = true; break; case EAM.UPDATE_FAILED: nx.error("$Updater:Update failed.", event.getMessage()); // this._updating = false; // this._canRetry = true; failed = true; break; case EAM.ERROR_UPDATING: nx.error("$Updater:Asset update error:", event.getAssetId(), event.getMessage()); break; default: break; } // 失败 if (failed) { this._am.setEventCallback(null); nx.dt.fnInvoke(this._updateListener, false, "UpdateFailed", event.getEventCode()); this._updating = false; this._updateListener = null; } // 更新完成重启 if (needRestart) { this._am.setEventCallback(null); this._updateListener = null; // 重构查询路径列表 var newPaths = this._am.getLocalManifest().getSearchPaths(); nx.debug("$Updater:清单额外查询路径:", JSON.stringify(newPaths)); // 额外路径追加 var searchPaths = jsb.fileUtils.getSearchPaths(); for (var i = 0; i < newPaths.length; i++) { if (searchPaths.indexOf(newPaths[i]) == -1) { Array.prototype.unshift.apply(searchPaths, [newPaths[i]]); } } // 更新本地查询路径 cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths)); jsb.fileUtils.setSearchPaths(searchPaths); // 重启 nx.restart(); } } }); // 模块导出 module.exports = HotUpdater; cc._RF.pop();