热更新功能求指导

先说一下我目前做的步骤:
1.在当前项目中执行 node version_generator.js -v 1.4.4 -u http://172.16.1.230/h5/update/ -s build/jsb-binary/ -d assets/ 生成了对应的配置文件。然后将打包的原生项目中的src+res 2个文件夹,加上2个生成的配置文件,上传到服务器对应目录。

2.在当前项目中删除部分功能及JS文件。

3.重新跑上面的脚本。然后添加热更新界面,提示版本升级直接由服务器传过来,跟本地版本对比,不同的话直接去热更新。

4.在打包好的安卓原生包中,在main.js的头部添加
if (cc.sys.isNative) {
var hotUpdateSearchPaths = cc.sys.localStorage.getItem(‘HotUpdateSearchPaths’);
if (hotUpdateSearchPaths) {
jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths));
}
}

5.以下是我的热更新相关代码:
cc.Class({
extends: cc.Component,

properties: {
    updatePanel: {
        default: null,
        type: cc.Node
    },
    manifestUrl: {
        default: null,
        url: cc.RawAsset
    },
    percent: {
        default: null,
        type: cc.Label
    },
    lblErr: {
        default: null,
        type: cc.Label
    }
},

checkCb: function (event) {
    console.log('Code: ' + event.getEventCode());
    console.log('---HotUpdate-----  走了checkCb'+'Code: ' + event.getEventCode());
    switch (event.getEventCode())
    {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            console.log("No local manifest file found, hot update skipped.");
            cc.eventManager.removeListener(this._checkListener);
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            cc.log("Fail to download manifest file, hot update skipped.");
            cc.eventManager.removeListener(this._checkListener);
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            cc.log("Already up to date with the latest remote version.");
            cc.eventManager.removeListener(this._checkListener);
            this.lblErr.string += "游戏不需要更新\n";
            cc.director.loadScene("loading");
            break;
        case jsb.EventAssetsManager.NEW_VERSION_FOUND:
            this._needUpdate = true;
            this.updatePanel.active = true;
            this.percent.string = '00.00%';
            cc.eventManager.removeListener(this._checkListener);
            break;
        default:
            break;
    }
    this.hotUpdate();
},

updateCb: function (event) {
    var needRestart = false;
    var failed = false;
    switch (event.getEventCode())
    {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            cc.log('No local manifest file found, hot update skipped.');
            failed = true;
            break;
        case jsb.EventAssetsManager.UPDATE_PROGRESSION:
            var percent = event.getPercent();
            var percentByFile = event.getPercentByFile();

            var msg = event.getMessage();
            if (msg) {
                cc.log(msg);
            }
            cc.log(percent.toFixed(2) + '%');
            this.percent.string = percent + '%';
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            cc.log('Fail to download manifest file, hot update skipped.');
            failed = true;
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            cc.log('Already up to date with the latest remote version.');
            failed = true;
            break;
        case jsb.EventAssetsManager.UPDATE_FINISHED:
            cc.log('Update finished. ' + event.getMessage());

            needRestart = true;
            break;
        case jsb.EventAssetsManager.UPDATE_FAILED:
            cc.log('Update failed. ' + event.getMessage());

            this._failCount ++;
            if (this._failCount < 5)
            {
                this._am.downloadFailedAssets();
            }
            else
            {
                cc.log('Reach maximum fail count, exit update process');
                this._failCount = 0;
                failed = true;
            }
            break;
        case jsb.EventAssetsManager.ERROR_UPDATING:
            cc.log('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
            break;
        case jsb.EventAssetsManager.ERROR_DECOMPRESS:
            cc.log(event.getMessage());
            break;
        default:
            break;
    }

    if (failed) {
        cc.eventManager.removeListener(this._updateListener);
        this.updatePanel.active = false;
    }

    if (needRestart) {
        cc.eventManager.removeListener(this._updateListener);
        // Prepend the manifest's search path
        var searchPaths = jsb.fileUtils.getSearchPaths();
        var newPaths = this._am.getLocalManifest().getSearchPaths();
        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);
        this.lblErr.string += "游戏资源更新完毕\n";
        cc.game.restart();
    }
},

hotUpdate: function () {
    console.log('---HotUpdate-----  走了hotUpdate');
    if (this._am && this._needUpdate) {
        console.log('---HotUpdate-----  走了hotUpdate&& true');
        this.lblErr.string += "开始更新游戏资源...\n";
        this._updateListener = new jsb.EventListenerAssetsManager(this._am, this.updateCb.bind(this));
        cc.eventManager.addListener(this._updateListener, 1);

        this._failCount = 0;
        this._am.update();
    }
},

// use this for initialization
onLoad: function () {
    // Hot update is only available in Native build
    console.log('---HotUpdate-----  走了Hotupdate的onload');
    if (!cc.sys.isNative) {
        return;
    }
    this.lblErr.string += "检查游戏资源...\n";
    var storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'ddmj-asset');
    console.log('Storage path for remote asset : ' + storagePath);
    this.lblErr.string += storagePath + "\n";
    console.log('Local manifest URL : ' + this.manifestUrl);
    this._am = new jsb.AssetsManager(this.manifestUrl, storagePath);
    this._am.retain();

    this._needUpdate = false;
    if (this._am.getLocalManifest().isLoaded())
    {
        console.log('---HotUpdate-----  getLocalManifest().isLoaded()');
        this._checkListener = new jsb.EventListenerAssetsManager(this._am, this.checkCb.bind(this));
        cc.eventManager.addListener(this._checkListener, 1);

        this._am.checkUpdate();
    }
},

onDestroy: function () {
    this._am && this._am.release();
}

});

