Cocos2d-x Lua中的AssetsManagerEx

Cocos2d-x Lua中的熱更機(jī)制主要是通過AssetsManagerEx來實(shí)現(xiàn)的亿驾。

傳統(tǒng)的熱更方式

傳統(tǒng)PC的方式是將差異文件打包成一個(gè)壓縮包亭敢,客戶端根據(jù)大版本差異该园,將對應(yīng)的壓縮包下載到本地后解壓覆蓋槽驶。這種做法的好處在于下載一個(gè)文件會(huì)比較快审洞。缺點(diǎn)在于當(dāng)客戶端版本比較多的時(shí)候呼畸,升級壓縮包會(huì)變得很多痕支,進(jìn)而難以維護(hù)。其次是如果壓縮包體積過大蛮原,解壓時(shí)間會(huì)比較長卧须,而且不容易制作進(jìn)度條,導(dǎo)致程序感覺被卡住了儒陨。

AssetsManagerEx采用比較所有文件是否一致的方式花嘶,首先需要將所有文件的md5散列表計(jì)算出來,然后生成對應(yīng)格式的manifest文件蹦漠。這種方式更類似網(wǎng)頁加載的方式椭员,即網(wǎng)頁顯示時(shí)若本地有緩存則比對緩存與服務(wù)器是否一致,若相同則使用本地緩存笛园,若不一直則下載更新隘击。這樣服務(wù)器只需要保存一個(gè)完整的最新客戶端。如果更新了某個(gè)文件研铆,只需要替換服務(wù)器上對應(yīng)的文件埋同,然后修改文件中的版本號和文件的md5散列碼。此種做法的優(yōu)點(diǎn)在于沒有解壓縮的過程蚜印,缺點(diǎn)是更新文件比較多的時(shí)候會(huì)略慢莺禁,而且有一定幾率的下載失敗。

熱更新基本原理

  • 不能更新主程序窄赋,只能更新資源和腳本文件
    C++生成的主程序只能通過升級安全包哟冬,其他文件可通過HTTP動(dòng)態(tài)下載到手機(jī)中楼熄,然后程序內(nèi)部重新執(zhí)行入口函數(shù),以達(dá)到更新代碼邏輯和資源圖片的效果浩峡,所以C++代碼在程序上線前必須保證最完善可岂。
  • 下載的文件會(huì)存放到手機(jī)的可寫入目錄中,該目錄中文件的優(yōu)先級必須高于程序原始安裝目錄翰灾。
    以HTTP方式下載后的文件并不能直接覆蓋安裝程序所在目錄中的同名文件缕粹,因?yàn)闄?quán)限不足。由于Lua使用動(dòng)態(tài)加載纸淮,只要在搜索路徑中將可寫入目錄的優(yōu)先級設(shè)置為最高平斩,那么即使兩個(gè)目錄中存在同名文件,程序也會(huì)優(yōu)先使用最新下載的文件咽块。AssetsManagerEx類的create()方法中會(huì)見用戶定義的可寫入目錄設(shè)置為最高優(yōu)先級绘面。
  • 資源文件和腳本文件被加載后,即使程序在運(yùn)行中文件也可以直接被刪除侈沪,以確保文件可以被動(dòng)態(tài)替換揭璃。
  • 手機(jī)本地和服務(wù)器中保存了程序中所有文件的md5散列碼列表,通過比對兩個(gè)文件中md5散列碼中亭罪,過濾出需要更新的文件瘦馍,并進(jìn)行下載。

熱更新的實(shí)現(xiàn)流程

  1. 開發(fā)可以遍歷項(xiàng)目中所有文件并生成對應(yīng)版本的version.manifestproject.manifest文件的工具

version.manifestproject.manifest的格式本質(zhì)上是一致的应役,version.manifest中只包含大版本號信息情组,而project.manifest包含version.manifest中所有內(nèi)容和所有項(xiàng)目文件信息,這樣做的好處在于當(dāng)項(xiàng)目文件很多的時(shí)候扛吞,project.manifest會(huì)比較大呻惕,所以單獨(dú)分割出來一個(gè)version.manifest來比較大版本,如果大版本不一致就不用下載project.manifest滥比。

對于項(xiàng)目src目錄下的cocos亚脆、framework等庫文件,如果確定不會(huì)修改就不用生成到project.manifest文件中盲泛,如果確實(shí)需要修改某個(gè)文件濒持,可以手動(dòng)加入到project.manifest文件中。建議不要修改寺滚,避免日后維護(hù)困難柑营。

/*version.manifest*/
{
  //服務(wù)器中存放完整最新版本程序的目錄位置,即項(xiàng)目的根目錄村视。
  "packageUrl":"http://192.168.0.164/update/files/",
  //服務(wù)器存放version.manifest文件的URL地址
  "remoteVersionUrl":"http://192.168.0.164/update/version/version.manifest",
  //服務(wù)器存放project.manifest文件的URL地址
  "remoteManifestUrl":"http://192.168.0.164/update/version/project.manifest",
  //程序版本號官套,采用 "大版本.日期.小版本" 格式
  "version":"1.20190112.01",
  //客戶端引擎版本
  "engineVersion":"Cocos2d-lua v3.3 Final"
}

