文档章节

quick-cocos2d-x基于源码加密打包功能的更新策略(1)

SunLightJuly
 SunLightJuly
发布于 2013/12/01 22:44
字数 1879
阅读 18487
收藏 26

Quick-cocos2d-x增加了编译及加密源代码的功能(具体可参考这篇文章)。以此功能为基础,我实现了一个版本更新模块,解决了自己项目中的版本更新需求。现抛砖引玉,与大家分享。

从基本原理和方案讲起比较枯燥,直接从介绍具体用法开始吧。

要能够在线更新文件,一个服务器是必须的。我目前实现的是用HTTP协议取文件,只需要有一个基本的web服务器,能通过类似http://<server>/<filename>的链接取到文件即可。当然,如果需要根据平台和版本进行文件的分发,服务器端还需要进行相应配置。

要调试下面的例子,自己在内网甚至就在本机上搭建一个最简单的web服务器就可以了。

一、基本更新功能

1.创建一个可以自动更新的程序

首先准备好我们的quick-x工程。作为例子,我们直接使用create_project来创建一个新工程helloworld来使用。这一步不用我多说。

接下来,请到这里下载我写的更新模块。只需要根目录下的update.lua文件即可,其他的目录下只是我的一些例子和工具。 

(2014.5.30加注:quick-x的2.2.3版本里的sample/2048使用了这一更新模块,可以使用例子中的update.lua文件)

将update.lua文件加到helloworld工程的scripts目录下。修改文件中“local server = "http://192.168.1.98:8088/"”这一句,改成自己的服务器地址。
在scripts目录下创建一个新文件appentry.lua,然后打开工程原来的main.lua文件,把里面调用程序入口的代码复制过来。如果你使用的是最新版的quick-x,那么就只有“require("app.MyApp").new():run()”这一句。保存appentry.lua文件。
现在修改main.lua文件,去掉原来的程序入口代码,改成“require "update"”。
这样,更新模块就添加好了。程序在启动时,将先运行更新模块,完成后,自动调用appentry进入原来程序的真正入口。
现在可以先运行看看了,相信大家都会选择最方便的player来调试的。实际上真机也是没问题的。
运行后,界面上首先会显示“Loading...”,然后再进入熟悉的“Hello,world”界面。

接下来我们调试与服务器的连接是否正常。在服务器上创建一个flist文件,内容为:

local list = { 
  ver = "1.0.1", 
  stage = { 
  }, 
  remove = { 
  }, 
} 
return list

需要保证用http://<server>/flist这样的网址能取到flist。如果是最基本的web服务器,把flist文件放在web服务目录的根下面就可以。如果希望用http://<server>/getfile?filename=flist这样的形式取文件,请自己修改update.lua里的相关代码。

现在重新运行程序,运行结果看起来没有什么不同。不过,如果是在player上调试,应该能在helloworld工程目录下找到flist文件,和服务器上的文件内容是一样的,说明我们从服务器取到了文件,连接是正常的。如果是真机,请在device.writablePath指向的目录下找flist文件。

现在,我们已经有一个可以自动更新版本的程序了。为了模拟真实的应用环境,我们将把源码加密打包再进行后面的调试。如果还不知道应该怎么打包,请再认真参考前面的文章。另外,推荐使用QuickXDev插件进行打包(可参考这一篇)。
为了后面更好的演示图片资源的更新,打包前可以修改一下MainScene.lua,在界面上添加一张图片,如下:

display.addSpriteFramesWithFile(GAME_TEXTURE_DATA_FILENAME, GAME_TEXTURE_IMAGE_FILENAME) 
self.bg = display.newSprite("#logo.png", display.cx-200, display.cy-200) 
self:addChild(self.bg)

将资源放到res目录下,在config.lua里配置好GAME_TEXTURE_DATA_FILENAME和GAME_TEXTURE_IMAGE_FILENAME的值。运行能正常显示图片后,就可以真正打包源码了。

假如你是完全按照参考文章去打包的,那你应该会将打包后的文件game.zip放在res目录下,并将scripts目录下所有原来的源码全部移走,启动程序,运行结果和没打包之前一致。

2.简单的功能更新

现在,我们希望将显示的文字改成中文。代码的修改是很简单的,将MainScene.lua中显示的字串“Hello, World”改成“你好,世界”就可以了。
但我们怎么让程序自动进行更新呢?当然是打包新代码然后放到服务器上让程序来取了。

