我刚刚开始弄热更新,基本是照搬了案例教程里面的代码,生成manifest的工具是从扩展商量下来的热更新插件
现在遇到一个很奇怪的问题,我设置了一个缓存目录
this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'GHGame');
将远程服务器上的文件下载到该目录,
当我第一次运行程序的时候,运行正常,会检测到更新,然后下载文件。
重启app以后,检测到已经是最新版本,但是,此时,缓存目录下的文件会被全部清除,当我下次再打开App的时候,又会重新检测到有新版本,然后下载到该目录下。
然后就会如此往复,一次提示有更新,下载文件,重启app后,提示已经是最新版本,然后将目录清空。
下面是我使用的代码,请高手看看
初始AssetsManager
private InitAssetsManager()
{
//设置热更新的目录
this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'GHGame');
//console.log('Storage path for remote asset : ' + this._storagePath);
this._am = new jsb.AssetsManager("", this._storagePath, this.VersionCompareHandle);
if (!cc.sys.ENABLE_GC_FOR_NATIVE_OBJECTS) {
this._am.retain();
}
this._am.setVerifyCallback(function (path, asset)
{
// When asset is compressed, we don't need to check its md5, because zip file have been deleted.
var compressed = asset.compressed;
// Retrieve the correct md5 value.
var expectedMD5 = asset.md5;
// asset.path is relative path and path is absolute.
var relativePath = asset.path;
// The size of asset file, but this value could be absent.
var size = asset.size;
if (compressed) {
//panel.info.string = "Verification passed : " + relativePath;
return true;
}
else {
//panel.info.string = "Verification passed : " + relativePath + ' (' + expectedMD5 + ')';
return true;
}
});
if (cc.sys.os === cc.sys.OS_ANDROID)
{
// Some Android device may slow down the download process when concurrent tasks is too much.
// The value may not be accurate, please do more test and find what's most suitable for your game.
this._am.setMaxConcurrentTask(2);
}
}
由于我需要动态变更更新网址,所有写了一个处理本地manifest的代码
处理本地manifest
private HandleLocalManifest()
{
//读取原始Manifest
let filestring;
if (jsb.fileUtils.isFileExist(this._storagePath + "/originProject.manifest"))
{
filestring = jsb.fileUtils.getStringFromFile(this._storagePath + "/originProject.manifest");
}
else
{
filestring = jsb.fileUtils.getStringFromFile(this.originManifestUrl);
}
console.log(filestring);
//转换成json
let obj = JSON.parse(filestring);
//拼接远程3个远程url
//let url=GameRuntimeData.GetInstance().url;
let url = "http://127.0.0.1/GHGame/hotUpdateServer/GHGame";
obj.packageUrl = url + obj.packageUrl;
obj.remoteManifestUrl = url + obj.remoteManifestUrl;
obj.remoteVersionUrl = url + obj.remoteVersionUrl;
this._manifestObj = obj;
//保存成本地文件
let afterString = JSON.stringify(obj);
console.log(afterString);
jsb.fileUtils.writeStringToFile(afterString, this._storagePath + "/project.manifest")
this._am.loadLocalManifest(this._storagePath + "/project.manifest");
}
然后就是检查更新和执行更新
检查更新 和 检查的监听
CheckUpdate()
{
this._checkListener = new jsb.EventListenerAssetsManager(this._am, this.checkCb.bind(this));
cc.eventManager.addListener(this._checkListener, 1);
this._am.checkUpdate();
this._updating = true;
}
checkCb(event)
{
cc.log('Code: ' + event.getEventCode());
let skipUpdate:boolean=false;
let startUpdate:boolean=false;
switch (event.getEventCode())
{
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST://获取本地manifest失败
console.log("No local manifest file found, hot update skipped.");
skipUpdate=true;
break;
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST://下载远程manifest失败
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST://解析远程manifest失败
console.log("Fail to download manifest file, hot update skipped.");
skipUpdate=true;
break;
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE://已经是最新版本
console.log("Already up to date with the latest remote version,hot update skipped");
skipUpdate=true;
break;
case jsb.EventAssetsManager.NEW_VERSION_FOUND://发现新版本
console.log('New version found, please try to update.');
startUpdate=true;
break;
default:
return;
}
cc.eventManager.removeListener(this._checkListener);
this._checkListener = null;
this._updating = false;
if (skipUpdate)
{
//发送跳过更新消息
MsgSystem.GetInstance().PostMsg(MsgDefine.hotUpdate_skip);
}
if (startUpdate)
{
//发送开始更新消息
MsgSystem.GetInstance().PostMsg(MsgDefine.hotUpdate_start);
//开始更新
this.StartUpdate();
}
}
如果检查到有新版本,就会进行开始更新
开始更新 和 更新的监听
StartUpdate()
{
//开始更新
if (this._am && !this._updating)
{
this._updateListener = new jsb.EventListenerAssetsManager(this._am, this.updateCb.bind(this));
cc.eventManager.addListener(this._updateListener, 1);
this._am.update();
this._updating = true;
}
}
checkCb(event)
{
cc.log('Code: ' + event.getEventCode());
let skipUpdate:boolean=false;
let startUpdate:boolean=false;
switch (event.getEventCode())
{
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST://获取本地manifest失败
console.log("No local manifest file found, hot update skipped.");
skipUpdate=true;
break;
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST://下载远程manifest失败
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST://解析远程manifest失败
console.log("Fail to download manifest file, hot update skipped.");
skipUpdate=true;
break;
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE://已经是最新版本
console.log("Already up to date with the latest remote version,hot update skipped");
skipUpdate=true;
break;
case jsb.EventAssetsManager.NEW_VERSION_FOUND://发现新版本
console.log('New version found, please try to update.');
startUpdate=true;
break;
default:
return;
}
cc.eventManager.removeListener(this._checkListener);
this._checkListener = null;
this._updating = false;
if (skipUpdate)
{
//发送跳过更新消息
MsgSystem.GetInstance().PostMsg(MsgDefine.hotUpdate_skip);
}
if (startUpdate)
{
//发送开始更新消息
MsgSystem.GetInstance().PostMsg(MsgDefine.hotUpdate_start);
//开始更新
this.StartUpdate();
}
}
如果检查到有更新 就开始进行更新
StartUpdate()
{
//开始更新
if (this._am && !this._updating)
{
this._updateListener = new jsb.EventListenerAssetsManager(this._am, this.updateCb.bind(this));
cc.eventManager.addListener(this._updateListener, 1);
this._am.update();
this._updating = true;
}
}
更新过程中的监听
updateCb(event)
{
var finish = false;
var failed = false;
switch (event.getEventCode()) {
// case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST://未找到本地 manifest
// console.log('No local manifest file found, hot update skipped.');
// failed = true;
// break;
case jsb.EventAssetsManager.UPDATE_PROGRESSION://更新下载进度
//this.panel.byteProgress.progress = event.getPercent();
//this.panel.fileProgress.progress = event.getPercentByFile();
//this.panel.fileLabel.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
//this.panel.byteLabel.string = event.getDownloadedBytes() + ' / ' + event.getTotalBytes();
MsgSystem.GetInstance().PostMsg(MsgDefine.hotUpdate_percent,{percent:event.getPercent()});
console.log(event.getPercent());
// var msg = event.getMessage();
// if (msg) {
// //this.panel.info.string = 'Updated file: ' + msg;
// // cc.log(event.getPercent()/100 + '% : ' + msg);
// }
break;
// case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST://下载远程服务器上的manifest失败
// case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST://解析远程服务器上的manifest失败
// console.log('Fail to download manifest file, hot update skipped.');
// failed = true;
// break;
// case jsb.EventAssetsManager.ALREADY_UP_TO_DATE://已经升级到最近版本
// console.log('Already up to date with the latest remote version.');
// failed = true;
// break;
case jsb.EventAssetsManager.UPDATE_FINISHED://更新完成
console.log('Update finished. ' + event.getMessage());
finish = true;
break;
case jsb.EventAssetsManager.UPDATE_FAILED://更新失败
console.log('Update failed. ' + event.getMessage());
this._updating = false;
failed=true;
break;
case jsb.EventAssetsManager.ERROR_UPDATING://下载失败
console.log('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
failed=true;
break;
case jsb.EventAssetsManager.ERROR_DECOMPRESS://解压失败
console.log(event.getMessage());
failed=true;
break;
default:
break;
}
//如果更新失败
if (failed) {
cc.eventManager.removeListener(this._updateListener);
this._updateListener = null;
this._updating = false;
//发送更新失败消息
MsgSystem.GetInstance().PostMsg(MsgDefine.hotUpdate_faild);
}
//如果更新完成,需要重启
if (finish) {
//将下载的新的project.mainfest
let filestring = jsb.fileUtils.getStringFromFile(this._storagePath + "/project.manifest");
//转换成json
let obj = JSON.parse(filestring);
//修改3个远程url
obj.packageUrl = "";
obj.remoteManifestUrl = "/project.manifest";
obj.remoteVersionUrl = "/version.manifest";
let afterString = JSON.stringify(obj);
//console.log(afterString);
jsb.fileUtils.writeStringToFile(afterString, this._storagePath + "/originProject.manifest")
cc.eventManager.removeListener(this._updateListener);
this._updateListener = null;
// Prepend the manifest's search path
var searchPaths = jsb.fileUtils.getSearchPaths();
var newPaths = this._am.getLocalManifest().getSearchPaths();
console.log(JSON.stringify(newPaths));
Array.prototype.unshift(searchPaths, newPaths);
// This value will be retrieved and appended to the default search path during game startup,
// please refer to samples/js-tests/main.js for detailed usage.
// !!! Re-add the search paths in main.js is very important, otherwise, new scripts won't take effect.
cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
jsb.fileUtils.setSearchPaths(searchPaths);
cc.audioEngine.stopAll();
//cc.game.restart();
//发送更新完成的消息
MsgSystem.GetInstance().PostMsg(MsgDefine.hotUpdate_finish);
//setTimeout(function(){cc.game.restart();},3000);
}
}
在检测到更新完成以后 我写了以下代码 重新生成originProject.manifest,来确保以后都可以正常的热更新,去掉了固定的url,对应到开头处理本地manifest的地方
if (finish) {
//将下载的新的project.mainfest
let filestring = jsb.fileUtils.getStringFromFile(this._storagePath + "/project.manifest");
//转换成json
let obj = JSON.parse(filestring);
//修改3个远程url
obj.packageUrl = "";
obj.remoteManifestUrl = "/project.manifest";
obj.remoteVersionUrl = "/version.manifest";
let afterString = JSON.stringify(obj);
//console.log(afterString);
jsb.fileUtils.writeStringToFile(afterString, this._storagePath + "/originProject.manifest")
写了很多 请高手帮忙看看,特别是我生成文件目录的地方是不是错了