cocos2d-js 在线更新代码脚本 动态更新脚本程序 热更新 绕过平台审核 不需重新上架
使用方法:
1、所有js必须使用zip打包,但不强求只打包为1个文件。但不同zip不要有重复的js。
2、非js可以用zip,也可以直接列出。
由于确保所有资源都下载完成后才解压js,所以玩家即使N次更新失败,还是会妥妥的停留在上一版。
一、cocos2d-js 动态更新的基本思路
动态更新的好处不言而喻,不需要重新上架审核,能节省很多时间,也能让用户尽快使用上最新的版本,减少下载的成本。
- 官方BETA版本后提供了AssetsManager类,可以完成动态更新的步骤,说明:https://github.com/chukong/cocos-docs/blob/master/manual/framework/html5/v3/assets-manager/zh.md
- cocos2d程序安装后,以Android为例,程序存在于2个地方:apk安装目录(/data/dalvik-cache),apk数据目录(/data/data/[包名])
- AssetsManager根据projec.manifest文件的配置,把新文件下载到apk数据目录,并默认把这个下载目录设置为最优先搜索的地方。
- project.json文件中指定的js文件,将在程序main.js启动前就加载完。main.js不需要写到这个list中。所以需要动态更新的js,不能列在这个json中。
- 除了main.js外,把其他js列到一个文件中:src/jsList.js。AssetsManager检查完之后,先加载这个jsList.js,然后根据里边的配置再加载全部js。
二、程序发布步骤
本文参考:https://github.com/faint2death/cocos2d-js/blob/master/assetsmanager.md,但配置的方式不一样,本文更偏于使用官方的配置。按参考文章的写法,更新多次之后,project.manifest文件会很大,这影响用户更新的速度。
1、修改main.js,加载AssetsManager功能
cc.game.onStart = function(){
cc.view.setDesignResolutionSize(800, 450, cc.ResolutionPolicy.SHOW_ALL);
cc.view.resizeWithBrowserSize(true);
var failCount = 0;
var maxFailCount = 1; //最大错误重试次数
/**
* 自动更新js和资源
*/
var AssetsManagerLoaderScene = cc.Scene.extend({
_am:null,
_progress:null,
_percent:0,
run:function(){
if (!cc.sys.isNative) {
this.loadGame();
return;
}
var layer = new cc.Layer();
this.addChild(layer);
this._progress = new cc.LabelTTF.create("update 0%", "Arial", 12);
this._progress.x = cc.winSize.width / 2;
this._progress.y = cc.winSize.height / 2 + 50;
layer.addChild(this._progress);
var storagePath = (jsb.fileUtils ? jsb.fileUtils.getWritablePath() : "./");
this._am = new jsb.AssetsManager("res/project.manifest", storagePath);
this._am.retain();
if (!this._am.getLocalManifest().isLoaded())
{
cc.log("Fail to update assets, step skipped.");
this.loadGame();
}
else
{
var that = this;
var listener = new cc.EventListenerAssetsManager(this._am, function(event) {
switch (event.getEventCode()){
case cc.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
cc.log("No local manifest file found, skip assets update.");
that.loadGame();
break;
case cc.EventAssetsManager.UPDATE_PROGRESSION:
that._percent = event.getPercent();
cc.log(that._percent + "%");
var msg = event.getMessage();
if (msg) {
cc.log(msg);
}
break;
case cc.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
case cc.EventAssetsManager.ERROR_PARSE_MANIFEST:
cc.log("Fail to download manifest file, update skipped.");
that.loadGame();
break;
case cc.EventAssetsManager.ALREADY_UP_TO_DATE:
cc.log("ALREADY_UP_TO_DATE.");
that.loadGame();
break;
case cc.EventAssetsManager.UPDATE_FINISHED:
cc.log("Update finished.");
that.loadGame();
break;
case cc.EventAssetsManager.UPDATE_FAILED:
cc.log("Update failed. " + event.getMessage());
failCount++;
if (failCount < maxFailCount)
{
that._am.downloadFailedAssets();
}
else
{
cc.log("Reach maximum fail count, exit update process");
failCount = 0;
that.loadGame();
}
break;
case cc.EventAssetsManager.ERROR_UPDATING:
cc.log("Asset update error: " + event.getAssetId() + ", " + event.getMessage());
that.loadGame();
break;
case cc.EventAssetsManager.ERROR_DECOMPRESS:
cc.log(event.getMessage());
that.loadGame();
break;
default:
break;
}
});
cc.eventManager.addListener(listener, 1);
this._am.update();
cc.director.runScene(this);
}
this.schedule(this.updateProgress, 0.5);
},
loadGame:function(){
//jsList是jsList.js的变量,记录全部js。
cc.loader.loadJs(["src/jsList.js"], function(){
cc.loader.loadJs(jsList, function(){
cc.director.runScene(new MainScene());
});
});
},
updateProgress:function(dt){
this._progress.string = "update" + this._percent + "%";
},
onExit:function(){
cc.log("AssetsManager::onExit");
this._am.release();
this._super();
}
});
var scene = new AssetsManagerLoaderScene();
scene.run();
};
cc.game.run();
2、建立jsList.js。使用固定名字jsList,这个跟第1步的代码相对应。
var jsList = [
"src/resource.js",
"src/app.js"
]
3、修改project.json。加入extensions模块,删除jsList的内容。
{
"project_type": "javascript", "debugMode" : 1,
"showFPS" : true,
"frameRate" : 60,
"id" : "gameCanvas",
"renderMode" : 0,
"engineDir":"frameworks/cocos2d-html5", "modules" : ["cocos2d", "extensions"], //貌似这个对jsb是无效的,只有html5才有效 "jsList" : [ ]
}4、项目res目录增加一个project.manifest文件,AssetsManager.js里会用到。url填写自己服务器的地址,packageUrl是准备动态更新的文件的存放目录。
{
"packageUrl" : "http://192.168.1.11:8000/res",
"remoteManifestUrl" : "http://192.168.1.11:8000/res/project.manifest",
"remoteVersionUrl" : "http://192.168.1.11:8000/res/version.manifest",
"version" : "1.0.1",
"engineVersion" : "3.0 rc0",
"assets" : { }, "searchPaths" : [
]
}
5、打包程序。此时即使没有网络,也已经可以运行基础版本。
三、动态更新测试
1、服务器放置version.manifest和新的project.manifest。
AssetsManager会先检查version.manifest,判断是否有更新。如果有,再拉取project.manifest。可以说version.manifest就是缩小版的project.manifest,只有头几行,两者一致。
version.manifest:
{
"packageUrl" : "http://192.168.1.11:8000/res",
"remoteManifestUrl" : "http://192.168.1.11:8000/res/project.manifest",
"remoteVersionUrl" : "http://192.168.1.11:8000/res/version.manifest",
"version" : "1.0.1",
"engineVersion" : "3.0 rc0"
}project.manifest:
{
"packageUrl" : "http://192.168.1.11:8000/res",
"remoteManifestUrl" : "http://192.168.1.11:8000/res/project.manifest",
"remoteVersionUrl" : "http://192.168.1.11:8000/res/version.manifest",
"version" : "1.0.1",
"engineVersion" : "3.0 rc0",
"assets" : {
"src/app.zip" : {
"md5" : "D07D260D8072F786A586A6A430D0E98B",
"compressed" : true
}
}, "searchPaths" : [
]
}
manifest这里使用了官方说明没有提到的compressed,src/app.zip并没有在初始打包的程序中,这个只是更新用的。指定了compressed=true,AssetsManager下载后会自动解压这个文件,并保留这个文件。这样就可以减少网络传输的文件大小。
app.zip压缩的是app.js,解压后将覆盖初始化安装的app.js,从而实现了动态更新。
这里可以多次更新,不断更新version号即可,每次AssetsManager会检查文件是否存在、文件md5是否一致,如果不存在或者md5不一致都会重新下载。
2、无需重新打包发布,直接打开cocos2d程序,可以看到update的字样,如果打开了logcat,也可以看到对应的日志。
cocos2d-js 在线更新代码脚本 动态更新脚本程序 热更新 绕过平台审核 不需重新上架的更多相关文章
- Unity3D热更新全书-何谓热更新,为何热更新,如何热更新
首先来赞叹一下中文,何谓为何如何,写完才发现这三个词是如此的有规律. 为何赞叹中文?因为这是一篇针对新手程序员的文字,是一节语文课. 然后来做一下说文解字,也就是 何谓热更新 热更新,每个程序员一听就 ...
- 开源:AspNetCore 应用程序热更新升级工具(全网第一份公开的解决方案)
1:下载.开源.使用教程 下载地址:Github 下载 .其它下载 开源地址:https://github.com/cyq1162/AspNetCoreUpdater 使用教程: 解压AspNetCo ...
- 微信小程序热更新,小程序提示版本更新,版本迭代,强制更新,微信小程序版本迭代
相信很多人在做小程序的时候都会有迭代每当版本迭代的时候之前老版本的一些方法或者显示就不够用了这就需要用到小程序的热更新.或者说是提示升级小程序版本 editionUpdate:function(){ ...
- cocos2d JS 使用代码判断对象类型
changeAtlasScoreString : function (score,tfScore) { if(tfScore.getDescription() == "LabelAtlas& ...
- 【Quick 3.3】资源脚本加密及热更新(三)热更新模块
[Quick 3.3]资源脚本加密及热更新(三)热更新模块 注:本文基于Quick-cocos2dx-3.3版本编写 一.介绍 lua相对于c++开发的优点之一是代码可以在运行的时候才加载,基于此我们 ...
- Unity3D热更新之LuaFramework篇[09]--资源热更新与代码热更新的具体实现
前言 在上一篇文章 Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建 中,我介绍了热更新的基本原理,并且着手搭建一台服务器. 本篇就做一个实战练习,真正的来实现热 ...
- 另类Unity热更新大法:代码注入式补丁热更新
对老项目进行热更新 项目用纯C#开发的? 眼看Unity引擎热火朝天,无数程序猿加入到了Unity开发的大本营. 一些老项目,在当时ulua/slua还不如今天那样的成熟,因此他们选择了全c#开发:也 ...
- iOS热更新-8种实现方式
一.JSPatch 热更新时,从服务器拉去js脚本.理论上可以修改和新建所有的模块,但是不建议这样做. 建议 用来做紧急的小需求和 修复严重的线上bug. 二.lua脚本 比如: wax.热更新时,从 ...
- ios app 实现热更新(无需发新版本实现app添加新功能)
目前能够实现热更新的方法,总结起来有以下三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的iOS应用 ios app可以在运行时从服务器拉取最新的js文件到 ...
随机推荐
- 多个Jar的合并操作
同事要写Android平台下的打包工具,遇到需要将多个jar合并成一个jar的问题.这里列一下操作步骤: 1.将所有jar文件复制至某临时目录中,通过jar命令解压得到所有的.class文件 > ...
- CoreDNS介绍
本文介绍 CoreDNS 相关配置以及验证方法,实验环境为 Kubernetes 1.11,搭建方法参考kubeadm安装kubernetes V1.11.1 集群 busybox 的槽点 开始之前先 ...
- Leetcode刷题记录:构建最大数二叉树
题目要求,题目地址 给定一个不含重复数字的数组,最大二叉树构建规则如下: 1.根是数组中最大的数字 2.左边的子树是最大数字左边的内容 3.右边的子树是最大数字右边的内容 答案 class Solut ...
- 【Java并发】JUC—ReentrantReadWriteLock有坑,小心读锁!
好长一段时间前,某些场景需要JUC的读写锁,但在某个时刻内读写线程都报超时预警(长时间无响应),看起来像是锁竞争过程中出现死锁(我猜).经过排查项目并没有能造成死锁的可疑之处,因为业务代码并不复杂(仅 ...
- Netty 4.0.0.CR6 发布,高性能网络服务框架
Netty 4.0 发布第 6 个 RC 版本,该版本值得关注的改进有: SslHandler and JZlibEncoder now works correctly. (#1475 and #14 ...
- C++对带有分隔符的字符串 分割为数字的通用解决方案
需求: 数据库取出的字段类似于 "1,3,4" 然后用数字处理后,,比如 "1,2,3" 再存回去 #include<stdio.h> #inclu ...
- Oracle简单的备份和恢复-导入和导出-目录
ylbtech-Oracle:Oracle简单的备份和恢复-导入和导出-目录 Oracle安全运行离不开良好的备份和恢复机制,因为我们不是DBA.所以我们也就不过多的讲解DBA的备份和恢复.作为程序员 ...
- android adb源码分析(1)
ADB是Android debug bridge的缩写,它使用PC机可以通过USB或网络与android设备通讯. adb的源码位于system/core/adb目录下,先来看下编译脚本Android ...
- 第一章 Typescript 介绍
Typescript 介绍 一.Typescript 简介 Typescript 是微软开发的 Javascript 的超集,Typescript 兼容 Javascript,可以载入 Javascr ...
- 使用 CSS 接收用户的点击事情并对相关节点进行操作
问题背景:使用纯 CSS 方案,实现导航栏tab切换 实现 Tab 切换的难点在于如何使用 CSS 接收到用户的点击事情并对相关的节点进行操作.即是: 如何接收点击事件 如何操作相关DOM 下面看看如 ...