#灵感/代码缓存 ## SessionMgr ``` cs using System; using System.Collections; using System.Collections.Generic; using System.Linq; using HTFramework.Utility; using IslandMatch; using UnityEngine; using Newtonsoft.Json; using UnityEngine.Networking; namespace CGBU_SDK { /// /// 会话时间管理类 /// public class SessionMgr : MonoSingleton { // private const string appId = "3f99e16c541a"; // private const string reportUrl = "https://global-receiver-ias.icongamesg.com/report/?appid=" + appId; private const string StartSession = "start_session"; private const string EndSession = "end_session"; // private const string sessionCachePrefsKey = "sessionCachePrefsKey"; private const string ReSendUrl = "&batch=1"; private string _sessionId; private string _publicString; private long _startEventTimestamp; private long _endEventTimestamp; private Dictionary _eventDic; private Dictionary _userDataDic; private string _uid = String.Empty; private string _uuid = String.Empty; #region 生命周期 private void Awake() { _uid = SystemInfo.deviceUniqueIdentifier; } private void OnDestroy() { StopNetworkRequest(); } /// /// 切后台 暂停游戏 /// /// private void OnApplicationPause(bool pauseStatus) { if (pauseStatus) { SendEndSessionEvent(); } ReSend(); } /// /// 退出游戏 /// private void OnApplicationQuit() { AddToList(CreateEndEvent()); } private SessionEventData CreateEndEvent() { _endEventTimestamp = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000; SessionEventData _sessionEndEventData = new SessionEventData { uuid = _uuid, event_name = EndSession, event_timestamp = _endEventTimestamp, public_properties = _publicString, event_properties = _eventDic }; _sessionEndEventData.event_name = EndSession; _sessionEndEventData.event_timestamp = _endEventTimestamp; _sessionEndEventData.event_properties["session_dur"] = _endEventTimestamp - _startEventTimestamp; _sessionEndEventData.event_properties["user_properties"] = _userDataDic; return _sessionEndEventData; } #endregion #region 会话收发&业务逻辑 /// /// 发送结束会话事件 /// private void SendEndSessionEvent() { SessionEventData endData = CreateEndEvent(); ReportEvent(endData); } /// /// 初始化 发送开始会话事件 /// /// /// /// /// /// public void OnInit(bool wake,string publicString,string uid = null,Dictionary eventDataDic = null,Dictionary userDataDic = null) { // if (PlayerPrefs.HasKey(sessionCachePrefsKey)) // { // PlayerPrefs.DeleteKey(sessionCachePrefsKey); // PlayerPrefs.Save(); // } // return; if (!wake) { Destroy(gameObject); return; } SessionCache.Instance.OnInit(publicString, 7); _uid = uid != null ? uid : _uid; _publicString = publicString; _startEventTimestamp = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000; // _sessionId = _uid + _startEventTimestamp + GenerateRandomString(10); _sessionId = DateTime.Now.ToUniversalTime().Ticks.ToString(); _uuid = Guid.NewGuid().ToString(); _userDataDic = new Dictionary(); _eventDic = new Dictionary { ["session_id"] = _sessionId, ["session_dur"] = 0, ["user_properties"] = _userDataDic }; SessionEventData _sessionStartEventData = new SessionEventData { uuid = _uuid, event_name = StartSession, event_timestamp = _startEventTimestamp, public_properties = _publicString, event_properties = _eventDic }; ChangeEventDataDic(eventDataDic); ChangeUserDataDic(userDataDic); ReportEvent(_sessionStartEventData); ReSend(); } /// /// 修改事件数据 /// /// public void ChangeEventDataDic(Dictionary eventDataDic) { if (eventDataDic != null) { Dictionary mergedDict = _eventDic.Union(eventDataDic.Where(kvp => !_eventDic.ContainsKey(kvp.Key))) .ToDictionary(pair => pair.Key, pair => pair.Value); _eventDic = mergedDict; } } /// /// 修改用户数据 /// /// public void ChangeUserDataDic(Dictionary userDataDic) { _userDataDic = userDataDic == null ? _userDataDic : userDataDic; } private void ReportEvent(SessionEventData eventData) { AddToList(eventData); StartNetworkRequest(Instance.SendSessionEvent(eventData)); } /// /// 单独发送 会话数据 /// /// /// /// private IEnumerator SendSessionEvent(SessionEventData eventData) { string eventDataStr = JsonConvert.SerializeObject(eventData); // 发送POST请求 using (UnityWebRequest www = new UnityWebRequest(GlobalConst.AnalyseUrl + GlobalConst.AnalyseAppId, "POST")) { byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(eventDataStr); www.uploadHandler = new UploadHandlerRaw(bodyRaw); www.downloadHandler = new DownloadHandlerBuffer(); www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); // 检查是否有错误发生 if (www.result != UnityWebRequest.Result.Success) { // Debug.Log("Error: " + www.error); } else { // 获取服务器响应的文本内容 // string responseText = www.downloadHandler.text; // 输出服务器响应内容 // Debug.Log("Server Response: " + responseText); if (eventData != null) //如果是批量重发,就清空缓存器 { SessionCache.Instance.RemoveEventData(eventData.event_name,eventData.uuid); } } if (www.isNetworkError || www.isHttpError) { // Debug.LogError("Error: " + www.error); } } } private void ReSend() { string ListStr = String.Empty; Dictionary> showDic = SessionCache.Instance.CleanDelayAndCollectEvent(ref ListStr); if (ListStr != String.Empty && ListStr.Length > 0) { StartNetworkRequest(Instance.SendCacheEvent(ListStr,showDic)); } } /// /// 发送缓存数据 /// /// private IEnumerator SendCacheEvent(string ListStr,Dictionary> showDic) { // 发送POST请求 using (UnityWebRequest www = new UnityWebRequest(GlobalConst.AnalyseUrl + GlobalConst.AnalyseAppId + ReSendUrl, "POST")) { byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(ListStr); www.uploadHandler = new UploadHandlerRaw(bodyRaw); www.downloadHandler = new DownloadHandlerBuffer(); www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); // 检查是否有错误发生 if (www.result != UnityWebRequest.Result.Success) { // Debug.Log("Error: " + www.error); } else { // 获取服务器响应的文本内容 // string responseText = www.downloadHandler.text; // 输出服务器响应内容 // Debug.Log("Server Response: " + responseText); foreach (KeyValuePair> keyValuePair in showDic) { for (int i = 0; i < keyValuePair.Value.Count; i++) { if (SessionCache.Instance.SessionDic.ContainsKey(keyValuePair.Key) && SessionCache.Instance.SessionDic[keyValuePair.Key].ContainsKey(keyValuePair.Value[i])) { SessionCache.Instance.SessionDic[keyValuePair.Key].Remove(keyValuePair.Value[i]); } } keyValuePair.Value.Clear(); } showDic.Clear(); ReSend(); } if (www.isNetworkError || www.isHttpError) { // Debug.LogError("Error: " + www.error); } } } private void AddToList(SessionEventData sessionEventData) { SessionCache.Instance.AddEvetData(Session_Name.start_end_session,sessionEventData); } #endregion #region 协程处理 private Coroutine networkCoroutine; private void StartNetworkRequest(IEnumerator coroutine) { if (networkCoroutine == null) //检查是否已有协程在运行 { networkCoroutine = StartCoroutine(coroutine); } else { StopCoroutine(networkCoroutine); networkCoroutine = StartCoroutine(coroutine); } } private void StopNetworkRequest() { if (networkCoroutine != null) { StopCoroutine(networkCoroutine); networkCoroutine = null; } } #endregion } /// /// 消息事件 缓存器 /// public class SessionCache : Singleton { public Dictionary> SessionDic; private const string sessionCacheKey = "sessionCacheKey"; private const string tempIdCacheKey = "tempIdCacheKey"; private string _publicString = String.Empty; private int _deleteDay; //延迟几天删除 public void OnInit(string publicString,int day) { // if (PlayerPrefs.HasKey(sessionCacheKey)) // { // PlayerPrefs.DeleteKey(sessionCacheKey); // PlayerPrefs.Save(); // } // return; _publicString = publicString; _deleteDay = day; InitData(); } private void InitData() { if (PlayerPrefs.HasKey(sessionCacheKey)) { SessionDic = JsonConvert.DeserializeObject>>(PlayerPrefs.GetString(sessionCacheKey, "")); } else { SessionDic = new Dictionary>(); } } public void AddEvetData(Session_Name event_Name,object eventData) { switch (event_Name) { case Session_Name.start_end_session: SessionEventData start_end_session = eventData as SessionEventData; start_end_session.public_properties = String.Empty; if (!SessionDic.ContainsKey(Session_Name.start_end_session.ToString())) { Dictionary start_sessionDic = new Dictionary(); SessionDic.Add(Session_Name.start_end_session.ToString(), start_sessionDic); } if (!SessionDic[Session_Name.start_end_session.ToString()].ContainsKey(start_end_session.uuid)) { SessionDic[Session_Name.start_end_session.ToString()].Add(start_end_session.uuid,JsonConvert.SerializeObject(start_end_session)); } break; case Session_Name.default_session: EventData default_session = eventData as EventData; default_session.public_properties = String.Empty; if (!SessionDic.ContainsKey(Session_Name.default_session.ToString())) { Dictionary default_sessionDic = new Dictionary(); SessionDic.Add(Session_Name.default_session.ToString(), default_sessionDic); } if (!SessionDic[Session_Name.default_session.ToString()].ContainsKey(default_session.uuid)) { SessionDic[Session_Name.default_session.ToString()].Add(default_session.uuid,JsonConvert.SerializeObject(default_session)); } break; } SaveCache(); } /// /// 保存缓存数据 /// public void SaveCache() { PlayerPrefs.SetString(sessionCacheKey,JsonConvert.SerializeObject(SessionDic)); PlayerPrefs.Save(); } /// /// 移除特定缓存数据 /// /// 对应缓存eventName名称 /// public void RemoveEventData(string event_Name, string uuid) { if (SessionDic.ContainsKey(event_Name) && SessionDic[event_Name].ContainsKey(uuid)) { SessionDic[event_Name].Remove(uuid); } } /// /// 清理过期数据 /// /// public Dictionary> CleanDelayAndCollectEvent(ref string ListStr) { Dictionary> _deleteDic = new Dictionary>(); //过期需要清理的缓存数据 Dictionary> _showDic = new Dictionary>(); //单次缓存数据的存储 List eventList = new List(10); //和服务端沟通 定单次缓存的 数组容量为10 foreach (KeyValuePair> keyValuePair in SessionDic) { switch (keyValuePair.Key) { case "start_end_session": foreach (KeyValuePair valuePair in keyValuePair.Value) { SessionEventData start_end_session_SessionEventData = JsonConvert.DeserializeObject(valuePair.Value.ToString()); start_end_session_SessionEventData.public_properties = _publicString; if (GetDeleyTime(start_end_session_SessionEventData.event_timestamp)) { if (!_deleteDic.ContainsKey(Session_Name.start_end_session.ToString())) { List uuidList = new List(); _deleteDic.Add(Session_Name.start_end_session.ToString(),uuidList); } _deleteDic[Session_Name.start_end_session.ToString()].Add(start_end_session_SessionEventData.uuid); } else { if (eventList.Count < 10) { eventList.Add(start_end_session_SessionEventData); if (!_showDic.ContainsKey(Session_Name.start_end_session.ToString())) { List uuidList = new List(); _showDic.Add(Session_Name.start_end_session.ToString(),uuidList); } _showDic[Session_Name.start_end_session.ToString()].Add(start_end_session_SessionEventData.uuid); } } } break; case "default_session": foreach (KeyValuePair valuePair in keyValuePair.Value) { EventData default_session_SessionEventData = JsonConvert.DeserializeObject(valuePair.Value.ToString()); default_session_SessionEventData.public_properties = _publicString; if (GetDeleyTime(default_session_SessionEventData.event_timestamp)) { if (!_deleteDic.ContainsKey(Session_Name.default_session.ToString())) { List uuidList = new List(); _deleteDic.Add(Session_Name.default_session.ToString(),uuidList); } _deleteDic[Session_Name.default_session.ToString()].Add(default_session_SessionEventData.uuid); } else { if (eventList.Count < 10) { eventList.Add(default_session_SessionEventData); if (!_showDic.ContainsKey(Session_Name.default_session.ToString())) { List uuidList = new List(); _showDic.Add(Session_Name.default_session.ToString(),uuidList); } _showDic[Session_Name.default_session.ToString()].Add(default_session_SessionEventData.uuid); } } } break; } } foreach (KeyValuePair> keyValuePair in _deleteDic) { for (int i = 0; i < keyValuePair.Value.Count; i++) { SessionDic[keyValuePair.Key].Remove(keyValuePair.Value[i]); } } if (eventList.Count > 0) { ListStr = JsonConvert.SerializeObject(eventList); } else { ListStr = String.Empty; } return _showDic; } private bool GetDeleyTime(long t) { double time = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000 - t; if (Math.Floor(time / 86400) > _deleteDay) { return true; } return false; } /// /// 处理临时id /// /// public long TempId() { //缓存临时id的机制 long _uid; if (EliminateModule.TempUid()) { if (!PlayerPrefs.HasKey(tempIdCacheKey)) { PlayerPrefs.SetString(tempIdCacheKey,EliminateModule.GetUid()); PlayerPrefs.Save(); } _uid = long.Parse(PlayerPrefs.GetString(tempIdCacheKey)); } else { if (PlayerPrefs.HasKey(tempIdCacheKey)) { EventData match_tmp_event = new EventData { uuid = Guid.NewGuid().ToString(), event_name = "match_tmp_id", event_properties = { {"tmp_uid",long.Parse(PlayerPrefs.GetString(tempIdCacheKey))}, {"real_uid",long.Parse(EliminateModule.GetUid())} } }; AddEvetData(Session_Name.default_session, match_tmp_event); PlayerPrefs.DeleteKey(tempIdCacheKey); PlayerPrefs.Save(); } _uid = long.Parse(EliminateModule.GetUid()); } return _uid; } } /// /// 开始&结束会话 /// [Serializable] public class SessionEventData { public string uuid; public string event_name; public long event_timestamp; public string public_properties; public Dictionary event_properties; } /// /// 普通会话 /// [Serializable] public class EventData { public string uuid; public string event_name; public long event_timestamp; public string public_properties; public Dictionary event_properties; public int tempUf; } public enum Session_Name { start_end_session, //开始/结束会话 default_session //普通会话 } } ```