博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
游戏启动热更检测
阅读量:6676 次
发布时间:2019-06-25

本文共 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.Action
onDownloadVerFileProgress; 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 Dictionary
s_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/

你可能感兴趣的文章
【8-23】node.js学习笔记
查看>>
实验吧flag整理
查看>>
HDU 1849 Rabbit and Grass
查看>>
iOS:原生二维码扫描
查看>>
JavaScript数据类型(转)
查看>>
Makefile: (实验) 目标命令的结束标志
查看>>
Python自动化开发学习的第十周----Redis
查看>>
volley7--NetworkDispatcher从网络中获取数据
查看>>
git和GItHub的区别
查看>>
ftp服务器搭建流程详解
查看>>
C#面向对象(四):其他面向对象知识
查看>>
bzoj2539
查看>>
My thoughts after NOIP 2018(1)
查看>>
烂泥:学习Nagios(二):Nagios配置
查看>>
模拟实现 百度翻译 右下方的可折叠的分享按钮列表
查看>>
天降祥瑞,搬家来到cnblogs
查看>>
360 2015校园招聘 第一题
查看>>
Git上传代码的步骤
查看>>
sass基础常用指南
查看>>
数学 Codeforces Round #282 (Div. 2) B. Modular Equations
查看>>