CocosCreator2.4.6熱更新+動態修改版號
- 承鑫 郭
- 2021年7月29日
- 讀畢需時 3 分鐘
前言
本篇以Cocos2.3.4這篇熱更新做延續 。
由於使用CocosCreator來做App都會需要熱更新功能,經過Coocs版本翻新熱更新的功能也有一些寫法改變,最近更新專案版本同時順了一遍熱更新發現有很多地方有改進,也有新的坑點,藉此紀錄來方便以後查看,也希望可以對一些接觸到2.4.6版本的人有所幫助。
熱更新原理
https://docs.cocos.com/creator/manual/zh/advanced-topics/hot-update.html https://docs.cocos.com/creator/manual/zh/advanced-topics/assets-manager.html 原理請參考官方文檔,上面有詳細解說,本次紀錄只有針對可能會遇到的坑點或是測試上會遇到的問題進行解說,基本上還是照著官方文檔操作,所以官方文件務必詳細看過。
熱更新管理者
官方熱更新腳本 基本上可以按照自己專案的需求從官方的熱更新.js做修改,如果沒有需求就不用修改,也可以先下載官方範例跑跑看,目前本專案架構是客戶端會使用Http請求遠程的服務器資源地址、版號、是否為大版本更新,強制覆蓋本地local的manifest的資料,讓更新地址以及版號可以隨開發者更新。 修改重點如下:
新增一個UpdateControl.Json並放到遠程伺服器
{
"hotUpdate": true,
"hotUpdateUrl": "http://169.254.240.209:8000",
"version": "ver_2_0",
"forceBigUpdate": false
}
熱更新時先使用xhr抓取此Json檔,取出熱更新位址以及版本號等資訊帶入熱更新管理者
window.HotUpdateManager.GetInstance().init(this.updateControl.hotUpdateUrl + "/" + this.updateControl.version + "/", this.updateControl);
更改local manifest熱更新地址
//更改本地目錄 更新地址
HotUpdateHandler.prototype.UpdateLocalConfigUrl = function () {
if (this._updating) {
return;
}
this._updating = true;
this._storagePath = this.getSavePath();
if (!jsb.fileUtils.isDirectoryExist(this._storagePath)) {
jsb.fileUtils.createDirectory(this._storagePath);
}
this.project_storagePath = this._storagePath + '/project.manifest';
//修改本地文件 //大版本更新時 version必須設定到最新版 才不會一直卡在更新輪迴
let jsonData = {
"packageUrl": "http://xxx.xxx/cocos-hu/ly/",
"remoteManifestUrl": "http://xxx.xxx/cocos-hu/ly/project.manifest",
"remoteVersionUrl": "http://xxx.xxx/cocos-hu/ly/version.manifest",
"version": "0.0.0",
"assets": {
},
"searchPaths": [
]
};
jsonData.packageUrl = this.HotUpdateUrl;
jsonData.remoteManifestUrl = this.HotUpdateUrl + "project.manifest";
jsonData.remoteVersionUrl = this.HotUpdateUrl + "version.manifest";
let writeData = JSON.stringify(jsonData);
//如果沒有project.manifest 強制寫入一個0.0.0版給他
if (!jsb.fileUtils.isFileExist(this.project_storagePath)) {
console.log(this.project_storagePath);
console.log('如果沒有project.manifest 強制寫入一個1.0版給他');
jsb.fileUtils.writeStringToFile(writeData, this.project_storagePath);
this.manifestUrl = this.project_storagePath;
this.HotUpdatePrepare();
}else{
//覆蓋遠程URL
cc.loader.load(this.project_storagePath, function (error, data) {
if (error) {
console.log("error : " + error);
return;
}
let jsonData = JSON.parse(data);
jsonData.packageUrl = this.HotUpdateUrl;
jsonData.remoteManifestUrl = jsonData.packageUrl + "project.manifest";
jsonData.remoteVersionUrl = jsonData.packageUrl + "version.manifest";
cc.log("重寫本地配置文件更新地址:" + this.HotUpdateUrl);
let writeData = JSON.stringify(jsonData);
if (jsb.fileUtils.isFileExist(this.project_storagePath)) {
jsb.fileUtils.removeDirectory(this.project_storagePath);
cc.log("删除已有初始目录");
}
//模擬器測試 出現過沒刪掉的情況 加個二次刪除 預防報錯
if (jsb.fileUtils.isFileExist(this.project_storagePath)) {
jsb.fileUtils.removeFile(this.project_storagePath);
cc.log("删除已有初始目录");
}
jsb.fileUtils.writeStringToFile(writeData, this.project_storagePath);
this.manifestUrl = this.project_storagePath;
this.HotUpdatePrepare();
}.bind(this));
}
};
比對版本改為版本不一致就return -1
//比對版本
HotUpdateHandler.prototype.VersionCompareHandle = function () {
let handle = function (versionA, versionB) { };
if (this.Test) {
return handle
}
else{
handle = function (versionA, versionB) {
//檢查目前配置的版型
console.log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);
var vA = versionA.split('.');
var vB = versionB.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 -1;
}
}
if (vB.length > vA.length) {
return -1;
}
else {
return 0;
}
};
return handle;
}
}
buildtemplate的main.js最前面加上優先搜尋熱更新的路徑
(function () {
if (typeof window.jsb === 'object') {
var hotUpdateSearchPaths = localStorage.getItem('HotUpdateSearchPaths');
if (hotUpdateSearchPaths) {
var paths = JSON.parse(hotUpdateSearchPaths);
jsb.fileUtils.setSearchPaths(paths);
var fileList = [];
var storagePath = paths[0] || '';
var tempPath = storagePath + '_temp/';
var baseOffset = tempPath.length;
if (jsb.fileUtils.isDirectoryExist(tempPath) && !jsb.fileUtils.isFileExist(tempPath + 'project.manifest.temp')) {
jsb.fileUtils.listFilesRecursively(tempPath, fileList);
fileList.forEach(srcPath => {
var relativePath = srcPath.substr(baseOffset);
var dstPath = storagePath + relativePath;
if (srcPath[srcPath.length] == '/') {
cc.fileUtils.createDirectory(dstPath)
}
else {
if (cc.fileUtils.isFileExist(dstPath)) {
cc.fileUtils.removeFile(dstPath)
}
cc.fileUtils.renameFile(srcPath, dstPath);
}
})
cc.fileUtils.removeDirectory(tempPath);
}
}
}
})();
Demo


結語
熱更新在App開發上是不可或缺的系統,但是每個專案的對於熱更新的需求皆不相同,有些只是想要做圖片資源的熱更新,有些是活動需要使用熱更新,所以了解官方文件每個流程的細節並對每個專案再做變化,就能因應各種需求,也藉由一些修改讓自己對於Cocos熱更新的流程更加熟悉,日後修改維護成本都會降低,藉此空擋時間紀錄一下當前最新版本的熱更新!
Comments