原文地址:http://www.cocoachina.com/bbs/read.php?tid=213061
3 Updater(C++)
AssetsManager 中提供了下载资源,访问更新列表,解压zip包,删除临时文件,设置搜索路径等等一系列的功能。但它的使用方式相当死板,我只能传递一个获取版本号的地址,一个zip包的地址,一个临时文件夹路径,然后就干等着。期间啥也干不了。
当然,我可以通过 quick 为其增加的 registerScriptHandler 方法让lua得知下载进度和网络状态等等。但下载进度的数字居然以事件名的方式通过字符串传过来的!这个就太匪夷所思了点。
于是,我对这个 AssetsManager 进行了修改。因为修改的东西实在太多,改完后就不好意思再叫这个名字了(其实主要是现在的名字比较短 XD)。我们只需要记住这个 Updater 是使用 AssetsManager 修改的即可。
在上面SunLightJuly和Henry同学的方法中,使用的是 CCHTTPRequest 来获取网络资源的。CCHTTPRequest 封装了cURL 操作。而在 Updater 中,是直接封装的 cURL 操作。
在我的设计中,逻辑应该尽量放在lua中,C++部分只提供功能供lua调用。因为lua可以进行热更新,而C++部分则只能整包更新。
Updater 主要实现的内容如下:
3.1 删除了不需要的方法
get和set相关的一堆方法都被删除了。new对象的时候也不必传递参数了。
3.2 增加 getUpdateInfo 方法
这个方法通过HTTP协议获取升级列表数据,获取到的数据直接返回,C++并不做处理。
3.3 修改 update 方法
这个方法通过HTTP协议下载升级包,需要提供四个参数:
- zip文件的url;
- zip文件的保存位置;
- zip 文件的解压临时目录;
- 解压之前是否需要清空临时目录。
3.4 修改事件类型
我把把传递给lua的事件分成了四种类型:
3.4.1 UPDATER_MESSAGE_UPDATE_SUCCEED
事件名为 success,代表更新成功,zip文件下载并解压完毕;
3.4.2 UPDATER_MESSAGE_STATE
事件名为 state,更新过程中的状态(下载开始、结束,解压开始、结束)也传递给了lua。这个方法是这样实现的:
复制代码
- void Updater::Helper::handlerState(Message *msg)
- {
- StateMessage* stateMsg = (StateMessage*)msg->obj;
- if(stateMsg->manager->_delegate)
- {
- stateMsg->manager->_delegate->onState(stateMsg->code);
- }
- if (stateMsg->manager->_scriptHandler)
- {
- std::string stateMessage;
- switch ((StateCode)stateMsg->code)
- {
- case kDownStart:
- stateMessage = "downloadStart";
- break;
-
- case kDownDone:
- stateMessage = "downloadDone";
- break;
-
- case kUncompressStart:
- stateMessage = "uncompressStart";
- break;
- case kUncompressDone:
- stateMessage = "uncompressDone";
- break;
-
- default:
- stateMessage = "stateUnknown";
- }
-
- CCScriptEngineManager::sharedManager()
- ->getScriptEngine()
- ->executeEvent(
- stateMsg->manager->_scriptHandler,
- "state",
- CCString::create(stateMessage.c_str()),
- "CCString");
- }
-
- delete ((StateMessage*)msg->obj);
- }
|
3.4.3 UPDATER_MESSAGE_PROGRESS
事件名为 progress,传递的对象为一个 CCInteger ,代表进度。详细的实现可以看
源码
。
3.4.4 UPDATER_MESSAGE_ERROR
事件名为 error,传递的对象是一个 CCString,值有这样几个:
- errorCreateFile
- errorNetwork
- errorNoNewVersion
- errorUncompress
- errorUnknown
方法的实现和上面的 UPDATER_MESSAGE_STATE 类似,这里就不贴了。详细的实现可以看
源码
。
Updater(C++) 部分只做了这些苦力工作,而具体的分析逻辑(分析getUserInfo返回的数据决定是否升级、如何升级和升级什么),下载命令的发出(调用update方法),解压成功之后的操作(比如合并新文件到就文件中,更新文件索引列表等等),全部需要lua来做。下面是一个处理Updater(C++)事件的lua函数的例子。
复制代码
- function us._updateHandler(event, value)
- updater.state = event
- if event == "success" then
- updater.stateValue = value:getCString()
- -- 成功之后更新资源列表,合并新资源
- updater.updateFinalResInfo()
- -- 调用成功后的处理函数
- if us._succHandler then
- us._succHandler()
- end
- elseif event == "error" then
- updater.stateValue = value:getCString()
- elseif event == "progress" then
- updater.stateValue = tostring(value:getValue())
- elseif event == "state" then
- updater.stateValue = value:getCString()
- end
- -- us._label 是一个CCLabelTTF,用来显示进度和状态
- us._label:setString(updater.stateValue)
- assert(event ~= "error",
- string.format("Update error: %s !", updater.stateValue))
- end
-
- updater:registerScriptHandler(us._updateHandler)
|