/*project.manifest*/
{
  //服務(wù)器中存放完整最新版本程序的目錄位置,即項(xiàng)目的根目錄。
  "packageUrl":"http://192.168.0.164/update/files/",
  //服務(wù)器存放version.manifest文件的URL地址
  "remoteVersionUrl":"http://192.168.0.164/update/version/version.manifest",
  //服務(wù)器存放project.manifest文件的URL地址
  "remoteManifestUrl":"http://192.168.0.164/update/version/project.manifest",
  //程序版本號奶赔,采用 "大版本.日期.小版本" 格式
  "version":"1.20190112.01",
  //客戶端引擎版本
  "engineVersion":"Cocos2d-lua v3.3 Final",
  //資源文件
  "assets":{
    "res/images/test.png":{
      "md5":"e6aed0272011da3039ccc1008040cbce"
    },
    //資源文件為zip且compress為true表示惋嚎,更新完畢后進(jìn)行解壓。
    //由于zip文件是獨(dú)立打包計(jì)算md5站刑,日后的比較必須以zip包做比較另伍,實(shí)際維護(hù)起來比較麻煩,不建議使用绞旅。
    "res/zip/test.zip":{
      "md5":"e6aed0272011da3039ccc1008040cbce",
      "compressed":true
    }
  }
}
  1. project.manifest文件存放到主程序某個(gè)目錄(version)中并制作安裝包摆尝。
srv/version/project.manifest
  1. version.manifest存放到remoteVersionUrl對應(yīng)服務(wù)器指定目錄下
  2. project.manifest存放到remoteManifestUrl對應(yīng)服務(wù)器指定目錄下
  3. 將最新的代碼存放到packageUrl對應(yīng)服務(wù)器指定目錄下,注意要與assets下的路徑對應(yīng)因悲。
  4. 客戶端執(zhí)行更新代碼
-- 設(shè)置新文件保存路徑
local writablePath = cc.FileUtils:getInstance():getWritablePath()
local storagePath = writablePath.."version"
-- 創(chuàng)建資源管理器
local file = "src/version/project.manifest"
local assetsManagerEx = cc.AssetsManagerEx:create(file, storagePath)
assetsManagerEx:retain()
-- 監(jiān)聽下載消息
local function assetsManagerExHandler(event)
    local eventCode = event:getEventCode()
    local assetManagerExCode = cc.EventAssetsManagerEx.EventCode
    if eventCode == assetManagerExCode.ALREADY_UP_TO_DATE then
        print("當(dāng)前已是最新版本")
        -- 進(jìn)入游戲主界面
    end
    if eventCode == assetManagerExCode.NEW_VERSION_FOUND then
        print("發(fā)現(xiàn)新版本堕汞,開始升級...")
    end
    if eventCode == assetManagerExCode.PROGRESSION then
        print("當(dāng)前更新進(jìn)度為"..event.getPercent())
    end
    if eventCode == assetManagerExCode.UPDATE_FINISHED then
        print("更新完畢,準(zhǔn)備重啟...")
        app:run()
    end
    if eventCode == assetManagerExCode.ERROR_NO_LOCAL_MANIFEST then
        print("熱更失敾瘟铡:本地不存在manifest文件")
    end
    if eventCode == assetsManagerExCode.ERROR_DOWNLOAD_MANIFEST then
        print("熱更失斁世省:manifest文件下載失敗")
    end
    if eventCode == assetsManagerExCode.ERROR_PARSE_MANIFEST then
        print("熱更失敗:manifest文件解析失敗")
    end
    if eventCode == assetManagerExCode.ERROR_UPDATING then
        print("熱更失斝痢:文件更新失敗")
    end
end
local dispatcher = cc.Director:getInstance():getEventDispatcher()
local eventListenerAssetsManagerEx = cc.EventListenerAssetsManagerEx:create(assetsManagerEx, assetsManagerExHandler)
dispatcher:addEventListenerWithFixedPriority(eventListenerAssetsManagerEx, 1)
-- 檢查版本并升級
assetsManagerEx:update()

使用注意

  • storagePath路徑一旦確認(rèn)不能更換否則會(huì)造成多版本混亂
  • assetsManagerEx:retain()缺失會(huì)造成下載失敗
  • 如果文件是只讀的,會(huì)造成更新失敗绣否。
  • 客戶端獲取當(dāng)前本地版本
local localManifest = assetsManagerEx:getLocalManifest()
local version = localManifest:getVersion()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末誊涯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蒜撮,更是在濱河造成了極大的恐慌暴构,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件段磨,死亡現(xiàn)場離奇詭異取逾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)苹支,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門砾隅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人债蜜,你說我怎么就攤上這事晴埂。” “怎么了寻定?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵儒洛,是天一觀的道長。 經(jīng)常有香客問我狼速,道長琅锻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮恼蓬,結(jié)果婚禮上惊完,老公的妹妹穿的比我還像新娘。我一直安慰自己滚秩,他們只是感情好专执,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著郁油,像睡著了一般本股。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上桐腌,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天拄显,我揣著相機(jī)與錄音,去河邊找鬼案站。 笑死躬审,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蟆盐。 我是一名探鬼主播承边,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼石挂!你這毒婦竟也來了博助?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤痹愚,失蹤者是張志新(化名)和其女友劉穎富岳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拯腮,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡窖式,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了动壤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萝喘。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖狼电,靈堂內(nèi)的尸體忽然破棺而出蜒灰,到底是詐尸還是另有隱情,我是刑警寧澤肩碟,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布强窖,位于F島的核電站,受9級特大地震影響削祈,放射性物質(zhì)發(fā)生泄漏翅溺。R本人自食惡果不足惜脑漫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咙崎。 院中可真熱鬧优幸,春花似錦、人聲如沸褪猛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伊滋。三九已至碳却,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笑旺,已是汗流浹背昼浦。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筒主,地道東北人关噪。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像乌妙,于是被迫代替她去往敵國和親使兔。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容