运行起来后,界面提示有新版本,然后确定后,跳转到update.fire。
加载上面代码中的onload,
控制台打印出:
06-20 15:11:04.731 19345-19407/com.vivigames.scmj D/cocos2d-x debug info: —HotUpdate----- 走了Hotupdate的onload
06-20 15:11:04.741 19345-19407/com.vivigames.scmj D/cocos2d-x debug info: Storage path for remote asset : /data/user/0/com.vivigames.scmj/files/ddmj-asset
06-20 15:11:04.741 19345-19407/com.vivigames.scmj D/cocos2d-x debug info: Local manifest URL : res/raw-assets/project.manifest
06-20 15:11:04.751 19345-19407/com.vivigames.scmj D/cocos2d-x: find in flash memory dirPath(/data/user/0/com.vivigames.scmj/files/ddmj-asset/)
06-20 15:11:04.771 19345-19407/com.vivigames.scmj D/cocos2d-x debug info: —HotUpdate----- getLocalManifest().isLoaded()
06-20 15:11:04.781 19345-19345/com.vivigames.scmj W/System.err: stat failed: ENOENT (No such file or directory) : /data/user/0/com.vivigames.scmj/files/ddmj-asset/version.manifest.tmp
06-20 15:11:04.781 19345-19345/com.vivigames.scmj W/System.err: stat failed: ENOENT (No such file or directory) : /data/user/0/com.vivigames.scmj/files/ddmj-asset/version.manifest.tmp
06-20 15:11:04.851 19345-19345/com.vivigames.scmj D/Cocos2dxDownloader: onSuccess(i:200 headers:[Lcz.msebera.android.httpclient.Header;@abb7f62 file:/data/user/0/com.vivigames.scmj/files/ddmj-asset/version.manifest.tmp

然后游戏重启。

所以,问题出现在
onload中的this._am.checkUpdate();这句话,执行完后没有走checkCb()这个回调。求大佬分析问题所在!
万分感谢!

我发现是配置文件里的版本号问题,然后修改后能够走到下载步骤,
但是在我所有文件下载到100%的时候,AssetsManager又给上面代码中的updateCb 发了一个 Code=3的消息,即NEW_VERSION_FOUND,
然后就停住不动了,什么原因?

折腾了一下午也没找到原因,但是发现以下情况:
1.文件下载了,但是没有更新,退出游戏后,进来仍然提示需要更新;
2.远程的manifest文件替换了本地的manifest;
3.进行了多次从0%-100%的下载,每次下载完都会发送code=3的通知,就是不发送下载完成的通知。
所以猜测是不是下载的文件有问题。

有么有大神带带路啊~~

@panda 大佬~求助

兄弟有没有解决?我也遇到同样的问题。如果解决了,求公布解决方法:grin:

1赞

我使用的引擎版本是1.5.1 使用的官方提供的demo测试的https://github.com/cocos-creator/tutorial-hot-update/tree/master
步骤跟你的差不多,更新完成之后在本地下载了文件,提示更新完成,但是table的场景不能加载,求大神指导@panda

请问您解决这个问题了吗?我也是出现这个问题,不进入table