JJBB/Assets/Plugins/Script/AssetUpdate/AssetUpdateManager.cs

426 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 在AssetBundleManager等资源管理器生成前预先处理资源问题的管理器
// 提前处理资源更新,服务器列表下载等一系列情况
// 注这个东西运作的时候没有AssetBundle没有Lua不要试图做任何相关操作。
using System.Collections.Generic;
using System.Reflection;
using AssetUpdate;
using Games.GlobeDefine;
using UnityEngine;
using UnityEngine.EventSystems;
using SceneHub = UnityEngine.SceneManagement.SceneManager;
public class AssetUpdateManager : MonoBehaviour
{
// 处理不同渠道的Php链接数据
private const string _channelConfig = "Channel.txt";
private IAssetAsyncAction _currentAction;
public static Assembly dllAssembly { get; private set; }
private static string _channel;
public static string channel
{
get { return _channel; }
private set { _channel = value; }
}
public static string assetVersionUri { get; private set; }
public static bool useResources
{
get { return _useResources; }
}
private static bool _useResources = true;
public AssetUpdateState state { get; private set; }
public AssetUpdateError error { get; private set; }
public static string assetUri { get; private set; }
public static int assetVersion { get; private set; }
public static string apkUri { get; private set; }
public static string apkVersion { get; private set; }
public List<AssetDependencyItem> downloadList { get; private set; }
public AssetDependencyInfo mainInfo { get; private set; }
public Dictionary<string, string> streamingPathInfo { get; private set; }
private const string currentVersionPref = "CurrentVersion";
public static int LoadCurrentVersion()
{
var currentVersion = PlayerPrefs.GetInt(currentVersionPref, default(int));
if (currentVersion <= 0)
{
var versionFile = Resources.Load<TextAsset>(AssetConst.currentVersionFile).text;
int version;
if (int.TryParse(versionFile, out version))
currentVersion = version;
}
return currentVersion;
}
private void SaveCurrentVersion()
{
PlayerPrefs.SetInt(currentVersionPref, assetVersion);
}
private void Awake()
{
Debug.Log("AssetUpdateManager Awake");
_useResources = false;
AssetUpdateDownloaderTick.CreateInstance();
if (!FirstSceneBg.instance)
FirstSceneBg.CreateInstance();
CreateEventSystem();
}
public static void CreateEventSystem()
{
if (!EventSystem.current)
{
var eventObj = new GameObject("EventSystem");
eventObj.AddComponent<EventSystem>();
eventObj.AddComponent<StandaloneInputModule>();
DontDestroyOnLoad(eventObj);
}
}
private void OnConfigLoad(WWW www)
{
var text = string.IsNullOrEmpty(www.error) ? www.text : string.Empty;
var channelError = false;
if (string.IsNullOrEmpty(text))
channelError = true;
else
{
var lines = AssetUtils.TextToLines(text);
if (lines.Length < 2)
channelError = true;
else
{
channel = lines[0].Trim();
assetVersionUri = lines[1].Trim();
if (string.IsNullOrEmpty(channel) || string.IsNullOrEmpty(assetVersionUri))
channelError = true;
if (lines.Length > 2)
{
var extra = lines[2].Trim();
if (lines.Length > 2 && !string.IsNullOrEmpty(extra))
FirstSceneBg.instance.SetPublishText(extra);
}
}
}
if (channelError)
Debug.LogError("Unable to Parse Channel file! This is not recoverable!");
else
{
// 清理上次执行残留的rawJsonText
// 当前项目没有类似数据缓存库一样的类,暂时直接用静态传递
assetUri = string.Empty;
state = AssetUpdateState.GetUpdateInfo;
StartCurrentAction();
}
FirstSceneBg.instance.ShowGameVersion();
// 清理上次执行残留的rawJsonText
// 当前项目没有类似数据缓存库一样的类,暂时直接用静态传递
assetUri = string.Empty;
state = AssetUpdateState.GetUpdateInfo;
StartCurrentAction();
}
private void Start()
{
// 特别处理Android Resume时期的诡异情况该状况下AssetBundle未被清空但实际Bundle管理器已被析构
AssetBundle.UnloadAllAssetBundles(true);
Debug.Log("加载渠道文件" + _channelConfig);
AssetUpdateDownloaderTick.instance.LoadStreamingAsset(_channelConfig, OnConfigLoad);
}
private void OnDestroy()
{
// 即使AppQuit也需要处理OnDestroy否则会在编辑器中导致下载不中断
if (state != AssetUpdateState.Complete && _currentAction != null)
{
_currentAction.Dispose();
_currentAction = null;
}
}
private void StartCurrentAction()
{
switch (state)
{
case AssetUpdateState.GetUpdateInfo:
{
var httpAction = new HttpsGetAction(10f);
_currentAction = httpAction;
httpAction.Start();
}
break;
case AssetUpdateState.DownloadAssetList:
{
var assetListAction = new AssetVersionAction();
_currentAction = assetListAction;
assetListAction.Start(assetVersion, assetUri);
}
break;
case AssetUpdateState.CompareAssetList:
{
var assetCompareAction = new AssetCompareAction();
_currentAction = assetCompareAction;
assetCompareAction.Start(mainInfo);
}
break;
case AssetUpdateState.DownloadFile:
{
var downloadAction = new ProjectDownloadAction();
_currentAction = downloadAction;
downloadAction.Start(assetUri, downloadList);
}
break;
default:
{
Debug.LogError(string.Format("Unhandled state {0} in StartCurrentAction", state));
}
break;
}
}
private static T ConvertAction<T>(IAssetAsyncAction action) where T : class, IAssetAsyncAction
{
var result = action as T;
if (result == null)
Debug.LogError("Logic Error: current Action is not " + typeof(T));
return result;
}
public static JsonAssetInfo HandleHttpGetAction(HttpsGetAction httpAction)
{
JsonAssetInfo jsonAssetInfo = null;
if (httpAction != null)
{
if (httpAction.jsonData == null)
Debug.LogError("HttpsGetAction Error: failed to get json from server");
else
jsonAssetInfo = JsonAssetInfo.Create(httpAction.jsonData);
}
return jsonAssetInfo;
}
private void EndCurrentAction()
{
error = AssetUpdateError.UnknownError;
switch (state)
{
case AssetUpdateState.GetUpdateInfo:
{
var httpAction = ConvertAction<HttpsGetAction>(_currentAction);
error = AssetUpdateError.AssetJsonError;
if (httpAction != null)
{
JsonAssetInfo jsonAssetInfo = HandleHttpGetAction(httpAction);
Debug.Log("更新资源信息: " + jsonAssetInfo);
if (jsonAssetInfo == null)
Debug.LogError("Failed to convert jsonData to JsonAssetInfo");
else
{
assetUri = jsonAssetInfo.assetUri;
assetVersion = jsonAssetInfo.assetVersion;
apkUri = jsonAssetInfo.apkUri;
apkVersion = jsonAssetInfo.apkVersion;
error = apkVersion == Application.version
? AssetUpdateError.Success
: AssetUpdateError.ApkUpdate;
}
}
}
break;
case AssetUpdateState.DownloadAssetList:
{
var assetInfoAction = ConvertAction<AssetVersionAction>(_currentAction);
if (assetInfoAction != null)
{
error = assetInfoAction.error;
if (error == AssetUpdateError.Success)
mainInfo = assetInfoAction.mainInfo;
}
}
break;
case AssetUpdateState.CompareAssetList:
{
var assetCompareAction = ConvertAction<AssetCompareAction>(_currentAction);
if (assetCompareAction != null)
{
downloadList = assetCompareAction.downloadList;
streamingPathInfo = assetCompareAction.streamingPathInfo;
error = AssetUpdateError.Success;
}
}
break;
case AssetUpdateState.DownloadFile:
{
var downloadAction = ConvertAction<ProjectDownloadAction>(_currentAction);
if (downloadAction != null)
error = downloadAction.error;
}
break;
case AssetUpdateState.Complete:
case AssetUpdateState.Error:
break;
default:
{
Debug.LogError(string.Format("Unhandled state {0} in StartCurrentAction", state));
}
break;
}
}
private void HandleStateError()
{
var errorState = state;
state = AssetUpdateState.Error;
Debug.LogError("Error on Step " + errorState);
switch (error)
{
case AssetUpdateError.AssetJsonError:
{
LiteConfirmWin.Open("资源同步错误", "无法获得服务器文件版本号!\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
}
break;
case AssetUpdateError.VersionDataError:
{
LiteConfirmWin.Open("资源清单错误", "无法获得正确的服务器文件清单!\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
}
break;
case AssetUpdateError.DownloadError:
{
LiteConfirmWin.Open("资源下载错误", "无法下载所需文件!\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
}
break;
case AssetUpdateError.FileCreateError:
{
LiteConfirmWin.Open("读写错误", "无法更新资源文件!\n请检查硬盘容量并确保游戏拥有响应读写权限",
new LiteConfirmButtonData("确定", RestartProcess));
}
break;
case AssetUpdateError.ApkError:
case AssetUpdateError.ApkUpdate:
{
OpenApkUri(apkUri);
}
break;
case AssetUpdateError.UserCancel:
{
// 用户自行选择取消更新
RestartProcess();
}
break;
default:
{
Debug.LogError(string.Format("Unhandled error type {0} in HandleStateError", error));
LiteConfirmWin.Open("网络错误", "无法获得服务器列表\n请在网络通畅的情况下再次尝试",
new LiteConfirmButtonData("确定", RestartProcess));
}
break;
}
}
private void OnAllActionComplete()
{
_currentAction = null;
TryToEndProcess();
}
private static void OnApkUpdateConfirm(string uri)
{
Debug.Log(string.Format("Open apk uri at {0}!", uri));
Application.OpenURL(uri);
// 锁死当前界面,防止用户关闭浏览器后,需要重启唤起
OpenApkUri(uri);
}
public static void OpenApkUri(string uri)
{
LiteConfirmWin.Open("安装包更新", "点击确定从商店下载最新版本的游戏安装包!\n" + uri,
new LiteConfirmButtonData("确定", () => OnApkUpdateConfirm(uri)));
}
private void RestartProcess()
{
SceneHub.LoadScene(SceneHub.GetActiveScene().name);
}
private void Update()
{
if (state < AssetUpdateState.Complete && _currentAction != null)
// 完成当前Action
if (_currentAction.UpdateTimeout())
{
// 从当前Action中读取错误码
EndCurrentAction();
if (error == AssetUpdateError.Success)
{
state++;
if (state == AssetUpdateState.Complete)
OnAllActionComplete();
else
StartCurrentAction();
}
else
{
HandleStateError();
}
}
}
private void TryToEndProcess()
{
// if (_complete && _ui.complete) EndProcess();
GameObject.DestroyObject(this);
if (state == AssetUpdateState.Complete)
StartGame();
}
private void StartGame()
{
SaveCurrentVersion();
SceneHub.LoadScene(GlobeVar.sceneLogin);
}
#region
public enum AssetUpdateState
{
GetUpdateInfo,
DownloadAssetList,
CompareAssetList,
DownloadFile,
Complete,
Error
}
public enum AssetUpdateError
{
Success,
FileCreateError,
AssetJsonError,
VersionDataError,
DownloadError,
ApkError,
UserCancel,
ApkUpdate,
UnknownError
}
#endregion
}