每次启动游戏热更重复更新的bug是咋回事

安卓平台 版本1.9.3 表现就是每次启动游戏会进行热更 热更成功之后restart重启游戏 然后这是正常的,如果关闭游戏 在启动 那么就会重复上述流程 每次启动游戏都会重新进行热更…我想问下这是啥问题 有没有大佬能说下的。

我贴下对比版本的assetsManager代码
this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : ‘/’));
this._am = new jsb.AssetsManager(this.manifestUrl;, this._storagePath, this.versionCompareHandle);

this.manifestUrl;是 指向的文件是

然后我还试了 this._am = new jsb.AssetsManager("", this._storagePath, this.versionCompareHandle);也不对

还试了var testPath = “res/project.manifest”;
this._am = new jsb.AssetsManager(url, this._storagePath, this.versionCompareHandle);也不对……

求各位大佬告诉我咋解决启动游戏重复更新的bug

@jare @huanxinyin 人… 艾特下官方看看

以下hotupdate代码
var UpdatePanel = require(‘UpdatePanel’);

cc.Class({
extends: cc.Component,

properties: {
    panel: UpdatePanel,
    manifestUrl: cc.RawAsset,
    updateUI: cc.Node,
    _updating: false,
    _canRetry: false,
    _storagePath: ''
},

show: function () {
    if (this.updateUI.active === false) {
        this.updateUI.active = true;
    }
},
hide: function(){
    if (this.updateUI.active === true) {
        this.updateUI.active = false;
    }
},
// use this for initialization
onLoad: function () {
    // Hot update is only available in Native build
    console.log("进了热更了");
    if (!cc.sys.isNative) {
        this.hide();
        return;
    }
    this.show();
    this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/'));
    cc.log('Storage path for remote asset : ' + this._storagePath);

    // Setup your own version compare handler, versionA and B is versions in string
    // if the return value greater than 0, versionA is greater than B,
    // if the return value equals 0, versionA equals to B,
    // if the return value smaller than 0, versionA is smaller than B.
    this.versionCompareHandle = function (versionA, versionB) {
        cc.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 a - b;
            }
        }
        if (vB.length > vA.length) {
            return -1;
        }
        else {
            return 0;
        }
    };

    // Init with empty manifest url for testing custom manifest
    let url = this.manifestUrl;
    // if (cc.loader.md5Pipe) {
    //     url = cc.loader.md5Pipe.transformURL(url);
    // }
    var testPath = "res/project.manifest";
    this._am = new jsb.AssetsManager(url, this._storagePath, this.versionCompareHandle);
    // this._am = new jsb.AssetsManager('', this._storagePath, this.versionCompareHandle);

    var panel = this.panel;
    // Setup the verification callback, but we don't have md5 check function yet, so only print some message
    // Return true if the verification passed, otherwise return false
    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;
        }
    });

    this.panel.info.string = '正在进行更新检测...';

    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);
        // this.panel.info.string = "Max concurrent tasks count have been limited to 2";
    }
    
    this.panel.fileProgress.progress = 0;
    this.panel.byteProgress.progress = 0;
    this.checkUpdate();
},

checkUpdate: function () {
    if (this._updating) {
        // this.panel.info.string = 'Checking or updating ...';
        console.log("Checking or updating ...");
        return;
    }
    if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
        // Resolve md5 url
        var url = this.manifestUrl;
        // if (cc.loader.md5Pipe) {
        //     url = cc.loader.md5Pipe.transformURL(url);
        // }
        // console.log("check update url ",url);
        this._am.loadLocalManifest(url);
    }
    if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
        this.panel.info.string = '加载热更文件失败,请重新下载游戏 ...';
        return;
    }
    // this._am.setEventCallback(this.checkCb.bind(this));

    this._updateListener = new jsb.EventListenerAssetsManager(this._am, this.checkCb.bind(this));
    cc.eventManager.addListener(this._updateListener, 1);

    this._am.checkUpdate();
    this._updating = true;
},

checkCb: function (event) {
    cc.log('Code: ' + event.getEventCode());
    this.needUpdate = false;
    this.isNew = false;
    switch (event.getEventCode())
    {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            this.panel.info.string = "本地升级文件未找到";
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            this.panel.info.string = "获取更新信息失败";
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            this.panel.info.string = "已经是最新版本了.";
            this.isNew = true;
            break;
        case jsb.EventAssetsManager.NEW_VERSION_FOUND:
            this.panel.info.string = '发现新版本,即将准备更新,请勿关闭...';
            this.panel.checkBtn.active = false;
            this.panel.fileProgress.progress = 0;
            this.panel.byteProgress.progress = 0;
            this.needUpdate = true;
            break;
        default:
            this.panel.info.string = '更新中...';
            return;
    }
    
    // this._am.setEventCallback(null);
    this._updateListener = new jsb.EventListenerAssetsManager(this._am,null);
    cc.eventManager.addListener(this._updateListener, 1);

    this._checkListener = null;
    this._updating = false;
    if(this.needUpdate == true){ //检测到了 调用热更1
        this.hotUpdate();
    }
    else if(this.isNew == true){
        this.hide();
    }
},