因为我们只修改了MainScene.lua,所以我们只需要打包这个文件就可以了。打包时需要注意的是,MainScene.lua是放在app\scenes目录下的,所以它在打包目录下也应该放在相同的两级目录之下才行。
我们将新打包的文件随便改个文件名(其实在这一情境中,仍然叫game.zip也是没问题的),比如update.bin。将它放到服务器上,当然仍然要保证http://<server>/update.bin这样的网址能取到。

接下来我们修改服务器上的flist文件,如下:

local list = { 
  ver = "1.0.2", 
  stage = { 
    {name="update.bin", code="8c528975dec8b6da5811e92f10a41be0", act="load"}, 
  }, 
  remove = { 
  }, 
} 
return list

可以看出,list文件的版本号变成了1.0.2,这样客户端程序就知道有了更新,准备取新的文件。

stage里指出这个版本里有多少需要下载到客户端的文件。
name是文件名。code是文件的MD5码,用于验证文件。如果不想验证文件,code可以等于nil或者干脆不写这一键值。但不进行文件验证显然是不利的,除了不能保证下载文件的正确性而引起程序崩溃,还有就是不能进行同名文件的更新,如果原来已经下载过update.bin,不进行验证的话默认原来的文件是正确的,客户端程序将不会重新下载update.bin。
文件的md5码取得是很容易的,有很多方法。我实现更新模块时顺便写了个取md5的小程序,放在更新模块工程的tools目录下,使用方法很简单,将要取md5的文件放在getMd5/files目录下,用player打开getMd5工程运行,工程目录下生成的flist.txt里就是需要的内容了。
act="load"表明这一文件是代码文件,需要载入运行,如果是普通的图片资源,可以等于nil或者直接不写这一键值。

现在,可以运行客户端程序了。“Loading...”界面过后,显示的是“你好,世界”,自动更新成功了!

接下来我们将讨论一下更新的基本原理,以确认我们的更新方式是真正可行的,同时进一步演示如何进行更深层次的功能更新(如资源路径变化的处理framework包修改update模块自身更新等)。当然,更新机制的健壮性(不能因为更新失败,或者更新文件被破坏造成程序无法工作),还有如何根据平台和机型进行版本文件的分发等,也是我们要讨论的。

后一篇: quick-cocos2d-x基于源码加密打包功能的更新策略(2)

© 著作权归作者所有

共有 人打赏支持
SunLightJuly
粉丝 59
博文 15
码字总数 12480
作品 0
成都
私信 提问
加载中

评论(70)

SunLightJuly
SunLightJuly

引用来自“qq626928256”的评论

13大神,我有一事不明,为什么在update.lua中的ctor里面,创建精灵什么的都不显示,只有label可以显示呢
没有这种问题的。一般是你自己在某些地方的处理出错了。
q
qq626928256
13大神,我有一事不明,为什么在update.lua中的ctor里面,创建精灵什么的都不显示,只有label可以显示呢
smallmoves
smallmoves

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print

引用来自“smallmoves”的评论

谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈

引用来自“SunLightJuly”的评论

你加载文件的代码是怎么样的?

引用来自“smallmoves”的评论

require(device.writablePath .. "upd/src/app/main/MainPage") zip包是下载到upd目录下的

引用来自“SunLightJuly”的评论

这样做是不可以的,使用quick工具编译打包加密后,已经不是以目录文件的方式存在了,而且require命令也并不能识别zip中的文件。正确的使用方法,应该是使用LuaLoadChunksFromZIP接口加载zip文件,然后就可以调用: require("app.main.MainPage") 注意是点号分隔,而且大小写一定要和打包时的文件名一致。

引用来自“smallmoves”的评论

我看到在update的endProcess里有调用cc.LuaLoadChunksFromZIP(self.path..v.name)的,然后我require("app.main.MainPage")这样也还是找不到文件

引用来自“SunLightJuly”的评论

首先检查log输出,确认LuaLoadChunksFromZIP的加载是成功的。如果zip加载是成功的,那么应该是打包时有问题,请仔细阅读本文中,在打包时文件所放目录的说明。
居然是act=load这个地方,load忘了加上引号,现在终于更新好了,实在是太感谢你了~~
smallmoves
smallmoves

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print

引用来自“smallmoves”的评论

谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈

