967 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			967 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C#
		
	
/*
 | 
						||
 * 
 | 
						||
    Copyright 2019, ThinkingData, Inc
 | 
						||
    Licensed under the Apache License, Version 2.0 (the "License");
 | 
						||
    you may not use this file except in compliance with the License.
 | 
						||
    You may obtain a copy of the License at
 | 
						||
 | 
						||
        http://www.apache.org/licenses/LICENSE-2.0
 | 
						||
 | 
						||
    Unless required by applicable law or agreed to in writing, software
 | 
						||
    distributed under the License is distributed on an "AS IS" BASIS,
 | 
						||
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						||
    See the License for the specific language governing permissions and
 | 
						||
    limitations under the License.
 | 
						||
    SDK VERSION:2.2.1
 | 
						||
 */
 | 
						||
#if !(UNITY_5_4_OR_NEWER)
 | 
						||
#define DISABLE_TA
 | 
						||
#warning "Your Unity version is not supported by us - ThinkingAnalyticsSDK disabled"
 | 
						||
#endif
 | 
						||
#if !(UNITY_EDITOR || UNITY_IOS || UNITY_ANDROID || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN)
 | 
						||
#define DISABLE_TA
 | 
						||
#warning "Your Unity Platfrom is not supported by us - ThinkingAnalyticsSDK disabled"
 | 
						||
#endif
 | 
						||
 | 
						||
using System;
 | 
						||
using System.Collections.Generic;
 | 
						||
using System.Threading;
 | 
						||
using ThinkingAnalytics.Utils;
 | 
						||
using ThinkingAnalytics.Wrapper;
 | 
						||
using UnityEngine;
 | 
						||
#if UNITY_EDITOR
 | 
						||
using UnityEditor;
 | 
						||
using UnityEditor.Callbacks;
 | 
						||
//using UnityEditor.iOS.Xcode;
 | 
						||
#endif
 | 
						||
using System.IO;
 | 
						||
using ThinkingAnalytics.TaException;
 | 
						||
 | 
						||
