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)