引用来自“SunLightJuly”的评论

你加载文件的代码是怎么样的?

引用来自“smallmoves”的评论

require(device.writablePath .. "upd/src/app/main/MainPage") zip包是下载到upd目录下的

引用来自“SunLightJuly”的评论

这样做是不可以的,使用quick工具编译打包加密后,已经不是以目录文件的方式存在了,而且require命令也并不能识别zip中的文件。正确的使用方法,应该是使用LuaLoadChunksFromZIP接口加载zip文件,然后就可以调用: require("app.main.MainPage") 注意是点号分隔,而且大小写一定要和打包时的文件名一致。

引用来自“smallmoves”的评论

我看到在update的endProcess里有调用cc.LuaLoadChunksFromZIP(self.path..v.name)的,然后我require("app.main.MainPage")这样也还是找不到文件

引用来自“SunLightJuly”的评论

首先检查log输出,确认LuaLoadChunksFromZIP的加载是成功的。如果zip加载是成功的,那么应该是打包时有问题,请仔细阅读本文中,在打包时文件所放目录的说明。
恩,我再看看,太感谢啦~~
SunLightJuly
SunLightJuly

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print

引用来自“smallmoves”的评论

谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈

引用来自“SunLightJuly”的评论

你加载文件的代码是怎么样的?

引用来自“smallmoves”的评论

require(device.writablePath .. "upd/src/app/main/MainPage") zip包是下载到upd目录下的

引用来自“SunLightJuly”的评论

这样做是不可以的,使用quick工具编译打包加密后,已经不是以目录文件的方式存在了,而且require命令也并不能识别zip中的文件。正确的使用方法,应该是使用LuaLoadChunksFromZIP接口加载zip文件,然后就可以调用: require("app.main.MainPage") 注意是点号分隔,而且大小写一定要和打包时的文件名一致。

引用来自“smallmoves”的评论

我看到在update的endProcess里有调用cc.LuaLoadChunksFromZIP(self.path..v.name)的,然后我require("app.main.MainPage")这样也还是找不到文件
首先检查log输出,确认LuaLoadChunksFromZIP的加载是成功的。如果zip加载是成功的,那么应该是打包时有问题,请仔细阅读本文中,在打包时文件所放目录的说明。
smallmoves
smallmoves

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print

引用来自“smallmoves”的评论

谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈

引用来自“SunLightJuly”的评论

你加载文件的代码是怎么样的?

引用来自“smallmoves”的评论

require(device.writablePath .. "upd/src/app/main/MainPage") zip包是下载到upd目录下的

引用来自“SunLightJuly”的评论

这样做是不可以的,使用quick工具编译打包加密后,已经不是以目录文件的方式存在了,而且require命令也并不能识别zip中的文件。正确的使用方法,应该是使用LuaLoadChunksFromZIP接口加载zip文件,然后就可以调用: require("app.main.MainPage") 注意是点号分隔,而且大小写一定要和打包时的文件名一致。
我看到在update的endProcess里有调用cc.LuaLoadChunksFromZIP(self.path..v.name)的,然后我require("app.main.MainPage")这样也还是找不到文件
SunLightJuly
SunLightJuly

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print

引用来自“smallmoves”的评论

谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈

引用来自“SunLightJuly”的评论

你加载文件的代码是怎么样的?

引用来自“smallmoves”的评论

require(device.writablePath .. "upd/src/app/main/MainPage") zip包是下载到upd目录下的
这样做是不可以的,使用quick工具编译打包加密后,已经不是以目录文件的方式存在了,而且require命令也并不能识别zip中的文件。正确的使用方法,应该是使用LuaLoadChunksFromZIP接口加载zip文件,然后就可以调用: require("app.main.MainPage") 注意是点号分隔,而且大小写一定要和打包时的文件名一致。
smallmoves
smallmoves

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print

引用来自“smallmoves”的评论

谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈

引用来自“SunLightJuly”的评论

你加载文件的代码是怎么样的?
require(device.writablePath .. "upd/src/app/main/MainPage") zip包是下载到upd目录下的
SunLightJuly
SunLightJuly

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print

引用来自“smallmoves”的评论

谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈
你加载文件的代码是怎么样的?
smallmoves
smallmoves

引用来自“smallmoves”的评论

