cocos2d-lua 3.15.1 热更新

我用的是 AssetsManagerEx 去做更新。
在iOS上面可以更新到,但是Android更新不到。两者是用同一套lua语言去实现。

  1. 现在是不是要区分 64位跟32位的luac, 我是不是可以用 compilelua 这个命令去统一打包
    2.getWritablePath() 去做下载时候,是不是没有权限去写入,在Android上面。由于我对Android不熟悉,不知道是不是没有下载到 data/data 里面,或者我根本就没有查对下载的文件路径。

有了帮助下我吗?我对cocos2d不熟悉,对Android也不熟悉

ROOT后查看是否有下载

哦,Android需要ROOT才能看到文件是吧。谢谢了。

3.15.1 下载的权限都有吧。我在网上也看到有人说权限不够

猜测应该是路径问题,上代码吧,无代码无真相

local UpdateScene = class("UpdateScene",cc.load("mvc").ViewBase)
local downDir = cc.FileUtils:getInstance():getWritablePath()
local s = cc.Director:getInstance():getWinSize()
VERSION = "1.0.0"
--REMARK
--这是热更新场景。res下文件project.manifest前3行为需要更新的assets文件的http地址。cc.AssetsManagerEx会自动读取这个地址,对比版本和MD5值去下载。
--详情可去了解cocos2dx的AssetsManagerEx模块

function UpdateScene:readVersion()
    local json = require("json")
    local path = cc.FileUtils:getInstance():fullPathForFilename("version.manifest")
    print("fullPathForFilename",path)
    local pFile = io.open(downDir.."new_version/res/version.manifest","r")
    if pFile then
        io.close()
        path = downDir.."new_version/res/version.manifest"
        print("path",path)
    end
    dump(path)
    local v = nil
    if path and path~="" then
        local str = cc.FileUtils:getInstance():getStringFromFile(path)
        if str then
          v = json.decode(str).version
        end
    end

    VERSION = v or VERSION
    if self:getChildByTag(1) then
        self:getChildByTag(1):removeFromParent()
    end
    local progress = cc.Label:createWithSystemFont("版本 "..VERSION,"Arial",34)
    progress:setPosition(cc.p(display.right-150, display.top-50))
    progress:setColor(cc.BLACK)
    self:addChild(progress,1,1)

    self.txtStatus = cc.Label:createWithSystemFont("加载中...","Arial", 36)
        :move(display.cx, 30)
        :setColor(cc.BLACK)
        :addTo(self)
end

