栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

android cocoscreator 热更新 超详细篇(五)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

android cocoscreator 热更新 超详细篇(五)

前言

前面 学了 android cocoscreator 相互调用(三)
这章 主要学习在 android 里 热更 js 代码及资源(cocoscreator 官方也有介绍,不过不是很详细,也有用热插件的,商店里有),这章介绍手动操作脚本生成热更新文件及测试热更新

1: 准备
win7 64位
cocoscreator2.0.10 (新版本如 2.4.7应该也是可以的)
node 版本 13.14 版 (再高好像不支持win7了)

2:创建个helloworld 工程 再生成APK
1:增加2个按钮 check hotupdate 分别绑定 checkfun hotupdatefun 函数


2: HelloWorld.js 代码如下

cc.Class({
    extends: cc.Component,

    properties: {
        label: {
            default: null,
            type: cc.Label
        },
        // defaults, set visually when attaching this script to the Canvas
     //   text: 'Hello, World!',
		/eh///
		//包名 暂定 org.cocos2d.helloworld
		//project.mainfest  文件存放地
		manifestUrl: {
            type: cc.Asset,     // use 'type:' to define Asset object directly
            default: null,      // object's default value is null
          },
        _updating: false,		//是否正在更新中
        _canRetry: false,		//能否重试
        _storagePath: ''		//android /data/data/包名/files/ 下就是这个存放目录
		/
    },

    // use this for initialization
    onLoad: function () {
      //  this.label.string = this.text;
	  /
        this.outputlog("onLoad");
        // Hot update is only available in Native build
        if (!cc.sys.isNative) {
            this.outputlog("jsb is not isNative");
            return;
        }
        if(!jsb){
            this.outputlog("jsb is null");
            return ;
        }

        this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'my-remote-asset');// /data/data/包名/files/my-remote-asset
        this.outputlog('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.
        var self = this;
        this.versionCompareHandle = function (versionA, versionB) {
            self .outputlog("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
        this._am = new jsb.AssetsManager('', this._storagePath, this.versionCompareHandle);
        // if (!cc.sys.ENABLE_GC_FOR_NATIVE_OBJECTS) {  // this._am.retain(); 没有这个函数  eh
        //     this._am.retain();
        // }
        // 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) {
                self .outputlog("Verification passed : " + relativePath);
                return true;
            }
            else {
                self .outputlog("Verification passed : " + relativePath + ' (' + expectedMD5 + ')');
                return true;
            }
        });
        this.outputlog("Hot update is ready, please check or directly update.");
        this.label.string = "Hot update is ready, please check or directly update.";

        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.outputlog("Max concurrent tasks count have been limited to 2");
        }
        // this.checkfun();
        ///
    },

    // called every frame
    update: function (dt) {

    },
	/eh///
	//日志输出
    outputlog:function(){//可变参数  arguments
        let strlog="";
		for (var i=0; i 

3: 构建再执行 脚本生成 manifest 文件
1> 先构建**(第一次)**
构建是为了生成 buildjsb-link(或jsb_default) 这里选择的是link 模板
主要就是为了res 和 src 这两个目录 为后面生成manifest文件用
2> 把 version_generator.js 放到工程根目录下

version_generator.js内容如下

var fs = require('fs');
var path = require('path');
var crypto = require('crypto');

var manifest = {
	//记得先装个node 啊
    //packageUrl 服务器更新数据包根目录  hotupdate 目录下有 src res 加 2个 manifest(project,version) 如下
	//version  版本号
    packageUrl: 'http://192.168.1.4/hotupdate/',
    remoteManifestUrl: 'http://192.168.1.4/hotupdate/project.manifest',
    remoteVersionUrl: 'http://192.168.1.4/hotupdate/version.manifest',
    version: '1.0.0',
    assets: {},
    searchPaths: []
};

//生成的manifest文件存放目录 就是用node version_generator.js 生成2个manifest 存放的路径
var dest = 'assets/';
//项目构建后资源的目录
var src = 'build/jsb-link/'; //这里选择的是link模板,选择default 需要修改下

// Parse arguments
var i = 2;
while ( i < process.argv.length) {
    var arg = process.argv[i];

    switch (arg) {
    case '--url' :
    case '-u' :
        var url = process.argv[i+1];
        manifest.packageUrl = url;
        manifest.remoteManifestUrl = url + 'project.manifest';
        manifest.remoteVersionUrl = url + 'version.manifest';
        i += 2;
        break;
    case '--version' :
    case '-v' :
        manifest.version = process.argv[i+1];
        i += 2;
        break;
    case '--src' :
    case '-s' :
        src = process.argv[i+1];
        i += 2;
        break;
    case '--dest' :
    case '-d' :
        dest = process.argv[i+1];
        i += 2;
        break;
    default :
        i++;
        break;
    }
}


function readDir (dir, obj) {
    var stat = fs.statSync(dir);
    if (!stat.isDirectory()) {
        return;
    }
    var subpaths = fs.readdirSync(dir), subpath, size, md5, compressed, relative;
    for (var i = 0; i < subpaths.length; ++i) {
        if (subpaths[i][0] === '.') {
            continue;
        }
        subpath = path.join(dir, subpaths[i]);
        stat = fs.statSync(subpath);
        if (stat.isDirectory()) {
            readDir(subpath, obj);
        }
        else if (stat.isFile()) {
            // Size in Bytes
            size = stat['size'];
            md5 = crypto.createHash('md5').update(fs.readFileSync(subpath, 'binary')).digest('hex');
            compressed = path.extname(subpath).toLowerCase() === '.zip';

            relative = path.relative(src, subpath);
            relative = relative.replace(/\/g, '/');
            relative = encodeURI(relative);
            obj[relative] = {
                'size' : size,
                'md5' : md5
            };
            if (compressed) {
                obj[relative].compressed = true;
            }
        }
    }
}

var mkdirSync = function (path) {
    try {
        fs.mkdirSync(path);
    } catch(e) {
        if ( e.code != 'EEXIST' ) throw e;
    }
}

// Iterate res and src folder
readDir(path.join(src, 'src'), manifest.assets);
readDir(path.join(src, 'res'), manifest.assets);

var destManifest = path.join(dest, 'project.manifest');
var destVersion = path.join(dest, 'version.manifest');

mkdirSync(dest);

fs.writeFile(destManifest, JSON.stringify(manifest), (err) => {
  if (err) throw err;
  console.log('Manifest successfully generated');
});

delete manifest.assets;
delete manifest.searchPaths;
fs.writeFile(destVersion, JSON.stringify(manifest), (err) => {
  if (err) throw err;
  console.log('Version successfully generated');
});

这里已经把远程路径配好了,所以只需要 执行 node version_generator.js 会产生manifest 文件

如果没配置或跟文件里的不一样可以用 这里第一次版本号先用1.0.0 (下次为个 1.0.1 自己随意增加)
node version_generator.js -v 1.0.0 -u http://192.168.1.4/hotupdate/ -s build/jsb-link/ -d assets/
就4个附加参数 -v -u -s -d 知道为什么? 跟 version_generator.js 一一对应的

执行 node version_generator.js 或 node version_generator.js -v -u -s -d 带参数这种(个人觉得直接在文件里写好省事)

为什么会生成在这,看 version_generator.js 里配置 或看 -d 的参数
把project.manifest 文件 拖过去

保存场景 再次构建**(第二次)** ,
构建完了,修改buildjsb-linkmain.js 在 window.boot(); 前 (因为选择的是link 模板)

var isRuntime = (typeof loadRuntime === 'function');
    if (isRuntime) {
        require('src/settings.js');
        require('src/cocos2d-runtime.js');
        require('jsb-adapter/engine/index.js');
    }
    else {
        require('src/settings.js');
        require('src/cocos2d-jsb.js');
        require('jsb-adapter/jsb-engine.js');
    }
	///eh add/
	//HelloWorld.js  updateCb 函数 cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
	var hotUpdateSearchPaths = cc.sys.localStorage.getItem('HotUpdateSearchPaths'); //必须一致
	 if (hotUpdateSearchPaths) {
		  window.jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths));
	 }
	 require('src/settings.js'); //重新加载一次 或上面的就不加载
	 

    cc.macro.CLEANUP_IMAGE_CACHE = true;
    window.boot();