您好,请问下,我在下载文件的时候,有时候会报错:
[LUA-print] REQUEST 1 - event.name = completed
[LUA-print] REQUEST 1 - getResponseStatusCode() = 200
[LUA-print] REQUEST 1 - getResponseDataLength() = 120
[LUA-print] ----------------------------------------
2015-05-07 09:39:15.043 player3[494:8172] NSConcreteAttributedString initWithString:: nil value
能不能帮忙看看为什么啊,多谢了~

引用来自“SunLightJuly”的评论

这个报错一般是print时后面的字串有非法字符、太长等,你接收到二进制数据以后不要把它用来print
谢谢了哈,这个问题找到了,是flist里面又非法字符,但是现在还有另一个问题:我的资源目录下有update,MyApp,MainScene,然后其他的通过热更新下载编译并加密过的zip,但是MainScene读取不到zip里面的table所在的lua文件: can not get file data of src//var/mobile/Containers/Data/Application/60F44B83-D7FB-4B8A-848D-78FC0709671F/Documents/upd/src/app/main/MainPage.lua 还请在帮忙看看我这个方式有什么问题,谢谢哈
quick-cocos2d-x基于源码加密打包功能的更新策略(3)

前篇: quick-cocos2d-x基于源码加密打包功能的更新策略(1) quick-cocos2d-x基于源码加密打包功能的更新策略(2) 三、更新流程说明及特性分析 A.更新流程 加载初始安装包,载入旧资源列表 取最...

SunLightJuly
2013/12/05
4.5K
8
quick-cocos2d-x基于源码加密打包功能的更新策略(2)

前一篇:quick-cocos2d-x基于源码加密打包功能的更新策略(1) 二、更新原理讨论及更复杂的更新功能 1.更新原理 在前面的更新过程中,从服务器取文件列表,并根据文件列表再更新相关的文件,这...

SunLightJuly
2013/12/02
0
50
quick-cocos2d-x平台Lua源码打包后运行出错的一种情况

quick-cocos2d-x平台的Lua源码打包及加密功能是其提供的方便功能之一(具体可参考lonewolf的这篇文章)。今天Quick-x群里的一位朋友在使用时遇到了点问题,经过我们的探讨找到了原因。虽然是个...

SunLightJuly
2013/12/31
0
5
浅析Android手游lua脚本的加密与解密

本文转载自 梦幻西游手游美术资源加密分析 浅析android手游lua脚本的加密与解密 lua、luac、luaJIT三种文件的关系 lua手游过程中有三种文件:lua、luac、luaJIT。lua是明文代码,直接用记事本...

qq_32400847
2017/11/12
0
0
quick-cocos2d-x源文件编译及加密详解

quick-cocos2d-x是用lua脚本来写的,而lua是明文形式,如果不对脚本进行处理,那么我们所写的代码将可能暴露给别人(apk和ipa都是简单的zip包装)。 quick-cocos2d-x框架为我们提供了一个可编...

lonewolf
2013/11/23
0
43

没有更多内容

加载失败,请刷新页面

加载更多

Nginx反向代理

Nginx反向代理 应用场景 A 机器运行的nginx提供的web服务,只有一个内网地址192.168.254.128(内网) B机器有两块网卡,一个地址是192.168.254.137(内网),另一个是192.168.79.128(外网)...

李超小牛子
今天
2
0
数据库事务隔离级别

当数据库上有多个事务同时执行的时候,可能出现下面问题: 脏读(dirty read):指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访...

Jacktanger
今天
1
0
4.61 - 第二个JAVA应用 4.62/63 - Tomcat的管理功能

4.61 - 第二个JAVA应用 方法一:配置文件: /usr/local/tomcat/conf/server.xml <Host name="www.aminglinux.cc" appBase="/data/wwwroot/www.aminglinux.cc" unpackWARs="tr......

Champin
今天
0
0
MariaDB密码重置

MariaDB密码重置 如果记得root的密码: mysqladmin -uroot -paminglinux password "aming-linux" //用此方式将原密码aminglinux重置为aming-linux 如果不记得原密码: # vi /etc/my.cnf......

wzb88
昨天
1
0
印度封禁抖音,称导致该国年轻人“文化堕落”!

本文经授权转载自顶级程序员 (ID:TopCoding) 作者 | 江户川雨 责编 | https://weavi.com/13775725 https://weavi.com/13775726 https://weavi.com/13775724 https://weavi.com/13775723 ......

陈刚生
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部