namespace ThinkingAnalytics
 | 
						||
{
 | 
						||
    /// <summary>
 | 
						||
    /// Dynamic super properties interfaces.
 | 
						||
    /// </summary>
 | 
						||
    public interface IDynamicSuperProperties
 | 
						||
    {
 | 
						||
        Dictionary<string, object> GetDynamicSuperProperties();
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 内部使用的特殊事件类, 不要直接使用此类。
 | 
						||
    /// </summary>
 | 
						||
    public class ThinkingAnalyticsEvent
 | 
						||
    {
 | 
						||
        public enum Type
 | 
						||
        {
 | 
						||
            FIRST,
 | 
						||
            UPDATABLE,
 | 
						||
            OVERWRITABLE
 | 
						||
        }
 | 
						||
 | 
						||
        public ThinkingAnalyticsEvent(string eventName, Dictionary<string, object> properties) {
 | 
						||
            EventName = eventName;
 | 
						||
            Properties = properties;
 | 
						||
        }
 | 
						||
 | 
						||
        public Type? EventType { get; set; }
 | 
						||
        public string EventName { get; set; }
 | 
						||
        public Dictionary<string, object> Properties { get; set; }
 | 
						||
 | 
						||
        public DateTime EventTime { get; set; }
 | 
						||
        public string ExtraId { get; set; }
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 首次(唯一)事件。默认情况下采集设备首次事件。请咨询数数客户成功获取支持。
 | 
						||
    /// </summary>
 | 
						||
    public class TDFirstEvent : ThinkingAnalyticsEvent
 | 
						||
    {
 | 
						||
        public TDFirstEvent(string eventName, Dictionary<string, object> properties) : base(eventName, properties)
 | 
						||
        {
 | 
						||
            EventType = Type.FIRST;
 | 
						||
        }
 | 
						||
        
 | 
						||
        /// <summary>
 | 
						||
        /// 设置用于检测是否首次的 ID,默认情况下会使用设备 ID
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="firstCheckId">用于首次事件检测的 ID</param>
 | 
						||
        public void SetFirstCheckId(string firstCheckId)
 | 
						||
        {
 | 
						||
            ExtraId = firstCheckId;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 可被更新的事件。请咨询数数客户成功获取支持。
 | 
						||
    /// </summary>
 | 
						||
    public class TDUpdatableEvent : ThinkingAnalyticsEvent
 | 
						||
    {
 | 
						||
        public TDUpdatableEvent(string eventName, Dictionary<string, object> properties, string eventId) : base(eventName, properties)
 | 
						||
        {
 | 
						||
            EventType = Type.UPDATABLE;
 | 
						||
            ExtraId = eventId;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 可被重写的事件。请咨询数数客户成功获取支持。
 | 
						||
    /// </summary>
 | 
						||
    public class TDOverWritableEvent : ThinkingAnalyticsEvent
 | 
						||
    {
 | 
						||
        public TDOverWritableEvent(string eventName, Dictionary<string, object> properties, string eventId) : base(eventName, properties)
 | 
						||
        {
 | 
						||
            EventType = Type.OVERWRITABLE;
 | 
						||
            ExtraId = eventId;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    /// <summary>
 | 
						||
    /// 预置属性
 | 
						||
    /// </summary>
 | 
						||
    public class TDPresetProperties 
 | 
						||
    {
 | 
						||
		public static string BundleId 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#bundle_id"];}
 | 
						||
        }
 | 
						||
		public static string Carrier 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#carrier"];}
 | 
						||
        }
 | 
						||
 | 
						||
		public static string DeviceId
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#device_id"];}
 | 
						||
        }
 | 
						||
		public static string DeviceModel 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#device_model"];}
 | 
						||
        }
 | 
						||
		public static string Manufacturer 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#manufacturer"];}
 | 
						||
        }
 | 
						||
		public static string NetworkType 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#network_type"];}
 | 
						||
        }
 | 
						||
		public static string OS 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#os"];}
 | 
						||
        }
 | 
						||
		public static string OSVersion 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#os_version"];}
 | 
						||
        }
 | 
						||
		public static int ScreenHeight 
 | 
						||
        { 
 | 
						||
            get {return (int)TDPresetProperties.PresetProperties["#screen_height"];}
 | 
						||
        }
 | 
						||
		public static int ScreenWidth 
 | 
						||
        { 
 | 
						||
            get {return (int)TDPresetProperties.PresetProperties["#screen_width"];}
 | 
						||
        }
 | 
						||
		public static string SystemLanguage 
 | 
						||
        { 
 | 
						||
            get {return (string)TDPresetProperties.PresetProperties["#system_language"];}
 | 
						||
        }
 | 
						||
		public static double ZoneOffset 
 | 
						||
        { 
 | 
						||
            get {return (double)TDPresetProperties.PresetProperties["#zone_offset"];}
 | 
						||
        }
 | 
						||
		public static Dictionary<string, object> PresetProperties 
 | 
						||
        {
 | 
						||
            get { return TDPresetProperties.ToEventPresetProperties();} 
 | 
						||
        }
 | 
						||
 | 
						||
        // 返回事件预置属性的Key以"#"开头,不建议直接作为事件的Property使用
 | 
						||
        public static Dictionary<string, object> ToEventPresetProperties()
 | 
						||
        {
 | 
						||
            return ThinkingAnalyticsAPI.GetPresetProperties();
 | 
						||
        }
 | 
						||
         
 | 
						||
    }
 | 
						||
 | 
						||
    // 自动采集事件类型
 | 
						||
    [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,
 | 
						||
        NO_CRASH = APP_START | APP_END | APP_INSTALL
 | 
						||
    }
 | 
						||
 | 
						||
    public class ThinkingAnalyticsAPI : MonoBehaviour, TaExceptionHandler
 | 
						||
    {
 | 
						||
#region settings
 | 
						||
        [System.Serializable]
 | 
						||
        public struct Token
 | 
						||
        {
 | 
						||
            public string appid;
 | 
						||
            public string serverUrl;
 | 
						||
            public TAMode mode;
 | 
						||
            public TATimeZone timeZone;
 | 
						||
            public string timeZoneId;
 | 
						||
 | 
						||
            public Token(string appId, string serverUrl, TAMode mode, TATimeZone timeZone, string timeZoneId = null)
 | 
						||
            {
 | 
						||
                appid = appId;
 | 
						||
                this.serverUrl = serverUrl;
 | 
						||
                this.mode = mode;
 | 
						||
                this.timeZone = timeZone;
 | 
						||
                this.timeZoneId = timeZoneId;
 | 
						||
            }
 | 
						||
 | 
						||
            public string getTimeZoneId()
 | 
						||
            {
 | 
						||
                switch (timeZone)
 | 
						||
                {
 | 
						||
                    case TATimeZone.UTC:
 | 
						||
                        return "UTC";
 | 
						||
                    case TATimeZone.Asia_Shanghai:
 | 
						||
                        return "Asia/Shanghai";
 | 
						||
                    case TATimeZone.Asia_Tokyo:
 | 
						||
                        return "Asia/Tokyo";
 | 
						||
                    case TATimeZone.America_Los_Angeles:
 | 
						||
                        return "America/Los_Angeles";
 | 
						||
                    case TATimeZone.America_New_York:
 | 
						||
                        return "America/New_York";
 | 
						||
                    case TATimeZone.Other:
 | 
						||
                        return timeZoneId;
 | 
						||
                    default:
 | 
						||
                        break;
 | 
						||
                }
 | 
						||
                return null;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        public enum TATimeZone
 | 
						||
        {
 | 
						||
            Local,
 | 
						||
            UTC,
 | 
						||
            Asia_Shanghai,
 | 
						||
            Asia_Tokyo,
 | 
						||
            America_Los_Angeles,
 | 
						||
            America_New_York,
 | 
						||
            Other = 100
 | 
						||
        }
 | 
						||
 | 
						||
        public enum TAMode
 | 
						||
        {
 | 
						||
            NORMAL = 0,
 | 
						||
            DEBUG = 1,
 | 
						||
            DEBUG_ONLY = 2
 | 
						||
        }
 | 
						||
 | 
						||
        public enum NetworkType
 | 
						||
        {
 | 
						||
            DEFAULT = 1,
 | 
						||
            WIFI = 2,
 | 
						||
            ALL = 3
 | 
						||
        }
 | 
						||
 | 
						||
        [Header("Configuration")]
 | 
						||
        [Tooltip("是否打开 Log")]
 | 
						||
        public bool enableLog = true;
 | 
						||
        [Tooltip("设置网络类型")]
 | 
						||
        public NetworkType networkType = NetworkType.DEFAULT;
 | 
						||
 | 
						||
        [Header("Project")]
 | 
						||
        [Tooltip("项目相关配置, APP ID 会在项目申请时给出")]
 | 
						||
        [HideInInspector]
 | 
						||
        public Token[] tokens = new Token[1];
 | 
						||
 | 
						||
#endregion
 | 
						||
 | 
						||
        public readonly string VERSION = "2.2.1";
 | 
						||
 | 
						||
        private static ThinkingAnalyticsAPI taAPIInstance;
 | 
						||
 | 
						||
        //配置Xcode选项
 | 
						||
#if UNITY_EDITOR
 | 
						||
        //[PostProcessBuild]
 | 
						||
        [PostProcessBuildAttribute(88)]
 | 
						||
        public static void onPostProcessBuild(BuildTarget target, string targetPath)
 | 
						||
        {
 | 
						||
//            if (target != BuildTarget.iOS)
 | 
						||
//            {
 | 
						||
//                Debug.LogWarning("Target is not iPhone. XCodePostProcess will not run");
 | 
						||
//                return;
 | 
						||
//            }
 | 
						||
 | 
						||
//            string projPath = Path.GetFullPath(targetPath) + "/Unity-iPhone.xcodeproj/project.pbxproj";
 | 
						||
 | 
						||
//            UnityEditor.iOS.Xcode.PBXProject proj = new UnityEditor.iOS.Xcode.PBXProject();
 | 
						||
//            proj.ReadFromFile(projPath);
 | 
						||
//#if UNITY_2019_3_OR_NEWER
 | 
						||
//            string targetGuid = proj.GetUnityFrameworkTargetGuid();
 | 
						||
//#else
 | 
						||
//            string targetGuid = proj.TargetGuidByName(PBXProject.GetUnityTargetName());
 | 
						||
//#endif
 | 
						||
 | 
						||
//            //Build Property
 | 
						||
//            proj.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");//BitCode  NO
 | 
						||
//            proj.SetBuildProperty(targetGuid, "GCC_ENABLE_OBJC_EXCEPTIONS", "YES");//Enable Objective-C Exceptions
 | 
						||
 | 
						||
//            string[] headerSearchPathsToAdd = { "$(SRCROOT)/Libraries/Plugins/iOS/ThinkingSDK/Source/main", "$(SRCROOT)/Libraries/Plugins/iOS/ThinkingSDK/Source/common" };
 | 
						||
//            proj.UpdateBuildProperty(targetGuid, "HEADER_SEARCH_PATHS", headerSearchPathsToAdd, null);// Header Search Paths
 | 
						||
 | 
						||
//            //Add Frameworks
 | 
						||
//            proj.AddFrameworkToProject(targetGuid, "WebKit.framework", true);
 | 
						||
//            proj.AddFrameworkToProject(targetGuid, "CoreTelephony.framework", true);
 | 
						||
//            proj.AddFrameworkToProject(targetGuid, "SystemConfiguration.framework", true);
 | 
						||
//            proj.AddFrameworkToProject(targetGuid, "Security.framework", true);
 | 
						||
 | 
						||
//            //Add Lib
 | 
						||
//            proj.AddFileToBuild(targetGuid, proj.AddFile("usr/lib/libsqlite3.tbd", "libsqlite3.tbd", PBXSourceTree.Sdk));
 | 
						||
//            proj.AddFileToBuild(targetGuid, proj.AddFile("usr/lib/libz.tbd", "libz.tbd", PBXSourceTree.Sdk));
 | 
						||
 | 
						||
//            proj.WriteToFile(projPath);
 | 
						||
        }        
 | 
						||
#endif
 | 
						||
 | 
						||
            /// <summary>
 | 
						||
            /// 设置自定义访客 ID,用于替换系统生成的访客 ID
 | 
						||
            /// </summary>
 | 
						||
            /// <param name="FIRSTId">访客 ID</param>
 | 
						||
            /// <param name="appId">项目 ID(可选)</param>
 | 
						||
            public static void Identify(string FIRSTId, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).Identify(FIRSTId);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 返回当前的访客 ID.
 | 
						||
        /// </summary>
 | 
						||
        /// <returns>访客 ID</returns>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static string GetDistinctId(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                return getInstance(appId).GetDistinctId();
 | 
						||
            }
 | 
						||
            return null;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置账号 ID. 该方法不会上传用户登录事件.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="account">账号 ID</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void Login(string account, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).Login(account);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 清空账号 ID. 该方法不会上传用户登出事件.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目 ID(可选) </param>
 | 
						||
        public static void Logout(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).Logout();
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 主动触发上报缓存事件到服务器. 
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void Flush(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).Flush();
 | 
						||
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 开启自动采集功能.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void EnableAutoTrack(AUTO_TRACK_EVENTS events, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).EnableAutoTrack(events);
 | 
						||
 | 
						||
                //C#异常捕获提前,包含所有端
 | 
						||
                if ((events & AUTO_TRACK_EVENTS.APP_CRASH) != 0)
 | 
						||
                {
 | 
						||
                    ThinkingSDKExceptionHandler eHandler = new ThinkingSDKExceptionHandler();
 | 
						||
                    eHandler.SetTaExceptionHandler(taAPIInstance);
 | 
						||
                    eHandler.RegisterTaExceptionHandler();
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// 异常捕获回调
 | 
						||
        public void InvokeTaExceptionHandler(string eventName, Dictionary<string, object> properties)
 | 
						||
        {
 | 
						||
            Track(eventName, properties);
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// track 简单事件. 该事件会先缓存在本地,达到触发上报条件或者主动调用 Flush 时会上报到服务器.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="eventName">事件名称</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void Track(string eventName, string appId = "")
 | 
						||
        {
 | 
						||
            Track(eventName, null, appId);
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// track 事件及事件属性. 该事件会先缓存在本地,达到触发上报条件或者主动调用 Flush 时会上报到服务器.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="eventName">事件名称</param>
 | 
						||
        /// <param name="properties">Properties</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void Track(string eventName, Dictionary<string, object> properties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).Track(eventName, properties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// track 事件及事件属性,并指定 #event_time 属性. 该事件会先缓存在本地,达到触发上报条件或者主动调用 Flush 时会上报到服务器. 从 v1.3.0 开始,会考虑 date 的时区信息。支持 UTC 和 local 时区.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="eventName">事件名称</param>
 | 
						||
        /// <param name="properties">事件属性</param>
 | 
						||
        /// <param name="date">事件时间</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void Track(string eventName, Dictionary<string, object> properties, DateTime date, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).Track(eventName, properties, date);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        public static void Track(ThinkingAnalyticsEvent analyticsEvent, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).Track(analyticsEvent);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置公共事件属性. 公共事件属性指的就是每个事件都会带有的属性.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="superProperties">公共事件属性</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void SetSuperProperties(Dictionary<string, object> superProperties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).SetSuperProperties(superProperties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 删除某个公共事件属性.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="property">属性名称</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UnsetSuperProperty(string property, string appId  = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UnsetSuperProperty(property);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 返回当前公共事件属性.
 | 
						||
        /// </summary>
 | 
						||
        /// <returns>公共事件属性</returns>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static Dictionary<string, object> GetSuperProperties(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                return getInstance(appId).GetSuperProperties();
 | 
						||
            }
 | 
						||
            return null;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 清空公共事件属性.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void ClearSuperProperties(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).ClearSuperProperty();
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 返回事件预置属性,Key以"#"开头,不建议直接作为事件的Property使用
 | 
						||
        /// </summary>
 | 
						||
        /// <returns>事件预置属性</returns>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static Dictionary<string, object> GetPresetProperties(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                return getInstance(appId).GetPresetProperties();
 | 
						||
            }
 | 
						||
            return null;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 记录事件时长. 调用 TimeEvent 为某事件开始计时,当 track 传该事件时,SDK 会在在事件属性中加入 #duration 这一属性来表示事件时长,单位为秒.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="eventName">事件名称</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void TimeEvent(string eventName, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).TimeEvent(eventName);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置用户属性. 该接口上传的属性将会覆盖原有的属性值.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserSet(Dictionary<string, object> properties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserSet(properties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置用户属性. 该接口上传的属性将会覆盖原有的属性值.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="dateTime">用户属性设置的时间</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserSet(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserSet(properties, dateTime);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 重置一个用户属性.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="property">用户属性名称</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserUnset(string property, string appId = "")
 | 
						||
        {
 | 
						||
            List<string> properties = new List<string>();
 | 
						||
            properties.Add(property);
 | 
						||
            UserUnset(properties, appId);
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 重置一组用户属性
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性列表</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserUnset(List<string> properties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserUnset(properties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 重置一组用户属性, 并指定操作时间
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性列表</param>
 | 
						||
        /// <param name="dateTime">操作时间</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserUnset(List<string> properties, DateTime dateTime, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserUnset(properties, dateTime);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置用户属性. 当该属性之前已经有值的时候,将会忽略这条信息.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserSetOnce(Dictionary<string, object> properties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserSetOnce(properties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置用户属性. 当该属性之前已经有值的时候,将会忽略这条信息.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="dateTime">操作时间</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserSetOnce(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserSetOnce(properties, dateTime);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 对数值类用户属性进行累加. 如果该属性还未被设置,则会赋值 0 后再进行计算.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="property">属性名称</param>
 | 
						||
        /// <param name="value">数值</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserAdd(string property, object value, string appId = "")
 | 
						||
        {
 | 
						||
            Dictionary<string, object> properties = new Dictionary<string, object>()
 | 
						||
                {
 | 
						||
                    { property, value }
 | 
						||
                };
 | 
						||
            UserAdd(properties, appId);
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 对数值类用户属性进行累加. 如果属性还未被设置,则会赋值 0 后再进行计算.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserAdd(Dictionary<string, object> properties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserAdd(properties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 对数值类用户属性进行累加. 如果属性还未被设置,则会赋值 0 后再进行计算.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="dateTime">操作时间</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserAdd(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserAdd(properties, dateTime);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 对 List 类型的用户属性进行追加.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserAppend(Dictionary<string, object> properties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserAppend(properties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 对 List 类型的用户属性进行追加.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="properties">用户属性</param>
 | 
						||
        /// <param name="dateTime">操作时间</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserAppend(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserAppend(properties, dateTime);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 删除用户数据. 之后再查询该名用户的用户属性,但该用户产生的事件仍然可以被查询到
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserDelete(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserDelete();
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 删除用户数据并指定操作时间.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void UserDelete(DateTime dateTime, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).UserDelete(dateTime);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 设置允许上报数据到服务器的网络类型.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="networkType">网络类型</param>
 | 
						||
        /// <param name="appId">项目 ID(可选)</param>
 | 
						||
        public static void SetNetworkType(NetworkType networkType, string appId =  "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).SetNetworkType(networkType);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// Gets the device identifier.
 | 
						||
        /// </summary>
 | 
						||
        /// <returns>The device identifier.</returns>
 | 
						||
        public static string GetDeviceId()
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                return getInstance("").GetDeviceId();
 | 
						||
            } 
 | 
						||
            return null;
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// Sets the dynamic super properties.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="dynamicSuperProperties">Dynamic super properties interface.</param>
 | 
						||
        /// <param name="appId">App ID (optional).</param>
 | 
						||
        public static void SetDynamicSuperProperties(IDynamicSuperProperties dynamicSuperProperties, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).SetDynamicSuperProperties(dynamicSuperProperties);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 停止上报数据,并且清空本地缓存数据(未上报的数据、已设置的访客ID、账号ID、公共属性)
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目ID</param>
 | 
						||
        public static void OptOutTracking(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).OptOutTracking();
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 停止上报数据,清空本地缓存数据,并且发送 user_del 到服务端.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目ID</param>
 | 
						||
        public static void OptOutTrackingAndDeleteUser(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).OptOutTrackingAndDeleteUser();
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 恢复上报数据
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目ID</param>
 | 
						||
        public static void OptInTracking(string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).OptInTracking();
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 暂停/恢复上报数据,本地缓存不会被清空
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="enabled">是否打开上报数据</param>
 | 
						||
        /// <param name="appId">项目ID</param>
 | 
						||
        public static void EnableTracking(bool enabled, string appId = "")
 | 
						||
        {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                getInstance(appId).EnableTracking(enabled);
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 创建轻量级实例,轻量级实例与主实例共享项目ID. 访客ID、账号ID、公共属性不共享
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="appId">项目ID</param>
 | 
						||
        /// <returns>轻量级实例的 token </returns>
 | 
						||
        public static string CreateLightInstance(string appId = "") {
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                ThinkingAnalyticsWrapper lightInstance = getInstance(appId).CreateLightInstance();
 | 
						||
                instance_lock.EnterWriteLock();
 | 
						||
                try
 | 
						||
                {
 | 
						||
                    sInstances.Add(lightInstance.GetAppId(), lightInstance);
 | 
						||
                } finally
 | 
						||
                {
 | 
						||
                    instance_lock.ExitWriteLock();
 | 
						||
                }
 | 
						||
                return lightInstance.GetAppId();
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                return null;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 传入时间戳校准 SDK 时间.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="timestamp">当前 Unix timestamp, 单位 毫秒</param>
 | 
						||
        public static void CalibrateTime(long timestamp)
 | 
						||
        {
 | 
						||
            ThinkingAnalyticsWrapper.CalibrateTime(timestamp);
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 传入 NTP Server 地址校准 SDK 时间.
 | 
						||
        ///
 | 
						||
        /// 您可以根据您用户所在地传入访问速度较快的 NTP Server 地址, 例如 time.asia.apple.com
 | 
						||
        /// SDK 默认情况下会等待 3 秒,去获取时间偏移数据,并用该偏移校准之后的数据.
 | 
						||
        /// 如果在 3 秒内未因网络原因未获得正确的时间偏移,本次应用运行期间将不会再校准时间.
 | 
						||
        /// </summary>
 | 
						||
        /// <param name="timestamp">可用的 NTP 服务器地址</param>
 | 
						||
        public static void CalibrateTimeWithNtp(string ntpServer)
 | 
						||
        {
 | 
						||
            ThinkingAnalyticsWrapper.CalibrateTimeWithNtp(ntpServer);
 | 
						||
        }
 | 
						||
 | 
						||
        //多实例场景,设置默认的appid
 | 
						||
        public static void setDefaultAppid(string appid)
 | 
						||
        {
 | 
						||
            if (sInstances.Count > 0 && sInstances.ContainsKey(appid))
 | 
						||
            {
 | 
						||
                default_appid = appid;
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
#region internal
 | 
						||
 | 
						||
        void Awake()
 | 
						||
        {
 | 
						||
            taAPIInstance = this;
 | 
						||
#if DISABLE_TA
 | 
						||
            tracking_enabled = false;
 | 
						||
#endif
 | 
						||
            TD_Log.EnableLog(enableLog);
 | 
						||
            ThinkingAnalyticsWrapper.SetVersionInfo(VERSION);
 | 
						||
            if (TA_instance == null)
 | 
						||
            {
 | 
						||
                DontDestroyOnLoad(gameObject);
 | 
						||
                TA_instance = this;
 | 
						||
            } else
 | 
						||
            {
 | 
						||
                Destroy(gameObject);
 | 
						||
                return;
 | 
						||
            }
 | 
						||
 | 
						||
            if (tracking_enabled)
 | 
						||
            {
 | 
						||
                default_appid = tokens[0].appid;
 | 
						||
                instance_lock.EnterWriteLock();
 | 
						||
                try
 | 
						||
                {
 | 
						||
                    ThinkingAnalyticsWrapper.EnableLog(enableLog);
 | 
						||
                    foreach (Token token in tokens)
 | 
						||
                    {
 | 
						||
                        //Debug.Log("token:"+token.appid);
 | 
						||
                        if (!string.IsNullOrEmpty(token.appid))
 | 
						||
                        {
 | 
						||
                            ThinkingAnalyticsWrapper wrapper = new ThinkingAnalyticsWrapper(token);
 | 
						||
                            wrapper.SetNetworkType(networkType);
 | 
						||
                            sInstances.Add(token.appid,wrapper);
 | 
						||
 | 
						||
                        }
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                finally
 | 
						||
                {
 | 
						||
                    instance_lock.ExitWriteLock();
 | 
						||
                }
 | 
						||
                if (sInstances.Count == 0)
 | 
						||
                {
 | 
						||
                    tracking_enabled = false;
 | 
						||
                }
 | 
						||
                //else
 | 
						||
                //{
 | 
						||
                //    getInstance(default_appid).SetNetworkType(networkType);
 | 
						||
                //}
 | 
						||
 | 
						||
            }
 | 
						||
        }
 | 
						||
      
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        private static ThinkingAnalyticsAPI TA_instance;
 | 
						||
        private static string default_appid; // 如果用户调用接口时不指定项目 ID,默认使用第一个项目 ID
 | 
						||
        private static bool tracking_enabled = true;
 | 
						||
        private static ReaderWriterLockSlim instance_lock = new ReaderWriterLockSlim();
 | 
						||
        private static readonly Dictionary<string, ThinkingAnalyticsWrapper> sInstances = 
 | 
						||
            new Dictionary<string, ThinkingAnalyticsWrapper>();
 | 
						||
 | 
						||
        private static ThinkingAnalyticsWrapper getInstance(string appid)
 | 
						||
        {
 | 
						||
            instance_lock.EnterReadLock();
 | 
						||
            try
 | 
						||
            {
 | 
						||
                if (sInstances.Count > 0 && sInstances.ContainsKey(appid))
 | 
						||
                {
 | 
						||
                    return sInstances[appid];
 | 
						||
                }
 | 
						||
                return sInstances[default_appid];
 | 
						||
            } finally
 | 
						||
            {
 | 
						||
                instance_lock.ExitReadLock();
 | 
						||
            }
 | 
						||
        }
 | 
						||
#endregion
 | 
						||
    }
 | 
						||
}
 |