您的位置:首页 > 移动开发 > Cocos引擎

quick-cocos2d 之动态更新

2015-06-01 20:09 651 查看
quick-cocos2d之动态更新
 

1.创建一个UpdateScene.lua 作为你的更新模块。

require("config")
require("framework.init")
require("datastore")
require("framework.cc.init")
 
local
UpdateScene
=class("UpdateScene",

      
function()

          
returndisplay.newScene(UpdateScene)

      
end)

 
local server ="http://192.168.3.2/" --192.168.3.2
local versionFile 
= "version/version"

local allFileList 
= "version/V"

local nowVersion  
= nil -- 当前版本号

local bigVersion  
= nil -- 服务器最大的版本号

 
function UpdateScene:ctor()
   
DataStore:init()

   
self.mIsHandover = false -- 控制
noUpdateStart只回调一次
   
self.needRestart = false -- 是否需要重启

   
self.needDownload = false -- 是否需要下载

 
self.path =device.writablePath
self:createDownPath(self.path)
self:createDownPath(self.path.."res/")
self:createDownPath(self.path.."src/")
 
--把当前的版本号从本地取出来
nowVersion =self:getVersion("nowVersion")
ifnowVersion == nil or nowVersion == "" then
nowVersion = Config.gameVersion
end
 
   
self.progressLabel = display.newTTFLabel({

   
text = "您好,世界",

   
font = "Arial",

   
size = 35,

   
color = cc.c3b(255, 0, 0), -- 使用纯红色

   
align = cc.TEXT_ALIGNMENT_LEFT,

   
valign = cc.VERTICAL_TEXT_ALIGNMENT_CENTER,

    dimensions = cc.size(400, 200)
   
}):pos(display.cx,display.cy):addTo(self)

   
self.progressLabel:setString("更新.....")

end
 
--根据服务器取出来的版本文件加载要更新的资源
functionUpdateScene:downIndexedVersion()
   
if self.needDownload then --需要重新下载apk

      
--apk 下载 链接

      
return    

   
end

 
   
if not self.nowDownIndex then

      
self.nowDownIndex = 1

   
end

   
   
local versionUrl =server..versionFile..self.needDownVersions[self.nowDownIndex].version..

   
"."..self.needDownVersions[self.nowDownIndex].id

 
   
local packageUrl =self.needDownVersions[self.nowDownIndex].fileUrl

 
   
if self.nowDownIndex == 1 then

self.assetsManager =cc.AssetsManager:new(packageUrl,versionUrl,self.path) 
--资源包路径,版本号路径,下载好的资源存储路径

      
self.assetsManager:setDelegate(handler(self,self.onSuccess), cc.ASSETSMANAGER_PROTOCOL_SUCCESS )—设置加载完成的回调函数

      
self.assetsManager:setDelegate(handler(self, self.onProgress),cc.ASSETSMANAGER_PROTOCOL_PROGRESS ) —设置加载进度的回调函数

      
self.assetsManager:setDelegate(handler(self,self.onError), cc.ASSETSMANAGER_PROTOCOL_ERROR ) —设置加载出现错误的回调函数

      
self.assetsManager:retain()

   
else

      
self.assetsManager:setVersionFileUrl(versionUrl)

       
self.assetsManager:setPackageUrl(packageUrl)

   
end

 
   
if self.assetsManager:checkUpdate() then

        
      
self.assetsManager:update()

   
end

end
 
--从服务器获取最新版本号
functionUpdateScene:getNewestVersion()
   
function callback(event)

      
local ok = (event.name == "completed")

      
local request = event.request

      
if event.name then

          
self.progressLabel1:setString("requestevent.name = " .. event.name)

          
print("request event.name = " ..event.name) 

      
end

      
if not ok then

          
self.progressLabel1:setString("请求失败"..request:getErrorMessage())

          
print("请求失败"..request:getErrorMessage())

          
--self:pro

          
self:performWithDelay(

          
function ()

               self:noUpdateStart()
          
end,2)

          
return

      
end

      
local code = request:getResponseStatusCode()

      
if code ~= 200 then

          
print("请求错误,代码"..request:getResponseStatusCode())

          
self:performWithDelay(

          
function ()

              
self:noUpdateStart()

          
end,2)

          
return

      
end

      
if json.decode(request:getResponseString())   then

          
print(request:getResponseString())

           
local needDownVersions =json.decode(request:getResponseString())

          
if needDownVersions.code == 200 then

             
if needDownVersions.needRestart > 0 then

                 
self.needRestart = true 

                   
end

              
ifneedDownVersions.needDownload > 0 then

                 
self.needDownload = true

             
end 

             
self.needDownVersions =needDownVersions.list

 
             
