using System; using System.Collections.Generic; using System.Threading; using ThinkingSDK.PC.Config; using ThinkingSDK.PC.Constant; using ThinkingSDK.PC.DataModel; using ThinkingSDK.PC.Request; using ThinkingSDK.PC.Storage; using ThinkingSDK.PC.TaskManager; using ThinkingSDK.PC.Time; using ThinkingSDK.PC.Utils; using UnityEngine; namespace ThinkingSDK.PC.Main { [Flags] public enum AUTO_TRACK_EVENTS { NONE = 0, APP_START = 1 << 0, // 当应用进入前台的时候触发上报,对应 ta_app_start APP_END = 1 << 1, // 当应用进入后台的时候触发上报,对应 ta_app_end APP_CRASH = 1 << 4, // 当出现未捕获异常的时候触发上报,对应 ta_app_crash APP_INSTALL = 1 << 5, // 应用安装后首次打开的时候触发上报,对应 ta_app_install ALL = APP_START | APP_END | APP_INSTALL | APP_CRASH } public interface IDynamicSuperProperties { Dictionary GetDynamicSuperProperties(); } public class ThinkingSDKInstance { private string mAppid; private string mServer; private string mDistinctID; private string mAccountID; private bool mOptTracking = true; private Dictionary mTimeEvents = new Dictionary(); private bool mEnableTracking = true; private Dictionary mSupperProperties = new Dictionary(); private ThinkingSDKConfig mConfig; private ThinkingSDKBaseRequest mRequest; private ThinkingSDKTimeCalibration mTimeCalibration; private IDynamicSuperProperties mDynamicProperties; private ThinkingSDKTask mTask = new ThinkingSDKTask(); ResponseHandle mResponseHandle; public void SetTimeCalibratieton(ThinkingSDKTimeCalibration timeCalibration) { this.mTimeCalibration = timeCalibration; } private ThinkingSDKInstance() { } private void DefaultData() { DistinctId(); AccountID(); SuperProperties(); DefaultTrackState(); } public ThinkingSDKInstance(string appid,string server):this(appid,server,null) { } public ThinkingSDKInstance(string appid, string server, ThinkingSDKConfig config) { mResponseHandle = delegate (Dictionary result) { mTask.Release(); }; if (config == null) { this.mConfig = ThinkingSDKConfig.GetInstance(appid, server); } else { this.mConfig = config; } this.mAppid = appid; this.mServer = server; if (this.mConfig.GetMode() == Mode.NORMAL) { this.mRequest = new ThinkingSDKNormalRequest(appid, this.mConfig.NormalURL()); } else { this.mRequest = new ThinkingSDKDebugRequest(appid,this.mConfig.DebugURL()); if (this.mConfig.GetMode() == Mode.DEBUG_ONLY) { ((ThinkingSDKDebugRequest)this.mRequest).SetDryRun(1); } } DefaultData(); } public ThinkingSDKTimeInter GetTime(DateTime dateTime) { ThinkingSDKTimeInter time = null; if ( dateTime == DateTime.MinValue || dateTime == null) { if (mTimeCalibration == null)//判断是否有时间校准 { time = new ThinkingSDKTime(mConfig.TimeZone(), DateTime.Now); } else { time = new ThinkingSDKCalibratedTime(mTimeCalibration, mConfig.TimeZone()); } } else { time = new ThinkingSDKTime(mConfig.TimeZone(), dateTime); } return time; } //设置访客ID public void Identifiy(string distinctID) { if (IsPaused()) { return; } if (!string.IsNullOrEmpty(distinctID)) { this.mDistinctID = distinctID; ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.DISTINCT_ID,distinctID); } } public string DistinctId() { this.mDistinctID = (string)ThinkingSDKFile.GetData(this.mAppid,ThinkingSDKConstant.DISTINCT_ID, typeof(string)); if (string.IsNullOrEmpty(this.mDistinctID)) { this.mDistinctID = ThinkingSDKUtil.RandomID(); ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.DISTINCT_ID, this.mDistinctID); } return this.mDistinctID; } public void Login(string accountID) { if (IsPaused()) { return; } if (!string.IsNullOrEmpty(accountID)) { this.mAccountID = accountID; ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.ACCOUNT_ID, accountID); } } public string AccountID() { this.mAccountID = (string)ThinkingSDKFile.GetData(this.mAppid,ThinkingSDKConstant.ACCOUNT_ID, typeof(string)); return this.mAccountID; } public void Logout() { if (IsPaused()) { return; } this.mAccountID = ""; ThinkingSDKFile.DeleteData(this.mAppid,ThinkingSDKConstant.ACCOUNT_ID); } //TODO public void EnableAutoTrack(AUTO_TRACK_EVENTS events) { if ((events & AUTO_TRACK_EVENTS.APP_INSTALL) != 0) { object result = ThinkingSDKFile.GetData(mAppid, ThinkingSDKConstant.IS_INSTALL, typeof(int)); if (result == null) { ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.IS_INSTALL, 1); Track(ThinkingSDKConstant.INSTALL_EVENT); } } if ((events & AUTO_TRACK_EVENTS.APP_START) != 0) { Track(ThinkingSDKConstant.START_EVENT); } } public void Track(string eventName) { Track(eventName, null, DateTime.MinValue); } public void Track(string eventName, Dictionary properties) { Track(eventName, properties, DateTime.MinValue); } public void Track(string eventName, Dictionary properties, DateTime date) { Track(eventName, properties, date, false); } public void Track(string eventName, Dictionary properties, DateTime date, bool immediately) { ThinkingSDKTimeInter time = GetTime(date); ThinkingSDKEventData data = new ThinkingSDKEventData(time, eventName, properties); SendData(data, immediately); } private void SendData(ThinkingSDKEventData data) { SendData(data, false); } private void SendData(ThinkingSDKEventData data, bool immediately) { if (this.mDynamicProperties != null) { data.SetProperties(this.mDynamicProperties.GetDynamicSuperProperties(),false); } if (this.mSupperProperties != null && this.mSupperProperties.Count > 0) { data.SetProperties(this.mSupperProperties,false); } data.SetProperties(ThinkingSDKUtil.DeviceInfo(), false); float duration = 0; if (mTimeEvents.ContainsKey(data.EventName())) { int beginTime = (int)mTimeEvents[data.EventName()]; int nowTime = Environment.TickCount; duration = (float)((nowTime - beginTime) / 1000.0); mTimeEvents.Remove(data.EventName()); } if (duration != 0) { data.SetDuration(duration); } SendData((ThinkingSDKBaseData)data, immediately); } private void SendData(ThinkingSDKBaseData data) { SendData(data, false); } private void SendData(ThinkingSDKBaseData data, bool immediately) { if (IsPaused()) { return; } if (!string.IsNullOrEmpty(this.mAccountID)) { data.SetAccountID(this.mAccountID); } if (string.IsNullOrEmpty(this.mDistinctID)) { DistinctId(); } data.SetDistinctID(this.mDistinctID); IList> list = new List>(); list.Add(data.ToDictionary()); if (this.mConfig.GetMode() == Mode.NORMAL && this.mRequest.GetType() != typeof(ThinkingSDKNormalRequest)) { this.mRequest = new ThinkingSDKNormalRequest(this.mAppid, this.mConfig.NormalURL()); } if (immediately) { mRequest.SendData(null, list); } else { mTask.StartRequest(mRequest, mResponseHandle, list); } } /// /// 发送数据 /// public void Flush() { mTask.SyncInvokeAllTask(); } public void Track(ThinkingSDKEventData analyticsEvent) { ThinkingSDKTimeInter time = GetTime(analyticsEvent.Time()); analyticsEvent.SetTime(time); SendData(analyticsEvent); } public void SetSuperProperties(Dictionary superProperties) { if (IsPaused()) { return; } Dictionary properties = new Dictionary(); string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string)); if (!string.IsNullOrEmpty(propertiesStr)) { properties = ThinkingSDKJSON.Deserialize(propertiesStr); } ThinkingSDKUtil.AddDictionary(properties, superProperties); this.mSupperProperties = properties; ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, ThinkingSDKJSON.Serialize(this.mSupperProperties)); } public void UnsetSuperProperty(string propertyKey) { if (IsPaused()) { return; } Dictionary properties = new Dictionary(); string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string)); if (!string.IsNullOrEmpty(propertiesStr)) { properties = ThinkingSDKJSON.Deserialize(propertiesStr); } if (properties.ContainsKey(propertyKey)) { properties.Remove(propertyKey); } this.mSupperProperties = properties; ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, ThinkingSDKJSON.Serialize(this.mSupperProperties)); } public Dictionary SuperProperties() { string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string)); if (!string.IsNullOrEmpty(propertiesStr)) { this.mSupperProperties = ThinkingSDKJSON.Deserialize(propertiesStr); } return this.mSupperProperties; } public Dictionary PresetProperties() { Dictionary presetProperties = new Dictionary(); presetProperties[ThinkingSDKConstant.DEVICE_ID] = ThinkingSDKDeviceInfo.DeviceID(); presetProperties[ThinkingSDKConstant.CARRIER] = ThinkingSDKDeviceInfo.Carrier(); presetProperties[ThinkingSDKConstant.OS] = ThinkingSDKDeviceInfo.OS(); presetProperties[ThinkingSDKConstant.SCREEN_HEIGHT] = ThinkingSDKDeviceInfo.ScreenHeight(); presetProperties[ThinkingSDKConstant.SCREEN_WIDTH] = ThinkingSDKDeviceInfo.ScreenWidth(); presetProperties[ThinkingSDKConstant.MANUFACTURE] = ThinkingSDKDeviceInfo.Manufacture(); presetProperties[ThinkingSDKConstant.DEVICE_MODEL] = ThinkingSDKDeviceInfo.DeviceModel(); presetProperties[ThinkingSDKConstant.SYSTEM_LANGUAGE] = ThinkingSDKDeviceInfo.MachineLanguage(); presetProperties[ThinkingSDKConstant.OS_VERSION] = ThinkingSDKDeviceInfo.OSVersion(); presetProperties[ThinkingSDKConstant.NETWORK_TYPE] = ThinkingSDKDeviceInfo.NetworkType(); presetProperties[ThinkingSDKConstant.APP_BUNDLEID] = ThinkingSDKAppInfo.AppIdentifier(); presetProperties[ThinkingSDKConstant.ZONE_OFFSET] = ThinkingSDKUtil.ZoneOffset(DateTime.Now, this.mConfig.TimeZone()); return presetProperties; } public void ClearSuperProperties() { if (IsPaused()) { return; } this.mSupperProperties.Clear(); ThinkingSDKFile.DeleteData(this.mAppid,ThinkingSDKConstant.SUPER_PROPERTY); } public void TimeEvent(string eventName) { if (!mTimeEvents.ContainsKey(eventName)) { mTimeEvents.Add(eventName, Environment.TickCount); } } public void UserSet(Dictionary properties) { UserSet(properties, DateTime.MinValue); } public void UserSet(Dictionary properties,DateTime dateTime) { ThinkingSDKTimeInter time = GetTime(dateTime); ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_SET, properties); SendData(data); } public void UserUnset(string propertyKey) { UserUnset(propertyKey, DateTime.MinValue); } public void UserUnset(string propertyKey, DateTime dateTime) { ThinkingSDKTimeInter time = GetTime(dateTime); Dictionary properties = new Dictionary(); properties[propertyKey] = 0; ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties); SendData(data); } public void UserUnset(List propertyKeys) { UserUnset(propertyKeys,DateTime.MinValue); } public void UserUnset(List propertyKeys, DateTime dateTime) { ThinkingSDKTimeInter time = GetTime(dateTime); Dictionary properties = new Dictionary(); foreach (string key in propertyKeys) { properties[key] = 0; } ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties); SendData(data); } public void UserSetOnce(Dictionary properties) { UserSetOnce(properties, DateTime.MinValue); } public void UserSetOnce(Dictionary properties, DateTime dateTime) { ThinkingSDKTimeInter time = GetTime(dateTime); ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_SETONCE, properties); SendData(data); } public void UserAdd(Dictionary properties) { UserAdd(properties, DateTime.MinValue); } public void UserAdd(Dictionary properties, DateTime dateTime) { ThinkingSDKTimeInter time = GetTime(dateTime); ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_ADD, properties); SendData(data); } public void UserAppend(Dictionary properties) { UserAppend(properties, DateTime.MinValue); } public void UserAppend(Dictionary properties, DateTime dateTime) { ThinkingSDKTimeInter time = GetTime(dateTime); ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_APPEND, properties); SendData(data); } public void UserDelete() { UserDelete(DateTime.MinValue); } public void UserDelete(DateTime dateTime) { ThinkingSDKTimeInter time = GetTime(dateTime); Dictionary properties = new Dictionary(); ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_DEL,properties); SendData(data); } public void SetDynamicSuperProperties(IDynamicSuperProperties dynamicSuperProperties) { if (IsPaused()) { return; } this.mDynamicProperties = dynamicSuperProperties; } private bool IsPaused() { return !mEnableTracking || !mOptTracking; } /* 停止或开启数据上报,默认是开启状态,设置为停止时还会清空本地的访客ID,账号ID,静态公共属性 其中true表示可以上报数据,false表示停止数据上报 **/ public void OptTracking(bool optTracking) { mOptTracking = optTracking; int opt = optTracking ? 1 : 0; ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.OPT_TRACK, opt); if (!optTracking) { ThinkingSDKFile.DeleteData(mAppid, ThinkingSDKConstant.ACCOUNT_ID); ThinkingSDKFile.DeleteData(mAppid, ThinkingSDKConstant.DISTINCT_ID); ThinkingSDKFile.DeleteData(mAppid, ThinkingSDKConstant.SUPER_PROPERTY); this.mAccountID = null; this.mDistinctID = null; this.mSupperProperties = new Dictionary(); } } //是否暂停数据上报,默认是正常上报状态,其中true表示可以上报数据,false表示暂停数据上报 public void EnableTracking(bool isEnable) { mEnableTracking = isEnable; int enable = isEnable ? 1 : 0; ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.ENABLE_TRACK,enable); } private void DefaultTrackState() { object enableTrack = ThinkingSDKFile.GetData(mAppid, ThinkingSDKConstant.ENABLE_TRACK, typeof(int)); object optTrack = ThinkingSDKFile.GetData(mAppid, ThinkingSDKConstant.OPT_TRACK, typeof(int)); if (enableTrack != null) { this.mEnableTracking = ((int)enableTrack) == 1; } else { this.mEnableTracking = true; } if (optTrack != null) { this.mOptTracking = ((int)optTrack) == 1; } else { this.mOptTracking = true; } } //停止数据上报 public void OptTrackingAndDeleteUser() { UserDelete(); OptTracking(false); } public string TimeString(DateTime dateTime) { return ThinkingSDKUtil.FormatDate(dateTime, mConfig.TimeZone()); } } }