本文共 46914 字,大约阅读时间需要 156 分钟。
using UnityEngine;using UnityEngine.Events;using UnityEngine.Networking;using System.Collections;using System.Collections.Generic;using System.IO;using AssetManagement;////// 游戏启动更新检查/// public partial class LaunchUpdate : MonoBehaviour{ private static string s_LogFilePath = Path.Combine(AssetDefine.ExternalSDCardsPath, "launch.log"); private static int s_LogFileSize = 1024 * 1024 * 5; //5m public static bool LogEnabled = true; public enum HotUpdateStepConst { LocalVer, RemoteVer, AssetsFiles, RemoteAssetsFiles, DownloadManifest, DownloaderHotUpdateAssets, } public enum HotUpdateErrorCode : int { None = 0, RemoteVerDownloaderError = 1000, //服务器版本文件下载异常 RemoteVerDecodeError = 2000, //服务器版本文件解析异常 RemoteFileListDownloaderError = 3000, //服务器文件列表下载异常 RemoteFileListDecodeError = 3002, //服务器文件列表解析异常 RemoteFileListMD5Error = 3003, //服务器文件列表md5校验失败 ManifestMD5Error = 4001, //清单文件md5校验失败 ManifestDownloaderError = 4003, //清单文件下载失败 } public enum ProgressType { Checkup, //检查资源 Downloading, //下载资源 } //注意如果不检查更新将直接用包内资源跑,也不会启动后台下载 public bool p_IsCheckUpdate = true; public System.ActiononDownloadVerFileProgress; public System.Action onUpdateComplete; const string c_VersionFileName = "version.txt"; const string c_FileListFileName = "files"; const string c_ManifestFileName = "xassetmanifest"; private XVersionFile m_BuildingVersion; //本地版本文件 sdcard->StreamingAssets private XVersionFile m_LocalVersion; //服务器版本文件 private XVersionFile m_RemoteVersion; //内置文件列表 private XAssetsFiles m_BuildinFiles; //本地文件列表 private XAssetsFiles m_LocalFiles; //服务器文件列表 private XAssetsFiles m_RemoteFiles; //远程文件列表在完成更新后保存在本地 private byte[] m_RemoteFilesBytes; //启动更新列表 private List m_UpdateNeedDownload; //后台更新列表 private List m_BackgroundNeedDownload; //启动列表中是否有dll需要生启游戏 private bool m_LaunchDllUpdate = false; private HotUpdateErrorCode m_ErrorCode; private string m_ErrorStr; void Start() { CheckUpdateLoggerSize(); RecordLogger(string.Empty); RecordLogger(string.Empty); RecordLogger("Start .."); StartUpdate(); } void StartUpdate() { m_ErrorCode = HotUpdateErrorCode.None; m_ErrorStr = string.Empty; StartCoroutine(StartUpHotUpdate()); } IEnumerator StartUpHotUpdate() { //没有连接网络提示连接网络 if (!XUtility.IsNetworkValid()) { RecordLogger(string.Format("StartUpHotUpdate -> NetworkValid .. Application.internetReachability = {0}", Application.internetReachability)); DefaultAlertGUI.Open(UpdateConst.GetLanguage(11301), UpdateConst.GetLanguage(11302), "", "", DefaultAlertGUI.ButtonOpt.None); while (!XUtility.IsNetworkValid()) yield return 0; DefaultAlertGUI.Close(); } yield return HotUpdateStep(HotUpdateStepConst.LocalVer); if (this.m_ErrorCode == HotUpdateErrorCode.None) { RecordLogger(string.Format("StartUpHotUpdate -> finish..")); if (XConfig.defaultConfig.isSDKPattern) HmlSdkProxy.instance.UploadUpdate(2);//热更新成功完成 OnUpdateComplete(); } else { string title = UpdateConst.GetLanguage(11301); string content = string.Format(UpdateConst.GetLanguage(11306), m_ErrorCode.ToString() + "\n" + m_ErrorStr); DefaultAlertGUI alert = DefaultAlertGUI.Open(title, content, UpdateConst.GetLanguage(11305), "", DefaultAlertGUI.ButtonOpt.Sure); UpdateUtility.ShowTextTip(string.Format(UpdateConst.GetLanguage(1201), this.m_ErrorCode)); XLogger.ReportException("更新检查异常", m_ErrorCode.ToString(), m_ErrorStr); yield return alert.Wait(); StartUpdate(); } } //返回当前可信度最高的文件列表 XAssetsFiles GetValidFiles() { return m_RemoteFiles != null ? m_RemoteFiles : (m_LocalFiles != null ? m_LocalFiles : m_BuildinFiles); } IEnumerator HotUpdateStep(HotUpdateStepConst step) { if (this.m_ErrorCode != HotUpdateErrorCode.None) { RecordLogger(string.Format("HotUpdateStep -> m_ErrorCode = {0} m_ErrorStr = {1}", this.m_ErrorCode, this.m_ErrorStr)); yield break; } else { this.m_ErrorCode = HotUpdateErrorCode.None; } bool isSDKPattern = XConfig.defaultConfig.isSDKPattern;//SDK模式 switch (step) { case HotUpdateStepConst.LocalVer: //检查本地版本 { CheckLocalVersion(); SetProgress(ProgressType.Checkup, 0.1f, UpdateConst.GetLanguage(11001)); if (m_LocalVersion == null) { RecordLogger(string.Format("HotUpdateStep -> {0} p_IsCheckUpdate = {1} Ver == null ", step, p_IsCheckUpdate)); } else { RecordLogger(string.Format("HotUpdateStep -> {0} p_IsCheckUpdate = {1} Ver = {2} ", step, p_IsCheckUpdate, UpdateUtility.GetVersionStrInfo(m_LocalVersion))); } if (p_IsCheckUpdate) yield return HotUpdateStep(HotUpdateStepConst.RemoteVer); else //不检更新 CheckLocalAssetFiles(); //暂定为第一次安装解压完成 if (isSDKPattern && isFirstInstall) HmlSdkProxy.instance.UploadUnzip(2); break; } case HotUpdateStepConst.RemoteVer: //检查服务器版本 { if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.RemoteVer. start"); } yield return CheckRemoteVersionCoroutine(); SetProgress(ProgressType.Checkup, 0.2f); if (m_RemoteVersion == null) { RecordLogger(string.Format("HotUpdateStep -> {0} p_IsCheckUpdate = {1} Ver == null ", step, p_IsCheckUpdate)); } else { RecordLogger(string.Format("HotUpdateStep -> {0} p_IsCheckUpdate = {1} Ver = {2} ", step, p_IsCheckUpdate, UpdateUtility.GetVersionStrInfo(m_RemoteVersion))); } if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.RemoteVer. end"); } yield return HotUpdateStep(HotUpdateStepConst.AssetsFiles); break; } case HotUpdateStepConst.AssetsFiles: //检查本地文件列表 { if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.AssetsFiles. start"); } CheckLocalAssetFiles(); SetProgress(ProgressType.Checkup, 0.3f, UpdateConst.GetLanguage(11003)); if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.AssetsFiles. end"); } RecordLogger(string.Format("HotUpdateStep -> {0} isVerChange = {1}", step, isVerChange())); if (isVerChange()) //版本发生变化 yield return HotUpdateStep(HotUpdateStepConst.RemoteAssetsFiles); else //版本未发生变化校验本地文件 yield return HotUpdateStep(HotUpdateStepConst.DownloaderHotUpdateAssets); break; } case HotUpdateStepConst.RemoteAssetsFiles: //检查远程文件列表 { RecordLogger(string.Format("HotUpdateStep -> {0}", step)); if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.RemoteAssetsFiles. start"); } yield return CheckRemoteAssetFilesCoroutine(); SetProgress(ProgressType.Checkup, 0.4f); if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.RemoteAssetsFiles. end"); } yield return HotUpdateStep(HotUpdateStepConst.DownloadManifest); break; } case HotUpdateStepConst.DownloadManifest: //下载清单文件 { RecordLogger(string.Format("HotUpdateStep -> {0}", step)); if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.DownloadManifest. start"); } yield return CheckDownloadMainfest(); SetProgress(ProgressType.Checkup, 0.5f); if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.DownloadManifest. end"); } yield return HotUpdateStep(HotUpdateStepConst.DownloaderHotUpdateAssets); break; } case HotUpdateStepConst.DownloaderHotUpdateAssets: //收集并下载启动更新资源 { RecordLogger(string.Format("HotUpdateStep -> {0}", step)); if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.DownloaderHotUpdateAssets. start"); } if (isSDKPattern) HmlSdkProxy.instance.UploadUpdate(1); yield return CollectNeedDownloadFiles(); SetProgress(ProgressType.Checkup, 1f); if (LogEnabled) { XLogger.DEBUG("LaunchUpdate::HotUpdateStep HotUpdateStepConst.DownloaderHotUpdateAssets. end"); } UpdateUtility.ShowTextTip(string.Format(UpdateConst.GetLanguage(5000), m_UpdateNeedDownload.Count, m_BackgroundNeedDownload.Count, m_LaunchDllUpdate, GetValidFiles().p_FileCount)); if (LogEnabled) XLogger.INFO(string.Format("m_UpdateNeedDownload:{0} m_BackgroundNeedDownload:{1} m_LaunchDllUpdate:{2} m_RemoteFiles:{3}", m_UpdateNeedDownload.Count, m_BackgroundNeedDownload.Count, m_LaunchDllUpdate, GetValidFiles().p_FileCount)); yield return DownloadUpdateAssets(); SetProgress(ProgressType.Downloading, 1f); break; } default: break; } } void RecordLogger(string content) { XLogger.RecordLog(s_LogFilePath, content, "Launch "); } void CheckUpdateLoggerSize() { FileInfo finfo = new FileInfo(s_LogFilePath); if (finfo.Exists && finfo.Length >= s_LogFileSize) finfo.Delete(); } void SetProgress(ProgressType t, float v, string desc = "") { if (t == ProgressType.Checkup) { //DefaultLoaderGUI.SetProgressText(UpdateConst.GetLanguage(10002)); DefaultLoaderGUI.SetProgress(v); } else { //DefaultLoaderGUI.SetProgressText(UpdateConst.GetLanguage(10003)); DefaultLoaderGUI.SetProgress(v); } if (!string.IsNullOrEmpty(desc)) { DefaultLoaderGUI.SetProgressText(desc); } //Debug.Log(t + " " + v); } void OnUpdateComplete() { UpdateUtility.ShowTextTip(UpdateConst.GetLanguage(10000)); if (m_RemoteFiles != null) { string verpath = AssetDefine.ExternalSDCardsPath + c_VersionFileName; XFileUtility.WriteText(verpath, JsonUtility.ToJson(m_RemoteVersion, true)); string flspath = AssetDefine.ExternalSDCardsPath + c_FileListFileName; XFileUtility.WriteBytes(flspath, m_RemoteFilesBytes); m_RemoteFilesBytes = null; } RecordLogger(string.Format("OnUpdateComplete -> m_LaunchDllUpdate:{0} XConfig.defaultConfig.isDllUpdate:{1}", m_LaunchDllUpdate, XConfig.defaultConfig.isDllUpdate));#if !UNITY_EDITOR if (m_LaunchDllUpdate && XConfig.defaultConfig.isDllUpdate) { //并重启 UpdateUtility.InitDll(); return; }#endif if (onUpdateComplete != null) { onUpdateComplete.Invoke(); } if (p_IsCheckUpdate) { //启动后台下载 StartCoroutine(LaunchBackgroundDownloader()); } }}
using System;using UnityEngine;using UnityEngine.Networking;using System.Collections.Generic;using System.Collections;using System.IO;using AssetManagement;public partial class LaunchUpdate{ //是否第一次安装 private bool isFirstInstall = false; //检查本地版本 void CheckLocalVersion() { UpdateUtility.ShowTextTip(UpdateConst.GetLanguage(1000)); if (LogEnabled) XLogger.INFO("LaunchUpdate::CheckVersion. begin"); string sdcardVerPath = Path.Combine(AssetDefine.ExternalSDCardsPath, c_VersionFileName); bool sdcardValidate = false; if (File.Exists(sdcardVerPath)) { //扩展卡版本文件载入 string versionJson = File.ReadAllText(sdcardVerPath); if (string.IsNullOrEmpty(versionJson)) { //内容为空 XLogger.INFO(string.Format("LaunchUpdate::CheckVersion() sdcard version is Empty ! path={0}", sdcardVerPath)); UpdateUtility.ShowTextTip(UpdateConst.GetLanguage(1010)); } else { try { m_LocalVersion = UpdateUtility.DeVersion(versionJson, sdcardVerPath); sdcardValidate = true; } catch (System.Exception e) { //解析异常 XLogger.INFO(string.Format("LaunchUpdate::CheckVersion() sdcard version decode error ! path={0} error={1} data={2}", sdcardVerPath, e.ToString(), versionJson)); UpdateUtility.ShowTextTip(UpdateConst.GetLanguage(1020)); } } } else { //暂定为第一次安装解压,有好的方法在移动 isFirstInstall = true; if (XConfig.defaultConfig.isSDKPattern) HmlSdkProxy.instance.UploadUnzip(1); } //若扩展卡版本文件不存在或是出现异常则使用内置版本文件 if (!sdcardValidate) { //为了正确识别覆盖安装,若内置版本 //内置版本文件载入 if (LogEnabled) XLogger.INFO(string.Format("LaunchUpdate::CheckVersion() load buildin version ! path={0}", sdcardVerPath)); string buildinVerPath = Path.Combine(AssetDefine.BuildinAssetPath, c_VersionFileName); string versionJson = string.Empty; string error = string.Empty; versionJson = XFileUtility.ReadStreamingFile(buildinVerPath, out error); if (string.IsNullOrEmpty(error)) { //内容为空 if (string.IsNullOrEmpty(versionJson)) { UpdateUtility.ShowTextTip(UpdateConst.GetLanguage(1100)); XLogger.INFO(string.Format("LaunchUpdate::CheckVersion() buildin version error ! path={0} error={1}", buildinVerPath, "content is Empty")); } else { try { m_LocalVersion = UpdateUtility.DeVersion(versionJson, buildinVerPath); } catch (System.Exception e) { UpdateUtility.ShowTextTip(UpdateConst.GetLanguage(1101)); //解析异常 XLogger.INFO(string.Format("LaunchUpdate::CheckVersion() buildin version decode error! path={0} error={1} data={2}", buildinVerPath, e.ToString(), versionJson)); } } } } if (LogEnabled) XLogger.INFO("LaunchUpdate::CheckVersion. end"); XAssetsFiles.s_CurrentVersion = m_LocalVersion; //显示版本号 UpdateUtility.SetUIVersionInfo(m_LocalVersion, null); } //检查远程版本 IEnumerator CheckRemoteVersionCoroutine() { string random = DateTime.Now.ToString("yyyymmddhhmmss"); string remoteVerUrl = AssetDefine.RemoteDownloadUrl + c_VersionFileName + "?v=" + random; RecordLogger(string.Format("CheckRemoteVersionCoroutine. remoteVerUrl: {0}", remoteVerUrl)); using (UnityWebRequest uwr = UnityWebRequest.Get(remoteVerUrl)) { UnityWebRequestAsyncOperation async = uwr.SendWebRequest(); while (!async.isDone) { if (onDownloadVerFileProgress != null) onDownloadVerFileProgress.Invoke(async.progress); SetProgress(ProgressType.Checkup, 0.1f + async.progress * 0.1f, UpdateConst.GetLanguage(11002)); yield return 0; } if (!string.IsNullOrEmpty(uwr.error) || uwr.isHttpError || uwr.isNetworkError) { m_ErrorCode = HotUpdateErrorCode.RemoteVerDownloaderError; XLogger.ERROR(string.Format("LaunchUpdate::CheckRemoteVersionCoroutine() remote version download error ! remoteVerUrl={0} error={1} url={2}", remoteVerUrl, uwr.error, remoteVerUrl)); yield break; } string jsonData = uwr.downloadHandler.text; if (string.IsNullOrEmpty(jsonData)) { m_ErrorCode = HotUpdateErrorCode.RemoteVerDecodeError; XLogger.ERROR(string.Format("LaunchUpdate::CheckRemoteVersionCoroutine() remote version content is Empty ! path={0} error={1} url={2}", remoteVerUrl, "content is Empty", remoteVerUrl)); } else { try { m_RemoteVersion = UpdateUtility.DeVersion(jsonData, remoteVerUrl); } catch (System.Exception e) { m_ErrorCode = HotUpdateErrorCode.RemoteVerDecodeError; XLogger.INFO(string.Format("LaunchUpdate::CheckRemoteVersionCoroutine() remote version decode error! path={0} error={1} data={2}", remoteVerUrl, e.ToString(), jsonData)); } } } XAssetsFiles.s_CurrentVersion = m_RemoteVersion; //显示版本号 UpdateUtility.SetUIVersionInfo(m_LocalVersion, m_RemoteVersion); } //版本是否发生改变 bool isVerChange() { //没有文件列表 if (GetValidFiles() == null) return true; //如果本地文件列表存在表示更新过,但是清单文件意外丢失 if (File.Exists(AssetDefine.ExternalSDCardsPath + c_FileListFileName) && !File.Exists(AssetDefine.ExternalSDCardsPath + c_ManifestFileName)) return true; //版本改表 if (m_LocalVersion != null && m_RemoteVersion != null) { #if UNITY_EDITOR //编辑器不检查 代码和预制体 if ( m_LocalVersion.p_ArtVersion.svnVer != m_RemoteVersion.p_ArtVersion.svnVer) { return true; }#else if (m_LocalVersion.p_DevVersion.svnVer != m_RemoteVersion.p_DevVersion.svnVer || m_LocalVersion.p_ArtVersion.svnVer != m_RemoteVersion.p_ArtVersion.svnVer) { return true; } #endif return false; } return true; } //检查本地文件列表 void CheckLocalAssetFiles() { if (LogEnabled) XLogger.DEBUG("LaunchUpdate::CheckLocalFileList. start"); string sdcardPath = Path.Combine(AssetDefine.ExternalSDCardsPath, c_FileListFileName); if (File.Exists(sdcardPath)) { //扩展卡版本文件载入 string jsonData = UpdateUtility.ReadAssetList(AssetBundle.LoadFromFile(sdcardPath)); if (string.IsNullOrEmpty(jsonData)) { //内容为空 XLogger.DEBUG(string.Format("LaunchUpdate::CheckLocalFileList() sdcard assetFiles is Empty ! path={0}", sdcardPath)); } else { try { m_LocalFiles = UpdateUtility.DeFileList(jsonData); XAssetsFiles.s_CurrentAssets = m_LocalFiles; } catch (System.Exception e) { //解析异常 XLogger.DEBUG(string.Format("LaunchUpdate::CheckLocalFileList() sdcard assetFiles decode error ! path={0} error={1} data={2}", sdcardPath, e.ToString(), jsonData)); } } } //内置文件列表 //if (!sdcardValidate) { //内置版本文件载入 if (LogEnabled) XLogger.DEBUG(string.Format("LaunchUpdate::CheckLocalFileList() load buildin assetFiles ! path={0}", sdcardPath)); string buildinPath = Path.Combine(AssetDefine.BuildinAssetPath, c_FileListFileName); string jsonData = string.Empty; //string error = string.Empty; jsonData = UpdateUtility.ReadBuildinAssetList(buildinPath); if (string.IsNullOrEmpty(jsonData)) { //内容为空 XLogger.DEBUG(string.Format("LaunchUpdate::CheckLocalFileList() buildin assetFiles error ! path={0} error={1}", buildinPath, "content is Empty")); } else { try { m_BuildinFiles = UpdateUtility.DeFileList(jsonData); XAssetsFiles.s_BuildingtAssets = m_BuildinFiles; if (XAssetsFiles.s_CurrentAssets == null) XAssetsFiles.s_CurrentAssets = m_BuildinFiles; } catch (System.Exception e) { //解析异常 XLogger.DEBUG(string.Format("LaunchUpdate::CheckLocalFileList() buildin version decode error! path={0} error={1} data={2}", buildinPath, e.ToString(), jsonData)); } } } if (LogEnabled) XLogger.DEBUG("LaunchUpdate::CheckLocalFileList. end"); } //检查服务器文件列表 IEnumerator CheckRemoteAssetFilesCoroutine() { string tempPath = AssetManager.Instance.AssetLoaderOptions.GetAssetDownloadSavePath(c_FileListFileName + ".dtemp"); AssetFileThreadDownloader downloader = AssetFileThreadDownloader.Get(c_FileListFileName, tempPath, m_RemoteVersion.p_files_md5, m_RemoteVersion.p_files_md5); while (!downloader.IsDone()) { SetProgress(ProgressType.Checkup, 0.3f + downloader.progress * 0.1f, UpdateConst.GetLanguage(11004)); yield return 0; } //下载出现异常 if (!string.IsNullOrEmpty(downloader.Error)) { m_ErrorCode = HotUpdateErrorCode.RemoteFileListDownloaderError; m_ErrorStr = string.Format("LaunchUpdate::CheckRemoteAssetFilesCoroutine() downloader err ! path={0} error={1}", downloader.WebUrl, downloader.Error); XLogger.ERROR(m_ErrorStr); yield break; } try { if (File.Exists(downloader.DownloadPath)) { m_RemoteFilesBytes = File.ReadAllBytes(downloader.DownloadPath); File.Delete(downloader.DownloadPath); } } catch (System.Exception ex) { XLogger.ERROR(string.Format("LaunchUpdate::CheckRemoteAssetFilesCoroutine() downloader err ! path={0} error={1}", downloader.WebUrl, ex.ToString())); yield break; } string jsonData = string.Empty; try { //解析 jsonData = UpdateUtility.ReadAssetList(AssetBundle.LoadFromMemory(m_RemoteFilesBytes)); } catch (System.Exception ex) { XLogger.ERROR(string.Format("LaunchUpdate::CheckRemoteAssetFilesCoroutine() path={0} error={1}", downloader.WebUrl, ex.ToString())); } if (string.IsNullOrEmpty(jsonData)) { //解析异常 m_ErrorCode = HotUpdateErrorCode.RemoteFileListDecodeError; m_ErrorStr = string.Format("LaunchUpdate::CheckRemoteAssetFilesCoroutine() remote assetFiles content is Empty ! path={0} error={1}", downloader.WebUrl, "content is Empty"); XLogger.ERROR(m_ErrorStr); } else { try { m_RemoteFiles = UpdateUtility.DeFileList(jsonData); XAssetsFiles.s_CurrentAssets = m_RemoteFiles; } catch (System.Exception e) { m_ErrorCode = HotUpdateErrorCode.RemoteFileListDecodeError; m_ErrorStr = string.Format("LaunchUpdate::CheckRemoteAssetFilesCoroutine() remote assetFiles decode error! path={0} error={1} data={2}", downloader.WebUrl, e.ToString(), jsonData); XLogger.ERROR(m_ErrorStr); } } } //下载清单文件 IEnumerator CheckDownloadMainfest() { AssetFileThreadDownloader downloader = AssetFileThreadDownloader.Get(c_ManifestFileName, null, m_RemoteVersion.p_manifest_md5); while (!downloader.IsDone()) { SetProgress(ProgressType.Checkup, 0.4f + downloader.GetProgress() * 0.1f, UpdateConst.GetLanguage(11004)); yield return 0; } yield return downloader; if (!string.IsNullOrEmpty(downloader.Error)) { if (downloader.state == AssetDownloader.State.ErrorMd5) m_ErrorCode = HotUpdateErrorCode.ManifestMD5Error; else m_ErrorCode = HotUpdateErrorCode.ManifestDownloaderError; m_ErrorStr = string.Format("LaunchUpdate::CheckDownloadMainfest() downloader err ! path={0} error={1}", downloader.WebUrl, downloader.Error); XLogger.ERROR(m_ErrorStr); yield break; } } //收集需要下载的文件 IEnumerator CollectNeedDownloadFiles() { int downloadTag = XConfig.defaultConfig.initDownloadTag; RecordLogger(string.Format("HotUpdateStep -> {0} downloadTag={1}.", "CollectNeedDownloadFiles", downloadTag)); m_UpdateNeedDownload = new List(); m_BackgroundNeedDownload = new List (); XAssetsFiles files = GetValidFiles();//服务器、本地、包内 XAssetsFiles localFiles = m_LocalFiles != null ? m_LocalFiles : m_BuildinFiles; int count = 0; int totalCount = files.p_AllFiles.Count; bool isdone = false; System.Threading.ThreadPool.QueueUserWorkItem((object state) => { if (LogEnabled) XLogger.DEBUG("LaunchUpdate::CollectNeedDownloadFiles. start"); foreach (var asset in files.p_AllFiles) { count++; string sdcardPath = AssetDefine.ExternalSDCardsPath + asset.path; //string fileMd5 = string.Empty; bool exists = File.Exists(sdcardPath); //if (exists) //fileMd5 = XFileUtility.FileMd5(sdcardPath); XAssetsFiles.FileStruct add = null; //本地或首包 XAssetsFiles.FileStruct file = null; //是否为最新 //sd卡有并且md5也对应得上 表示为最新的文件 bool isNewest = exists && localFiles != null && localFiles.allFilesMap.TryGetValue(asset.path, out file) && file.md5 == asset.md5; bool isBuilding = (asset.options & XAssetsFiles.FileOptions.BUILDING) == XAssetsFiles.FileOptions.BUILDING; if (isBuilding) //是否为首包 { //此资源为内置/首包资源 //但内置/首包中不存在 或者 已经发生变化!需要下载 if (m_BuildinFiles == null || !m_BuildinFiles.allFilesMap.TryGetValue(asset.path, out file) || file.md5 != asset.md5) { //并且本地没有最新的 if (!isNewest) add = asset; } } else { //不是内置/首包资源 // 本地不存在 或者 文件不是最新的!需要下载 md5超慢放弃 //if (string.IsNullOrEmpty(fileMd5) || fileMd5 != asset.md5) //{ // add = asset; //} // 本地不存在 或者 文件不是最新的!需要下载 if (!exists || localFiles == null || !localFiles.allFilesMap.TryGetValue(asset.path, out file) || file.md5 != asset.md5) { add = asset; } } if (add == null) continue; //本地的文件不是最新的文件了需要删掉 if (exists) { if (((add.options & XAssetsFiles.FileOptions.LUA) == XAssetsFiles.FileOptions.LUA)) { } else File.Delete(sdcardPath); } if (downloadTag != -1 && downloadTag == add.tag) { //启动需要下载的扩展包 m_UpdateNeedDownload.Add(add); if ((add.options & XAssetsFiles.FileOptions.DLL) == XAssetsFiles.FileOptions.DLL) m_LaunchDllUpdate = true; RecordLogger(string.Format("tagDownload -> name={0} size={1} tag={2} exist={3} isBuilding={4} smd5={5} lmd5={6}", add.path, XUtility.FormatBytes(add.size), add.tag, exists, isBuilding, add.md5, file != null ? file.md5 : "null")); } else if ((add.options & XAssetsFiles.FileOptions.LAUNCHDOWNLOAD) == XAssetsFiles.FileOptions.LAUNCHDOWNLOAD) { //启动需要下载 m_UpdateNeedDownload.Add(add); if ((add.options & XAssetsFiles.FileOptions.DLL) == XAssetsFiles.FileOptions.DLL) m_LaunchDllUpdate = true; RecordLogger(string.Format("LaunchDownload -> name={0} size={1} tag={2} exist={3} isBuilding={4} smd5={5} lmd5={6}", add.path, XUtility.FormatBytes(add.size), add.tag, exists, isBuilding, add.md5, file != null ? file.md5 : "null")); } else { //后台需要下载 m_BackgroundNeedDownload.Add(add); } } isdone = true; if (LogEnabled) XLogger.DEBUG("LaunchUpdate::CollectNeedDownloadFiles. end"); }); while (!isdone) { float p = (float)count / (float)totalCount; SetProgress(ProgressType.Checkup, 0.5f + p * 0.5f, string.Format(UpdateConst.GetLanguage(11005), p * 100)); yield return 0; } SetProgress(ProgressType.Checkup, 1f, string.Format(UpdateConst.GetLanguage(11005), 100f)); } //下载启动更新文件 IEnumerator DownloadUpdateAssets() { if (m_UpdateNeedDownload.Count < 1) { RecordLogger(string.Format("HotUpdateStep -> {0} count={1} ", "DownloadUpdateAssets", 0)); SetProgress(ProgressType.Downloading, 1); yield break; } bool isFastUpdate = true; AssetFileDownloadQueue download = gameObject.AddComponent (); download.onBeginStep = () => { RecordLogger(string.Format("HotUpdateStep::onBeginDownload -> {0} ", download.currentDownloader.WebUrl)); }; download.onEndStep = () => { string err = download.currentDownloader.Error; err = string.IsNullOrEmpty(err) ? "" : "Error=" + err; RecordLogger(string.Format("HotUpdateStep::onEndStep -> {0} {1}", download.currentDownloader.WebUrl, err)); }; download.errorPause = true; download.SetFiles(m_UpdateNeedDownload); RecordLogger(string.Format("HotUpdateStep -> {0} count={1} totalSize={2}.", "DownloadUpdateAssets", download.totalFileCount, XUtility.FormatBytes(download.bytesTotal))); float downloadAlertSize = XConfig.defaultConfig.downloadAlertSize; //提示下载大小 float bytesSize = download.bytesTotal * XConfig.defaultConfig.downloadSizeFactor; float downSize = Mathf.Round((bytesSize / 1048576.0f) * 100.0f)/100.0f; Debug.Log("downSize: " + downSize); if (downSize >= downloadAlertSize) { string tipContent = string.Format(UpdateConst.GetLanguage(XUtility.IsNetworkWifi() ? 10010 : 10011), XUtility.FormatBytes(bytesSize)); DefaultAlertGUI alertDownloadTip = DefaultAlertGUI.Open("", tipContent, UpdateConst.GetLanguage(11206), "", DefaultAlertGUI.ButtonOpt.Sure); yield return alertDownloadTip.Wait(); } download.StartDownload(); float lastProgress = 0; while (!download.isDone) { if (download.isPause) { //下载出现异常 if (!XUtility.IsNetworkValid()) { //下载过程中把网络关掉了 DefaultAlertGUI.Open(UpdateConst.GetLanguage(11301), UpdateConst.GetLanguage(11302), "", "", DefaultAlertGUI.ButtonOpt.None); while (!XUtility.IsNetworkValid()) yield return 0; DefaultAlertGUI.Close(); download.StartDownload(); } else { string content = string.Format(UpdateConst.GetLanguage(11303), download.currentFS.path + " \n" + download.error); string title = UpdateConst.GetLanguage(11301); string sureStr = UpdateConst.GetLanguage(11304); DefaultAlertGUI alert = DefaultAlertGUI.Open(title, content, sureStr, "", DefaultAlertGUI.ButtonOpt.Sure); XLogger.ReportException("更新下载异常", download.currentFS.path, download.error); //等待玩家点击重试 yield return alert.Wait(); download.StartDownload(); } } else { string tip = string.Empty; if (isFastUpdate || Time.frameCount % 20 == 0) { tip = string.Format(UpdateConst.GetLanguage(11006), XUtility.FormatBytes(download.bytesReceived * XConfig.defaultConfig.downloadSizeFactor), XUtility.FormatBytes(download.bytesTotal * XConfig.defaultConfig.downloadSizeFactor), Mathf.Clamp(download.currentFileIdx + 1, 0, download.totalFileCount), Mathf.Clamp(download.totalFileCount, 0, download.totalFileCount), XUtility.FormatBytes(download.downloadSpeed)); } if (download.progress > lastProgress) lastProgress = download.progress; SetProgress(ProgressType.Downloading, lastProgress, tip); } yield return 0; } } IEnumerator CollectBackgroundDownloaderFiles() { //版本没有发生变化,将不会走到 CollectNeedDownloadFiles 不会收集后台需要下载的资源 if (m_BackgroundNeedDownload == null) { RecordLogger(string.Format("HotUpdateStep -> {0}", "CollectBackgroundDownloaderFiles")); XAssetsFiles localFiles = m_LocalFiles != null ? m_LocalFiles : m_BuildinFiles; XAssetsFiles files = GetValidFiles(); int count = 0; int totalCount = files.p_AllFiles.Count; bool isdone = false; System.Threading.ThreadPool.QueueUserWorkItem((object state) => { if (LogEnabled) XLogger.DEBUG("LaunchUpdate::CollectBackgroundDownloaderFiles. start"); m_BackgroundNeedDownload = new List (); foreach (var asset in files.p_AllFiles) { count++; string sdcardPath = AssetDefine.ExternalSDCardsPath + asset.path; bool exists = File.Exists(sdcardPath); XAssetsFiles.FileStruct add = null; XAssetsFiles.FileStruct file; if (m_BuildinFiles == null || !m_BuildinFiles.allFilesMap.TryGetValue(asset.path, out file) || file.md5 != asset.md5) { //首包不存在 add = asset; } if (!exists || localFiles == null || !localFiles.allFilesMap.TryGetValue(asset.path, out file) || file.md5 != asset.md5) { //本地不存在此资源 add = asset; } else { //本地存在的文件,究竟需不需要md5验证下是不是发生改变,md5验证将会延长文件校验时间 //如果不用文件本身的md5,可能会有一种情况。玩家在后台下载的过程中,关掉游戏,此时本地文件列表是服务器最新文件列表, //再次启动游戏文件列表对比将筛选不出来发生改变的同名文件,这个时候文件的md5跟列表中的md5对比就可以解决. //try //{ // string fmd5 = XFileUtility.FileMd5(sdcardPath); // if (localFiles == null || !localFiles.allFilesMap.TryGetValue(asset.path, out file) || fmd5 != asset.md5) // { // add = asset; // } //} //catch (System.Exception ex) //{ // XLogger.ERROR(string.Format("LaunchUpdate::CollectBackgroundDownloaderFiles. path = {0} error = {1}", asset.path, ex.ToString())); //} } if (asset == null) continue; if (exists) { if (((add.options & XAssetsFiles.FileOptions.LUA) == XAssetsFiles.FileOptions.LUA)) { } else File.Delete(sdcardPath); } m_BackgroundNeedDownload.Add(asset); } isdone = true; if (LogEnabled) XLogger.DEBUG("LaunchUpdate::CollectBackgroundDownloaderFiles. end"); }); while (!isdone) yield return 0; } } //启动后台文件下载 IEnumerator LaunchBackgroundDownloader() { yield return CollectBackgroundDownloaderFiles(); bool backgroundDownload = XConfig.defaultConfig.backgroundDownload; UpdateUtility.ShowTextTip(string.Format(UpdateConst.GetLanguage(5001), m_BackgroundNeedDownload.Count + " " + backgroundDownload)); BackgroundDownloadQueue.Instance.SetFiles(m_BackgroundNeedDownload); int totalSize = 0; //tag各类型的数量 Dictionary tagType = new Dictionary (); foreach (var asset in m_BackgroundNeedDownload) { if (!tagType.ContainsKey(asset.tag)) tagType.Add(asset.tag, 0); ++tagType[asset.tag]; totalSize += asset.size; } RecordLogger(string.Format("HotUpdateStep -> {0} count={1} totalSize={2}. backgroundDownload={3}", "LaunchBackgroundDownloader", m_BackgroundNeedDownload.Count, XUtility.FormatBytes(totalSize), backgroundDownload)); foreach (var item in tagType) RecordLogger(string.Format(" -> tag={0} count={1}", item.Key, item.Value)); if (backgroundDownload) { BackgroundDownloadQueue.Instance.StartAutoDownload(); }//#if UNITY_IOS// if (!HmlPHPData.VerifyApp)// { // BackgroundDownloadQueue.Instance.StartAutoDownload(); // }//#endif }}
using UnityEngine;using System.Collections;using System.Collections.Generic;public class UpdateConst{ private static Dictionarys_UpdateLanguage = new Dictionary () { { 1000,@" 检查游戏版本!"}, { 1010,@" 内存卡版本文件内容为空!"}, { 1020,@" 内存卡版本文件解析异常!"}, { 1100,@" 内置版本文件内容为空!"}, { 1101,@" 内置版本文件解析异常!"}, { 1201,@" 版本检查发生异常! {0}"}, { 5000,@" 启动更新:{0} 后台更新:{1} CSharp重启:{2} 总文件数:{3}"}, { 5001,@" 后台下载:{0}"}, { 5005,@" 下载成功:{0}/{1} {2}"}, { 5006,@" 下载失败:{0} error: {1}"}, { 10000,@" 版本更新完成!"}, { 10002,@" 正在校验文件"}, { 10003,@" 正在更新文件"}, { 10010,"游戏发现新内容,立即更新体验!\n (资源大小为 {0}流量)"}, { 10011,"游戏发现新内容,立即更新体验!\n (资源大小为 {0}流量,建议连接WIFI)"}, { 11001,@"检查版本"}, { 11002,@"检查服务器版本"}, { 11003,@"检查本地文件列表"}, { 11004,@"下载资产清单"}, { 11005,@"校验本地文件{0:F}%"}, { 11006,@"正在更新文件{0}/{1} 文件数{2}/{3} {4}/s"}, { 11007,@"正在初始化资源..."}, { 11008,@"正在初始化游戏配置..."}, { 11009,@"初始化完成,即将进入游戏"}, { 11206,@"确定"}, { 11207,@"取消"}, { 11301,@"提示"}, { 11302," 当前没有可使用的网络,请连接正确的网络4G/Wifi!\n 连接网络后将自动继续"}, { 11303," 文件下载发生异常!\n 可以尝试重试或是重启游戏修复\n {0}"}, { 11304,@"再试一把"}, { 11305,@"重试"}, { 11306,"资源检查发生异常!\n {0}\n请点击【重试】进行重新加载\n (若多次重试无效,请联系客服)"}, { 11307,@"获取资源地址失败,请联系客服!是否重试?"}, { 11308,@" 检测到未开启OpenGL 为了您更好的体验游戏, 请前往【置中心-引擎设置-画质渲染模式】勾选OpenGL模式"}, { 12000,@"声音组件初始化失败!"}, { 12001,@"材质组件初始化失败!"}, }; private static Dictionary s_IOSLanguage = new Dictionary () { { 1000,@" 检查游戏版本!"}, { 1010,@" 内存卡版本文件内容为空!"}, { 1020,@" 内存卡版本文件解析异常!"}, { 1100,@" 内置版本文件内容为空!"}, { 1101,@" 内置版本文件解析异常!"}, { 1201,@" 版本检查发生异常! {0}"}, { 5000,@" 启动更新:{0} 后台更新:{1} CSharp重启:{2} 总文件数:{3}"}, { 5001,@" 后台下载:{0}"}, { 5005,@" 下载成功:{0}/{1} {2}"}, { 5006,@" 下载失败:{0} error: {1}"}, { 10000,@" 版本更新完成!"}, { 10002,@" 正在校验文件"}, { 10003,@" 正在更新文件"}, { 10010,"游戏发现新内容,立即更新体验!\n (资源大小为 {0}流量)"}, { 10011,"游戏发现新内容,立即更新体验!\n (资源大小为 {0}流量,建议连接WIFI)"}, //{11001,@"检查版本"}, //{11002,@"检查服务器版本"}, //{11003,@"检查本地文件列表"}, //{11004,@"下载资产清单"}, //{11005,@"校验本地文件{0:F}%"}, //{11006,@"正在更新文件{0}/{1} 文件数{2}/{3} {4}/s"}, //{11007,@"正在初始化游戏配置,即将进入游戏"}, { 11001,@"无需消耗流量、无解压"}, { 11002,@"无需消耗流量、无解压"}, { 11003,@"无需消耗流量、无解压"}, { 11004,@"无需消耗流量、无解压"}, { 11005,@"无需消耗流量、无解压{0:F}%"}, { 11006,@"无需消耗流量、无解压{0}/{1} 文件数{2}/{3} {4}/s"}, { 11007,@"无需消耗流量、无解压"}, { 11206,@"确定"}, { 11207,@"取消"}, { 11301,@"提示"}, { 11302," 当前没有可使用的网络,请连接正确的网络4G/Wifi!\n 连接网络后将自动继续"}, { 11303," 文件下载发生异常!\n 可以尝试重试或是重启游戏修复\n {0}"}, { 11304,@"再试一把"}, { 11305,@"重试"}, { 11306,"资源检查发生异常!\n {0}\n请点击【重试】进行重新加载\n (若多次重试无效,请联系客服)"}, { 11307,@"获取资源地址失败,请联系客服!是否重试?"}, { 12000,@"声音组件初始化失败!"}, { 12001,@"材质组件初始化失败!"}, }; public static string GetLanguage(int id) { if (HmlPHPData.IsIosVerify()) { return s_IOSLanguage.ContainsKey(id) ? s_IOSLanguage[id] : id.ToString(); } else { return s_UpdateLanguage.ContainsKey(id) ? s_UpdateLanguage[id] : id.ToString(); } }}
using UnityEngine;using System.Collections.Generic;using System.IO;using System.Runtime.CompilerServices;using System.Text;public class UpdateUtility{ //解析版本文件 public static XVersionFile DeVersion(AssetBundle assetBundle, string path) { XVersionFile version = null; TextAsset textAsset = assetBundle.LoadAsset("version"); if (textAsset == null || string.IsNullOrEmpty(textAsset.text)) { XLogger.ERROR(string.Format("LaunchUpdate::CheckVersion() 版本文件损坏 ! path={0}", path)); } else { version = JsonUtility.FromJson (textAsset.text); Debug.Log(textAsset.text); Resources.UnloadAsset(textAsset); } assetBundle.Unload(true); return version; } public static XVersionFile DeVersion(string data, string path) { XVersionFile version = null; version = JsonUtility.FromJson (data); return version; } public static XAssetsFiles DeFileList(string data) { XAssetsFiles assetFiles = null; assetFiles = JsonUtility.FromJson (data); return assetFiles; } public static string ReadAssetList(AssetBundle ab) { if (ab == null) return null; string data = string.Empty; if (ab != null) { TextAsset textAsset = ab.LoadAsset (ab.GetAllAssetNames()[0]); if (textAsset != null) { data = textAsset.text; Resources.UnloadAsset(textAsset); } ab.Unload(true); } return data; } public static string GetVersionStrInfo(XVersionFile version) { return string.Format("Dev:{0}|{1} Art:{2}|{3} files:{4} manifest:{5}", version.p_DevVersion.svnVer, version.p_DevVersion.buildDate, version.p_ArtVersion.svnVer, version.p_ArtVersion.buildDate, version.p_files_md5, version.p_manifest_md5); } //初始化Dll public static void InitDll() { #if !UNITY_EDITOR && (UNITY_ANDROID || UNITY_STANDALONE_WIN) string path = "00/00000000000000000000000000000001.asset"; path = Path.Combine(AssetManagement.AssetDefine.ExternalSDCardsPath, path); if (File.Exists(path)) { try { AssetBundle ab = AssetBundle.LoadFromFile(path); TextAsset[] texts = ab.LoadAllAssets (); string dllPath = AssetManagement.AssetDefine.DataDataPath;#if UNITY_STANDALONE_WIN dllPath = Path.Combine(dllPath, "Managed");#endif foreach (var text in texts) { string savePath = Path.Combine(dllPath, string.Format("{0}.dll", text.name)); XFileUtility.WriteBytes(savePath, text.bytes); Resources.UnloadAsset(text); } ab.Unload(true); XMobileUtility.RestartApplication(); } catch (System.Exception e) { XLogger.ERROR(string.Format("UpdateUtility::InitDll error:{0}", e.ToString())); } }#endif } public static string ReadBuildinAssetList(string path) { string error = string.Empty; return ReadAssetList(XFileUtility.ReadStreamingAssetBundle(path, out error)); } public static void SetUIVersionInfo(XVersionFile local, XVersionFile server) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("Art {0}", Application.version); if (local != null) { sb.AppendFormat(".{0}", local.p_ArtVersion.svnVer); if (server != null && server.p_ArtVersion.svnVer != local.p_ArtVersion.svnVer) sb.AppendFormat(" - {0}", server.p_ArtVersion.svnVer); } sb.Append("\n"); sb.AppendFormat("Dev {0}", Application.version); if (local != null) { sb.AppendFormat(".{0}", local.p_DevVersion.svnVer); if (server != null && server.p_DevVersion.svnVer != local.p_DevVersion.svnVer) sb.AppendFormat(" - {0}", server.p_DevVersion.svnVer); } DefaultLoaderGUI.SetVerText(sb.ToString()); } public static void ShowTextTip(string str) { SystemTipGUI.ShowTip(str); }}
转载地址:http://ubrxo.baihongyu.com/