保存main.js,再点编译生成APK (根据机子好坏等段时间)

编译完成得到APK,路径 这里选择的是link模板,选择default 路径有点区别的

以上是生成APK的工程,可以保存起来,以后修改都是在这个基础上的进行的

3:修改工程测试热跟新
1: 第一次测试,先修改 icon 再加个 lable ,简单修改下代码
目标:热更新完了,左下角新增加了lable 显示 原lable内容+[测试] 2个字
cocos 图标 会增加一条竖的红线
修改如下构建,构建就可以了,构建完了,修改 version_generator.js里的 版本号 这里修改为1.0.1

修改 再执行 node version_generator.js 生成新的 2个manifest 把生成的project.manifest version.manifest ,这里在assets 目录下,不确定是最新的话,看修改时日期
同时把 buildjsb-link 目录下 res,src 目录放到 packageUrl 写的目录下,

这里是本地测试,192.168.1.4是本机IP,装的是xampp ,apk 装在模拟器里测试的

安装完APK 的显示

点击check

点击hotupdate 结果如下图 ,重新启动APK,结果也如下图,这样代表 热更新OK了

最后看看在android 里的热更新 下载代码与资源存放目录
运行在夜神模拟器7.0.0.5里,路径 /data/data/包名/files 下

4 热更新及测试结束(记得保存一份生成APK的工程代码,后面任何改动可以以此为基础)
1: project.manifest 一定要在 manifestUrl:{ type: cc.Asset,… } 上,不需要删,执行 node version_generator.js 会覆盖的
2: 只需要构建
3: 修改版本号 (version_generator.js 里)
4: 执行 node version_generator.js
5: 把相应文件及目录放入远端服务器目录下就行了
工程代码如有需要后续再上传

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/690994.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号