笔记:热更新详细操作

更多笔记:【微信公众号】 CocosCreator笔记

Step 1

首先请详细阅读官方文档:

http://docs.cocos.com/creator/manual/zh/advanced-topics/hot-update.html

是不是就感觉不用继续看了

下载文档中提到的version_generator.js文件,用于生成 Manfiest 文件的 NodeJS 脚本。将其放在项目根目录下~

Step 2

注意步骤的顺序:

1.构建,不要勾选 MD5 Cache

2.根据构建目录运行下面命令,生成manifest,自动放到asset下

jsb-default:

node version_generator.js -v 1.0.0 -u http://your-server-address/hot-update/remote-assets/ -s build/jsb-default/ -d assets/
jsb-link:

node version_generator.js -v 1.0.0 -u http://your-server-address/hot-update/remote-assets/ -s build/jsb-link/ -d assets/
下面是参数说明:

-v 指定 Manifest 文件的主版本号。

-u 指定服务器远程包的地址,这个地址需要和最初发布版本中 Manifest 文件的远程包地址一致,否则无法检测到更新。

-s 本地原生打包版本的目录相对路径。

-d 保存 Manifest 文件的地址。

3.(仅发布整包时需要)在编辑器中拖拽project.manifest到UpdateComponent脚本的manifestUrl

UpdateComponent脚本挂载到更新场景里~

下边是代码:

const {ccclass, property} = cc._decorator;

@ccclass
export default class UpdateComponent extends cc.Component {

@property({type: cc.Asset})
manifestUrl: cc.Asset = null;

@property
nameScene = "";

@property(cc.ProgressBar)
progressBar = null;

_storagePath = "";

_assetsManager = null;

start () {
    this._storagePath = jsb.fileUtils.getWritablePath() + "asset/";
    console.log(this._storagePath);
    this._assetsManager = new jsb.AssetsManager(this.manifestUrl.nativeUrl, this._storagePath);
    this._assetsManager.setMaxConcurrentTask(3);

    this.checkAsset();
}

checkAsset()
{
    this._assetsManager.setEventCallback(this.callCheck.bind(this));
    this._assetsManager.checkUpdate();
}

updateAsset()
{
    this._assetsManager.setEventCallback(this.callUpdate.bind(this));
    this._assetsManager.update();
}

callCheck(event) 
{      
    let update = false;
    switch (event.getEventCode())
    {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            console.log('No local manifest file found, hot update skipped.');
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
        case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
            console.log('Fail to download manifest file, hot update skipped.');
            break;
        case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
            console.log('Already up to date with the latest remote version.');               
            break;
        case jsb.EventAssetsManager.NEW_VERSION_FOUND:
            console.log('New version found, please try to update.');   
            update = true;
            break;
        default:
            return;
    }

    this._assetsManager.setEventCallback(null);
    if (update) {
        this.updateAsset();
    } else {
        cc.director.loadScene(this.nameScene);
    }
}

callUpdate(event)
{
    let finished = false;
    let failed = false;
    switch (event.getEventCode())
    {
        case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
            console.log('No local manifest file found, hot update skipped.');
            failed = true;
            break;
        case jsb.EventAssetsManager.UPDATE_PROGRESSION:
            //event.getPercent();
            //event.getPercentByFile();

            //event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
            //event.getDownloadedBytes() + ' / ' + event.getTotalBytes();
            
            this.progressBar.progress = event.getPercent();
            break;
        case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
        case jsb.EventAssetsManager.ERROR_PARSE_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());
            finished = true;
            break;
        case jsb.EventAssetsManager.UPDATE_FAILED:
            console.log('Update failed. ' + event.getMessage());              
            break;
        case jsb.EventAssetsManager.ERROR_UPDATING:
            console.log('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
            break;
        case jsb.EventAssetsManager.ERROR_DECOMPRESS:
            console.log(event.getMessage());
            break;
        default:
            break;
    }

    if (failed) {
        this._assetsManager.setEventCallback(null);
    }

    if (finished) {
        this._assetsManager.setEventCallback(null);         
        cc.audioEngine.stopAll();
        cc.game.restart();
    }
}

}

4.再次构建

5.(仅发布完整包时需要)打开main.js,在 require(xxx) 后 window.boot() 前加上下边的代码

if (cc.sys.isNative) {
let pathAsset = jsb.fileUtils.getWritablePath() + “asset/”
jsb.fileUtils.addSearchPath(pathAsset,true);
}

6.把生成的两个manifest文件复制到 build/jsb-default/ 或 build/jsb-link/ 目录下

7.把两个manifest文件和res文件夹和src文件夹放到服务器上

9赞

mark

mark - 热更新流程

mark

mark - 热更新流程

MARK

鸦哥,我2.4.2版本,手机浏览器能访问到本地服务器文件,但是checkUpdate的时候一直返回jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST
这是什么原因啊?

本地服务器?

嗯,自己express搭了一个服务器,问题好像找到了,前面我没放project.mainifest,他好像check的时候两个文件都会去找,然后两个文件的版本都得改

鸦哥,我这遇到一个很扯的问题:
原本一个人调试是没有问题的,然后两个人调试(一个人只打包一个人只放更新),然后更新下来就出问题了,更新后找不到本地的manifest,打包这边查到在native/19/文件夹,更新下来是native/e5/文件夹,search path里没有/e5/,只有/19/,原因应该是更新的人合并的时候动了loading.fire里拖进去的project文件导致构建的路径不一致了,这种要怎么处理?目前是测试阶段,临时的处理的方案就是又同步了一次代码重新打包。。。如果上线后出现这种意外也太难受了吧?

只有在整包发布的时候,才会有拖那个project文件的情况啊~
热更新的话,只是构建,然后用脚本生成那个文件

是这样的,我新加的热更新,然后他同步我代码的时候git里有冲突把新增的字段丢失了所以重新拖了一次,如果下次还出现类似问题有什么办法提前处理或预防不?

你们这是开发阶段吧,这种热更新流程,肯定是要在发布阶段去做

有条件的话,可以搞成流水线··自动化去做

嗯,我在处理这块东西,看见说要构建两次我就准备换成命令行打包了。。。前面没注意,只弄了个一次构建后的脚本。。
但是这样也没法避免万一出现类似的问题。。。比如不小心。。。那就只有打新包了?

这种人为的问题,我也不知道咋搞···就像我不小心写了个bug?

这么晚一个个的还在加班吗?

这种本质上应该也算是代码不严谨吧?主要是路径问题,关键不知道这玩意在哪处理

你同步代码错了,这种问题还能怎么预防???

要这么说的话,可以把那个文件放到resources目录,动态加载,获取路径