hotUpdate: function () {
    if (this._am && !this._updating) {
        // this._am.setEventCallback(this.updateCb.bind(this));
        this._updateListener = new jsb.EventListenerAssetsManager(this._am, this.updateCb.bind(this));
        cc.eventManager.addListener(this._updateListener, 1);

        if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
            // Resolve md5 url
            var url = this.manifestUrl;
            // if (cc.loader.md5Pipe) {
            //     url = cc.loader.md5Pipe.transformURL(url);
            // }
            this._am.loadLocalManifest(url);
        }

        this._failCount = 0;
        this._am.update();
        this.panel.updateBtn.active = false;
        this._updating = true;
    }
},

updateCb: function (event) {
    var needRestart = false;
    var failed = false;
    switch (event.getEventCode())
    {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            this.panel.info.string = '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();

            var msg = event.getMessage();
            if (msg) {
                this.panel.info.string = '正在更新: ' + msg;
                // cc.log(event.getPercent()/100 + '% : ' + msg);
            }
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            this.panel.info.string = 'Fail to download manifest file, hot update skipped.';
            failed = true;
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            this.panel.info.string = 'Already up to date with the latest remote version.';
            failed = true;
            break;
        case jsb.EventAssetsManager.UPDATE_FINISHED:
            this.panel.info.string = 'Update finished. ' + event.getMessage();
            needRestart = true;
            break;
        case jsb.EventAssetsManager.UPDATE_FAILED:
            this.panel.info.string = 'Update failed. ' + event.getMessage();
            // this.panel.retryBtn.active = true;
            this._updating = false;
            this._canRetry = true;
            break;
        case jsb.EventAssetsManager.ERROR_UPDATING:
            this.panel.info.string = 'Asset update error: ' + event.getAssetId() + ', ' + event.getMessage();
            break;
        case jsb.EventAssetsManager.ERROR_DECOMPRESS:
            this.panel.info.string = event.getMessage();
            break;
        default:
            break;
    }

    if (failed) {
        // this._am.setEventCallback(null);
        this._updateListener = new jsb.EventListenerAssetsManager(this._am,null);
        cc.eventManager.addListener(this._updateListener, 1);
        this._updateListener = null;
        this._updating = false;
    }

    if (needRestart) {
        // this._am.setEventCallback(null);
        this._updateListener = new jsb.EventListenerAssetsManager(this._am,null);
        cc.eventManager.addListener(this._updateListener, 1);
        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.apply(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();
    }
},

onDestroy: function () {
    if (this._updateListener) {
        // this._am.setEventCallback(null);
        this._updateListener = new jsb.EventListenerAssetsManager(this._am,null);
        cc.eventManager.addListener(this._updateListener, 1);
        this._updateListener = null;
    }
}

});

人工顶。。

searchPath 加到存档里了吗? 没有加的话, 读取的还是包里的版本号. 或者是你 main.js 中没有读取这个路径.

加了啊哥们,我上面贴代码了,有空了可以看看哪里的问题,就照着官方的做的,不知道为何就有这个bug。。。

我仔细看了下你的贴的代码, 也麻烦您仔细看下我的最后一句话.

你的 setSearchPaths 是临时的, 这次启动有效. 为了下次启动时也能设置, 需要把这个存到存档中 (你的代码中已经有了). 还需要在 main.js 中读取存档, 设置 jsb.fileUtils.setSearchPaths.

你再你的 main.js 的上方加入:

    if (window.cc && cc.sys.isNative) { 
        var hotUpdateSearchPaths = cc.sys.localStorage.getItem('HotUpdateSearchPaths'); 
        if (hotUpdateSearchPaths) { 
            jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths)); 
        }
    }

试下.

是不是热更新资源目录里的manifest文件的版本号高于或等于根目录下面的manifest文件的版本号

老哥 我在main里面已经加过这一段了……

我热更成功一次之后目录下的manifest应该是等于服务器里的啊

更新成功后如果本地的版本高于或者等于远程热更新的版本号,再次启动应用的时候会检测为不需要更新会删除掉更新目录里的资源的,我之前碰到的就是这个问题

你可以在更新后退出游戏,再重新打开游戏,看下热更新的缓存目录里是不是被清空了确认是不是这个问题

························

应该是这个问题,那你咋解决的啊 更新成功之后本地的肯定等于远程的啊