1. 程式人生 > >ios lua 增量更新,更新內部程式碼

ios lua 增量更新,更新內部程式碼


基於Cocos2d-x+Lua的技術架構的遊戲的更新,只更新指令碼即可。Lua中可以實現對於C++類的繼承,更新邏輯還是比較容易的。
App有兩個路子:一個是基於PhoneGap或者React Native的混合開發(天貓好像已經遷移到了React Native上);一種是使用JSPatch來為程式打補丁。不過就功能來看,還是React Native要強大一點,畢竟定位不一樣。 那遊戲是怎這麼做的,通過Lua或者js。下載下來的是指令碼,只是文字檔案,那當然可以更新。

比較有名的專案有Wax和JSPatch,就是做了這麼一個事情。

參考地址:

知乎討論熱更新帖

http://www.zhihu.com/question/28079874

基於Quick-cocos2dx 2.2.3 的動態更新實現完整篇。(打包,伺服器介面,模組自更新)

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

1,如何設計更新伺服器介面。 2,不改變原框架的程式碼的情況下如何實現更新,並且可以實現精確的進度。 3,如何按照版本打包。 4,如何跨n個小版本更新。 5,版本回滾。 6,如何更新你的自動更新模組和framework_precomplied.zip程式碼。

先直接上程式碼UpdateScene.lua:

程式碼位置為:你的遊戲目錄/update/UpdateScene.lua

require("config")
require("framework.init")
require("framework.shortcodes")
require("framework.cc.init")


local UpdateScene  = class("UpdateScene", function()
    return display.newScene("UpdateScene")
end)


local NEEDUPDATE   = true
local server       = "http://伺服器ip:3001/"
local versionFile  = "version/?fileVersion="
local allFileList  = "version/?id="
local nowVersion   = CCUserDefault:sharedUserDefault():getStringForKey("current-version-code")
local bigVersion   = CCUserDefault:sharedUserDefault():getStringForKey("VERSION_BIG")


function UpdateScene:ctor(  )
    display.newSprite("kfs_background.png", display.cx, display.cy):addTo(self)
 self.path = device.writablePath.."kdfs/"
 
    self:createDownPath(self.path)
    self:createDownPath(self.path.."res/")
    self:createDownPath(self.path.."scripts/")


    if string.len(nowVersion) == 0 then
        nowVersion = bigVersion..".0"
    end
    local list      = string.split(nowVersion,".")
    self.nowId      = tonumber(list[3])
    self.versionBig = list[1].."."..list[2]


    --大版本變化了
    if self.versionBig ~= bigVersion then 
        self:delAllFilesInDirectory(self.path)
    end
        
    NEEDUPDATE          = CCUserDefault:sharedUserDefault():getBoolForKey("CanUpdate")
    --NEEDUPDATE          = true
    
    self.updateProgress = self:newProgressTimer( "kfs_jindutiaobox.png","kfs_jindutiao.png" ):pos(display.cx,120):addTo(self)
    self.progressLabel  = ui.newTTFLabel({text = "更新", size = 26, align = ui.TEXT_ALIGN_CENTER, color = display.COLOR_BLACK}):pos(display.cx,160):addTo(self) 
end


function UpdateScene:downIndexedVersion(  )
    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 = AssetsManager:new(packageUrl,versionUrl,self.path)  --資源包路徑,程式碼號路徑,儲存路徑
        self.assetsManager:registerScriptHandler(handler(self, self.downHandler))
    else
        self.assetsManager:setVersionFileUrl(versionUrl)
        self.assetsManager:setPackageUrl(packageUrl)
    end


    if self.assetsManager:checkUpdate() then
        self.assetsManager:update()
    end
end


