local First = {} local json = require "rapidjson" local firstText = require "app/first/first_text" local FIRST_ROOT_PREFAB_PATH = "assets/first/ui/first_root.prefab" local FIRST_UI_PREFAB_PATH = "assets/first/ui/first.prefab" local BFLaunchMgr = CS.BF.BFMain.Instance.GameLaunchMgr local BFPlatform = CS.BF.BFPlatform local BFSDKManager = CS.BF.BFMain.Instance.SDKMgr local PlayerPrefs = CS.UnityEngine.PlayerPrefs local TYPE_BF_TOUCH_EVENT = typeof(CS.BF.UITouchEvent) local TYPE_TEXT = typeof(CS.UnityEngine.UI.Text) local VISIBLE_SCALE = { x = 1, y = 1, z = 1} local NOT_VISIBLE_SCALE = { x = 0, y = 0, z = 0} local EVENT_UP_INSIDE = 3 local REQUEST_ADDR_TIME_OUT = 3 -- 请求版本信息的超时时间 local REQUEST_ADDR_MAX_RETRY_TIMES = 2 -- 最大重试次数 local REQUEST_ADDR_ERROR_TYPE = { VALUE_INVALID = "VALUE_INVALID", REQUEST_FAIL = "REQUEST_FAIL", TIME_OUT = "TIME_OUT" } local LANGUAGES = { ["en"] = true, ["cn"] = true, ["zh"] = true, -- ["id"] = true, -- 印尼 -- ["vi"] = true, -- 越南 -- ["fr"] = true, -- 法语 -- ["de"] = true, -- 德语 -- ["pt"] = true, -- 葡萄牙 -- ["ja"] = true, -- 日本 -- ["ko"] = true, -- 韩国 } function First:init() self:initLanguage() self:initLaunchRequester() end function First:initLanguage() -- self.language = PlayerPrefs.GetString("SELECTED_LANGUAGE", "") -- print("first init language " .. self.language) -- if not LANGUAGES[self.language] then -- self.language = self:getSystemLanguage() -- if self.language == nil then -- self.language = BFPlatform.GetCurrentLanguageInfo():GetFallbackLanguage() -- end -- PlayerPrefs.SetString("SELECTED_LANGUAGE", self.language) -- end -- 根据语言来,不切换 self.language = self:getSystemLanguage() if self.language == nil then self.language = BFPlatform.GetCurrentLanguageInfo():GetFallbackLanguage() end PlayerPrefs.SetString("SELECTED_LANGUAGE", self.language) self.stringMap = firstText.data self.strNoNetwork = self.stringMap["STR_NO_NETWORK_CONNECTION"][self.language] self.strOK = self.stringMap["STR_OK"][self.language] self.strGoto = self.stringMap["STR_GOTO"][self.language] self.strCancel = self.stringMap["STR_CANCEL"][self.language] self.strDownloading = self.stringMap["STR_DOWNLOADING_RES"][self.language] self.strRepair = self.stringMap["STR_REPAIR_RES"][self.language] -- 对话框提示文字 self.dialogStr = { [1] = self.stringMap["DIALOG_STR_1"][self.language], [2] = self.stringMap["DIALOG_STR_2"][self.language], [3] = self.stringMap["DIALOG_STR_3"][self.language], [4] = self.stringMap["DIALOG_STR_4"][self.language], [5] = self.stringMap["DIALOG_STR_5"][self.language], [6] = self.stringMap["DIALOG_STR_6"][self.language], [100] = self.stringMap["DIALOG_STR_100"][self.language], } -- 进度条提示文字 self.sliderStr = { [1] = self.stringMap["SLIDER_STR_1"][self.language], [2] = self.stringMap["SLIDER_STR_2"][self.language], [3] = self.stringMap["SLIDER_STR_3"][self.language], [4] = self.stringMap["SLIDER_STR_4"][self.language], [5] = self.stringMap["SLIDER_STR_5"][self.language], [6] = self.stringMap["SLIDER_STR_6"][self.language], } end function First:getSystemLanguage() local sdkLanguage = BFSDKManager:GetLanguage() print("first get sdk language " .. sdkLanguage) local languageInfo = self:splitString(sdkLanguage, "_") if not languageInfo or #languageInfo ~= 2 then print("first return system language nil") return nil end local language = languageInfo[1] local country = languageInfo[2] if language and language == "zh" then if country and country == "CN" then language = "cn" end end if not LANGUAGES[language] then language = nil end if language then print("first return system language " .. language) else print("first return system language nil") end return language end function First:splitString(input, delimiter) input = tostring(input) delimiter = tostring(delimiter) if (delimiter=='') then return false end local pos, arr = 0, {} for st, sp in function() return string.find(input, delimiter, pos, true) end do table.insert(arr, string.sub(input, pos, st - 1)) pos = sp + 1 end table.insert(arr, string.sub(input, pos)) return arr end function First:initLaunchRequester() local lr = BFLaunchMgr.LaunchRequester -- 当前多语言 lr:SetLanguageName(self.language) -- 第一次请求版本号 lr:SetFirstRequestAction(function(version, identifier, onGetVersion) self:requestAddress(onGetVersion) end) -- 对话框 lr:SetShowDialogAction(function(eCode, okCallback) local str = self.dialogStr[eCode] or "" self:showDialog(str, okCallback) end) -- 多选对话框 lr:SetShowDialogComplexAction(function(eCode, okCallback, cancelCallback) local str = self.dialogStr[eCode] or "" if eCode == 1 or eCode == 6 then -- 前往商店的时候设置一下确认按钮的文本 self:showDialogComplex(str, okCallback, cancelCallback, self.strGoto) else self:showDialogComplex(str, okCallback, cancelCallback) end end) -- 隐藏对话框 lr:SetHideDialogAction(function() self:hideDialog() end) -- 进度条 lr:SetUpdateSliderAction(function(sliderCode, progress) local str = self.sliderStr[sliderCode] self:showSlider() self:setSliderText(str) self:setSliderPercentText("") end) -- 隐藏进度条 lr:SetHideSliderAction(function() self:hideSlider() end) -- 预检查完成 lr:SetPreCheckEndCallback(function() self:onPreCheckEnd() end) -- 获取到总进度 lr:SetGetTotalLengthCallback(function(totalSize) self.downloadTotalSize = totalSize local mb = totalSize / 1048576 if mb < 0.01 then mb = 0.01 end self.downloadTotalSizeStr = string.format("%sMB", (mb - mb % 0.01)) local str local isRepair = BFLaunchMgr.LaunchRequester.isAutoRepair if isRepair then str = string.format(self.strRepair, 0, self.downloadTotalSizeStr) else str = string.format(self.strDownloading, 0, self.downloadTotalSizeStr) end self:showSlider() self:setSliderText(str) self:setSliderPercentText("") end) -- 下载更新 lr:SetDownloadingCallback(function(size) local mb = size / 1048576 if mb < 0.01 then mb = 0.01 end local sizeStr = string.format("%sMB", (mb - mb % 0.01)) local str local isRepair = BFLaunchMgr.LaunchRequester.isAutoRepair if isRepair then str = string.format(self.strRepair, sizeStr, self.downloadTotalSizeStr) else str = string.format(self.strDownloading, sizeStr, self.downloadTotalSizeStr) end local progress = size / (self.downloadTotalSize or 1) self:showSlider() self:setSliderText(str) self:setSliderPercentText(math.floor(progress * 100) .. "%") end) -- 启动成功 lr:AddLaunchSuccCallback(function() CS.UnityEngine.Object.Destroy(self.firstUI) CS.UnityEngine.Object.Destroy(self.firstRoot) self.firstUI = nil self.firstRoot = nil end) end function First:showUI() local firstAb = BFLaunchMgr:GetFirstAB() self.firstAb = firstAb local firstRootAsset = self.firstAb:LoadAsset(FIRST_ROOT_PREFAB_PATH, typeof(CS.UnityEngine.GameObject)) self.firstRoot = CS.UnityEngine.Object.Instantiate(firstRootAsset) self.canvasTrans = self.firstRoot.transform:Find("canvas") if BFLaunchMgr.LaunchRequester.launchSucceed then self:showFirstUI() else self:showLogo() end end function First:loadFirstUI() if not self.firstUI then local firstUIAsset = self.firstAb:LoadAsset(FIRST_UI_PREFAB_PATH, typeof(CS.UnityEngine.GameObject)) self.firstUI = CS.UnityEngine.Object.Instantiate(firstUIAsset) self.firstUI.transform:SetParent(self.canvasTrans, false) self.progressText = self.firstUI.transform:Find("progress_text") self.sliderPercentText = self.progressText:GetComponent(TYPE_TEXT) self.sliderText = self.firstUI.transform:Find("slider_text"):GetComponent(TYPE_TEXT) local logoEn = self.firstUI.transform:Find("logo_en") local logoZH = self.firstUI.transform:Find("logo_zh") local logoCn = self.firstUI.transform:Find("logo_cn") if self.language == "zh" then logoZH.localScale = VISIBLE_SCALE logoEn.localScale = NOT_VISIBLE_SCALE logoCn.localScale = NOT_VISIBLE_SCALE elseif self.language == "cn" then logoCn.localScale = VISIBLE_SCALE logoEn.localScale = NOT_VISIBLE_SCALE logoZH.localScale = NOT_VISIBLE_SCALE else logoEn.localScale = VISIBLE_SCALE logoZH.localScale = NOT_VISIBLE_SCALE logoCn.localScale = NOT_VISIBLE_SCALE end self.dialogTrans = self.firstUI.transform:Find("message_box") self.confirmBtnTrans = self.firstUI.transform:Find("message_box/title_bg_img/ok_btn") local confirmBtn = self.confirmBtnTrans:GetComponent(TYPE_BF_TOUCH_EVENT) confirmBtn:AddTouchEventListener(function(eventType, x, y) if eventType == EVENT_UP_INSIDE and self.confirmCallback then self.confirmCallback() self:hideDialog() end end) self.confirmText = self.firstUI.transform:Find("message_box/title_bg_img/ok_btn/text"):GetComponent(TYPE_TEXT) self.confirmText.text = self.strOK self.cancelBtnTrans = self.firstUI.transform:Find("message_box/title_bg_img/cancel_btn") local cancelBtn = self.cancelBtnTrans:GetComponent(TYPE_BF_TOUCH_EVENT) cancelBtn:AddTouchEventListener(function(eventType, x, y) if eventType == EVENT_UP_INSIDE and self.cancelCallback then self.cancelCallback() self:hideDialog() end end) local cancelText = self.firstUI.transform:Find("message_box/title_bg_img/cancel_btn/text"):GetComponent(TYPE_TEXT) cancelText.text = self.strCancel self.contentText = self.firstUI.transform:Find("message_box/title_bg_img/content_tx"):GetComponent(TYPE_TEXT) local versionText = self.firstUI.transform:Find("version"):GetComponent(TYPE_TEXT) local appVersionText = self.stringMap["STR_APP_VERSION"][self.language] if appVersionText == nil then appVersionText = "App: " end local version = BFLaunchMgr:GetCurrentVersion() versionText.text = appVersionText .. version end end ---- 请求地址信息 function First:requestAddress(callback, times, totalTimes) local responded = false if (self.hasReceiveAddrSuccess == nil) then self.hasReceiveAddrSuccess = false end if (self.showAddrErrorBox == nil) then self.showAddrErrorBox = false end if times == nil then -- 本次循环的连接次数,每次连接会进行一定次数的自动重连 times = 0 end if totalTimes == nil then -- 用于标记唯一ID totalTimes = 0 end times = times + 1 totalTimes = totalTimes + 1 local connectStartTimes = os.clock() local loginCenterUrl = BFPlatform.GetLoginCenterURL() local version = BFLaunchMgr:GetCurrentVersion() print("requestAddress -- loginCenterUrl:" .. loginCenterUrl .. " version:" .. version .. " times:" .. times .. " totalTimes:" .. totalTimes) local args = { project_id = "b6", version = version, device_id = CS.UnityEngine.SystemInfo.deviceUniqueIdentifier, bundle_id = CS.UnityEngine.Application.identifier, env = "release", } local platform = "Editor" if CS.UnityEngine.Application.platform == CS.UnityEngine.RuntimePlatform.Android then platform = "Android" elseif CS.UnityEngine.Application.platform == CS.UnityEngine.RuntimePlatform.IPhonePlayer then platform = "iOS" end loginCenterUrl = loginCenterUrl .. "?platform=" .. CS.System.Uri.EscapeDataString(platform) for k, v in pairs(args) do loginCenterUrl = loginCenterUrl .. "&" .. k .. "=" .. CS.System.Uri.EscapeDataString(v) end -- 最后增加一个随机参数规避网络缓存的问题,保证每次都是新的请求 local guid = CS.BF.BFMain.Instance.SDKMgr.BFLoginSDKMgr:GetNewPlayerGuid() loginCenterUrl = loginCenterUrl .. "&random=" .. CS.System.Uri.EscapeDataString(guid) CS.BF.BFMain.Instance.SDKMgr.BFLoginSDKMgr:GetWithURL(loginCenterUrl, function (req, rsp) if rsp and rsp.IsSuccess == true then if rsp.Data then -- 有数据就算成功 local serverResult = json.decode(rsp.Data) if serverResult then responded = true -- 如果已经成功过了 不作处理 if self.hasReceiveAddrSuccess then return end self.hasReceiveAddrSuccess = true self.requestAddressRsp = rsp.Data if not self.showAddrErrorBox then self:setShenHeLanguageAndReqATT() -- 上报版本请求成功 local args = { client_version = version, client_version_url = loginCenterUrl, client_connect_time = (os.clock() - connectStartTimes)*1000, client_retry_times = totalTimes - 1 } CS.BF.BFMain.Instance.SDKMgr.BFThirdReportSDKMgr:PostThinkingAnalyticsEvent("client_request_version_success", json.encode(args)) -- 走后续步骤 if callback then callback(rsp.Data) end end else self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.REQUEST_FAIL, times, totalTimes) end else self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.REQUEST_FAIL, times, totalTimes) end else self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.REQUEST_FAIL, times, totalTimes) end end) CS.BF.BFMain.Instance.TaskMgr:EasyTimer(REQUEST_ADDR_TIME_OUT, function() if not responded and not self.hasReceiveAddrSuccess and not self.showAddrErrorBox then self:tryShowRequestAddrErrorBox(connectStartTimes, callback, REQUEST_ADDR_ERROR_TYPE.TIME_OUT, times, totalTimes) end end) end -- 请求地址失败的处理 function First:tryShowRequestAddrErrorBox(connectStartTimes, callback, reqAddrErrorType, times, totalTimes) if self.recordReqAddrFailTimes == nil then self.recordReqAddrFailTimes = {} end local hasRecord = self.recordReqAddrFailTimes[totalTimes] ~= nil print("tryShowRequestAddrErrorBox errorType:" .. reqAddrErrorType .. " hasRecord:" .. tostring(hasRecord) .. " times:" .. times .. " totalTimes:" .. totalTimes) if times > REQUEST_ADDR_MAX_RETRY_TIMES then if not self.showAddrErrorBox then if self.hasReceiveAddrSuccess then return end self.hasReceiveAddrSuccess = true CS.BF.BFMain.IsStandAlone = true self:setShenHeLanguageAndReqATT() if callback then callback("") end end else -- 静默重试 -- 重试 if not hasRecord then CS.BF.BFMain.Instance.TaskMgr:EasyTimer(0, function() self:requestAddress(callback, times, totalTimes) -- 重新开始 end) end end -- 失败上报 if not hasRecord then self.recordReqAddrFailTimes[totalTimes] = 1 local args = { client_version = BFLaunchMgr:GetCurrentVersion(), client_version_url = BFPlatform.GetLoginCenterURL(), client_connect_time = (os.clock() - connectStartTimes)*1000, client_error_type = reqAddrErrorType, client_retry_times = totalTimes - 1 } CS.BF.BFMain.Instance.SDKMgr.BFThirdReportSDKMgr:PostThinkingAnalyticsEvent("client_request_version_failed", json.encode(args)) end end -- 审核包特殊处理,语言设置,并且如果是ios则请求ATT function First:setShenHeLanguageAndReqATT() end function First:showFirstUI() self:loadFirstUI() self:hideSlider() self:hideDialog() end -- 隐藏确认框 function First:hideDialog() if self.dialogTrans then self.dialogTrans.gameObject:SetActive(false) end end -- 隐藏slider function First:hideSlider() if self.dialogTrans then self.progressText.gameObject:SetActive(false) end end -- 显示slider function First:showSlider() self.progressText.gameObject:SetActive(true) end -- 设置slider文本 function First:setSliderText(str) self.sliderText.text = str end -- 设置slider的文本 function First:setSliderPercentText(value) self.sliderPercentText.text = value end -- 显示对话框, ok function First:showDialog(contentStr, callback) self.dialogTrans.gameObject:SetActive(true) self.contentText.text = contentStr self.confirmText.text = self.strOK self.confirmCallback = callback self.cancelBtnTrans.gameObject:SetActive(false) self.confirmBtnTrans.localPosition = { x = 0, y = -95, z = 0 } end -- 显示对话框, ok cancel function First:showDialogComplex(contentStr, okCallback, cancelCallback, confirmStr) self.dialogTrans.gameObject:SetActive(true) self.contentText.text = contentStr self.confirmText.text = confirmStr or self.strOK self.confirmCallback = okCallback self.cancelCallback = cancelCallback self.cancelBtnTrans.gameObject:SetActive(true) self.confirmBtnTrans.localPosition = { x = 124, y = -95, z = 0 } end -- 显示项目logo function First:showLogo() self.logoEnd = true if self.preCheckEnd then self:onLogoEnd() end end -- logo播放完毕 function First:onLogoEnd() self:loadFirstUI() self:hideSlider() self:hideDialog() self:showSlider() BFLaunchMgr.LaunchRequester:PreCheckNextProcess() end -- 预检查完成 function First:onPreCheckEnd() self.preCheckEnd = true if self.logoEnd then self:onLogoEnd() end end function First:compareVersionThan(version1, version2, include) if not version1 or not version2 then return false end local versionStrs = self:split(version1, ".") local versionNum1 = tonumber(versionStrs[1]) local versionNum2 = tonumber(versionStrs[2]) local versionNum3 = tonumber(versionStrs[3]) local versionStrs2 = self:split(version2, ".") local versionNum21 = tonumber(versionStrs2[1]) local versionNum22 = tonumber(versionStrs2[2]) local versionNum23 = tonumber(versionStrs2[3]) if not versionNum1 or not versionNum2 or not versionNum3 or not versionNum21 or not versionNum22 or not versionNum23 then return false end if versionNum1 > versionNum21 then return true, true elseif versionNum1 < versionNum21 then return false end if versionNum2 > versionNum22 then return true, true elseif versionNum2 < versionNum22 then return false end if versionNum3 > versionNum23 then return true elseif versionNum3 < versionNum23 then return false end if include then return true end return false end function First:split(input, delimiter) input = tostring(input) delimiter = tostring(delimiter) if (delimiter=='') then return false end local pos,arr = 0, {} for st,sp in function() return string.find(input, delimiter, pos, true) end do table.insert(arr, string.sub(input, pos, st - 1)) pos = sp + 1 end table.insert(arr, string.sub(input, pos)) return arr end First:init() First:showUI() return First