动态修改热更URL,第一次成功,第二次失败!

流程
加载本地project.manifest,修改url,热更,
第一次可以成功,第二热更直接跳到状态:ALREADY_UP_TO_DATE,

代码如下:

`

const jsb = (window).jsb;

import { _decorator, Component, Node, Label, ProgressBar, Asset, game, sys, EventHandler, Event } from ‘cc’;
const { ccclass, property } = _decorator;
export const State_UPDATE_NEWFOUND = “newfound”//更新进度
export const State_UPDATE_PROGRESSION = “updateProgression”//更新进度
export const State_UPDATE_SKIP = “skip”//跳过
export const State_UPDATE_FAILED = “failed”//失败可以重试
export const State_UPDATE_ERR = “err”//更新错误
export const State_UPDATE_OVER = “over”//更新错误
export type updateData = {
state: string,//状态
message: string,//错误信息
downloadedFiles: number,
totalFiles: number,
downloadedBytes: number,
totalBytes: number,

}
class HostUpdate {
private updateEventHandle: EventHandler | null = null
private _am: jsb.AssetsManager | null = null
//存储地址
private _storagePath = “”
updateCb(event: any) {
if (!this._am) {
return
}
var needRestart = false;
var failed = false;
switch (event.getEventCode()) {

        case jsb.EventAssetsManager.NEW_VERSION_FOUND:
            // this.panel.info.string = 'New version found, please try to update. (' + Math.ceil(this._am.getTotalBytes() / 1024) + 'kb)';
            //this.panel.checkBtn.active = false;
            //this.panel.fileProgress.progress = 0;
            //this.panel.byteProgress.progress = 0;
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_NEWFOUND,//状态
                    message: "",//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }
                this.updateEventHandle.emit([data])
            }
            this._am.update();
            break;
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            //this.panel.info.string = 'No local manifest file found, hot update skipped.';
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_ERR,//状态
                    message: "加载本地版本失败",//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }
                this.updateEventHandle.emit([data])
            }
            break;
        case jsb.EventAssetsManager.UPDATE_PROGRESSION:
            //this.panel.byteProgress.progress = event.getPercent();
            //.panel.fileProgress.progress = event.getPercentByFile();

            //this.panel.fileLabel.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
            //this.panel.byteLabel.string = event.getDownloadedBytes() + ' / ' + event.getTotalBytes();
            //console.log(this.panel.fileLabel.string, this.panel.byteLabel.string);
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_PROGRESSION,//状态
                    message: "",//错误信息
                    downloadedFiles: event.getDownloadedFiles(),
                    totalFiles: event.getTotalFiles(),
                    downloadedBytes: event.getDownloadedBytes(),
                    totalBytes: event.getTotalBytes(),
                }
                this.updateEventHandle.emit([data])

            }
            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:
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            //this.panel.info.string = 'Fail to download manifest file, hot update skipped.';
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_ERR,//状态
                    message: "加载远程版本失败",//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }

                this.updateEventHandle.emit([data])
            }
            failed = true;
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            //this.panel.info.string = 'Already up to date with the latest remote version.';
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_SKIP,//状态
                    message: "",//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }

                this.updateEventHandle.emit([data])
            }
            failed = true;
            break;
        case jsb.EventAssetsManager.UPDATE_FINISHED:
            //  this.panel.info.string = 'Update finished. ' + event.getMessage();
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_OVER,//状态
                    message: "",//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }

                this.updateEventHandle.emit([data])
            }
            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;
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_FAILED,//状态
                    message: "加载本地版本失败",//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }
                this.updateEventHandle.emit([data])
            }
            break;
        case jsb.EventAssetsManager.ERROR_UPDATING:
            //  this.panel.info.string = 'Asset update error: ' + event.getAssetId() + ', ' + event.getMessage();
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_ERR,//状态
                    message: event.getMessage(),//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }

                this.updateEventHandle.emit([data])
            }
            break;
        case jsb.EventAssetsManager.ERROR_DECOMPRESS:
            // this.panel.info.string = event.getMessage();
            if (this.updateEventHandle) {
                var data: updateData = {
                    state: State_UPDATE_ERR,//状态
                    message: event.getMessage(),//错误信息
                    downloadedFiles: 0,
                    totalFiles: 0,
                    downloadedBytes: 0,
                    totalBytes: 0,
                }
                this.updateEventHandle.emit([data])
            }
            break;
        default:
            break;
    }

    if (failed) {
        this._am.setEventCallback(null!);
        //this._updateListener = null;
        //this._updating = false;
    }

    if (needRestart) {
        this._am.setEventCallback(null!);
        //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.
        localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
        jsb.fileUtils.setSearchPaths(searchPaths);

        // restart game.
        setTimeout(() => {
            game.restart();
        }, 1000)
    }
}
//重试
retry() {
    if (!this._am) {
        return
    }
    // if (!this._updating && this._canRetry) {
    //  this.panel.retryBtn.active = false;
    // this._canRetry = false;

    //this.panel.info.string = 'Retry failed Assets...';
    this._am.downloadFailedAssets();
    // }
}
// 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.
versionCompareHandle(versionA: string, versionB: string) {
    if (versionA==versionB){
        return 0
    }else{
        return -1
    }
    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 a - b;
        }
    }
    if (vB.length > vA.length) {
        return -1;
    }
    else {
        return 0;
    }
}
verifyCallback  (path: string, asset: any)  {
    // 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;
    }
}
checkAndUpdate  (version: string, localManifest: string, updateEvent: EventHandler, url?: string)   {
    this.updateEventHandle = updateEvent
    // Hot update is only available in Native build
    if (!jsb) {
        
        if (this.updateEventHandle) {
            var data: updateData = {
                state: State_UPDATE_SKIP,//状态
                message: "",//错误信息
                downloadedFiles: 0,
                totalFiles: 0,
                downloadedBytes: 0,
                totalBytes: 0,
            }

            this.updateEventHandle.emit([data])
        }

        return;
    }
    let loadManifest = jsb.fileUtils.getStringFromFile(localManifest);

    if (!loadManifest) {
        if (this.updateEventHandle) {
            var data: updateData = {
                state: State_UPDATE_ERR,//状态
                message: "加载本地版本文件失败",//错误信息
                downloadedFiles: 0,
                totalFiles: 0,
                downloadedBytes: 0,
                totalBytes: 0,
            }
            this.updateEventHandle.emit([data])
        }
        return;
    }
    let manifestObject = JSON.parse(loadManifest);
    if (url) {
        manifestObject.packageUrl = url;
        manifestObject.remoteManifestUrl = url   + version + '/project.manifest';
        manifestObject.remoteVersionUrl = url   + version + '/version.manifest';
    }
    var localVersion = manifestObject.version
    var compareVersion = this.versionCompareHandle(version, localVersion)
    if (compareVersion == 0) {
        if (updateEvent) {
            var data: updateData = {
                state: State_UPDATE_SKIP,//状态
                message: "",//错误信息
                downloadedFiles: 0,
                totalFiles: 0,
                downloadedBytes: 0,
                totalBytes: 0,
            }
            updateEvent.emit([data])
        }
        return
    }
    this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'blackjack-remote-asset');
    console.log('Storage path for remote asset : ' + this._storagePath);
    // Init with empty manifest url for testing custom manifest
    this._am = new jsb.AssetsManager("", this._storagePath, this.versionCompareHandle);
    // 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
    if (!this._am) {
        return
    }
    var manifest = new jsb.Manifest(JSON.stringify(manifestObject), this._storagePath);
    this._am.loadLocalManifest(manifest, this._storagePath);
    if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
        var data: updateData = {
            state: State_UPDATE_ERR,//状态
            message: "加载本地文件失败",//错误信息
            downloadedFiles: 0,
            totalFiles: 0,
            downloadedBytes: 0,
            totalBytes: 0,
        }
        updateEvent.emit([data])
        return;
    }
    this._am.setEventCallback(this.updateCb.bind(this));


    this._am.setVerifyCallback(this.verifyCallback.bind(this));
    //执行更新
    this._am.checkUpdate();
    // _am.update();
}
destroy() {
    if (this._am) {
        this._am.setEventCallback(null!);
    }
}

}

const hotUpdate = new HostUpdate()
//检查更新
export var checkAndUpdate = (version: string, localManifest: string, updateEvent: EventHandler, url?: string) => {
hotUpdate.checkAndUpdate(version, localManifest, updateEvent, url)
}
export function destroy() {

hotUpdate.destroy()

}
`

我看着你的代码,,好像是没有把修改的文件重新写入,具体你再看看吧。。

嗯,我以为不需要重新写入,文件,哎,大意了,谢谢了。