function UpdateScene:getNewestVersion(  )
    self.progressLabel:setString("正在獲取版本列表")


    if not NEEDUPDATE then
        print("當前版本為DEBUG版本,不需要更新!")
        self.progressLabel:setString("當前版本為DEBUG版本,不需要更新")
        self:performWithDelay(function (  )
            self:noUpdateStart()
        end,2)
        return
    end


    function callback(event)
        local ok = (event.name == "completed")
        local request = event.request
        if event.name then print("request event.name = " .. event.name) end
        if not ok then
            print("請求失敗 "..request:getErrorMessage())
            self.progressLabel:setString("版本更新列表請求網路出錯")
            self:performWithDelay(function (  )
                self:noUpdateStart()
            end,2)
            return
        end
        local code = request:getResponseStatusCode()
        if code ~= 200 then
            print("請求錯誤,程式碼 "..request:getResponseStatusCode())
            self.progressLabel:setString("版本更新列表請求網路出錯"..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
                self.needDownVersions = needDownVersions.list
                for i,v in ipairs(self.needDownVersions) do
                    if v.needRestart > 0 then
                        self.needRestart = true
                    end
                end
                if #self.needDownVersions > 0 then
                    self:downIndexedVersion()
                end
            else
                self.progressLabel:setString("當前版本已經是最新版本")
                self.updateProgress.progressTimer:setPercentage(100)
                self:performWithDelay(function (  )
                    self:noUpdateStart()
                end,2)
            end
        end
    end
     
    local request = network.createHTTPRequest(callback, server..allFileList..self.nowId.."&versionBig="..self.versionBig, "GET")
    request:setTimeout(10)
    request:start()
end


function UpdateScene:onEnter(  )
    self:getNewestVersion()
end


function UpdateScene:afterUpdateStart(  )
    if self.needRestart then
        print("提示需要重新啟動遊戲")
        require("game")
        game.exit()
        return
    end
    print("更新成功,啟動遊戲")
    package.loaded["config"] = nil
    CCLuaLoadChunksFromZIP("game.zip")
    require("game")
    game.startup()
end


function UpdateScene:noUpdateStart(  )
    print("沒有更新或者更新失敗啟動遊戲")
    require("game")
    CCLuaLoadChunksFromZIP("game.zip")
    game.startup()
end


function UpdateScene:downHandler( event )
    if event == "success" then 
        if self.nowDownIndex < #self.needDownVersions then 
            self.nowDownIndex = self.nowDownIndex +1
            self:downIndexedVersion()
        else
            self.progressLabel:setString("更新成功")
            self:performWithDelay(function (  )
                self:afterUpdateStart()
            end,2)
        end
    elseif string.startWith(event,"error") then
        local text = ""
        if event == "errorNetwork" then text = "網路出錯!" end
        if event == "errorNoNewVersion" then self.updateProgress.progressTimer:setPercentage(100) text = "已是最新" end
        if event == "errorUncompress" then text = "解壓出錯" end
        if event == "errorUnknown" then text = "未知錯誤" end
        self.progressLabel:setString(text)
        self:performWithDelay(function (  )
            self:noUpdateStart()
        end,2)
    else
        local alreadyDownPercent = (self.nowDownIndex - 1)*100/(#self.needDownVersions )
        print("alreadyDownPercent:",alreadyDownPercent)
        alreadyDownPercent = alreadyDownPercent + event/(#self.needDownVersions )
        alreadyDownPercent = math.floor(alreadyDownPercent)
        self.progressLabel:setString("已更新"..alreadyDownPercent.."%")
        self.updateProgress.progressTimer:setPercentage(alreadyDownPercent)
        self:progressTimerAction(self.updateProgress.progressTimer,self.updateProgress.progressTimer:getPercentage(),alreadyDownPercent)
    end
end


function UpdateScene: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


function UpdateScene:newProgressTimer( bgBarImg,progressBarImg ) 
    local bg = display.newSprite(bgBarImg)
    local progressTimer = CCProgressTimer:create(display.newSprite(progressBarImg))
    bg.progressTimer = progressTimer
    progressTimer:setType(kCCProgressTimerTypeBar) 
    progressTimer:setPercentage(0) 
    progressTimer:setMidpoint(ccp(0,0)) 
    progressTimer:setBarChangeRate(ccp(1, 0)) 
    progressTimer:setPosition(ccp(bg:getContentSize().width/2,bg:getContentSize().height/2)) 
    bg:addChild(progressTimer, 140)
    return bg
end


function UpdateScene:progressTimerAction( progressTimer,fromPercentage,toPercentage,duration )
    if not duration then duration = 0.3 end
    local ac = CCProgressFromTo:create(duration,fromPercentage,toPercentage)
    progressTimer:runAction(ac)
end


function UpdateScene: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


return UpdateScene
程式碼解釋:

NeedUpdate 這個變數代表自動更新開關,平常咱們在debug模式下等等時候,不需要這個這個功能,可以把它關掉。

server,versionFile,allFileList 這3個變數組成你增量更新所需要的2個伺服器介面。

server..versionFile 接受一個版本號作引數,返回的也是這個版本號,具體原因參見程式碼,主要是為了配合AssetsManager的引數需求。

server..allFileList 接受一個當前的版本的小版本號。比如全版本是 1.0.1 的話,那小版本就是1。同理 1.0.5的話,小版本id就是5。

server..allFileList?id=0&bigversion=1.0 則返回以下格式介面:

{"code":200,"list":[{"id":1,"fileUrl":"http://伺服器地址/vf/kdfs1.0.1.zip","version":"1.0","needRestart":0}]}
介面中有一個很重要的變數 needRestart 表示本次更新是否有需要重新啟動遊戲載入的更新包。具體原因見後文。 

其它程式碼不一一贅述。

以上就是伺服器介面設計篇。

接下來講講更新自更新模組和打包。

簡單講講實現方法。

前文的UpdateScene編譯成zip,然後和 framework_precompiled.zip 一起在放到res目錄下,遊戲啟動的時候別加載這兩個檔案。main.lua為如下程式碼:

function __G__TRACKBACK__(errorMessage)
    print("----------------------------------------")
    print("LUA ERROR: " .. tostring(errorMessage) .. "\n")
    print(debug.traceback("", 2))
    print("----------------------------------------")
end

local writablePath = CCFileUtils:sharedFileUtils():getWritablePath()

CCFileUtils:sharedFileUtils():addSearchPath(writablePath.."kdfs/".."res/")
CCFileUtils:sharedFileUtils():addSearchPath(writablePath.."kdfs/".."scripts/")
CCFileUtils:sharedFileUtils():addSearchPath("res/")
CCFileUtils:sharedFileUtils():addSearchPath("scripts/")

CCLuaLoadChunksFromZIP("framework_precompiled.zip")
CCLuaLoadChunksFromZIP("update.zip")

xpcall(function()
	CCDirector:sharedDirector():runWithScene(require("UpdateScene").new())
end, __G__TRACKBACK__)

並且在你的遊戲程式碼裡排除掉 UpdateScene.lua 。目的是為了保證遊戲啟動的時候載入的就是唯一的一份UpdateScene程式碼。

sh quick的目錄/bin/compile_scripts.sh -i 遊戲的目錄/update -o update.zip

我沒有把UpdateScene.lua 放到 scripts目錄下,而是有個單獨的目錄update。這樣的話可以單獨把這個目錄打包,然後啟動遊戲的時候載入。

可以參考下面的指令碼完整實現以下功能:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #!/bin/sh DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" APP_ROOT="遊戲目錄啦" echo "$DIR" echo "$APP_ROOT"

相關推薦

ios lua 增量更新更新內部程式碼

基於Cocos2d-x+Lua的技術架構的遊戲的更新,只更新指令碼即可。Lua中可以實現對於C++類的繼承,更新邏輯還是比較容易的。 App有兩個路子:一個是基於PhoneGap或者React Native的混合開發(天貓好像已經遷移到了React Nati

Can you answer these queries?(線段樹區間更新更新到點)

題目 連結:傳送門 A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapon to

mybatis實現批量更新更新的欄位也是動態的

把需要更新的引數封裝成一個物件list,需要注意list.add的是物件的引用!別重複使用一個物件封裝,要在for裡new物件封裝 然後把這個list傳到mapper.xml裡面用就行了; mapper.java片段程式碼: /** * 批量調整庫存

Ios更新實時程式碼更新動態更新動態庫framework

動態更新,iOS有三種處理方案 1,開源框架reactive native,但是程式語言是js iOS app可以在執行時從伺服器拉去最新的js檔案到本讀,然後執行,因為js是一門動態的指令碼語言 所以可以在執行時直接讀取js檔案執行,也因此能夠實現iOS的熱更新

iOS更新實時程式碼更新動態更新動態庫framework

  允許轉載! demo 下載   只要稽核通過後,無須再次稽核,就可以動態更新,iOS有三種處理方案:    一、開源框架 reactive native,但是程式語言是js   二、lua 指令碼   三、使用oc語言的動態庫framewo

WebStorm2017中專案更新智慧程式碼提示不顯示的解決方法

出現這個問題的時候,我百度了網上各種解決方法,都沒有用,後來就莫名其妙的好了。寫一個部落格記錄一下,以後再遇到同樣的問題的時候,給自己提供一個解決方法,雖然不能確保是不是有效,但多一種方法也沒有任何問題。對解決方法進行了一個總結,總結如下: 1.File-Power Save Mode,檢視該

有關IOS開發寫的好的部落格和網站(持續更新含盲點)

1. Swift中的trim方法處理字串:http://www.hangge.com/blog/cache/detail_1649.html 2. Swift語言中的@available和#available https://blog.csdn.net/offbye/article/deta

利用svn鉤子hooks/post-commit實現程式碼更新自動執行指令碼

1. 在svn伺服器對應的專案中會存在以下幾個目錄和檔案 conf  db  format  hooks  locks  README.txt 其中目錄hooks是放置程式碼提交執行的檔案 進入 hooks目錄新建一個 post-comm

elasticsearch 索引更新增量更新不停機修改升級 ,簡單使用

elasticsearch 使用 對es瞭解的並不是太多,記錄簡單使用場景。若哪裡不對,還請大人指出 舉例: 根據商品名稱搜尋商品 建立索引 product_v1 為什麼要帶v1呢,後面方便升級 #新增索引 put product_v1?pretty #檢視一下 get _cat

eclipse中使用svn提交更新程式碼

在新公司工作,版本管理工具變成了svn,之前一直用git作為版本管理,用的編輯IDE是IntelliJIDEA,在這個編輯器下工作,還是很方便的,但是現在使用eclipse和svn。有點不習慣,但還是將他們記下來。 這篇文章介紹的是在eclipse上使用svn 首先在提交程式碼的時候,會看到有的檔案前會有

Qt子執行緒如何更新UI完整的程式碼示例有圖有真相

      Qt涉及到大量的資料更新,影象處理,視訊編解碼時,在主執行緒直接進行會讓主執行緒阻塞,程式直接卡死,直達阻塞的部分完成,介面才更新,例如,我們需要在TextBrowser上迴圈顯示資料。        我需要點選【新增新行資料】,然後每隔1秒迴圈顯示資料,之

手淘版小程式“輕店鋪”開始內測;微信釋出iOS更新進一步優化訂閱號列表的閱讀體驗;百度智慧小程式月活破億

本週行業快訊 手淘版小程式“輕店鋪”開始內測  淘寶小程式終於開始內測,不過它不叫小程式,而叫“輕店鋪”。輕店鋪是一個支援個人或者企業進行開店的工具,具有群聊、發文章、門店導航等功能。目前輕店鋪支援個人和企業入駐,要求賬號完成實名認證。因仍處於內測階段,開發者

ios 企業證書明明已更新我的手機可以下載其他使用者都下載不了填坑

前言:企業 $299的賬號遇到的問題。事情的經過是這樣的~ 上週五的晚上,同事在微信群裡說我們的app下載不了了,他們都試過了都是一團黑乎乎的在那,一直不動呢。what~!!額~怎麼可能上個星期還可以下載的呀,而且證書早就更新過了,怎麼會呢!於是我自己手機掃描下

(一)solr 7.31版本window系統全程安裝搭建涵蓋專案用到的大部分配置常用查詢solr多條件查詢、排序配置資料庫定時同步全量與增量更新使用solrJ在java程式進行增刪改查

前言:由於專案最近在做淘寶客商品資訊查詢這一塊,做搜尋引擎,離不開全文搜尋伺服器,我這裡選擇了solr。solr的好處可以自行百科,這裡主要是講解技術。這篇文章主要講解window的安裝和使用。若大家感興趣或者專案用到,希望你能跟著我的步驟進行下去,如果遇到問題,可以後續看下我在最底下的問題

STM32 IAP韌體更新bootloader起始地址偏移後程式碼中還需設定中斷向量的偏移。

在 stm32f10x_flash.icf 中設定ROM的起始結束地址 /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x08004000; /*-Memory Regions-*/ define symbo

git 常用命令上傳下載更新線上程式碼

git 常用命令以及推薦git新建上傳個人部落格 $ git clone  //本地如果無遠端程式碼,先做這步,不然就忽略 $ git status //檢視本地自己修改了多少檔案 $ git add . //新增遠端不存在的git檔案 $ git commit  -m

C++輕量級文法分析器更新程式碼+DEMO×3(下載)

最新問題! 問題在於這條產生式: statement : block | sentence | ifstmt | whilestmt | forstmt; 當加入了ifstmt,whilestmt,

Apple釋出iOS 6.0.2更新修復Wi-Fi問題

Apple已經發布了iOS補丁,更新iPhone 5和iPad mini裝置的iOS版本到6.0.2。 發行說明只提及修復一個Wi-Fid的Bug。 iPhone 5使用者已經已經對Wi-Fi連線問題吐糟已久,估計很多使用者已經等這個更新等得脖子都長了。Apple在11月1日釋出的iOS 6.0.

軟體內部更新出現“解析包時出現問題”的錯誤後停止

       問題場景是:軟體從1.2.4升級到1.3.0的過程中出現瞭如題的問題即下載後安裝時出現“解析包時出現問題”的錯誤後停止。而且不是所有的手機都會出現這個問題,在華為2.2系統的測試機上是可以成功安裝的,而用魅族2X就不行。        首先我懷疑下載的ap

iOS 規避蘋果審查實現app store上的app版本強制更新

要想規避蘋果審查,我們需要通過呼叫資料介面來控制呼叫app 版本強制更新功能:當蘋果在審查的時候,我們可以通過後臺數據控制關閉版本強制更新功能,等蘋果稽核通過以後我通過後臺控制開啟版本強制更新功能。下面是app 版本強制更新功能實現的程式碼:AppDelegate.h檔案 #