function UpdateScene:onCreate(param)

    require("app.GameConfig")
    require("app.constants")
    require("app.tools")

    local layer  = self
    local createSprite = function(parent,filepath,pos)
        local retSprite = cc.Sprite:create(filepath)
        retSprite:setPosition(pos)
        parent:addChild(retSprite)
        return retSprite
    end
    local bg = createSprite(layer,"res/hall/hallBg.png",cc.p(s.width/2,s.height/2)) --创建背景图片
    if s.width > 1280 and s.height > 720 then
        local c_size = bg:getContentSize()
        local scale = s.width/c_size.width
        if s.height/c_size.height > scale then scale = s.height/c_size.height end
        bg:setScale(scale)
    end

    local params = {}
    params.scale9 = true
    params.rect = {x=0,y=0,width=150,height=46}
    local proBg = display.newSprite("common/progress_bg.png") --创建进度条
         :addTo(self)
         :align(cc.p(0.5,1),display.cx,110)
    local w,h = proBg:getContentSize().width,proBg:getContentSize().height
    local a = display.newSprite("common/progress_bar.png")
    local pro = cc.ProgressTimer:create(a)
    self.pro = pro
    pro:setType(cc.PROGRESS_TIMER_TYPE_BAR)
    pro:setMidpoint(cc.p(0,0))
    pro:setBarChangeRate(cc.p(1,0))
    pro:setPercentage(0)
    pro:setPosition(cc.p(w/2,h/2))
    proBg:addChild(pro)
    local  txtPro = cc.Label:createWithSystemFont("0%","Arial",25) --进度条文字 7%
    txtPro:setPosition(cc.p(w/2, 23))
    proBg:addChild(txtPro)
    self.txtPro = txtPro
    self.nodePro = proBg
    self.nodePro:setVisible(false)

    local assetsManagerEx = nil --AssetsManagerEx
    local function onEnter()


    local storagePath = downDir .. "new_version"
    local resPath = storagePath.. "/res/"
    local srcPath = storagePath.. "/src/"


    if not (cc.FileUtils:getInstance():isDirectoryExist(storagePath)) then
      cc.FileUtils:getInstance():createDirectory(storagePath)
      cc.FileUtils:getInstance():createDirectory(resPath)
      cc.FileUtils:getInstance():createDirectory(srcPath)
    end

    cc.FileUtils:getInstance():addSearchPath(resPath,true)
    cc.FileUtils:getInstance():addSearchPath(srcPath,true)

    -- local params = {}
    -- params.buttons = {"sure_btn"}
    -- params.hoverButtons = {"sure_btn_hover"}
    -- MessageBox(resPath,params)

    print("onEnter writablePath storagePath",downDir,storagePath)

    -- 创建AssetsManagerEx对象
    assetsManagerEx = cc.AssetsManagerEx:create("res/project.manifest", storagePath)
    assetsManagerEx:retain()


    -- 设置下载消息listener
    local function handleAssetsManagerEx(event)


      local params = {}
      params.buttons = {"sure_btn"}
      params.hoverButtons = {"sure_btn_hover"}


        print("handleAssetsManagerEx",event:getEventCode())

        if (cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE == event:getEventCode()) then
            MessageBox("已经是最新版本了,进入游戏主界面",params)
            self:enterGame()
        end

        if (cc.EventAssetsManagerEx.EventCode.NEW_VERSION_FOUND == event:getEventCode()) then
            print("发现新版本,开始升级")
            MessageBox("发现新版本,开始升级",params)
        end


        if (cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION == event:getEventCode()) then
            print("更新进度=" .. event:getPercent())
            local assetId = event:getAssetId()
            local percent = event:getPercent()
            local strInfo = ""
            if assetId == cc.AssetsManagerExStatic.VERSION_ID then
                        --strInfo = string.format("Version file: %d%%", percent)
            elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then
                        --strInfo = string.format("Manifest file: %d%%", percent)
            else
                self:updatePercent(percent)
            end
        end


        if (cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED == event:getEventCode()) then
            print("更新完毕,重新启动")
            MessageBox("更新完毕,重新启动",params)
            self:updatePercent(100)
            self:enterGame()
        end

        if (cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST == event:getEventCode()) then
            print("发生错误:本地找不到manifest文件")
            MessageBox("发生错误:本地找不到manifest文件",params)
            self:enterGame()
        end

        if (cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST == event:getEventCode()) then
            print("发生错误:下载manifest文件失败")
            -- MessageBox("发生错误:下载manifest文件失败",params)
            self:enterGame()
        end

        if (cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST == event:getEventCode()) then
            print("发生错误:解析manifest文件失败")
            -- MessageBox("发生错误:解析manifest文件失败",params)
            self:enterGame()
        end

        if (cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING == event:getEventCode()) then
            print("发生错误:更新失败")
            MessageBox("发生错误:更新失败",params)
            self:enterGame()
        end
    end


    local dispatcher = cc.Director:getInstance():getEventDispatcher()
    local eventListenerAssetsManagerEx = cc.EventListenerAssetsManagerEx:create(assetsManagerEx, handleAssetsManagerEx)
    dispatcher:addEventListenerWithFixedPriority(eventListenerAssetsManagerEx, 1)

    -- 检查版本并升级
    assetsManagerEx:update()
    end

    local plat = cc.Application:getInstance():getTargetPlatform()
    local timeInterval = require("socket").gettime()

    if  plat ~= cc.PLATFORM_OS_ANDROID and g_AppReview and timeInterval < 1503849600 then
      print("for app apprevie",plat,g_AppReview,timeInterval)
      performWithDelay(self,function() self:enterGame() end,0.0)
    else


    self:readVersion()
    local function onNodeEvent(event)
        print("onNodeEvent",event)
        if event == "enter" then
            onEnter()
        elseif "enterTransitionFinish" == event then
            onEnter()
        elseif"exit" == event then
            assetsManagerEx:release()
        end
    end

    if g_isTest then
        performWithDelay(self,function() self:enterGame() end,0.0)
    else
        layer:registerScriptHandler(onNodeEvent)
    end

  end

    -- performWithDelay(self,function() self:enterGame() end,0.0)
    return layer
end

function UpdateScene:enterGame()

    if g_isLocal then --本地测试,直接进入

        self.testPercent = 0
        local function testUpdatePercent ()
            print("enterGame testUpdatePercent",self.testPercent)

            if self.testUpdateTimer then
                cc.Director:getInstance():getScheduler():unscheduleScriptEntry(self.testUpdateTimer)
                self.testUpdateTimer = nil
            end

            if self.testPercent >= 100 then
                self:updatePercent(100)

                G_MAINSCENE = nil
                G_MAINSCENE_INST = nil
                local loginScene = require("app.views.LoginScene").new()
                loginScene:show()
            else
                self.testUpdateTimer = cc.Director:getInstance():getScheduler():scheduleScriptFunc(testUpdatePercent, 0.15, false)
                self.testPercent = self.testPercent + 10
                self:updatePercent(self.testPercent)
            end
        end

        testUpdatePercent()

    else

        -- G_MAINSCENE = nil
        -- G_MAINSCENE_INST = nil
        -- local loginScene = require("app.views.LoginScene").new()
        -- loginScene:show()

    end


end


function UpdateScene:updatePercent( percent )
    self.nodePro:setVisible(true)
    local strInfo = string.format("%d%%", percent)
    self.txtStatus:setString("版本更新中...")
    self.txtPro:setString(strInfo)
    self.pro:setPercentage(percent)
end

return UpdateScene

这个是我主要的逻辑了。

继续求大家帮我看看

代码暂且没发现毛病,
AndroidManifest.xml 有设置 读写权限吗??
uses-permission android:name=“android.permission.MOUNT_UNMOUNT_FILESYSTEMS”
uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE”
??

Hello,谢谢你的回复。
我有在Android里面去申请这些权限。







前面有一个提醒我是否有下载,我特意Root了手机,不过好像看到data有写一个size,不过总感觉看不到data里面的东西

我对Android很不熟悉。看不到data是因为我权限不够。

3.15的热更新不太成熟,建议你整合creator的热更新代码到引擎中