--版本号判断 是否已经是最新的

             
if needDownVersions.bigVersion == nowVersionthen

                 
self.progressLabel:setString("已经是-----最新的版本")

                 
self:performWithDelay(

                    
function ()

                        
self:noUpdateStart()

                    
end,1)

                 
return    

             
end

             
--版本号更换,并存储到本地

             
nowVersion = needDownVersions.bigVersion

             
self:setVersion("nowVersion",nowVersion,true)

             
if #self.needDownVersions > 0 then

                 
self:downIndexedVersion()

             
end

          
else

             
self.progressLabel:setString("当前版本已经是最新版本")

               
self:performWithDelay(

                 
function ()

                    
self:noUpdateStart()

                 
end,2)

          
end

      
end

   
end

   
--请求得到最新的版本号数据  回调函数callback

   
local request = network.createHTTPRequest(callback,server..allFileList, "GET")

   
request:setTimeout(10)

   
request:start()

end
--进入场景后开始更新判断
function UpdateScene:onEnter()
   
self:getNewestVersion()

end
--更新成功之后,启动游戏
function UpdateScene:afterUpdateStart()
   
if self.needRestart then

      
print("提示需要重新启动游戏")

       
local game = require("game")

          
game.exit();

       
return

   
end

   
Config.gameVersion = nowVersion

   
self.progressLabel:setString("
更新成功,启动游戏
")

   
local game = require("game")

   
game.startup();

end
--不有更新(或者没有成功)直接开始
functionUpdateScene:noUpdateStart()
   
if self.mIsHandover == true then

      
return

   
end

   
self.mIsHandover = true

   
Config.gameVersion = nowVersion

   
self.progressLabel:setString("没有更新或者更新失败启动游戏")

   
local game = require("game")

   
game.startup();

end
--更新错误回调
functionUpdateScene:onError(errorCode)
   
if errorCode == cc.ASSETSMANAGER_NETWORK then

      
text = "网络出错!"

   
end

   
if errorCode == cc.ASSETSMANAGER_NO_NEW_VERSION then

      
text = "没有新版本"

   
end

   
if errorCode == cc.ASSETSMANAGER_UNCOMPRESS then

      
text = "解压出错"

   
end

   
if errorCode == cc.ASSETSMANAGER_CREATE_FILE then

      
text = "未知错误"

   
end

   
print("text:",text)

   
self:performWithDelay(function ()

self:noUpdateStart()
end
 
--更新进度回调
function UpdateScene:onProgress( percent)
--
显示下载进度

localprogress = string.format("downloading %d%%",percent)
print("progress:",progress)
end
 
--
更新完成回调

function UpdateScene:onSuccess()
   
--每次更新可能有多个zip包,做下处理

   
if self.nowDownIndex < #self.needDownVersions then

       
self.nowDownIndex = self.nowDownIndex +1

       
self:downIndexedVersion()

   
else

       
-- "更新成功"

       
self:performWithDelay(function ()

           
self:afterUpdateStart()

       
end,2)

   
end

end
 
functionUpdateScene:createDownPath( path )
   
if not self:checkDirOK(path) then

       
print("更新目录创建失败,直接开始游戏")

       
self:noUpdateStart()

       
return

   
else

       
-- print("更新目录存在或创建成功")

   
end

end
--改变目录
function UpdateScene:checkDirOK(path )
   
require "lfs"

   
local oldpath = lfs.currentdir()

   
if lfs.chdir(path) then

       
lfs.chdir(oldpath)

       
return true

   
end

   
if lfs.mkdir(path) then

       
return true

   
end

end
--
 
--删除目录中所有文件
functionUpdateScene:delAllFilesInDirectory( path )
   
for file in lfs.dir(path) do

     
if file ~= "." and file ~= ".."then

         
local f = path..'/'..file

         
local attr = lfs.attributes (f)

         
assert (type(attr) == "table")

         
if attr.mode == "directory" then

             
self:delAllFilesInDirectory(f)

         
else

             
os.remove(f)

         
end

     
end

   
end

end
 
string.startWith =function(str,strStart)
   
local a,_ = string.find(str,strStart)

   
return a==1

end
 
string.split = function(s, p)
   
local rt= {}

   
string.gsub(s, '[^'..p..']+', function(w)table.insert(rt, w) end )

   
return rt

end
--版本号的本地存储
functionUpdateScene:setVersion(__key,__value,__isSave)
   
DataStore:setData(__key,__value,__isSave)

end
 
functionUpdateScene:getVersion(__key)
   
return DataStore:getData( __key )

end
 
return UpdateScene

 

main.lua
local writablePath =cc.FileUtils:getInstance():getWritablePath().."assets/"
cc.FileUtils:getInstance():addSearchPath(writablePath.."res/")
cc.FileUtils:getInstance():addSearchPath("res/")
cc.FileUtils:getInstance():addSearchPath(writablePath.."res/sound")
cc.FileUtils:getInstance():addSearchPath("res/sound")
cc.FileUtils:getInstance():addSearchPath(writablePath.."src/")
cc.FileUtils:getInstance():addSearchPath("src/")
local function main()
  package.path =package.path .. ";src/"
 cc.FileUtils:getInstance():setPopupNotify(false)
  cc.Director:getInstance():runWithScene(require("update.updatescene").new())
end
xpcall(main, __G__TRACKBACK__)
 

配置文件:

1. 如network.createHTTPRequest()中的第二个参数文件内容大致为(可根据需要自己配)

{"code":200,"bigVersion":"1.0.01","needRestart":0,"needDownload":0,

"list":[

{"fileUrl":"http://192.168.3.2/version/res.zip","version":"1.0","id":1},

{"fileUrl":"http://192.168.3.2/version/src.zip","version":"1.0","id":2}

]}

2.如AssetsManager:new(constchar*packageUrl,constchar*versionFileUrl,constchar*storagePath)

中的参数2versionFileUrl版本号文件,也就是在文件里面写一个版本号,例如:1.0.01

 

更新的大致流程:

1.  获取当前本地存储的版本号

2.  请求更新版本的数据,并以最新版本号与当前本地存储的版本号做比较

3.  版本不一致时,就利用[b]AssetsManager进行资源更新。否则退出让玩家开始游戏[/b]

 

AssetsManager的基本流程:

1.  配置需要更新的zip的URL,更新版本号的URL,更新存放的相对路径

2.  从Server获取该zip文件的版本号

3.  对比Client中的UserDefault.xml中current-version-code键的值(当前版本号)是否过期

4.  若Server的版本比Client的新,则通过http请求下载该zip

5.  解压缩该zip文件

6.  下载后通过CCFileUtils的fullPathForFilename方法来获取文件的引用

 

AssetsManager内部函数:

1.  构造函数

AssetsManager::AssetsManager(constchar*packageUrl,constchar*versionFileUrl,constchar*storagePath)

_packageUrl(packageUrl)//下载.zip文件地址

_versionFileUrl(versionFileUrl)//版本核查地址 v1.0

_storagePath(storagePath)//.zip下载后存储位置

2.  checkStoragePath
由1调用
检查_storagePath 存储地址不能为""并且不是以"/"结尾的,在结尾处加上"/"
3.getVersionCodelibcurl绑定的下载字符串回调函数通过checkUpdate里调用
把下载的字符串放到传过来的字符串指针里
4.checkUpdate
通过网络检查当前的版本是不是最新版本。如果是设置优先搜索资源路径setSearchPath
5.update
(1)下载地址、版本核查的网址都不能为null,存储的文件名以"。zip"后缀
(2)checkUpdate调用,是最新版本了返回,不是执行下面
(3)通过xml文件判断是不是下载完成了没有解压,是,解压,不是,调用,downLoad下载
(4)下载完成uncompress解压
(5)设置资源搜索优先级setSearchPath
(6)删除.zip源文件
6.createDirectory
创建目录
7.downLoad
执行下载资源,建立了指向本地资源的指针
 
关于详细讲解AssetsManager和动态更新的网站链接:

1.  http://blog.sina.com.cn/s/blog_923fdd9b0101edmv.html

2.  http://blog.csdn.net/renzhe20092584/article/details/9184163

3.  http://my.oschina.net/u/1785418/blog/283043

4.  http://zengrong.net/post/2131.htm

 

 

出现的问题:

1.  有可能出现AssetsManager这个文件为nil的情况。那是因为他与CURL 库提供 HTTP 网络功能有关联。CURL关闭后,assetsmanager等相关功能也会被去掉。

解决:在打包时应该在android工程下的jni\Application.mk中

把 CC_USE_CURL := 1修改为1 ,设置为开启状态 ,0为关闭状态

ifeq ($(CC_USE_CURL),1)

APP_CPPFLAGS += -DCC_USE_CURL=1

 

以上是参考西门大官人的:基于Quick-cocos2dx 2.2.3 的动态更新实现完整篇。(打包,服务器接口,模块自更新)所写的 

链接:http://my.oschina.net/u/1785418/blog/283043

 

 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: