/*
Thinkingdata Unitiy SDK v2.0.8
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.
*/
#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)
#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;
namespace ThinkingAnalytics
{
///
/// Dynamic super properties interfaces.
///
public interface IDynamicSuperProperties
{
Dictionary GetDynamicSuperProperties();
}
// 自动采集事件类型
[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 class ThinkingAnalyticsAPI : MonoBehaviour
{
#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
///
/// 设置自定义访客 ID,用于替换系统生成的访客 ID
///
/// 访客 ID
/// 项目 ID(可选)
public static void Identify(string uniqueId, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).Identify(uniqueId);
}
}
///
/// 返回当前的访客 ID.
///
/// 访客 ID
/// 项目 ID(可选)
public static string GetDistinctId(string appId = "")
{
if (tracking_enabled)
{
return getInstance(appId).GetDistinctId();
}
return null;
}
///
/// 设置账号 ID. 该方法不会上传用户登录事件.
///
/// 账号 ID
/// 项目 ID(可选)
public static void Login(string account, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).Login(account);
}
}
///
/// 清空账号 ID. 该方法不会上传用户登出事件.
///
/// 项目 ID(可选)
public static void Logout(string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).Logout();
}
}
///
/// 主动触发上报缓存事件到服务器.
///
/// 项目 ID(可选)
public static void Flush(string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).Flush();
}
}
///
/// 开启自动采集功能.
///
/// 项目 ID(可选)
public static void EnableAutoTrack(AUTO_TRACK_EVENTS events, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).EnableAutoTrack(events);
}
}
///
/// track 简单事件. 该事件会先缓存在本地,达到触发上报条件或者主动调用 Flush 时会上报到服务器.
///
/// 事件名称
/// 项目 ID(可选)
public static void Track(string eventName, string appId = "")
{
Track(eventName, null, appId);
}
///
/// track 事件及事件属性. 该事件会先缓存在本地,达到触发上报条件或者主动调用 Flush 时会上报到服务器.
///
/// 事件名称
/// Properties
/// 项目 ID(可选)
public static void Track(string eventName, Dictionary properties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).Track(eventName, properties);
}
}
///
/// track 事件及事件属性,并指定 #event_time 属性. 该事件会先缓存在本地,达到触发上报条件或者主动调用 Flush 时会上报到服务器. 从 v1.3.0 开始,会考虑 date 的时区信息。支持 UTC 和 local 时区.
///
/// 事件名称
/// 事件属性
/// 事件时间
/// 项目 ID(可选)
public static void Track(string eventName, Dictionary properties, DateTime date, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).Track(eventName, properties, date);
}
}
///
/// 设置公共事件属性. 公共事件属性指的就是每个事件都会带有的属性.
///
/// 公共事件属性
/// 项目 ID(可选)
public static void SetSuperProperties(Dictionary superProperties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).SetSuperProperties(superProperties);
}
}
///
/// 删除某个公共事件属性.
///
/// 属性名称
/// 项目 ID(可选)
public static void UnsetSuperProperty(string property, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UnsetSuperProperty(property);
}
}
///
/// 返回当前公共事件属性.
///
/// 公共事件属性
/// 项目 ID(可选)
public static Dictionary GetSuperProperties(string appId = "")
{
if (tracking_enabled)
{
return getInstance(appId).GetSuperProperties();
}
return null;
}
///
/// 清空公共事件属性.
///
/// 项目 ID(可选)
public static void ClearSuperProperties(string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).ClearSuperProperty();
}
}
///
/// 记录事件时长. 调用 TimeEvent 为某事件开始计时,当 track 传该事件时,SDK 会在在事件属性中加入 #duration 这一属性来表示事件时长,单位为秒.
///
/// 事件名称
/// 项目 ID(可选)
public static void TimeEvent(string eventName, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).TimeEvent(eventName);
}
}
///
/// 设置用户属性. 该接口上传的属性将会覆盖原有的属性值.
///
/// 用户属性
/// 项目 ID(可选)
public static void UserSet(Dictionary properties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserSet(properties);
}
}
///
/// 设置用户属性. 该接口上传的属性将会覆盖原有的属性值.
///
/// 用户属性
/// 用户属性设置的时间
/// 项目 ID(可选)
public static void UserSet(Dictionary properties, DateTime dateTime, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserSet(properties, dateTime);
}
}
///
/// 重置一个用户属性.
///
/// 用户属性名称
/// 项目 ID(可选)
public static void UserUnset(string property, string appId = "")
{
List properties = new List();
properties.Add(property);
UserUnset(properties, appId);
}
///
/// 重置一组用户属性
///
/// 用户属性列表
/// 项目 ID(可选)
public static void UserUnset(List properties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserUnset(properties);
}
}
///
/// 重置一组用户属性, 并指定操作时间
///
/// 用户属性列表
/// 操作时间
/// 项目 ID(可选)
public static void UserUnset(List properties, DateTime dateTime, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserUnset(properties, dateTime);
}
}
///
/// 设置用户属性. 当该属性之前已经有值的时候,将会忽略这条信息.
///
/// 用户属性
/// 项目 ID(可选)
public static void UserSetOnce(Dictionary properties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserSetOnce(properties);
}
}
///
/// 设置用户属性. 当该属性之前已经有值的时候,将会忽略这条信息.
///
/// 用户属性
/// 操作时间
/// 项目 ID(可选)
public static void UserSetOnce(Dictionary properties, DateTime dateTime, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserSetOnce(properties, dateTime);
}
}
///
/// 对数值类用户属性进行累加. 如果该属性还未被设置,则会赋值 0 后再进行计算.
///
/// 属性名称
/// 数值
/// 项目 ID(可选)
public static void UserAdd(string property, object value, string appId = "")
{
Dictionary properties = new Dictionary()
{
{ property, value }
};
UserAdd(properties, appId);
}
///
/// 对数值类用户属性进行累加. 如果属性还未被设置,则会赋值 0 后再进行计算.
///
/// 用户属性
/// 项目 ID(可选)
public static void UserAdd(Dictionary properties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserAdd(properties);
}
}
///
/// 对数值类用户属性进行累加. 如果属性还未被设置,则会赋值 0 后再进行计算.
///
/// 用户属性
/// 操作时间
/// 项目 ID(可选)
public static void UserAdd(Dictionary properties, DateTime dateTime, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserAdd(properties, dateTime);
}
}
///
/// 对 List 类型的用户属性进行追加.
///
/// 用户属性
/// 项目 ID(可选)
public static void UserAppend(Dictionary properties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserAppend(properties);
}
}
///
/// 对 List 类型的用户属性进行追加.
///
/// 用户属性
/// 操作时间
/// 项目 ID(可选)
public static void UserAppend(Dictionary properties, DateTime dateTime, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserAppend(properties, dateTime);
}
}
///
/// 删除用户数据. 之后再查询该名用户的用户属性,但该用户产生的事件仍然可以被查询到
///
/// 项目 ID(可选)
public static void UserDelete(string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserDelete();
}
}
///
/// 删除用户数据并指定操作时间.
///
/// 项目 ID(可选)
public static void UserDelete(DateTime dateTime, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).UserDelete(dateTime);
}
}
///
/// 设置允许上报数据到服务器的网络类型.
///
/// 网络类型
/// 项目 ID(可选)
public static void SetNetworkType(NetworkType networkType, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).SetNetworkType(networkType);
}
}
///
/// Gets the device identifier.
///
/// The device identifier.
public static string GetDeviceId()
{
if (tracking_enabled)
{
return getInstance("").GetDeviceId();
}
return null;
}
///
/// Sets the dynamic super properties.
///
/// Dynamic super properties interface.
/// App ID (optional).
public static void SetDynamicSuperProperties(IDynamicSuperProperties dynamicSuperProperties, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).SetDynamicSuperProperties(dynamicSuperProperties);
}
}
///
/// 停止上报数据,并且清空本地缓存数据(未上报的数据、已设置的访客ID、账号ID、公共属性)
///
/// 项目ID
public static void OptOutTracking(string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).OptOutTracking();
}
}
///
/// 停止上报数据,清空本地缓存数据,并且发送 user_del 到服务端.
///
/// 项目ID
public static void OptOutTrackingAndDeleteUser(string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).OptOutTrackingAndDeleteUser();
}
}
///
/// 恢复上报数据
///
/// 项目ID
public static void OptInTracking(string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).OptInTracking();
}
}
///
/// 暂停/恢复上报数据,本地缓存不会被清空
///
/// 是否打开上报数据
/// 项目ID
public static void EnableTracking(bool enabled, string appId = "")
{
if (tracking_enabled)
{
getInstance(appId).EnableTracking(enabled);
}
}
///
/// 创建轻量级实例,轻量级实例与主实例共享项目ID. 访客ID、账号ID、公共属性不共享
///
/// 项目ID
/// 轻量级实例的 token
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;
}
}
///
/// 传入时间戳校准 SDK 时间.
///
/// 当前 Unix timestamp, 单位 毫秒
public static void CalibrateTime(long timestamp)
{
ThinkingAnalyticsWrapper.CalibrateTime(timestamp);
}
///
/// 传入 NTP Server 地址校准 SDK 时间.
///
/// 您可以根据您用户所在地传入访问速度较快的 NTP Server 地址, 例如 time.asia.apple.com
/// SDK 默认情况下会等待 3 秒,去获取时间偏移数据,并用该偏移校准之后的数据.
/// 如果在 3 秒内未因网络原因未获得正确的时间偏移,本次应用运行期间将不会再校准时间.
///
/// 可用的 NTP 服务器地址
public static void CalibrateTimeWithNtp(string ntpServer)
{
ThinkingAnalyticsWrapper.CalibrateTimeWithNtp(ntpServer);
}
#region internal
void Awake()
{
#if DISABLE_TA
tracking_enabled = false;
#endif
TD_Log.EnableLog(enableLog);
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)
{
if (!string.IsNullOrEmpty(token.appid))
{
sInstances.Add(token.appid, new ThinkingAnalyticsWrapper(token));
}
}
}
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 sInstances =
new Dictionary();
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
}
}