热更新手动重启后下载的文件不见了,求指教!附上代码。。。

上次发帖没人回复!啊啊啊 !!如题!启动游戏后下载志愿并用cc.game.restart() 重启成功,新版本运行,但是手动关闭游戏后进游戏又需要下载更新,一直重复这样!在模拟器上就是这样热更新两次后就正常! main.js 文件也加上搜索路径,请求各位大大看看是不是哪里逻辑出问题, cocoscreator版本 1.6.2

const { ccclass, property } = cc._decorator;

@ccclass
export default class HotUpdate extends cc.Component {
@property(cc.Label)
load_label: cc.Label = null
@property(cc.ProgressBar)
load_progress: cc.ProgressBar = null
@property(cc.Label)
versionName: cc.Label = null

_serverURL: string = "http://192.168.0.210/hotupdate/hall/";
_storagePath: string = null;
_manifestLocal: string = null ;
assetsManager: any = null;
updateListener = null;
checkListener = null;
isUpdating = false;

onLoad() {
    this.node.on(cc.Node.EventType.TOUCH_START, function (event) {
        event.stopPropagation();
    })
    this.initPath();
    this.initUpdate();
}

initPath(){
    this._storagePath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/')+'hot';
    cc.log('this._storagePath = ',this._storagePath);
}

initUpdate(){
    cc.log("initUpdate>>>>>>>start");
    this.createJSBAssetsManager();

    let manifestLocalData ;
    let customManifestStr ;
    
    if (cc.sys.isNative) {
        this._storagePath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/')+'hot';
        this._manifestLocal = this._storagePath + "/project.manifest";
        if (jsb.fileUtils.isFileExist(this._manifestLocal)) {
            cc.log('_manifestLocal文件存在!');
            let str = jsb.fileUtils.getStringFromFile(this._manifestLocal);
            manifestLocalData= JSON.parse(str);
            this.versionName.string = 'v' + manifestLocalData.version
            // customManifestStr = JSON.stringify({
            //     "packageUrl":manifestLocalData.packageUrl,
            //     "remoteManifestUrl": manifestLocalData.remoteManifestUrl,
            //     "remoteVersionUrl": manifestLocalData.remoteVersionUrl,
            //     "version": manifestLocalData.version,
            //     "assets": manifestLocalData.assets,
            //     "searchPaths": manifestLocalData.searchPaths,
            // });
        } else {
            cc.log('_manifestLocal文件不存在!');
            this.versionName.string = 'v1.0.2'
            customManifestStr = JSON.stringify({
                "packageUrl": this._serverURL,
                "remoteManifestUrl": this._serverURL + "project.manifest",
                "remoteVersionUrl": this._serverURL + "version.manifest",
                "version": "1.0.2",
                "assets": {},
                "searchPaths": []
            });
        }
        this.load_label.string = "正在更新...";
        this.load_progress.progress = 0;
        
        if (this.assetsManager.getState() === jsb.AssetsManager.State.UNINITED) {
            cc.log('manifest uninit');
            let manifest = new jsb.Manifest(customManifestStr, this._storagePath)
            this.assetsManager.loadLocalManifest(manifest, this._storagePath);
        }else{
            if (jsb.fileUtils.isFileExist(this._manifestLocal)) {
                cc.log('manifest inited');
                this.assetsManager.loadLocalManifest(this._manifestLocal);
            } 
        }
        // this.updateListener = new jsb.EventListenerAssetsManager(this.assetsManager, this.updateListen.bind(this));
        // cc.eventManager.addListener(this.updateListener, 1);

        this.checkListener = new jsb.EventListenerAssetsManager(this.assetsManager, this.checkListen.bind(this));
        cc.eventManager.addListener(this.checkListener, 1);
        this.assetsManager.checkUpdate();

        // this.assetsManager.update();
        // this.isUpdating = true;
    } else {
        //直接加载大厅
        this.node.active = false
    }
    cc.log("initUpdate>>>>>>>end");
}


/**初始化大厅加载控制器*/
createJSBAssetsManager() {
    this.removeListener();
    let versionCompareHandle = function (versionA, versionB) {
        let vA = versionA.split('.');
        let vB = versionB.split('.');
        for (let i = 0; i < vA.length; ++i) {
            let a = parseInt(vA[i]);
            let b = parseInt(vB[i] || 0);
            if (a === b) {
                continue;
            } else {
                return a - b;

            }
        }
        if (vB.length > vA.length) {
            return -1;
        } else {
            return 0;
        }
    };
    this.assetsManager = new jsb.AssetsManager('', this._storagePath, versionCompareHandle);
    if (!cc.sys.ENABLE_GC_FOR_NATIVE_OBJECTS) {
        this.assetsManager.retain();
    }
    this.assetsManager.setVerifyCallback(function (path, asset) {
        let compressed = asset.compressed;
        let expectedMD5 = asset.md5;
        let relativePath = asset.path;
        let size = asset.size;
        if (compressed) {
            return true;
        } else {
            return true;
        }
    });
    //安卓系统最大线程2,防止线程太多导致错乱或其它异常,如卡顿等!
    if (cc.sys.os === cc.sys.OS_ANDROID) {
        this.assetsManager.setMaxConcurrentTask(2);
    }
    this.isUpdating = false;
}

alertViewCloseCallBack(){

}

checkUpdate() {
    this.createJSBAssetsManager();
    let customManifestStr ;
    let data ;
    this._manifestLocal = this._storagePath + "/project.manifest";
    if (jsb.fileUtils.isFileExist(this._manifestLocal)) {
        cc.log('checkUpdate >>> _manifestLocal文件不存在!');
        let str = jsb.fileUtils.getStringFromFile(this._manifestLocal);
        data= JSON.parse(str);
        customManifestStr = JSON.stringify({
            "packageUrl":data.packageUrl,
            "remoteManifestUrl": data.remoteManifestUrl,
            "remoteVersionUrl": data.remoteVersionUrl,
            "version": data.version,
            "assets": data.assets,
            "searchPaths": data.searchPaths,
        });
    }else {
        cc.log('checkUpdate >>> _manifestLocal文件不存在!');
        this.versionName.string = 'v1.0.2'
        customManifestStr = JSON.stringify({
            "packageUrl": this._serverURL,
            "remoteManifestUrl": this._serverURL + "project.manifest",
            "remoteVersionUrl": this._serverURL + "version.manifest",
            "version": "1.0.2",
            "assets": {},
            "searchPaths": []
        });
    }

    if (this.assetsManager.getState() === jsb.AssetsManager.State.UNINITED) {
        if (jsb.fileUtils.isFileExist(this._manifestLocal)) {
            console.log('加载本地Manifest');
            this.assetsManager.loadLocalManifest(this._manifestLocal);
        } else {
            console.log('加载网络Manifest');
            let manifest = new jsb.Manifest(customManifestStr, this._storagePath);
            this.assetsManager.loadLocalManifest(manifest, this._storagePath);
        }
    }
    this.checkListener = new jsb.EventListenerAssetsManager(this.assetsManager, this.checkListen.bind(this));
    cc.eventManager.addListener(this.checkListener, 1);
    this.assetsManager.checkUpdate();
    this.isUpdating = true;
}

/**检查更新监听*/
checkListen(event) {
    var self = this ;
    switch (event.getEventCode()) {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            console.log('加载失败!');
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            break;
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            console.log('加载失败');
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            console.log('已经是最新版本');
            break;
        case jsb.EventAssetsManager.NEW_VERSION_FOUND:
            console.log('发现新版本');
            this.updateListener = new jsb.EventListenerAssetsManager(this.assetsManager, this.updateListen.bind(this));
            cc.eventManager.addListener(this.updateListener, 1);
            this.assetsManager.update();
            this.isUpdating = true;

            // FactoryUtil.createAlertConfirmView("发现新版本,点击确定开始更新!",function(){
            //     self.assetsManager.update();
            // })
            
            break;
        default:
            console.log('checkListen error!');
            return;
    }
    cc.eventManager.removeListener(this.checkListener);
    this.checkListener = null;
    this.isUpdating = false;
}

/**加载更新监听*/
updateListen(event) {

    let failedCount = 0;
    let needRestart = false;
    let failed = false;

    switch (event.getEventCode()) {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            console.log('加载失败 >>> '+ event.getMessage());
            failed = true;
            break;
        case jsb.EventAssetsManager.UPDATE_PROGRESSION:
            let ByFile = event.getPercentByFile();
            let Percent = event.getPercent()
            if (!isNaN(ByFile)) {
                //百分比
                let per = Math.ceil(ByFile * 100)
                this.load_progress.progress = ByFile;
                // this.load_label.string = "正在加载资源("+ (per) +"%)";
                this.load_label.string ='正在更新:'+ (event.getDownloadedBytes() / 1024 / 1024).toFixed(2) + 'MB / ' + (event.getTotalBytes() / 1024 / 1024).toFixed(2) + "MB"
            }
            if (!isNaN(Percent)) {
                this.load_progress.progress = Percent
              //  this.loading_lab1.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
            }
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            break;
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            console.log('加载失败 >>> '+ event.getMessage());
            failed = true;
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            console.log('当前为最新版本!');
            this.node.active = false
            failed = false;
            break;
        case jsb.EventAssetsManager.UPDATE_FINISHED:
            console.log('更新完成!');
            this.load_progress.progress = 1;
            this.load_label.string = "正在加载资源 (100%)";
          //  console.log('v:' + this.assetsManager.getLocalManifest().getVersion())
            //this.versionName.string = 'v:' + this.assetsManager.getLocalManifest().getVersion()
            needRestart = true;
            failed = false;
            break;
        case jsb.EventAssetsManager.UPDATE_FAILED:
            console.log('加载失败 >>> Update failed: ' + event.getMessage());
            failed = true;
            break;
        case jsb.EventAssetsManager.ERROR_UPDATING:
            console.log('加载失败 >>> Asset update error: ' + event.getAssetId() + ',Message: ' + event.getMessage());
            failed = true;
            break;
        case jsb.EventAssetsManager.ERROR_DECOMPRESS:
            console.log('加载失败 >>> ',event.getMessage());
            failed = true;
            break;
        default:
            break;
    }

    if (failed) {
        failedCount++;
        if(failedCount<=3){
            //继续加载失败的文件          
            this.assetsManager.downloadFailedAssets();
        }else{
            console.log('加载失败文件失败超过3次!!!');
            return;
        }
    } 
    else {

        if (needRestart) {
            cc.log("needRestart!!!");
          // var searchPaths = this._storagePath;
            var searchPaths = jsb.fileUtils.getSearchPaths();
            var newPaths = this.assetsManager.getLocalManifest().getSearchPaths();
            cc.log('searchPaths=',searchPaths);
            cc.log('newPaths=',newPaths);

            Array.prototype.unshift(searchPaths, newPaths);
            cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
            jsb.fileUtils.setSearchPaths(searchPaths);
            cc.audioEngine.stopAll();
            cc.game.restart();
        }

            // if (needRestart) {
            //     //let searchPaths = this._storagePath;
            //     let searchPaths = jsb.fileUtils.getSearchPaths();
            //     let newPaths = this.assetsManager.getLocalManifest().getSearchPaths();
            //     console.log('needRestart and getSearchPaths = ',JSON.stringify(newPaths));

            //     cc.sys.localStorage.setItem('hotUpdateSearchPaths', JSON.stringify(searchPaths));
            //     jsb.fileUtils.setSearchPaths(searchPaths);
            //     this.removeListener();
            //     cc.game.restart();
            // }
        }
}

removeListener() {
    if (this.updateListener) {
        cc.eventManager.removeListener(this.updateListener);
        this.updateListener = null;
    }
    if (this.checkListener) {
        cc.eventManager.removeListener(this.checkListener);
        this.checkListener = null;
    }
    if (this.assetsManager && !cc.sys.ENABLE_GC_FOR_NATIVE_OBJECTS) {
        console.log('使用的是旧内存模型,调用retain()方法保证am不会给回收')
        this.assetsManager.release();
    }
    this.assetsManager = null;
    this.isUpdating = false;
}

onDestroy() {
   // this.removeListener();
    //this.unschedule(this.updateLoadingScene);
    //this.node.parent.stopAllActions()
}

}

提供给AssetsManager的Manifest有问题

你提供给AssetsManager一个storagePath和初始的Manifest1。

AssetsManager会从storagePath目录下尝试读取Manifest2,然后和你提供给它的Manifest1进行比对。

在热更新之后,

在你的代码中,由于你提供的Manifest1实际上和Manifest2是从同一个路径获取到的均为_storagePath/hot/project.manifest

所以在versionCompareHandle比对时候,将会得到版本返回值为0。

查看C++实现源码,可以发现这种时候会删除storagePath下的文件。

cocos在开发热更新模块的时候,希望开发者提供的是原始的Manifest,至于发生热更新之后新的Manifest,cocos会自己缓存好,不需要开发者操心。如果开发者提供了热更新之后的Manifest,会出现问题的。

写的比较乱,有问题再@我吧

首先很感谢您的回复!这么一说我倒是理解了,cocos自己有缓存manifest,不知cocos能否做到区分模块资源,让开发者自行区分需要更新下载的内容