[M] sync n3

This commit is contained in:
2024-12-09 16:54:19 +08:00
parent c90bbe86e7
commit 05331e6286
845 changed files with 6138 additions and 1307 deletions

View File

@@ -0,0 +1,180 @@
**v2.5.1** 2022/11/21
- 新增支持设置实例名称
- 新增支持获取国家/地区信息
- 优化代码
**v2.5.0** 2022/10/20
- 优化代码
**v2.4.1** 2022/08/08
- 支持 Package Manager 接入
- 新增自动采集场景加载、卸载事件
- 优化代码
**v2.4.0** 2022/06/24
- 新增支持去重追加用户属性
- 新增支持自动采集事件回调
- 新增支持 iOS / Android 数据加密上报
- 优化代码
**v2.3.1** 2022/04/21
- 新增预置属性禁用开关
- 优化代码
**v2.3.0** 2022/02/28
- 全平台支持缓存事件、批量发送
- 优化代码
**v2.2.5** 2022/01/17
- 新增预置属性`#app_version`
- 支持 Switch 等平台,放开对支持平台的限制
- 简化初始化流程,放开 Unity 预置体限制
- 优化代码
**v2.2.4** 2021/11/15
- 支持复杂数据类型传输
- 自动采集事件支持自定义属性
- 优化代码
**v2.2.3** 2021/09/24
- 适配 WebGL 平台
- 优化代码
**v2.2.2** 2021/09/15
- 支持手动初始化
- 支持事件黑名单
- 优化代码
**v2.2.1** 2021/07/21
- 优化代码
**v2.2.0** 2021/06/16
- 适配低版本 Xcode 版本
- 适配 .NET 3.5 / 2017.x 环境
- 新增 C# 异常采集
- 调整事件属性、公共属性、预置属性的覆盖顺序
- 更新 Android SDK (v2.7.0)、iOS SDK (v2.7.0)
**v2.1.5** 2021/04/19
- 兼容低版本 .NET
- 代码优化
**v2.1.4** 2021/03/15
- 适配 iOS 14
- 适配 Android 11
- 新增预置属性`#bundle_id` (应用唯一标识)
- 优化网络信号获取逻辑
**v2.1.3** 2021/01/04
- 支持 UnityEditor 中上报数据
- 支持 PC 端游戏 ( Windows, MacOS )
- 多实例场景,支持代码设置默认实例
**v.2.1.2**(2020-10-31)
- autodata中信息放入track事件的properties
- 移除iOS bundle资源文件
- install,start事件以后立即flush
- 新增iOS 5G信息采集;更新5G情况的数据上报判断逻辑
- 调整未知网络数据上报逻辑调整
- 默认上报策略调整为所有网络情况均可上报
- 大量安卓日志打印OOM异常优化
**v2.1.1** (2020-08-25)
- 修复特殊事件不设置timeZone导致上报错误的#zone_offset的问题.
**v2.1.0** (2020-08-24)
- 支持首次事件, 允许传入自定义的 ID 校验是否首次上报
- 支持可更新、可重写的事件
- 优化#lib/#lib_version 字段为 Unity SDK 信息
- 升级原生 SDK 版本为 v2.6.0
**v2.0.8** (2020-06-28)
- 更新原生 Android SDK解决极端情况下的空指针异常
**v2.0.7** (2020-06-23)
- 新增预置属性 #system_language
- 更新原生 SDK 版本号: Android v2.5.5, iOS v2.5.5
- Android 不再通过修改 gradle 配置来引入ThinkingAnalyticsSDK 依赖
**v2.0.6** (2020-06-17)
- 解决 iOS 32 位机型 long 型溢出的问题
**v2.0.5** (2020-05-19)
- 解决 2018.04 版本无法使用 ntp 校准时间的问题
**v2.0.4** (2020-05-15)
- 更新原生 iOS SDK 到 v2.5.2,解决上个版本中 Debug 模式问题
**v2.0.3** (2020-05-14)
- 更新原生 SDK 版本,适配 TA 后台埋点管理功能
- 优化代码,避免出现异常(可能会导致与其他崩溃采集 SDK 冲突)
**v2.0.2** (2020-04-17)
- 修复 Double 类型在自定义 CultureInfo 的场景下格式错误
**v2.0.1** (2020-04-14)
- 修复 Android 平台 DEBUG 模式上报事件的 BUG.
**v2.0.0** (2020-04-03)
- 修改自动采集逻辑,支持四种类型的自动采集事件:启动、关闭、崩溃、安装
- 支持 SDK 时间校准功能,支持时间戳校准和 NTP 服务器校准
- 允许为用户属性相关设置接口传入指定时间
**v1.4.3** (2020-03-19)
- 支持对数据 #time 属性的默认时区设置
- 更新原生 SDK 版本
**v1.4.2** (2020-02-21)
- 更新iOS 插件修复之前版本bug
**v1.4.1** (2020-02-14)
- 适配 Unity 2019.3.1f1
**v1.4.0** (2020-02-11)
- 属性值支持 List / Array 类型
- 新增 UserAppend 接口
- 支持 Debug 模式数据校验
- 支持为每个实例单独配置接收端地址
- 去除本地数据格式校验
**v1.3.1** (2019-12-25)
- 修复 Android 4.3 以下版本退出超时
- 修复 未包含 iOS 开发环境时的报错
**v1.3.0** (2019-10-18)
- 新增 UserUnset 接口:用于重置用户属性.
- 事件预置属性新增时间偏移,适配多时区需求
**v1.2.2** (2019-10-11)
- 优化 iOS 平台上报逻辑,解决缓存数据库异常导致的重复上报
**v1.2.1** (2019-09-27)
- 解决老版本 .NET 的兼容性问题
**v1.2.0** (2019-08-31)
- 支持关闭/打开数据上报
- 支持暂停/继续数据上报
- 支持轻量级实例
- 修复2019.2.1f 版本设置网络类型失败
- 修复timeEvent 不准确问题
- Android/iOS SDK 升级为2.1.0
**v1.1.0** (2019-08-09)
- 支持获取设备ID
- 支持动态公共属性
- 支持安装事件采集
- Android SDK 默认升级为2.0.2
- iOS SDK 升级为2.0.1
- 支持上报缓存选项用户可以选择主动调用StartTrack() 去开始上报
**v1.0.0** (2019-06-20)
- 支持访客ID 和用户账号的设置
- 支持事件和用户属性上报
- 支持 ta_app_start 和 ta_app_end 事件的自动上报
- 支持公共属性接口
- 支持 timeEvent 接口
- 支持多项目上报

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d66857cec492747aa8da439d6d1ff532
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1c3596aacf52e4dce91260e35b40c684
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,17 @@
{
"name": "ThinkingAnalytics-Editor",
"references": [
"ThinkingAnalytics"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: dbc881e260fba43c3b36c3da8364a4b1
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
namespace ThinkingData.Analytics.Editors
{
[CustomEditor(typeof(TDAnalytics))]
[CanEditMultipleObjects]
public class TD_Inspectors : Editor
{
private ReorderableList _stringArray;
public void OnEnable()
{
var appId = this.serializedObject.FindProperty("configs");
_stringArray = new ReorderableList(appId.serializedObject, appId, true, true, true, true)
{
drawHeaderCallback = DrawListHeader,
drawElementCallback = DrawListElement,
onRemoveCallback = RemoveListElement,
onAddCallback = AddListElement
};
_stringArray.elementHeight = 5 * (EditorGUIUtility.singleLineHeight + 10);
_stringArray.serializedProperty.isExpanded = true;
}
void DrawListHeader(Rect rect)
{
var arect = rect;
arect.height = EditorGUIUtility.singleLineHeight + 10;
arect.x += 14;
arect.width = 80;
GUIStyle style = new GUIStyle();
style.fontStyle = FontStyle.Bold;
GUI.Label(arect, "Instance Configurations", style);
}
void DrawListElement(Rect rect, int index, bool isActive, bool isFocused)
{
var spacing = 5;
var xSpacing = 85;
var arect = rect;
SerializedProperty item = _stringArray.serializedProperty.GetArrayElementAtIndex(index);
var serElem = this._stringArray.serializedProperty.GetArrayElementAtIndex(index);
arect.height = EditorGUIUtility.singleLineHeight;
arect.width = 240;
if (index == 0)
{
EditorGUI.PropertyField(arect, item, new GUIContent((index + 1) + " (default)"));
}
else
{
EditorGUI.PropertyField(arect, item, new GUIContent("" + (index + 1)));
}
arect.y += EditorGUIUtility.singleLineHeight + spacing;
GUIStyle style = new GUIStyle();
style.fontStyle = FontStyle.Bold;
EditorGUI.LabelField(arect, "APP ID:", style);
arect.x += xSpacing;
EditorGUI.PropertyField(arect, serElem.FindPropertyRelative("appId"), GUIContent.none);
arect.y += EditorGUIUtility.singleLineHeight + spacing;
arect.x -= xSpacing;
EditorGUI.LabelField(arect, "SERVER URL:", style);
arect.x += xSpacing;
EditorGUI.PropertyField(new Rect(arect.x, arect.y, arect.width, arect.height), serElem.FindPropertyRelative("serverUrl"), GUIContent.none);
arect.y += EditorGUIUtility.singleLineHeight + spacing;
arect.x -= xSpacing;
EditorGUI.LabelField(arect, "MODE:", style);
arect.x += xSpacing;
EditorGUI.PropertyField(arect, serElem.FindPropertyRelative("mode"), GUIContent.none);
arect.y += EditorGUIUtility.singleLineHeight + spacing;
arect.x -= xSpacing;
EditorGUI.LabelField(arect, "TimeZone:", style);
arect.x += xSpacing;
var a = serElem.FindPropertyRelative("timeZone");
if (a.intValue == 100)
{
EditorGUI.PropertyField(new Rect(arect.x, arect.y, 115, arect.height), a, GUIContent.none);
arect.x += 125;
EditorGUI.PropertyField(new Rect(arect.x, arect.y, 115, arect.height), serElem.FindPropertyRelative("timeZoneId"), GUIContent.none);
}
else
{
EditorGUI.PropertyField(arect, a, GUIContent.none);
}
}
void AddListElement(ReorderableList list)
{
if (list.serializedProperty != null)
{
list.serializedProperty.arraySize++;
list.index = list.serializedProperty.arraySize - 1;
SerializedProperty item = list.serializedProperty.GetArrayElementAtIndex(list.index);
item.FindPropertyRelative("appId").stringValue = "";
}
else
{
ReorderableList.defaultBehaviours.DoAddButton(list);
}
}
void RemoveListElement(ReorderableList list)
{
if (EditorUtility.DisplayDialog("Warnning", "Do you want to remove this element?", "Remove", "Cancel"))
{
ReorderableList.defaultBehaviours.DoRemoveButton(list);
}
}
public override void OnInspectorGUI()
{
DrawDefaultInspector();
this.serializedObject.Update();
var property = _stringArray.serializedProperty;
property.isExpanded = EditorGUILayout.Foldout(property.isExpanded, property.displayName);
if (property.isExpanded)
{
_stringArray.DoLayoutList();
}
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9e175a5169e2c4de78d15b28f2ce6520
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,104 @@
#if UNITY_EDITOR && UNITY_IOS
using System.IO;
using ThinkingData.Analytics.Utils;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using UnityEngine;
namespace ThinkingData.Analytics.Editors
{
public class TD_PostProcessBuild
{
//Xcode Build Settings
//[PostProcessBuild]
[PostProcessBuildAttribute(88)]
public static void OnPostProcessBuild(BuildTarget target, string targetPath)
{
if (target != BuildTarget.iOS)
{
Debug.LogWarning("[ThinkingData] Warning: Target is not iOS. XCodePostProcess will not run");
return;
}
string projPath = Path.GetFullPath(targetPath) + "/Unity-iPhone.xcodeproj/project.pbxproj";
PBXProject proj = new 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
proj.AddBuildProperty(targetGuid, "OTHER_LDFLAGS", "-ObjC");
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);
proj.AddFrameworkToProject(targetGuid, "UserNotifications.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);
//Info.plist
//Disable preset properties
string plistPath = Path.Combine(targetPath, "Info.plist");
PlistDocument plist = new PlistDocument();
plist.ReadFromFile(plistPath);
plist.root.CreateArray("TDDisPresetProperties");
TDPublicConfig.GetPublicConfig();
foreach (string item in TDPublicConfig.DisPresetProperties)
{
plist.root["TDDisPresetProperties"].AsArray().AddString(item);
}
plist.WriteToFile(plistPath);
}
}
}
#endif
#if UNITY_EDITOR && UNITY_ANDROID && UNITY_2019_1_OR_NEWER
using UnityEditor;
using UnityEditor.Android;
using UnityEngine;
using System.IO;
using System.Xml;
using System.Collections.Generic;
namespace ThinkingData.Analytics.Editors
{
class TD_PostProcessBuild : IPostGenerateGradleAndroidProject
{
// Copy configuration file ta_public_config.xml
public int callbackOrder { get { return 0; } }
public void OnPostGenerateGradleAndroidProject(string path)
{
// Copy configuration file ta_public_config.xml
string desPath = path + "/../launcher/src/main/res/values/ta_public_config.xml";
if (File.Exists(desPath))
{
File.Delete(desPath);
}
TextAsset textAsset = Resources.Load<TextAsset>("ta_public_config");
if (textAsset != null && textAsset.bytes != null)
{
File.WriteAllBytes(desPath, textAsset.bytes);
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 75476b67117c64ab1a25a2b94db96dcb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 thinking-analytics / data-collector / client-sdk
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.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d70dc3784c59e4df68c451bb5b5d1c85
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b77bb3c2e92f945f1b0f8e5c2f9bbe76
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 89fe14a74ae0f4916a24ea021891c1b9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 5f7f0ddaf71ac4a00a8d6e31e982eaed
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 640f04af2bfe244b69b495a42f69c4c6
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 69014c79b119c458a92bd3f477399bca
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 04844570eb35e4807bd54a34a89619c0
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b5e64871c9af447029fea9ebb8a01507
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eefcaefb9c6534ae78d8e6d4345a9531
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,213 @@
using System.Collections.Generic;
using UnityEngine;
using ThinkingSDK.PC.Main;
using ThinkingSDK.PC.Storage;
using ThinkingSDK.PC.Utils;
using ThinkingSDK.PC.Constant;
public class ThinkingSDKAutoTrack : MonoBehaviour
{
private string mAppId;
private TDAutoTrackEventType mAutoTrackEvents = TDAutoTrackEventType.None;
private Dictionary<string, Dictionary<string, object>> mAutoTrackProperties = new Dictionary<string, Dictionary<string, object>>();
private bool mStarted = false;
private TDAutoTrackEventHandler_PC mEventCallback_PC;
private static string TDAutoTrackEventType_APP_START = "AppStart";
private static string TDAutoTrackEventType_APP_END = "AppEnd";
private static string TDAutoTrackEventType_APP_CRASH = "AppCrash";
private static string TDAutoTrackEventType_APP_INSTALL = "AppInstall";
// Start is called before the first frame update
void Start()
{
}
void OnApplicationFocus(bool hasFocus)
{
if (hasFocus)
{
if ((mAutoTrackEvents & TDAutoTrackEventType.AppStart) != 0)
{
Dictionary<string, object> properties = new Dictionary<string, object>();
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_START))
{
ThinkingSDKUtil.AddDictionary(properties, mAutoTrackProperties[TDAutoTrackEventType_APP_START]);
}
if (mEventCallback_PC != null)
{
ThinkingSDKUtil.AddDictionary(properties, mEventCallback_PC.AutoTrackEventCallback_PC((int) TDAutoTrackEventType.AppStart, properties));
}
ThinkingPCSDK.Track(ThinkingSDKConstant.START_EVENT, properties, this.mAppId);
}
if ((mAutoTrackEvents & TDAutoTrackEventType.AppEnd) != 0)
{
ThinkingPCSDK.TimeEvent(ThinkingSDKConstant.END_EVENT, this.mAppId);
}
ThinkingPCSDK.PauseTimeEvent(false, appId: this.mAppId);
}
else
{
if ((mAutoTrackEvents & TDAutoTrackEventType.AppEnd) != 0)
{
Dictionary<string, object> properties = new Dictionary<string, object>();
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_END))
{
ThinkingSDKUtil.AddDictionary(properties, mAutoTrackProperties[TDAutoTrackEventType_APP_END]);
}
if (mEventCallback_PC != null)
{
ThinkingSDKUtil.AddDictionary(properties, mEventCallback_PC.AutoTrackEventCallback_PC((int) TDAutoTrackEventType.AppEnd, properties));
}
ThinkingPCSDK.Track(ThinkingSDKConstant.END_EVENT, properties, this.mAppId);
}
ThinkingPCSDK.Flush(this.mAppId);
ThinkingPCSDK.PauseTimeEvent(true, appId: this.mAppId);
}
}
void OnApplicationQuit()
{
if (Application.isFocused == true)
{
OnApplicationFocus(false);
}
//ThinkingPCSDK.FlushImmediately(this.mAppId);
}
public void SetAppId(string appId)
{
this.mAppId = appId;
}
public void EnableAutoTrack(TDAutoTrackEventType events, Dictionary<string, object> properties, string appId)
{
SetAutoTrackProperties(events, properties);
if ((events & TDAutoTrackEventType.AppInstall) != 0)
{
object result = ThinkingSDKFile.GetData(appId, ThinkingSDKConstant.IS_INSTALL, typeof(int));
if (result == null)
{
Dictionary<string, object> mProperties = new Dictionary<string, object>(properties);
ThinkingSDKFile.SaveData(appId, ThinkingSDKConstant.IS_INSTALL, 1);
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_INSTALL))
{
ThinkingSDKUtil.AddDictionary(mProperties, mAutoTrackProperties[TDAutoTrackEventType_APP_INSTALL]);
}
ThinkingPCSDK.Track(ThinkingSDKConstant.INSTALL_EVENT, mProperties, this.mAppId);
ThinkingPCSDK.Flush(this.mAppId);
}
}
if ((events & TDAutoTrackEventType.AppStart) != 0 && mStarted == false)
{
Dictionary<string, object> mProperties = new Dictionary<string, object>(properties);
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_START))
{
ThinkingSDKUtil.AddDictionary(mProperties, mAutoTrackProperties[TDAutoTrackEventType_APP_START]);
}
ThinkingPCSDK.Track(ThinkingSDKConstant.START_EVENT, mProperties, this.mAppId);
ThinkingPCSDK.Flush(this.mAppId);
}
if ((events & TDAutoTrackEventType.AppEnd) != 0 && mStarted == false)
{
ThinkingPCSDK.TimeEvent(ThinkingSDKConstant.END_EVENT, this.mAppId);
}
mStarted = true;
}
public void EnableAutoTrack(TDAutoTrackEventType events, TDAutoTrackEventHandler_PC eventCallback, string appId)
{
mAutoTrackEvents = events;
mEventCallback_PC = eventCallback;
if ((events & TDAutoTrackEventType.AppInstall) != 0)
{
object result = ThinkingSDKFile.GetData(appId, ThinkingSDKConstant.IS_INSTALL, typeof(int));
if (result == null)
{
ThinkingSDKFile.SaveData(appId, ThinkingSDKConstant.IS_INSTALL, 1);
Dictionary<string, object> properties = null;
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_INSTALL))
{
properties = mAutoTrackProperties[TDAutoTrackEventType_APP_INSTALL];
}
else
{
properties = new Dictionary<string, object>();
}
if (mEventCallback_PC != null)
{
ThinkingSDKUtil.AddDictionary(properties, mEventCallback_PC.AutoTrackEventCallback_PC((int)TDAutoTrackEventType.AppInstall, properties));
}
ThinkingPCSDK.Track(ThinkingSDKConstant.INSTALL_EVENT, properties, this.mAppId);
ThinkingPCSDK.Flush(this.mAppId);
}
}
if ((events & TDAutoTrackEventType.AppStart) != 0 && mStarted == false)
{
Dictionary<string, object> properties = null;
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_START))
{
properties = mAutoTrackProperties[TDAutoTrackEventType_APP_START];
}
else
{
properties = new Dictionary<string, object>();
}
if (mEventCallback_PC != null)
{
ThinkingSDKUtil.AddDictionary(properties, mEventCallback_PC.AutoTrackEventCallback_PC((int) TDAutoTrackEventType.AppStart, properties));
}
ThinkingPCSDK.Track(ThinkingSDKConstant.START_EVENT, properties, this.mAppId);
ThinkingPCSDK.Flush(this.mAppId);
}
if ((events & TDAutoTrackEventType.AppEnd) != 0 && mStarted == false)
{
ThinkingPCSDK.TimeEvent(ThinkingSDKConstant.END_EVENT, this.mAppId);
}
mStarted = true;
}
public void SetAutoTrackProperties(TDAutoTrackEventType events, Dictionary<string, object> properties)
{
mAutoTrackEvents = events;
if ((events & TDAutoTrackEventType.AppInstall) != 0)
{
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_INSTALL))
{
ThinkingSDKUtil.AddDictionary(mAutoTrackProperties[TDAutoTrackEventType_APP_INSTALL], properties);
}
else
mAutoTrackProperties[TDAutoTrackEventType_APP_INSTALL] = properties;
}
if ((events & TDAutoTrackEventType.AppStart) != 0)
{
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_START))
{
ThinkingSDKUtil.AddDictionary(mAutoTrackProperties[TDAutoTrackEventType_APP_START], properties);
}
else
mAutoTrackProperties[TDAutoTrackEventType_APP_START] = properties;
}
if ((events & TDAutoTrackEventType.AppEnd) != 0)
{
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_END))
{
ThinkingSDKUtil.AddDictionary(mAutoTrackProperties[TDAutoTrackEventType_APP_END], properties);
}
else
mAutoTrackProperties[TDAutoTrackEventType_APP_END] = properties;
}
if ((events & TDAutoTrackEventType.AppCrash) != 0)
{
if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_CRASH))
{
ThinkingSDKUtil.AddDictionary(mAutoTrackProperties[TDAutoTrackEventType_APP_CRASH], properties);
}
else
mAutoTrackProperties[TDAutoTrackEventType_APP_CRASH] = properties;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0ac1f96dfbfb046e79d0e2f5c3d94261
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 255aaff7c590d43c0893234eb5279770
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,192 @@
using System;
using System.Collections.Generic;
using ThinkingSDK.PC.Utils;
using ThinkingSDK.PC.Request;
using ThinkingSDK.PC.Constant;
using UnityEngine;
using System.Collections;
namespace ThinkingSDK.PC.Config
{
public enum Mode
{
/* normal mode, the data will be stored in the cache and reported in batches */
NORMAL,
/* debug mode, the data will be reported one by one */
DEBUG,
/* debug only mode, only verify the data, and will not store it */
DEBUG_ONLY
}
public class ThinkingSDKConfig
{
private string mToken;
private string mServerUrl;
private string mNormalUrl;
private string mDebugUrl;
private string mConfigUrl;
private string mInstanceName;
private Mode mMode = Mode.NORMAL;
private TimeZoneInfo mTimeZone;
public int mUploadInterval = 30;
public int mUploadSize = 30;
private List<string> mDisableEvents = new List<string>();
private static Dictionary<string, ThinkingSDKConfig> sInstances = new Dictionary<string, ThinkingSDKConfig>();
private ResponseHandle mCallback;
private ThinkingSDKConfig(string token,string serverUrl, string instanceName)
{
//verify server url
serverUrl = this.VerifyUrl(serverUrl);
this.mServerUrl = serverUrl;
this.mNormalUrl = serverUrl + "/sync";
this.mDebugUrl = serverUrl + "/data_debug";
this.mConfigUrl = serverUrl + "/config";
this.mToken = token;
this.mInstanceName = instanceName;
try
{
this.mTimeZone = TimeZoneInfo.Local;
}
catch (Exception)
{
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("TimeZoneInfo initial failed :" + e.Message);
}
}
private string VerifyUrl(string serverUrl)
{
Uri uri = new Uri(serverUrl);
serverUrl = uri.Scheme + "://" + uri.Host + ":" + uri.Port;
return serverUrl;
}
public void SetMode(Mode mode)
{
this.mMode = mode;
}
public Mode GetMode()
{
return this.mMode;
}
public string DebugURL()
{
return this.mDebugUrl;
}
public string NormalURL()
{
return this.mNormalUrl;
}
public string ConfigURL()
{
return this.mConfigUrl;
}
public string Server()
{
return this.mServerUrl;
}
public string InstanceName()
{
return this.mInstanceName;
}
public static ThinkingSDKConfig GetInstance(string token, string server, string instanceName)
{
ThinkingSDKConfig config = null;
if (!string.IsNullOrEmpty(instanceName))
{
if (sInstances.ContainsKey(instanceName))
{
config = sInstances[instanceName];
}
else
{
config = new ThinkingSDKConfig(token, server, instanceName);
sInstances.Add(instanceName, config);
}
}
else
{
if (sInstances.ContainsKey(token))
{
config = sInstances[token];
}
else
{
config = new ThinkingSDKConfig(token, server, null);
sInstances.Add(token, config);
}
}
return config;
}
public void SetTimeZone(TimeZoneInfo timeZoneInfo)
{
this.mTimeZone = timeZoneInfo;
}
public TimeZoneInfo TimeZone()
{
return this.mTimeZone;
}
public List<string> DisableEvents() {
return this.mDisableEvents;
}
public bool IsDisabledEvent(string eventName)
{
if (this.mDisableEvents == null)
{
return false;
}
else
{
return this.mDisableEvents.Contains(eventName);
}
}
public void UpdateConfig(MonoBehaviour mono, ResponseHandle callback = null)
{
mCallback = callback;
mono.StartCoroutine(this.GetWithFORM(this.mConfigUrl,this.mToken,null, ConfigResponseHandle));
}
private void ConfigResponseHandle(Dictionary<string, object> result)
{
try
{
int code = int.Parse(result["code"].ToString());
if (result != null && code == 0)
{
Dictionary<string, object> data = (Dictionary<string, object>)result["data"];
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Get remote config success: " + ThinkingSDKJSON.Serialize(data));
foreach (KeyValuePair<string, object> kv in data)
{
if (kv.Key == "sync_interval")
{
this.mUploadInterval = int.Parse(kv.Value.ToString());
}
else if (kv.Key == "sync_batch_size")
{
this.mUploadSize = int.Parse(kv.Value.ToString());
}
else if (kv.Key == "disable_event_list")
{
foreach (var item in (List<object>)kv.Value)
{
this.mDisableEvents.Add((string)item);
}
}
}
}
else
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Get remote config failed: " + ThinkingSDKJSON.Serialize(result));
}
}
catch (Exception ex)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Get remote config failed: " + ex.Message);
}
if (mCallback != null)
{
mCallback();
}
}
private IEnumerator GetWithFORM (string url, string appId, Dictionary<string, object> param, ResponseHandle responseHandle) {
yield return ThinkingSDKBaseRequest.GetWithFORM_2(this.mConfigUrl,this.mToken,param,responseHandle);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 472854a90c78a4dd4a16616ba3d3437d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,52 @@
namespace ThinkingSDK.PC.Config
{
public class ThinkingSDKPublicConfig
{
// Whether to print log
bool isPrintLog;
// sdk version
string version = "1.0";
// sdk name
string name = "Unity";
private static readonly ThinkingSDKPublicConfig config = null;
static ThinkingSDKPublicConfig()
{
config = new ThinkingSDKPublicConfig();
}
private static ThinkingSDKPublicConfig GetConfig()
{
return config;
}
public ThinkingSDKPublicConfig()
{
isPrintLog = false;
}
public static void SetIsPrintLog(bool isPrint)
{
GetConfig().isPrintLog = isPrint;
}
public static bool IsPrintLog()
{
return GetConfig().isPrintLog;
}
public static void SetVersion(string libVersion)
{
GetConfig().version = libVersion;
}
public static void SetName(string libName)
{
GetConfig().name = libName;
}
public static string Version()
{
return GetConfig().version;
}
public static string Name()
{
return GetConfig().name;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 47e9c09a25d664062bd8264d072b2f34
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e5cb18d25c15d4fca82ba5c10c117b9e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,116 @@
using System.Collections.Generic;
namespace ThinkingSDK.PC.Constant
{
public delegate void ResponseHandle(Dictionary<string,object> result = null);
public class ThinkingSDKConstant
{
// current platform
public static readonly string PLATFORM = "PC";
// date format style
public static readonly string TIME_PATTERN = "{0:yyyy-MM-dd HH:mm:ss.fff}";
// event type
public static readonly string TYPE = "#type";
// event time
public static readonly string TIME = "#time";
// distinct ID
public static readonly string DISTINCT_ID = "#distinct_id";
// event name
public static readonly string EVENT_NAME = "#event_name";
// account ID
public static readonly string ACCOUNT_ID = "#account_id";
// event properties
public static readonly string PROPERTIES = "properties";
// network type
public static readonly string NETWORK_TYPE = "#network_type";
// sdk version
public static readonly string LIB_VERSION = "#lib_version";
// carrier name
public static readonly string CARRIER = "#carrier";
// sdk name
public static readonly string LIB = "#lib";
// os name
public static readonly string OS = "#os";
// device ID
public static readonly string DEVICE_ID = "#device_id";
// device screen height
public static readonly string SCREEN_HEIGHT = "#screen_height";
//device screen width
public static readonly string SCREEN_WIDTH = "#screen_width";
// device manufacturer
public static readonly string MANUFACTURE = "#manufacturer";
// device model
public static readonly string DEVICE_MODEL = "#device_model";
// device system language
public static readonly string SYSTEM_LANGUAGE = "#system_language";
// os version
public static readonly string OS_VERSION = "#os_version";
// app version
public static readonly string APP_VERSION = "#app_version";
// app bundle ID
public static readonly string APP_BUNDLEID = "#bundle_id";
// zone offset
public static readonly string ZONE_OFFSET = "#zone_offset";
// project ID
public static readonly string APPID = "#app_id";
// unique ID for the event
public static readonly string UUID = "#uuid";
// first event ID
public static readonly string FIRST_CHECK_ID = "#first_check_id";
// special event ID
public static readonly string EVENT_ID = "#event_id";
// random ID
public static readonly string RANDOM_ID = "RANDDOM_ID";
// random ID(WebGL)
public static readonly string RANDOM_DEVICE_ID = "RANDOM_DEVICE_ID";
// event duration
public static readonly string DURATION = "#duration";
// flush time
public static readonly string FLUSH_TIME = "#flush_time";
// request data
public static readonly string REQUEST_DATA = "data";
// super properties
public static readonly string SUPER_PROPERTY = "super_properties";
// user properties action
public static readonly string USER_ADD = "user_add";
public static readonly string USER_SET = "user_set";
public static readonly string USER_SETONCE = "user_setOnce";
public static readonly string USER_UNSET = "user_unset";
public static readonly string USER_DEL = "user_del";
public static readonly string USER_APPEND = "user_append";
public static readonly string USER_UNIQ_APPEND = "user_uniq_append";
// Whether to pause data reporting
public static readonly string ENABLE_TRACK = "enable_track";
// Whether to stop data reporting
public static readonly string OPT_TRACK = "opt_track";
// Whether the installation is recorded
public static readonly string IS_INSTALL = "is_install";
// app install event
public static readonly string INSTALL_EVENT = "ta_app_install";
// app start event
public static readonly string START_EVENT = "ta_app_start";
// app end event
public static readonly string END_EVENT = "ta_app_end";
// app crash event
public static readonly string CRASH_EVENT = "ta_app_crash";
// app crash reason
public static readonly string CRASH_REASON = "#app_crashed_reason";
// scene load
public static readonly string APP_SCENE_LOAD = "ta_scene_loaded";
// scene unload
public static readonly string APP_SCENE_UNLOAD = "ta_scene_unloaded";
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 361e81159859b41d797fc238c8f55f17
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a138ac43e601b433093a111aff909263
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using ThinkingSDK.PC.Time;
namespace ThinkingSDK.PC.DataModel
{
public abstract class ThinkingSDKBaseData
{
// event type
private string mType;
// event time
private ThinkingSDKTimeInter mTime;
// distinct ID
private string mDistinctID;
// event name
private string mEventName;
// account ID
private string mAccountID;
// unique ID for the event
private string mUUID;
private Dictionary<string, object> mProperties = new Dictionary<string, object>();
public Dictionary<string, object> Properties()
{
return mProperties;
}
public void SetEventName(string eventName)
{
this.mEventName = eventName;
}
public void SetEventType(string eventType)
{
this.mType = eventType;
}
public string EventName()
{
return this.mEventName;
}
public void SetTime(ThinkingSDKTimeInter time)
{
this.mTime = time;
}
public ThinkingSDKTimeInter EventTime()
{
return this.mTime;
}
public void SetDataType(string type)
{
this.mType = type;
}
virtual public String GetDataType()
{
return this.mType;
}
public string AccountID()
{
return this.mAccountID;
}
public string DistinctID()
{
return this.mDistinctID;
}
public void SetAccountID(string accuntID)
{
this.mAccountID = accuntID;
}
public void SetDistinctID(string distinctID)
{
this.mDistinctID = distinctID;
}
public string UUID()
{
return this.mUUID;
}
public ThinkingSDKBaseData() { }
public ThinkingSDKBaseData(ThinkingSDKTimeInter time,string eventName)
{
this.SetBaseData(eventName);
this.SetTime(time);
}
public ThinkingSDKBaseData(string eventName)
{
this.SetBaseData(eventName);
}
public void SetBaseData(string eventName)
{
this.mEventName = eventName;
this.mUUID = System.Guid.NewGuid().ToString();
}
public ThinkingSDKBaseData(ThinkingSDKTimeInter time, string eventName, Dictionary<string, object> properties):this(time,eventName)
{
if (properties != null)
{
this.SetProperties(properties);
}
}
abstract public Dictionary<string, object> ToDictionary();
public void SetProperties(Dictionary<string, object> properties,bool isOverwrite = true)
{
if (isOverwrite)
{
foreach (KeyValuePair<string, object> kv in properties)
{
mProperties[kv.Key] = kv.Value;
}
}
else
{
foreach (KeyValuePair<string, object> kv in properties)
{
if (!mProperties.ContainsKey(kv.Key))
{
mProperties[kv.Key] = kv.Value;
}
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 69b1ae68ce0724b4290b99fb1920ffca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Time;
namespace ThinkingSDK.PC.DataModel
{
public class ThinkingSDKEventData:ThinkingSDKBaseData
{
private DateTime mEventTime;
private TimeZoneInfo mTimeZone;
private float mDuration;
private static Dictionary<string, object> mData;
public void SetEventTime(DateTime dateTime)
{
this.mEventTime = dateTime;
}
public void SetTimeZone(TimeZoneInfo timeZone)
{
this.mTimeZone = timeZone;
}
//public DateTime EventTime()
//{
// return this.mEventTime;
//}
public DateTime Time()
{
return mEventTime;
}
public ThinkingSDKEventData(string eventName) : base(eventName)
{
}
public ThinkingSDKEventData(ThinkingSDKTimeInter time, string eventName):base(time,eventName)
{
}
public ThinkingSDKEventData(ThinkingSDKTimeInter time, string eventName, Dictionary<string, object> properties):base(time,eventName,properties)
{
}
public override string GetDataType()
{
return "track";
}
public void SetDuration(float duration)
{
this.mDuration = duration;
}
public override Dictionary<string, object> ToDictionary()
{
if (mData == null)
{
mData = new Dictionary<string, object>();
}
else
{
mData.Clear();
}
mData[ThinkingSDKConstant.TYPE] = GetDataType();
mData[ThinkingSDKConstant.TIME] = this.EventTime().GetTime(this.mTimeZone);
mData[ThinkingSDKConstant.DISTINCT_ID] = this.DistinctID();
if (!string.IsNullOrEmpty(this.EventName()))
{
mData[ThinkingSDKConstant.EVENT_NAME] = this.EventName();
}
if (!string.IsNullOrEmpty(this.AccountID()))
{
mData[ThinkingSDKConstant.ACCOUNT_ID] = this.AccountID();
}
mData[ThinkingSDKConstant.UUID] = this.UUID();
Dictionary<string, object> properties = this.Properties();
properties[ThinkingSDKConstant.ZONE_OFFSET] = this.EventTime().GetZoneOffset(this.mTimeZone);
if (mDuration != 0)
{
properties[ThinkingSDKConstant.DURATION] = mDuration;
}
mData[ThinkingSDKConstant.PROPERTIES] = properties;
return mData;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d815c0c9730f473387bb0c0cd83098c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Utils;
namespace ThinkingSDK.PC.DataModel
{
public class ThinkingSDKFirstEvent:ThinkingSDKEventData
{
private string mFirstCheckId;
public ThinkingSDKFirstEvent(string eventName):base(eventName)
{
}
public void SetFirstCheckId(string firstCheckId)
{
mFirstCheckId = firstCheckId;
}
public string FirstCheckId()
{
if (string.IsNullOrEmpty(mFirstCheckId))
{
return ThinkingSDKDeviceInfo.DeviceID();
}
else
{
return mFirstCheckId;
}
}
override public Dictionary<string, object> ToDictionary()
{
Dictionary<string,object> dictionary = base.ToDictionary();
dictionary[ThinkingSDKConstant.FIRST_CHECK_ID] = FirstCheckId();
return dictionary;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 285f00076791947c8a99103da1a2653d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
using ThinkingSDK.PC.Constant;
namespace ThinkingSDK.PC.DataModel
{
public class ThinkingSDKOverWritableEvent:ThinkingSDKEventData
{
private string mEventID;
public ThinkingSDKOverWritableEvent(string eventName,string eventID) : base(eventName)
{
this.mEventID = eventID;
}
public override string GetDataType()
{
return "track_overwrite";
}
override public Dictionary<string, object> ToDictionary()
{
Dictionary<string, object> dictionary = base.ToDictionary();
dictionary[ThinkingSDKConstant.EVENT_ID] = mEventID;
return dictionary;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9609b6c1610254c6795e60fe0ce7a92b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
using ThinkingSDK.PC.Constant;
namespace ThinkingSDK.PC.DataModel
{
public class ThinkingSDKUpdateEvent:ThinkingSDKEventData
{
private string mEventID;
public ThinkingSDKUpdateEvent(string eventName, string eventID) : base(eventName)
{
this.mEventID = eventID;
}
public override string GetDataType()
{
return "track_update";
}
override public Dictionary<string, object> ToDictionary()
{
Dictionary<string, object> dictionary = base.ToDictionary();
dictionary[ThinkingSDKConstant.EVENT_ID] = mEventID;
return dictionary;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 25db2db9cd0d24311b5c5db04b42a604
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Time;
namespace ThinkingSDK.PC.DataModel
{
public class ThinkingSDKUserData:ThinkingSDKBaseData
{
public ThinkingSDKUserData(ThinkingSDKTimeInter time,string eventType, Dictionary<string,object> properties)
{
this.SetEventType(eventType);
this.SetTime(time);
this.SetBaseData(null);
this.SetProperties(properties);
}
override public Dictionary<string, object> ToDictionary()
{
Dictionary<string, object> data = new Dictionary<string, object>();
data[ThinkingSDKConstant.TYPE] = GetDataType();
data[ThinkingSDKConstant.TIME] = EventTime().GetTime(null);
data[ThinkingSDKConstant.DISTINCT_ID] = DistinctID();
if (!string.IsNullOrEmpty(AccountID()))
{
data[ThinkingSDKConstant.ACCOUNT_ID] = AccountID();
}
data[ThinkingSDKConstant.UUID] = UUID();
data[ThinkingSDKConstant.PROPERTIES] = Properties();
return data;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 890bcbb20acb741689b72692aaf6f60a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3166be662c1c1445387662fcb7118be5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,97 @@
using ThinkingSDK.PC.Config;
using System.Collections.Generic;
using ThinkingSDK.PC.Utils;
using UnityEngine;
namespace ThinkingSDK.PC.Main
{
public class LightThinkingSDKInstance : ThinkingSDKInstance
{
public LightThinkingSDKInstance(string appId, string server, ThinkingSDKConfig config, MonoBehaviour mono = null) : base(appId, server, null, config, mono)
{
}
public override void Identifiy(string distinctID)
{
if (IsPaused())
{
return;
}
if (!string.IsNullOrEmpty(distinctID))
{
this.mDistinctID = distinctID;
}
}
public override string DistinctId()
{
if (string.IsNullOrEmpty(this.mDistinctID))
{
this.mDistinctID = ThinkingSDKUtil.RandomID(false);
}
return this.mDistinctID;
}
public override void Login(string accountID)
{
if (IsPaused())
{
return;
}
if (!string.IsNullOrEmpty(accountID))
{
this.mAccountID = accountID;
}
}
public override string AccountID()
{
return this.mAccountID;
}
public override void Logout()
{
if (IsPaused())
{
return;
}
this.mAccountID = "";
}
public override void SetSuperProperties(Dictionary<string, object> superProperties)
{
if (IsPaused())
{
return;
}
ThinkingSDKUtil.AddDictionary(this.mSupperProperties, superProperties);
}
public override void UnsetSuperProperty(string propertyKey)
{
if (IsPaused())
{
return;
}
if (this.mSupperProperties.ContainsKey(propertyKey))
{
this.mSupperProperties.Remove(propertyKey);
}
}
public override Dictionary<string, object> SuperProperties()
{
return this.mSupperProperties;
}
public override void ClearSuperProperties()
{
if (IsPaused())
{
return;
}
this.mSupperProperties.Clear();
}
public override void EnableAutoTrack(TDAutoTrackEventType events, Dictionary<string, object> properties)
{
}
public override void SetAutoTrackProperties(TDAutoTrackEventType events, Dictionary<string, object> properties)
{
}
public override void Flush()
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7bff4ee40c5ed4a0cb4e4afe060d03c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,362 @@
using System;
using System.Collections.Generic;
using ThinkingSDK.PC.Config;
using ThinkingSDK.PC.DataModel;
using ThinkingSDK.PC.Time;
using ThinkingSDK.PC.Utils;
using UnityEngine;
namespace ThinkingSDK.PC.Main
{
public class ThinkingPCSDK
{
private ThinkingPCSDK()
{
}
private static readonly Dictionary<string, ThinkingSDKInstance> Instances = new Dictionary<string, ThinkingSDKInstance>();
private static readonly Dictionary<string, ThinkingSDKInstance> LightInstances = new Dictionary<string, ThinkingSDKInstance>();
private static string CurrentAppid;
private static ThinkingSDKInstance GetInstance(string appId)
{
ThinkingSDKInstance instance = null;
if (!string.IsNullOrEmpty(appId))
{
appId = appId.Replace(" ", "");
if (LightInstances.ContainsKey(appId))
{
instance = LightInstances[appId];
}
else if (Instances.ContainsKey(appId))
{
instance = Instances[appId];
}
}
if (instance == null)
{
instance = Instances[CurrentAppid];
}
return instance;
}
public static ThinkingSDKInstance CurrentInstance()
{
ThinkingSDKInstance instance = Instances[CurrentAppid];
return instance;
}
public static ThinkingSDKInstance Init(string appId, string server, string instanceName, ThinkingSDKConfig config = null, MonoBehaviour mono = null)
{
if (ThinkingSDKUtil.IsEmptyString(appId))
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("appId is empty");
return null;
}
ThinkingSDKInstance instance = null;
if (!string.IsNullOrEmpty(instanceName))
{
if (Instances.ContainsKey(instanceName))
{
instance = Instances[instanceName];
}
else
{
instance = new ThinkingSDKInstance(appId, server, instanceName, config, mono);
if (string.IsNullOrEmpty(CurrentAppid))
{
CurrentAppid = instanceName;
}
Instances[instanceName] = instance;
}
}
else
{
if (Instances.ContainsKey(appId))
{
instance = Instances[appId];
}
else
{
instance = new ThinkingSDKInstance(appId, server, null, config, mono);
if (string.IsNullOrEmpty(CurrentAppid))
{
CurrentAppid = appId;
}
Instances[appId] = instance;
}
}
return instance;
}
/// <summary>
/// Sets distinct ID
/// </summary>
/// <param name="distinctID"></param>
/// <param name="appId"></param>
public static void Identifiy(string distinctID, string appId = "")
{
GetInstance(appId).Identifiy(distinctID);
}
/// <summary>
/// Gets distinct ID
/// </summary>
/// <param name="appId"></param>
/// <returns></returns>
public static string DistinctId(string appId = "")
{
return GetInstance(appId).DistinctId();
}
/// <summary>
/// Sets account ID
/// </summary>
/// <param name="accountID"></param>
/// <param name="appId"></param>
public static void Login(string accountID,string appId = "")
{
GetInstance(appId).Login(accountID);
}
/// <summary>
/// Gets account ID
/// </summary>
/// <param name="appId"></param>
/// <returns></returns>
public static string AccountID(string appId = "")
{
return GetInstance(appId).AccountID();
}
/// <summary>
/// Clear account ID
/// </summary>
public static void Logout(string appId = "")
{
GetInstance(appId).Logout();
}
/// <summary>
/// Enable Auto-tracking Events
/// </summary>
/// <param name="events"></param>
/// <param name="appId"></param>
public static void EnableAutoTrack(TDAutoTrackEventType events, Dictionary<string, object> properties, string appId = "")
{
GetInstance(appId).EnableAutoTrack(events, properties);
}
public static void EnableAutoTrack(TDAutoTrackEventType events, TDAutoTrackEventHandler_PC eventCallback, string appId = "")
{
GetInstance(appId).EnableAutoTrack(events, eventCallback);
}
public static void SetAutoTrackProperties(TDAutoTrackEventType events, Dictionary<string, object> properties, string appId = "")
{
GetInstance(appId).SetAutoTrackProperties(events, properties);
}
public static void Track(string eventName,string appId = "")
{
GetInstance(appId).Track(eventName);
}
public static void Track(string eventName, Dictionary<string, object> properties, string appId = "")
{
GetInstance(appId).Track(eventName,properties);
}
public static void Track(string eventName, Dictionary<string, object> properties, DateTime date, string appId = "")
{
GetInstance(appId).Track(eventName, properties, date);
}
public static void Track(string eventName, Dictionary<string, object> properties, DateTime date, TimeZoneInfo timeZone, string appId = "")
{
GetInstance(appId).Track(eventName, properties, date, timeZone);
}
public static void TrackForAll(string eventName, Dictionary<string, object> properties)
{
foreach (string appId in Instances.Keys)
{
GetInstance(appId).Track(eventName, properties);
}
}
public static void Track(ThinkingSDKEventData eventModel,string appId = "")
{
GetInstance(appId).Track(eventModel);
}
public static void Flush (string appId = "")
{
GetInstance(appId).Flush();
}
//public static void FlushImmediately (string appId = "")
//{
// GetInstance(appId).FlushImmediately();
//}
public static void SetSuperProperties(Dictionary<string, object> superProperties,string appId = "")
{
GetInstance(appId).SetSuperProperties(superProperties);
}
public static void UnsetSuperProperty(string propertyKey, string appId = "")
{
GetInstance(appId).UnsetSuperProperty(propertyKey);
}
public static Dictionary<string, object> SuperProperties(string appId="")
{
return GetInstance(appId).SuperProperties();
}
public static Dictionary<string, object> PresetProperties(string appId="")
{
return GetInstance(appId).PresetProperties();
}
public static void ClearSuperProperties(string appId= "")
{
GetInstance(appId).ClearSuperProperties();
}
public static void TimeEvent(string eventName,string appId="")
{
GetInstance(appId).TimeEvent(eventName);
}
public static void TimeEventForAll(string eventName)
{
foreach (string appId in Instances.Keys)
{
GetInstance(appId).TimeEvent(eventName);
}
}
/// <summary>
/// Pause Event timing
/// </summary>
/// <param name="status">ture: puase timing, false: resume timing</param>
/// <param name="eventName">event name (null or empty is for all event)</param>
public static void PauseTimeEvent(bool status, string eventName = "", string appId = "")
{
GetInstance(appId).PauseTimeEvent(status, eventName);
}
public static void UserSet(Dictionary<string, object> properties, string appId = "")
{
GetInstance(appId).UserSet(properties);
}
public static void UserSet(Dictionary<string, object> properties, DateTime dateTime,string appId = "")
{
GetInstance(appId).UserSet(properties, dateTime);
}
public static void UserUnset(string propertyKey,string appId = "")
{
GetInstance(appId).UserUnset(propertyKey);
}
public static void UserUnset(string propertyKey, DateTime dateTime,string appId = "")
{
GetInstance(appId).UserUnset(propertyKey,dateTime);
}
public static void UserUnset(List<string> propertyKeys, string appId = "")
{
GetInstance(appId).UserUnset(propertyKeys);
}
public static void UserUnset(List<string> propertyKeys, DateTime dateTime, string appId = "")
{
GetInstance(appId).UserUnset(propertyKeys,dateTime);
}
public static void UserSetOnce(Dictionary<string, object> properties,string appId = "")
{
GetInstance(appId).UserSetOnce(properties);
}
public static void UserSetOnce(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
{
GetInstance(appId).UserSetOnce(properties,dateTime);
}
public static void UserAdd(Dictionary<string, object> properties, string appId = "")
{
GetInstance(appId).UserAdd(properties);
}
public static void UserAdd(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
{
GetInstance(appId).UserAdd(properties,dateTime);
}
public static void UserAppend(Dictionary<string, object> properties, string appId = "")
{
GetInstance(appId).UserAppend(properties);
}
public static void UserAppend(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
{
GetInstance(appId).UserAppend(properties,dateTime);
}
public static void UserUniqAppend(Dictionary<string, object> properties, string appId = "")
{
GetInstance(appId).UserUniqAppend(properties);
}
public static void UserUniqAppend(Dictionary<string, object> properties, DateTime dateTime, string appId = "")
{
GetInstance(appId).UserUniqAppend(properties,dateTime);
}
public static void UserDelete(string appId="")
{
GetInstance(appId).UserDelete();
}
public static void UserDelete(DateTime dateTime,string appId = "")
{
GetInstance(appId).UserDelete(dateTime);
}
public static void SetDynamicSuperProperties(TDDynamicSuperPropertiesHandler_PC dynamicSuperProperties, string appId = "")
{
GetInstance(appId).SetDynamicSuperProperties(dynamicSuperProperties);
}
public static void SetTrackStatus(TDTrackStatus status, string appId = "")
{
GetInstance(appId).SetTrackStatus(status);
}
public static void OptTracking(bool optTracking,string appId = "")
{
GetInstance(appId).OptTracking(optTracking);
}
public static void EnableTracking(bool isEnable, string appId = "")
{
GetInstance(appId).EnableTracking(isEnable);
}
public static void OptTrackingAndDeleteUser(string appId = "")
{
GetInstance(appId).OptTrackingAndDeleteUser();
}
public static string CreateLightInstance()
{
string randomID = System.Guid.NewGuid().ToString("N");
ThinkingSDKInstance lightInstance = ThinkingSDKInstance.CreateLightInstance();
LightInstances[randomID] = lightInstance;
return randomID;
}
public static void CalibrateTime(long timestamp)
{
ThinkingSDKTimestampCalibration timestampCalibration = new ThinkingSDKTimestampCalibration(timestamp);
ThinkingSDKInstance.SetTimeCalibratieton(timestampCalibration);
}
public static void CalibrateTimeWithNtp(string ntpServer)
{
ThinkingSDKNTPCalibration ntpCalibration = new ThinkingSDKNTPCalibration(ntpServer);
ThinkingSDKInstance.SetNtpTimeCalibratieton(ntpCalibration);
}
public static void OnDestory() {
Instances.Clear();
LightInstances.Clear();
}
public static string GetDeviceId()
{
return ThinkingSDKDeviceInfo.DeviceID();
}
public static void EnableLog(bool isEnable)
{
ThinkingSDKPublicConfig.SetIsPrintLog(isEnable);
}
public static void SetLibName(string name)
{
ThinkingSDKPublicConfig.SetName(name);
}
public static void SetLibVersion(string versionCode)
{
ThinkingSDKPublicConfig.SetVersion(versionCode);
}
public static string TimeString(DateTime dateTime, string appId = "")
{
return GetInstance(appId).TimeString(dateTime);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ee46cd65b236c4202a800c812df46325
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,786 @@
using System;
using System.Collections;
using System.Collections.Generic;
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]
// Auto-tracking Events Type
public enum TDAutoTrackEventType
{
None = 0,
AppStart = 1 << 0, // reporting when the app enters the foreground ta_app_start
AppEnd = 1 << 1, // reporting when the app enters the background ta_app_end
AppCrash = 1 << 4, // reporting when an uncaught exception occurs ta_app_crash
AppInstall = 1 << 5, // reporting when the app is opened for the first time after installation ta_app_install
AppSceneLoad = 1 << 6, // reporting when the scene is loaded in the app ta_scene_loaded
AppSceneUnload = 1 << 7, // reporting when the scene is unloaded in the app ta_scene_loaded
All = AppStart | AppEnd | AppInstall | AppCrash | AppSceneLoad | AppSceneUnload
}
// Data Reporting Status
public enum TDTrackStatus
{
Pause = 1, // pause data reporting
Stop = 2, // stop data reporting, and clear caches
SaveOnly = 3, // data stores in the cache, but not be reported
Normal = 4 // resume data reporting
}
public interface TDDynamicSuperPropertiesHandler_PC
{
Dictionary<string, object> GetDynamicSuperProperties_PC();
}
public interface TDAutoTrackEventHandler_PC
{
Dictionary<string, object> AutoTrackEventCallback_PC(int type, Dictionary<string, object>properties);
}
public class ThinkingSDKInstance
{
private string mAppid;
private string mServer;
protected string mDistinctID;
protected string mAccountID;
private bool mOptTracking = true;
private Dictionary<string, object> mTimeEvents = new Dictionary<string, object>();
private Dictionary<string, object> mTimeEventsBefore = new Dictionary<string, object>();
private bool mEnableTracking = true;
private bool mEventSaveOnly = false; //data stores in the cache, but not be reported
protected Dictionary<string, object> mSupperProperties = new Dictionary<string, object>();
protected Dictionary<string, Dictionary<string, object>> mAutoTrackProperties = new Dictionary<string, Dictionary<string, object>>();
private ThinkingSDKConfig mConfig;
private ThinkingSDKBaseRequest mRequest;
private static ThinkingSDKTimeCalibration mTimeCalibration;
private static ThinkingSDKTimeCalibration mNtpTimeCalibration;
private TDDynamicSuperPropertiesHandler_PC mDynamicProperties;
private ThinkingSDKTask mTask {
get {
return ThinkingSDKTask.SingleTask();
}
set {
this.mTask = value;
}
}
private static ThinkingSDKInstance mCurrentInstance;
private MonoBehaviour mMono;
private static MonoBehaviour sMono;
private ThinkingSDKAutoTrack mAutoTrack;
WaitForSeconds flushDelay;
public static void SetTimeCalibratieton(ThinkingSDKTimeCalibration timeCalibration)
{
mTimeCalibration = timeCalibration;
}
public static void SetNtpTimeCalibratieton(ThinkingSDKTimeCalibration timeCalibration)
{
mNtpTimeCalibration = timeCalibration;
}
private ThinkingSDKInstance()
{
}
private void DefaultData()
{
DistinctId();
AccountID();
SuperProperties();
DefaultTrackState();
}
public ThinkingSDKInstance(string appId,string server):this(appId,server,null,null)
{
}
public ThinkingSDKInstance(string appId, string server, string instanceName, ThinkingSDKConfig config, MonoBehaviour mono = null)
{
this.mMono = mono;
sMono = mono;
if (config == null)
{
this.mConfig = ThinkingSDKConfig.GetInstance(appId, server, instanceName);
}
else
{
this.mConfig = config;
}
this.mConfig.UpdateConfig(mono, ConfigResponseHandle);
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();
mCurrentInstance = this;
// dynamic loading ThinkingSDKTask ThinkingSDKAutoTrack
GameObject mThinkingSDKTask = new GameObject("ThinkingSDKTask", typeof(ThinkingSDKTask));
UnityEngine.Object.DontDestroyOnLoad(mThinkingSDKTask);
GameObject mThinkingSDKAutoTrack = new GameObject("ThinkingSDKAutoTrack", typeof(ThinkingSDKAutoTrack));
this.mAutoTrack = (ThinkingSDKAutoTrack) mThinkingSDKAutoTrack.GetComponent(typeof(ThinkingSDKAutoTrack));
if (!string.IsNullOrEmpty(instanceName))
{
this.mAutoTrack.SetAppId(instanceName);
}
else
{
this.mAutoTrack.SetAppId(this.mAppid);
}
UnityEngine.Object.DontDestroyOnLoad(mThinkingSDKAutoTrack);
}
private void EventResponseHandle(Dictionary<string, object> result)
{
int eventCount = 0;
if (result != null)
{
int flushCount = 0;
if (result.ContainsKey("flush_count"))
{
flushCount = (int)result["flush_count"];
}
if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
{
eventCount = ThinkingSDKFileJson.DeleteBatchTrackingData(flushCount, this.mConfig.InstanceName());
}
else
{
eventCount = ThinkingSDKFileJson.DeleteBatchTrackingData(flushCount, this.mAppid);
}
}
mTask.Release();
if (eventCount > 0)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Flush automatically (" + this.mAppid + ")");
Flush();
}
}
private void ConfigResponseHandle(Dictionary<string, object> result)
{
if (this.mConfig.GetMode() == Mode.NORMAL)
{
flushDelay = new WaitForSeconds(mConfig.mUploadInterval);
sMono.StartCoroutine(WaitAndFlush());
}
}
public static ThinkingSDKInstance CreateLightInstance()
{
ThinkingSDKInstance lightInstance = new LightThinkingSDKInstance(mCurrentInstance.mAppid, mCurrentInstance.mServer, mCurrentInstance.mConfig, sMono);
return lightInstance;
}
public ThinkingSDKTimeInter GetTime(DateTime dateTime)
{
ThinkingSDKTimeInter time = null;
if ( dateTime == DateTime.MinValue || dateTime == null)
{
if (mNtpTimeCalibration != null)// check if time calibrated
{
time = new ThinkingSDKCalibratedTime(mNtpTimeCalibration, mConfig.TimeZone());
}
else if (mTimeCalibration != null)// check if time calibrated
{
time = new ThinkingSDKCalibratedTime(mTimeCalibration, mConfig.TimeZone());
}
else
{
time = new ThinkingSDKTime(mConfig.TimeZone(), DateTime.Now);
}
}
else
{
time = new ThinkingSDKTime(mConfig.TimeZone(), dateTime);
}
return time;
}
// sets distisct ID
public virtual void Identifiy(string distinctID)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Setting distinct ID, DistinctId = " + distinctID);
if (IsPaused())
{
return;
}
if (!string.IsNullOrEmpty(distinctID))
{
this.mDistinctID = distinctID;
ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.DISTINCT_ID,distinctID);
}
}
public virtual 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 virtual void Login(string accountID)
{
if (IsPaused())
{
return;
}
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Login SDK, AccountId = " + accountID);
if (!string.IsNullOrEmpty(accountID))
{
this.mAccountID = accountID;
ThinkingSDKFile.SaveData(mAppid, ThinkingSDKConstant.ACCOUNT_ID, accountID);
}
}
public virtual string AccountID()
{
this.mAccountID = (string)ThinkingSDKFile.GetData(this.mAppid,ThinkingSDKConstant.ACCOUNT_ID, typeof(string));
return this.mAccountID;
}
public virtual void Logout()
{
if (IsPaused())
{
return;
}
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Logout SDK");
this.mAccountID = "";
ThinkingSDKFile.DeleteData(this.mAppid,ThinkingSDKConstant.ACCOUNT_ID);
}
//TODO
public virtual void EnableAutoTrack(TDAutoTrackEventType events, Dictionary<string, object> properties)
{
this.mAutoTrack.EnableAutoTrack(events, properties, mAppid);
}
public virtual void EnableAutoTrack(TDAutoTrackEventType events, TDAutoTrackEventHandler_PC eventCallback)
{
this.mAutoTrack.EnableAutoTrack(events, eventCallback, mAppid);
}
// sets auto-tracking events properties
public virtual void SetAutoTrackProperties(TDAutoTrackEventType events, Dictionary<string, object> properties)
{
this.mAutoTrack.SetAutoTrackProperties(events, properties);
}
public void Track(string eventName)
{
Track(eventName, null, DateTime.MinValue);
}
public void Track(string eventName, Dictionary<string, object> properties)
{
Track(eventName, properties, DateTime.MinValue);
}
public void Track(string eventName, Dictionary<string, object> properties, DateTime date)
{
Track(eventName, properties, date, null, false);
}
public void Track(string eventName, Dictionary<string, object> properties, DateTime date, TimeZoneInfo timeZone)
{
Track(eventName, properties, date, timeZone, false);
}
public void Track(string eventName, Dictionary<string, object> properties, DateTime date, TimeZoneInfo timeZone, bool immediately)
{
ThinkingSDKTimeInter time = GetTime(date);
ThinkingSDKEventData data = new ThinkingSDKEventData(time, eventName, properties);
if (timeZone != null)
{
data.SetTimeZone(timeZone);
}
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_PC(),false);
}
if (this.mSupperProperties != null && this.mSupperProperties.Count > 0)
{
data.SetProperties(this.mSupperProperties,false);
}
Dictionary<string, object> deviceInfo = ThinkingSDKUtil.DeviceInfo();
foreach (string item in ThinkingSDKUtil.DisPresetProperties)
{
if (deviceInfo.ContainsKey(item))
{
deviceInfo.Remove(item);
}
}
data.SetProperties(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 (mTimeEventsBefore.ContainsKey(data.EventName()))
{
int beforeTime = (int)mTimeEventsBefore[data.EventName()];
duration = duration + (float)(beforeTime / 1000.0);
mTimeEventsBefore.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);
if (this.mConfig.IsDisabledEvent(data.EventName()))
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Disabled Event: " + data.EventName());
return;
}
if (this.mConfig.GetMode() == Mode.NORMAL && this.mRequest.GetType() != typeof(ThinkingSDKNormalRequest))
{
this.mRequest = new ThinkingSDKNormalRequest(this.mAppid, this.mConfig.NormalURL());
}
if (immediately)
{
Dictionary<string, object> dataDic = data.ToDictionary();
this.mMono.StartCoroutine(mRequest.SendData_2(null, ThinkingSDKJSON.Serialize(dataDic), 1));
}
else
{
Dictionary<string, object> dataDic = data.ToDictionary();
int count = 0;
if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Enqueue data: \n" + ThinkingSDKJSON.Serialize(dataDic) + "\n AppId: " + this.mAppid);
count = ThinkingSDKFileJson.EnqueueTrackingData(dataDic, this.mConfig.InstanceName());
}
else
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Enqueue data: \n" + ThinkingSDKJSON.Serialize(dataDic) + "\n AppId: " + this.mAppid);
count = ThinkingSDKFileJson.EnqueueTrackingData(dataDic, this.mAppid);
}
if (this.mConfig.GetMode() != Mode.NORMAL || count >= this.mConfig.mUploadSize)
{
if (count >= this.mConfig.mUploadSize)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Flush automatically (" + this.mAppid + ")");
}
Flush();
}
}
}
private IEnumerator WaitAndFlush()
{
while (true)
{
yield return flushDelay;
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Flush automatically (" + this.mAppid + ")");
Flush();
}
}
/// <summary>
/// flush events data
/// </summary>
public virtual void Flush()
{
if (mEventSaveOnly == false) {
mTask.SyncInvokeAllTask();
int batchSize = (this.mConfig.GetMode() != Mode.NORMAL) ? 1 : mConfig.mUploadSize;
if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
{
mTask.StartRequest(mRequest, EventResponseHandle, batchSize, this.mConfig.InstanceName());
}
else
{
mTask.StartRequest(mRequest, EventResponseHandle, batchSize, this.mAppid);
}
}
}
//public void FlushImmediately()
//{
// if (mEventSaveOnly == false)
// {
// mTask.SyncInvokeAllTask();
// int batchSize = (this.mConfig.GetMode() != Mode.NORMAL) ? 1 : mConfig.mUploadSize;
// string list;
// int eventCount = 0;
// if (!string.IsNullOrEmpty(this.mConfig.InstanceName()))
// {
// list = ThinkingSDKFileJson.DequeueBatchTrackingData(batchSize, this.mConfig.InstanceName(), out eventCount);
// }
// else
// {
// list = ThinkingSDKFileJson.DequeueBatchTrackingData(batchSize, this.mAppid, out eventCount);
// }
// if (eventCount > 0)
// {
// this.mMono.StartCoroutine(mRequest.SendData_2(EventResponseHandle, list, eventCount));
// }
// }
//}
public void Track(ThinkingSDKEventData eventModel)
{
ThinkingSDKTimeInter time = GetTime(eventModel.Time());
eventModel.SetTime(time);
SendData(eventModel);
}
public virtual void SetSuperProperties(Dictionary<string, object> superProperties)
{
if (IsPaused())
{
return;
}
Dictionary<string, object> properties = new Dictionary<string, object>();
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 virtual void UnsetSuperProperty(string propertyKey)
{
if (IsPaused())
{
return;
}
Dictionary<string, object> properties = new Dictionary<string, object>();
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 virtual Dictionary<string, object> 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<string, object> PresetProperties()
{
Dictionary<string, object> presetProperties = new Dictionary<string, object>();
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.APP_VERSION] = ThinkingSDKAppInfo.AppVersion();
presetProperties[ThinkingSDKConstant.ZONE_OFFSET] = ThinkingSDKUtil.ZoneOffset(DateTime.Now, this.mConfig.TimeZone());
return presetProperties;
}
public virtual 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);
}
}
/// <summary>
/// Pause Event timing
/// </summary>
/// <param name="status">ture: puase timing, false: resume timing</param>
/// <param name="eventName">event name (null or empty is for all event)</param>
public void PauseTimeEvent(bool status, string eventName = "")
{
if (string.IsNullOrEmpty(eventName))
{
string[] eventNames = new string[mTimeEvents.Keys.Count];
mTimeEvents.Keys.CopyTo(eventNames, 0);
for (int i=0; i< eventNames.Length; i++)
{
string key = eventNames[i];
if (status == true)
{
int startTime = int.Parse(mTimeEvents[key].ToString());
int pauseTime = Environment.TickCount;
int duration = pauseTime - startTime;
if (mTimeEventsBefore.ContainsKey(key))
{
duration = duration + int.Parse(mTimeEventsBefore[key].ToString());
}
mTimeEventsBefore[key] = duration;
}
else
{
mTimeEvents[key] = Environment.TickCount;
}
}
}
else
{
if (status == true)
{
int startTime = int.Parse(mTimeEvents[eventName].ToString());
int pauseTime = Environment.TickCount;
int duration = pauseTime - startTime;
mTimeEventsBefore[eventName] = duration;
}
else
{
mTimeEvents[eventName] = Environment.TickCount;
}
}
}
public void UserSet(Dictionary<string, object> properties)
{
UserSet(properties, DateTime.MinValue);
}
public void UserSet(Dictionary<string, object> 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<string, object> properties = new Dictionary<string, object>();
properties[propertyKey] = 0;
ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties);
SendData(data);
}
public void UserUnset(List<string> propertyKeys)
{
UserUnset(propertyKeys,DateTime.MinValue);
}
public void UserUnset(List<string> propertyKeys, DateTime dateTime)
{
ThinkingSDKTimeInter time = GetTime(dateTime);
Dictionary<string, object> properties = new Dictionary<string, object>();
foreach (string key in propertyKeys)
{
properties[key] = 0;
}
ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties);
SendData(data);
}
public void UserSetOnce(Dictionary<string, object> properties)
{
UserSetOnce(properties, DateTime.MinValue);
}
public void UserSetOnce(Dictionary<string, object> properties, DateTime dateTime)
{
ThinkingSDKTimeInter time = GetTime(dateTime);
ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_SETONCE, properties);
SendData(data);
}
public void UserAdd(Dictionary<string, object> properties)
{
UserAdd(properties, DateTime.MinValue);
}
public void UserAdd(Dictionary<string, object> properties, DateTime dateTime)
{
ThinkingSDKTimeInter time = GetTime(dateTime);
ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_ADD, properties);
SendData(data);
}
public void UserAppend(Dictionary<string, object> properties)
{
UserAppend(properties, DateTime.MinValue);
}
public void UserAppend(Dictionary<string, object> properties, DateTime dateTime)
{
ThinkingSDKTimeInter time = GetTime(dateTime);
ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_APPEND, properties);
SendData(data);
}
public void UserUniqAppend(Dictionary<string, object> properties)
{
UserUniqAppend(properties, DateTime.MinValue);
}
public void UserUniqAppend(Dictionary<string, object> properties, DateTime dateTime)
{
ThinkingSDKTimeInter time = GetTime(dateTime);
ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNIQ_APPEND, properties);
SendData(data);
}
public void UserDelete()
{
UserDelete(DateTime.MinValue);
}
public void UserDelete(DateTime dateTime)
{
ThinkingSDKTimeInter time = GetTime(dateTime);
Dictionary<string, object> properties = new Dictionary<string, object>();
ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_DEL,properties);
SendData(data);
}
public void SetDynamicSuperProperties(TDDynamicSuperPropertiesHandler_PC dynamicSuperProperties)
{
if (IsPaused())
{
return;
}
this.mDynamicProperties = dynamicSuperProperties;
}
protected bool IsPaused()
{
bool mIsPaused = !mEnableTracking || !mOptTracking;
if (mIsPaused)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("SDK Track status is Pause or Stop");
}
return mIsPaused;
}
public void SetTrackStatus(TDTrackStatus status)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Change Status to " + status);
switch (status)
{
case TDTrackStatus.Pause:
mEventSaveOnly = false;
OptTracking(true);
EnableTracking(false);
break;
case TDTrackStatus.Stop:
mEventSaveOnly = false;
EnableTracking(true);
OptTracking(false);
break;
case TDTrackStatus.SaveOnly:
mEventSaveOnly = true;
EnableTracking(true);
OptTracking(true);
break;
case TDTrackStatus.Normal:
default:
mEventSaveOnly = false;
OptTracking(true);
EnableTracking(true);
Flush();
break;
}
}
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<string, object>();
ThinkingSDKFileJson.DeleteAllTrackingData(mAppid);
}
}
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());
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8287bb3311be54f52be240639203175f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: db5e3ec02eff54121adead1f781264b7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,155 @@
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Generic;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Utils;
using System.IO;
using UnityEngine.Networking;
using System.Collections;
using ThinkingSDK.PC.Config;
namespace ThinkingSDK.PC.Request
{
/*
* Enumerate the form of data reported by post, and the enumeration value represents json and form forms
*/
enum POST_TYPE { JSON, FORM };
public abstract class ThinkingSDKBaseRequest
{
private string mAppid;
private string mURL;
private string mData;
public ThinkingSDKBaseRequest(string appId, string url, string data)
{
mAppid = appId;
mURL = url;
mData = data;
}
public ThinkingSDKBaseRequest(string appId, string url)
{
mAppid = appId;
mURL = url;
}
public void SetData(string data)
{
this.mData = data;
}
public string APPID() {
return mAppid;
}
public string URL()
{
return mURL;
}
public string Data()
{
return mData;
}
/**
* initialization interface
*/
public static void GetConfig(string url,ResponseHandle responseHandle)
{
if (!ThinkingSDKUtil.IsValiadURL(url))
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Invalid Url:\n" + url);
}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var responseResult = new StreamReader(response.GetResponseStream()).ReadToEnd();
if (responseResult != null)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Request URL:\n"+url);
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Response:\n"+responseResult);
}
}
public bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
bool isOk = true;
// If there are errors in the certificate chain,
// look at each error to determine the cause.
if (sslPolicyErrors != SslPolicyErrors.None) {
for (int i=0; i<chain.ChainStatus.Length; i++) {
if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown) {
continue;
}
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan (0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
bool chainIsValid = chain.Build ((X509Certificate2)certificate);
if (!chainIsValid) {
isOk = false;
break;
}
}
}
return isOk;
}
abstract public IEnumerator SendData_2(ResponseHandle responseHandle, string data, int eventCount);
public static IEnumerator GetWithFORM_2(string url, string appId, Dictionary<string, object> param, ResponseHandle responseHandle)
{
string uri = url + "?appid=" + appId;
if (param != null)
{
uri = uri + "&data=" + ThinkingSDKJSON.Serialize(param);
}
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
webRequest.timeout = 30;
webRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Request URL: \n" + uri);
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
Dictionary<string,object> resultDict = null;
#if UNITY_2020_1_OR_NEWER
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.ProtocolError:
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Error response: \n" + webRequest.error);
break;
case UnityWebRequest.Result.Success:
string resultText = webRequest.downloadHandler.text;
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Response: \n" + resultText);
if (!string.IsNullOrEmpty(resultText))
{
resultDict = ThinkingSDKJSON.Deserialize(resultText);
}
break;
}
#else
if (webRequest.isHttpError || webRequest.isNetworkError)
{
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Error response: \n" + webRequest.error);
}
else
{
string resultText = webRequest.downloadHandler.text;
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Response: \n" + resultText);
if (!string.IsNullOrEmpty(resultText))
{
resultDict = ThinkingSDKJSON.Deserialize(resultText);
}
}
#endif
if (responseHandle != null)
{
responseHandle(resultDict);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3b31966af44764a508681ee9d6e24f7a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
using System.Collections.Generic;
using ThinkingSDK.PC.Config;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Utils;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
namespace ThinkingSDK.PC.Request
{
public class ThinkingSDKDebugRequest:ThinkingSDKBaseRequest
{
private int mDryRun = 0;
private string mDeviceID = ThinkingSDKDeviceInfo.DeviceID();
public void SetDryRun(int dryRun)
{
mDryRun = dryRun;
}
public ThinkingSDKDebugRequest(string appId, string url, string data):base(appId,url,data)
{
}
public ThinkingSDKDebugRequest(string appId, string url) : base(appId, url)
{
}
public override IEnumerator SendData_2(ResponseHandle responseHandle, string data, int eventCount)
{
this.SetData(data);
string uri = this.URL();
//string content = ThinkingSDKJSON.Serialize(this.Data()[0]);
string content = data.Substring(1,data.Length-2);
WWWForm form = new WWWForm();
form.AddField("appid", this.APPID());
form.AddField("source", "client");
form.AddField("dryRun", mDryRun);
form.AddField("deviceId", mDeviceID);
form.AddField("data", content);
using (UnityWebRequest webRequest = UnityWebRequest.Post(uri, form))
{
webRequest.timeout = 30;
webRequest.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Request:\n " + content + "\n URL = " + uri);
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
Dictionary<string,object> resultDict = null;
#if UNITY_2020_1_OR_NEWER
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.ProtocolError:
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response Error:\n " + webRequest.error);
break;
case UnityWebRequest.Result.Success:
string resultText = webRequest.downloadHandler.text;
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response:\n " + resultText);
if (!string.IsNullOrEmpty(resultText))
{
resultDict = ThinkingSDKJSON.Deserialize(resultText);
}
break;
}
#else
if (webRequest.isHttpError || webRequest.isNetworkError)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response Error:\n " + webRequest.error);
}
else
{
string resultText = webRequest.downloadHandler.text;
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response:\n " + resultText);
if (!string.IsNullOrEmpty(resultText))
{
resultDict = ThinkingSDKJSON.Deserialize(resultText);
}
}
#endif
if (responseHandle != null)
{
if (resultDict != null)
{
resultDict.Add("flush_count", eventCount);
}
responseHandle(resultDict);
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7849691904f3c426e81a91572a027863
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Utils;
using UnityEngine.Networking;
using System.Collections;
using ThinkingSDK.PC.Config;
namespace ThinkingSDK.PC.Request
{
public class ThinkingSDKNormalRequest:ThinkingSDKBaseRequest
{
public ThinkingSDKNormalRequest(string appId, string url, string data) :base(appId, url, data)
{
}
public ThinkingSDKNormalRequest(string appId, string url) : base(appId, url)
{
}
public override IEnumerator SendData_2(ResponseHandle responseHandle, string data, int eventCount)
{
this.SetData(data);
string uri = this.URL();
var flush_time = ThinkingSDKUtil.GetTimeStamp();
string content = "{\"#app_id\":\"" + this.APPID() + "\",\"data\":" + data + ",\"#flush_time\":" + flush_time + "}";
string encodeContent = Encode(content);
byte[] contentCompressed = Encoding.UTF8.GetBytes(encodeContent);
using (UnityWebRequest webRequest = new UnityWebRequest(uri, "POST"))
{
webRequest.timeout = 30;
webRequest.SetRequestHeader("Content-Type", "text/plain");
webRequest.SetRequestHeader("appid", this.APPID());
webRequest.SetRequestHeader("TA-Integration-Type", "PC");
webRequest.SetRequestHeader("TA-Integration-Version", ThinkingSDKPublicConfig.Version());
webRequest.SetRequestHeader("TA-Integration-Count", "1");
webRequest.SetRequestHeader("TA-Integration-Extra", "PC");
webRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(contentCompressed);
webRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Request:\n " + content + "\n URL = " + uri);
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
Dictionary<string, object> resultDict = null;
#if UNITY_2020_1_OR_NEWER
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
case UnityWebRequest.Result.ProtocolError:
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response Error:\n " + webRequest.error);
break;
case UnityWebRequest.Result.Success:
string resultText = webRequest.downloadHandler.text;
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response:\n " + resultText);
if (!string.IsNullOrEmpty(resultText))
{
resultDict = ThinkingSDKJSON.Deserialize(resultText);
}
break;
}
#else
if (webRequest.isHttpError || webRequest.isNetworkError)
{
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response Error:\n " + webRequest.error);
}
else
{
string resultText = webRequest.downloadHandler.text;
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Send event Response:\n " + resultText);
if (!string.IsNullOrEmpty(resultText))
{
resultDict = ThinkingSDKJSON.Deserialize(resultText);
}
}
#endif
if (responseHandle != null)
{
if (resultDict != null)
{
resultDict.Add("flush_count", eventCount);
}
responseHandle(resultDict);
}
}
}
private static string Encode(string inputStr)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(inputStr);
using (var outputStream = new MemoryStream())
{
using (var gzipStream = new GZipStream(outputStream, CompressionMode.Compress))
gzipStream.Write(inputBytes, 0, inputBytes.Length);
byte[] output = outputStream.ToArray();
return Convert.ToBase64String(output);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 992a71ad5ae554eb98a712f6a65b3a7f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 21f73e209611b40d3a1c87e9418529b2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@
using System;
using UnityEngine;
namespace ThinkingSDK.PC.Storage
{
public class ThinkingSDKFile
{
private static string connectorKey = "_";
public static string GetKey(string prefix,string key)
{
return prefix + connectorKey + key;
}
public static void SaveData(string prefix, string key, object value)
{
SaveData(GetKey(prefix, key), value);
}
public static void SaveData(string key, object value)
{
if (!string.IsNullOrEmpty(key))
{
if (value.GetType() == typeof(int))
{
PlayerPrefs.SetInt(key, (int)value);
}
else if (value.GetType() == typeof(float))
{
PlayerPrefs.SetFloat(key, (float)value);
}
else if (value.GetType() == typeof(string))
{
PlayerPrefs.SetString(key, (string)value);
}
PlayerPrefs.Save();
}
}
public static object GetData(string key, Type type)
{
if (!string.IsNullOrEmpty(key) && PlayerPrefs.HasKey(key))
{
if (type == typeof(int))
{
return PlayerPrefs.GetInt(key);
}
else if (type == typeof(float))
{
return PlayerPrefs.GetFloat(key);
}
else if (type == typeof(string))
{
return PlayerPrefs.GetString(key);
}
PlayerPrefs.Save();
}
return null;
}
public static object GetData(string prefix,string key, Type type)
{
key = GetKey(prefix, key);
return GetData(key, type);
}
public static void DeleteData(string key)
{
if (!string.IsNullOrEmpty(key))
{
if (PlayerPrefs.HasKey(key))
{
PlayerPrefs.DeleteKey(key);
}
}
}
public static void DeleteData(string prefix,string key)
{
key = GetKey(prefix, key);
DeleteData(key);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: be6ada75d19854acca2314015d2c6376
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using ThinkingSDK.PC.Utils;
namespace ThinkingSDK.PC.Storage
{
public class ThinkingSDKFileJson
{
// Save the event, return the number of cached events
internal static int EnqueueTrackingData(Dictionary<string, object> data, string prefix)
{
int eventId = EventAutoIncrementingID(prefix);
string trackingKey = GetEventKeysPrefix(prefix, eventId);
var dataJson = ThinkingSDKJSON.Serialize(data);
PlayerPrefs.SetString(trackingKey, dataJson);
IncreaseTrackingDataID(prefix);
int eventCount = EventAutoIncrementingID(prefix) - EventIndexID(prefix);
return eventCount;
}
// Get event end ID
internal static int EventAutoIncrementingID(string prefix)
{
string mEventAutoIncrementingID = GetEventAutoIncrementingIDKey(prefix);
return PlayerPrefs.HasKey(mEventAutoIncrementingID) ? PlayerPrefs.GetInt(mEventAutoIncrementingID) : 0;
}
// Auto increment event end ID
private static void IncreaseTrackingDataID(string prefix)
{
int id = EventAutoIncrementingID(prefix);
id += 1;
PlayerPrefs.SetInt(GetEventAutoIncrementingIDKey(prefix), id);
}
// Reset event end ID
private static void ResetTrackingDataID(string prefix)
{
int id = 0;
PlayerPrefs.SetInt(GetEventAutoIncrementingIDKey(prefix), id);
}
// Get event start ID
internal static int EventIndexID(string prefix)
{
string eventIndexID = GetEventIndexIDKey(prefix);
return PlayerPrefs.HasKey(eventIndexID) ? PlayerPrefs.GetInt(eventIndexID) : 0;
}
// Save time start ID
private static void SaveEventIndexID(int indexID, string prefix)
{
string eventIndexID = GetEventIndexIDKey(prefix);
PlayerPrefs.SetInt(eventIndexID, indexID);
}
// Fetch a specified number of events in batches
internal static string DequeueBatchTrackingData(int batchSize, string prefix, out int eventCount)
{
string batchData = eventBatchPrefix;
List<Dictionary<string, object>> tempDataList = new List<Dictionary<string, object>>();
int dataIndex = EventIndexID(prefix);
int maxIndex = EventAutoIncrementingID(prefix) - 1;
eventCount = 0;
while (eventCount < batchSize && dataIndex <= maxIndex) {
string trackingKey = GetEventKeysPrefix(prefix, dataIndex);
if (PlayerPrefs.HasKey(trackingKey)) {
string dataJson = PlayerPrefs.GetString(trackingKey);
if (eventCount < batchSize - 1 && dataIndex < maxIndex)
{
batchData = batchData + dataJson + eventBatchInfix;
}
else
{
batchData = batchData + dataJson;
}
eventCount++;
}
dataIndex++;
}
if (eventCount > 0)
{
batchData = batchData + eventBatchSuffix;
return batchData;
}
else
{
return null;
}
}
// Batch delete the specified number of events and return the remaining number of events
internal static int DeleteBatchTrackingData(int batchSize, string prefix)
{
int deletedCount = 0;
int dataIndex = EventIndexID(prefix);
int maxIndex = EventAutoIncrementingID(prefix) - 1;
while (deletedCount < batchSize && dataIndex <= maxIndex) {
string trackingKey = GetEventKeysPrefix(prefix, dataIndex);
if (PlayerPrefs.HasKey(trackingKey)) {
PlayerPrefs.DeleteKey(trackingKey);
deletedCount++;
}
dataIndex++;
}
SaveEventIndexID(dataIndex, prefix);
int eventCount = EventAutoIncrementingID(prefix) - EventIndexID(prefix);
return eventCount;
}
// Batch delete specified events
// internal static void DeleteBatchTrackingData(List<Dictionary<string, object>> batch, string prefix) {
// foreach(Dictionary<string, object> data in batch) {
// String id = data["id"].ToString();
// if (id != null && PlayerPrefs.HasKey(id)) {
// PlayerPrefs.DeleteKey(id);
// }
// }
// }
// Batch delete all events
internal static int DeleteAllTrackingData(string prefix)
{
DeleteBatchTrackingData(int.MaxValue, prefix);
SaveEventIndexID(0, prefix);
ResetTrackingDataID(prefix);
return 0;
}
private static string eventKeyInfix = "Event";
private static string eventIndexIDSuffix = "EventIndexID";
private static string eventAutoIncrementingIDSuffix = "EventAutoIncrementingID";
private static string eventBatchPrefix = "[";
private static string eventBatchInfix = ",";
private static string eventBatchSuffix = "]";
private static Dictionary<string, string> eventKeysPrefix = new Dictionary<string, string>() { };
private static Dictionary<string, string> eventIndexIDKeys = new Dictionary<string, string>() { };
private static Dictionary<string, string> eventAutoIncrementingIDKeys = new Dictionary<string, string>() { };
private static string GetEventKeysPrefix(string prefix, int index)
{
if (eventKeysPrefix.ContainsKey(prefix))
{
return eventKeysPrefix[prefix] + index;
}
else
{
string eventKey = prefix + eventKeyInfix;
eventKeysPrefix[prefix] = eventKey;
return eventKey + index;
}
}
private static string GetEventIndexIDKey(string prefix)
{
if (eventIndexIDKeys.ContainsKey(prefix))
{
return eventIndexIDKeys[prefix];
}
else
{
string eventKey = prefix + eventIndexIDSuffix;
eventIndexIDKeys[prefix] = eventKey;
return eventKey;
}
}
private static string GetEventAutoIncrementingIDKey(string prefix)
{
if (eventAutoIncrementingIDKeys.ContainsKey(prefix))
{
return eventAutoIncrementingIDKeys[prefix];
}
else
{
string eventKey = prefix + eventAutoIncrementingIDSuffix;
eventAutoIncrementingIDKeys[prefix] = eventKey;
return eventKey;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d4bedacbe272d46bda26db9388665562
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 372921461f6fe4648827f1a91a1759e1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,130 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using ThinkingSDK.PC.Request;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Storage;
using ThinkingSDK.PC.Main;
namespace ThinkingSDK.PC.TaskManager
{
[DisallowMultipleComponent]
public class ThinkingSDKTask : MonoBehaviour
{
private readonly static object _locker = new object();
private List<ThinkingSDKBaseRequest> requestList = new List<ThinkingSDKBaseRequest>();
private List<ResponseHandle> responseHandleList = new List<ResponseHandle>();
private List<int> batchSizeList = new List<int>();
private List<string> appIdList = new List<string>();
private static ThinkingSDKTask mSingleTask;
private bool isWaiting = false;
private float updateInterval = 0;
public static ThinkingSDKTask SingleTask()
{
return mSingleTask;
}
private void Awake() {
mSingleTask = this;
}
private void Start() {
}
private void Update() {
updateInterval += UnityEngine.Time.deltaTime;
if (updateInterval > 0.2)
{
updateInterval = 0;
if (!isWaiting && requestList.Count > 0)
{
WaitOne();
StartRequestSendData();
}
}
}
//private void OnDestroy()
//{
// ThinkingPCSDK.OnDestory();
//}
/// <summary>
/// hold signal
/// </summary>
public void WaitOne()
{
isWaiting = true;
}
/// <summary>
/// release signal
/// </summary>
public void Release()
{
isWaiting = false;
}
public void SyncInvokeAllTask()
{
}
public void StartRequest(ThinkingSDKBaseRequest mRequest, ResponseHandle responseHandle, int batchSize, string appId)
{
lock(_locker)
{
requestList.Add(mRequest);
responseHandleList.Add(responseHandle);
batchSizeList.Add(batchSize);
appIdList.Add(appId);
}
}
private void StartRequestSendData()
{
if (requestList.Count > 0)
{
ThinkingSDKBaseRequest mRequest;
ResponseHandle responseHandle;
string list;
int eventCount = 0;
lock (_locker)
{
mRequest = requestList[0];
responseHandle = responseHandleList[0];
list = ThinkingSDKFileJson.DequeueBatchTrackingData(batchSizeList[0], appIdList[0], out eventCount);
}
if (mRequest != null)
{
if (eventCount > 0 && list.Length > 0)
{
this.StartCoroutine(this.SendData(mRequest, responseHandle, list, eventCount));
}
else
{
if (responseHandle != null)
{
responseHandle(null);
}
}
lock(_locker)
{
requestList.RemoveAt(0);
responseHandleList.RemoveAt(0);
batchSizeList.RemoveAt(0);
appIdList.RemoveAt(0);
}
}
}
}
private IEnumerator SendData(ThinkingSDKBaseRequest mRequest, ResponseHandle responseHandle, string list, int eventCount) {
yield return mRequest.SendData_2(responseHandle, list, eventCount);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb96ead89c0c544608be4e0ad781de78
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
{
"name": "ThinkingSDK"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0a958a7eb80a248e1b8bc4553787c209
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c859b53e53b824a2aa36430c980862cf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using UnityEngine;
using System.Collections;
using System;
using System.Threading;
namespace ThinkingSDK.PC.Time
{
public class TDTimeout : MonoBehaviour
{
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public static void SetTimeout(int timeout, Action<object> action, object obj)
{
GameObject gameObject = new GameObject("TDTimeout");
var tdTimeout = gameObject.AddComponent<TDTimeout>();
tdTimeout._setTimeout(timeout, action, obj);
}
private void _setTimeout(int timeout, Action<object> action, object obj)
{
StartCoroutine(_wait(timeout, action, obj));
}
private IEnumerator _wait(int timeout, Action<object> action, object obj)
{
yield return new WaitForSeconds(timeout);
if (action != null)
{
action(obj);
}
Destroy(gameObject);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c4b6a31edd864c43a12c23d11ac6ddd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
using System;
using ThinkingSDK.PC.Utils;
namespace ThinkingSDK.PC.Time
{
public class ThinkingSDKCalibratedTime : ThinkingSDKTimeInter
{
private ThinkingSDKTimeCalibration mCalibratedTime;
private long mSystemElapsedRealtime;
private TimeZoneInfo mTimeZone;
private DateTime mDate;
public ThinkingSDKCalibratedTime(ThinkingSDKTimeCalibration calibrateTimeInter,TimeZoneInfo timeZoneInfo)
{
this.mCalibratedTime = calibrateTimeInter;
this.mTimeZone = timeZoneInfo;
this.mDate = mCalibratedTime.NowDate();
}
public string GetTime(TimeZoneInfo timeZone)
{
if (timeZone == null)
{
return ThinkingSDKUtil.FormatDate(mDate, mTimeZone);
}
else
{
return ThinkingSDKUtil.FormatDate(mDate, timeZone);
}
}
public double GetZoneOffset(TimeZoneInfo timeZone)
{
if (timeZone == null)
{
return ThinkingSDKUtil.ZoneOffset(mDate, mTimeZone);
}
else
{
return ThinkingSDKUtil.ZoneOffset(mDate, timeZone);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 46014ab35934a4a90b8329f357801cdf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using System;
namespace ThinkingSDK.PC.Time
{
public class ThinkingSDKDefinedTime : ThinkingSDKTimeInter
{
private string mTime;
private double mZoneOffset;
public ThinkingSDKDefinedTime(string time,double zoneOffset)
{
this.mTime = time;
this.mZoneOffset = zoneOffset;
}
public string GetTime(TimeZoneInfo timeZone)
{
return this.mTime;
}
public double GetZoneOffset(TimeZoneInfo timeZone)
{
return this.mZoneOffset;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 86eabc3f1cff146f89092cd516702db9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,131 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Linq;
namespace ThinkingSDK.PC.Time
{
public class ThinkingSDKNTPCalibration : ThinkingSDKTimeCalibration
{
public ThinkingSDKNTPCalibration(string ntpServer) {
double totalMilliseconds = ConvertDateTimeInt(DateTime.UtcNow);
this.mStartTime = (long)totalMilliseconds;
this.mSystemElapsedRealtime = Environment.TickCount;
// request scoket time
Socket socket = GetNetworkTimeSync(ntpServer, this);
// set scoket timeout
TDTimeout.SetTimeout(3, new Action<object>(ScoketTimeout), (object)socket);
}
private void ScoketTimeout(object obj)
{
if (obj is Socket)
{
Socket socket = (Socket)obj;
if (socket.Connected == true)
{
socket.Close();
}
}
}
protected static new double ConvertDateTimeInt(System.DateTime time)
{
DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (double)(time - startTime).TotalMilliseconds;
}
private static Socket GetNetworkTimeSync(string ntpServer, ThinkingSDKTimeCalibration timeCalibration)
{
// NTP message size - 16 bytes of the digest (RFC 2030)
var ntpData = new byte[48];
//Setting the Leap Indicator, Version Number and Mode values
ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode)
var addresses = Dns.GetHostEntry(ntpServer).AddressList;
var addressFirst = addresses.First(e => e.AddressFamily == AddressFamily.InterNetwork);
if (addressFirst == null)
{
addressFirst = addresses[0];
}
//The UDP port number assigned to NTP is 123
var ipEndPoint = new IPEndPoint(addressFirst, 123);
//NTP uses UDP
var socket = new Socket(ipEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
socket.Connect(ipEndPoint);
SocketAsyncEventArgs socketAsyncEventArgs = new SocketAsyncEventArgs();
socketAsyncEventArgs.SetBuffer(ntpData, 0, ntpData.Length);
socketAsyncEventArgs.UserToken = timeCalibration;
socketAsyncEventArgs.RemoteEndPoint = ipEndPoint;
socketAsyncEventArgs.Completed += SocketAsyncEventArgs_Completed;
// send socket request
socket.SendAsync(socketAsyncEventArgs);
return socket;
}
private static void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs eventArgs)
{
Socket socket = (Socket)sender;
if (eventArgs.SocketError == SocketError.Success)
{
if (eventArgs.LastOperation == SocketAsyncOperation.Send)
{
socket.ReceiveAsync(eventArgs);
}
else if (eventArgs.LastOperation == SocketAsyncOperation.Receive)
{
if (eventArgs.SocketError == SocketError.Success && eventArgs.Buffer.Length > 0)
{
DateTime ntpTime = ParseDateTimeWithNTPData(eventArgs.Buffer);
double totalMilliseconds = ConvertDateTimeInt(ntpTime);
ThinkingSDKTimeCalibration timeCalibration = (ThinkingSDKTimeCalibration)eventArgs.UserToken;
timeCalibration.mStartTime = (long)totalMilliseconds;
}
socket.Close();
}
else
{
socket.Close();
}
}
else
{
socket.Close();
}
}
static uint SwapEndianness(ulong x)
{
return (uint)(((x & 0x000000ff) << 24) + ((x & 0x0000ff00) << 8) + ((x & 0x00ff0000) >> 8) + ((x & 0xff000000) >> 24));
}
private static DateTime ParseDateTimeWithNTPData(byte[] ntpData)
{
//Offset to get to the "Transmit Timestamp" field (time at which the reply
//departed the server for the client, in 64-bit timestamp format."
const byte serverReplyTime = 40;
//Get the seconds part
ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime);
//Get the seconds fraction
ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4);
//Convert From big-endian to little-endian
intPart = SwapEndianness(intPart);
fractPart = SwapEndianness(fractPart);
var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L);
//**UTC** time
var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds);
return networkDateTime;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 610a0d13d17714116b2d436c4daf69a9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,42 @@
using System;
using ThinkingSDK.PC.Utils;
namespace ThinkingSDK.PC.Time
{
public class ThinkingSDKTime : ThinkingSDKTimeInter
{
private TimeZoneInfo mTimeZone;
private DateTime mDate;
public ThinkingSDKTime(TimeZoneInfo timezone, DateTime date)
{
this.mTimeZone = timezone;
this.mDate = date;
}
public string GetTime(TimeZoneInfo timeZone)
{
if (timeZone == null)
{
return ThinkingSDKUtil.FormatDate(mDate, mTimeZone);
}
else
{
return ThinkingSDKUtil.FormatDate(mDate, timeZone);
}
}
public double GetZoneOffset(TimeZoneInfo timeZone)
{
if (timeZone == null)
{
return ThinkingSDKUtil.ZoneOffset(mDate, mTimeZone);
}
else
{
return ThinkingSDKUtil.ZoneOffset(mDate, timeZone);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 482ba0db5b92b4f9e9475acfda6e496c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using System;
namespace ThinkingSDK.PC.Time
{
public class ThinkingSDKTimeCalibration
{
/// <summary>
/// Timestamp when time was calibrated
/// </summary>
public long mStartTime;
/// <summary>
/// System boot time when calibrating time
/// </summary>
public long mSystemElapsedRealtime;
public DateTime NowDate()
{
long nowTime = Environment.TickCount;
long timestamp = nowTime - this.mSystemElapsedRealtime + this.mStartTime;
// DateTime dt = DateTimeOffset.FromUnixTimeMilliseconds(timestamp).LocalDateTime;
// return dt;
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return dt.AddMilliseconds(timestamp);
}
protected static double ConvertDateTimeInt(System.DateTime time)
{
DateTime startTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (double)(time - startTime).TotalMilliseconds;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b9bb8b764cd4d47bd91702ea2c9a5ad5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
using System;
namespace ThinkingSDK.PC.Time
{
public interface ThinkingSDKTimeInter
{
string GetTime(TimeZoneInfo timeZone);
Double GetZoneOffset(TimeZoneInfo timeZone);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0cc5c74f7de224d3aa2fa4668ae7a9f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
using System;
using ThinkingSDK.PC.Config;
using ThinkingSDK.PC.Utils;
namespace ThinkingSDK.PC.Time
{
public class ThinkingSDKTimestampCalibration : ThinkingSDKTimeCalibration
{
public ThinkingSDKTimestampCalibration(long timestamp)
{
DateTime dateTimeUtcNow = DateTime.UtcNow;
this.mStartTime = timestamp;
this.mSystemElapsedRealtime = Environment.TickCount;
double time_offset = (ConvertDateTimeInt(dateTimeUtcNow) - timestamp) / 1000;
if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Time Calibration with NTP (" + timestamp + "), diff = " + time_offset.ToString("0.000s"));
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aef0ebc4f720643f3878a26fc71b6ddd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0ff15ea6a25e04a79b1289cb0664ef16
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,48 @@
using System;
using ThinkingSDK.PC.Config;
using ThinkingSDK.PC.Constant;
using UnityEngine;
namespace ThinkingSDK.PC.Utils
{
public class ThinkingSDKAppInfo
{
// sdk version
public static string LibVersion()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.LIB_VERSION))
{
return "";
}
return ThinkingSDKPublicConfig.Version() ;
}
// sdk name
public static string LibName()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.LIB))
{
return "";
}
return ThinkingSDKPublicConfig.Name();
}
// app version
public static string AppVersion()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.APP_VERSION))
{
return "";
}
return Application.version;
}
// app identifier, bundle ID
public static string AppIdentifier()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.APP_BUNDLEID))
{
return "";
}
return Application.identifier;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 85a9d7d4b192d42fb826f9620d01ef01
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,229 @@
using System;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Storage;
using UnityEngine;
namespace ThinkingSDK.PC.Utils
{
public class ThinkingSDKDeviceInfo
{
// devide ID
public static string DeviceID()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.DEVICE_ID))
{
return "";
}
#if (UNITY_WEBGL)
return RandomDeviceID();
#else
return SystemInfo.deviceUniqueIdentifier;
#endif
}
// A persistent random number, used as an alternative to the device ID (WebGL cannot obtain the device ID)
private static string RandomDeviceID()
{
string randomID = (string)ThinkingSDKFile.GetData(ThinkingSDKConstant.RANDOM_DEVICE_ID, typeof(string));
if (string.IsNullOrEmpty(randomID))
{
randomID = System.Guid.NewGuid().ToString("N");
ThinkingSDKFile.SaveData(ThinkingSDKConstant.RANDOM_DEVICE_ID, randomID);
}
return randomID;
}
// network type
public static string NetworkType()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.NETWORK_TYPE))
{
return "";
}
string networkType = "NULL";
if (Application.internetReachability == NetworkReachability.ReachableViaCarrierDataNetwork)
{
networkType = "Mobile";
}
else if (Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork)
{
networkType = "LAN";
}
return networkType;
}
// carrier name
public static string Carrier()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.CARRIER))
{
return "";
}
return "NULL";
}
// os name
public static string OS()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.OS))
{
return "";
}
string os = "other";
if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.Linux)
{
os = "Linux";
}
else if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX)
{
os = "MacOSX";
}
else if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows)
{
os = "Windows";
}
return os;
}
// os version
public static string OSVersion()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.OS_VERSION))
{
return "";
}
return SystemInfo.operatingSystem;
}
// device screen width
public static int ScreenWidth()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.SCREEN_WIDTH))
{
return 0;
}
return (int)(UnityEngine.Screen.currentResolution.width);
}
// device screen height
public static int ScreenHeight()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.SCREEN_HEIGHT))
{
return 0;
}
return (int)(UnityEngine.Screen.currentResolution.height);
}
// graphics card manufacturer name
public static string Manufacture()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.MANUFACTURE))
{
return "";
}
return SystemInfo.graphicsDeviceVendor;
}
// devide model
public static string DeviceModel()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.DEVICE_MODEL))
{
return "";
}
return SystemInfo.deviceModel;
}
// device language
public static string MachineLanguage()
{
if (ThinkingSDKUtil.DisPresetProperties.Contains(ThinkingSDKConstant.SYSTEM_LANGUAGE))
{
return "";
}
switch (Application.systemLanguage)
{
case SystemLanguage.Afrikaans:
return "af";
case SystemLanguage.Arabic:
return "ar";
case SystemLanguage.Basque:
return "eu";
case SystemLanguage.Belarusian:
return "be";
case SystemLanguage.Bulgarian:
return "bg";
case SystemLanguage.Catalan:
return "ca";
case SystemLanguage.Chinese:
return "zh";
case SystemLanguage.Czech:
return "cs";
case SystemLanguage.Danish:
return "da";
case SystemLanguage.Dutch:
return "nl";
case SystemLanguage.English:
return "en";
case SystemLanguage.Estonian:
return "et";
case SystemLanguage.Faroese:
return "fo";
case SystemLanguage.Finnish:
return "fu";
case SystemLanguage.French:
return "fr";
case SystemLanguage.German:
return "de";
case SystemLanguage.Greek:
return "el";
case SystemLanguage.Hebrew:
return "he";
case SystemLanguage.Icelandic:
return "is";
case SystemLanguage.Indonesian:
return "id";
case SystemLanguage.Italian:
return "it";
case SystemLanguage.Japanese:
return "ja";
case SystemLanguage.Korean:
return "ko";
case SystemLanguage.Latvian:
return "lv";
case SystemLanguage.Lithuanian:
return "lt";
case SystemLanguage.Norwegian:
return "nn";
case SystemLanguage.Polish:
return "pl";
case SystemLanguage.Portuguese:
return "pt";
case SystemLanguage.Romanian:
return "ro";
case SystemLanguage.Russian:
return "ru";
case SystemLanguage.SerboCroatian:
return "sr";
case SystemLanguage.Slovak:
return "sk";
case SystemLanguage.Slovenian:
return "sl";
case SystemLanguage.Spanish:
return "es";
case SystemLanguage.Swedish:
return "sv";
case SystemLanguage.Thai:
return "th";
case SystemLanguage.Turkish:
return "tr";
case SystemLanguage.Ukrainian:
return "uk";
case SystemLanguage.Vietnamese:
return "vi";
case SystemLanguage.ChineseSimplified:
return "zh";
case SystemLanguage.ChineseTraditional:
return "zh";
case SystemLanguage.Hungarian:
return "hu";
case SystemLanguage.Unknown:
return "unknown";
};
return "";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c84fe92f43c114ba7ad64250db8e124e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,630 @@
/*
* MIT License. Forked from GA_MiniJSON.
* I modified it so that it could be used for TD limitations.
*/
// using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Globalization;
namespace ThinkingSDK.PC.Utils
{
/* Based on the JSON parser from
* http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html
*
* I simplified it so that it doesn't throw exceptions
* and can be used in Unity iPhone with maximum code stripping.
*/
/// <summary>
/// This class encodes and decodes JSON strings.
/// Spec. details, see http://www.json.org/
///
/// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
/// All numbers are parsed to floats.
/// </summary>
public class ThinkingSDKJSON
{
/// <summary>
/// Parses the string json into a value
/// </summary>
/// <param name="json">A JSON string.</param>
/// <returns>An List&lt;object&gt;, a Dictionary&lt;string, object&gt;, a double, an integer,a string, null, true, or false</returns>
public static Dictionary<string, object> Deserialize(string json)
{
// save the string for debug information
if (json == null)
{
return null;
}
return Parser.Parse(json);
}
// Use caution!
public static List<object> DeserializeArray(string json)
{
// save the string for debug information
if (json == null)
{
return null;
}
return Parser.ParseArray(json);
}
sealed class Parser : IDisposable
{
const string WORD_BREAK = "{}[],:\"";
public static bool IsWordBreak(char c)
{
return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1;
}
enum TOKEN
{
NONE,
CURLY_OPEN,
CURLY_CLOSE,
SQUARED_OPEN,
SQUARED_CLOSE,
COLON,
COMMA,
STRING,
NUMBER,
TRUE,
FALSE,
NULL
};
StringReader json;
Parser(string jsonString)
{
json = new StringReader(jsonString);
}
public static Dictionary<string, object> Parse(string jsonString)
{
using (var instance = new Parser(jsonString))
{
return instance.ParseObject();
}
}
public static List<object> ParseArray(string jsonString)
{
using (var instance = new Parser(jsonString))
{
return instance.ParseArray();
}
}
public void Dispose()
{
json.Dispose();
json = null;
}
Dictionary<string, object> ParseObject()
{
Dictionary<string, object> table = new Dictionary<string, object>();
// ditch opening brace
json.Read();
// {
while (true)
{
switch (NextToken)
{
case TOKEN.NONE:
return null;
case TOKEN.COMMA:
continue;
case TOKEN.CURLY_CLOSE:
return table;
default:
// name
string name = ParseString();
if (name == null)
{
return null;
}
// :
if (NextToken != TOKEN.COLON)
{
return null;
}
// ditch the colon
json.Read();
// value
table[name] = ParseValue();
break;
}
}
}
List<object> ParseArray()
{
List<object> array = new List<object>();
// ditch opening bracket
json.Read();
// [
var parsing = true;
while (parsing)
{
TOKEN nextToken = NextToken;
switch (nextToken)
{
case TOKEN.NONE:
return null;
case TOKEN.COMMA:
continue;
case TOKEN.SQUARED_CLOSE:
parsing = false;
break;
default:
object value = ParseByToken(nextToken);
array.Add(value);
break;
}
}
return array;
}
object ParseValue()
{
TOKEN nextToken = NextToken;
return ParseByToken(nextToken);
}
object ParseByToken(TOKEN token)
{
switch (token)
{
case TOKEN.STRING:
string str = ParseString();
DateTime dateTime;
if (DateTime.TryParseExact(str, "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture, DateTimeStyles.None, out dateTime))
{
return dateTime;
}
return str;
case TOKEN.NUMBER:
return ParseNumber();
case TOKEN.CURLY_OPEN:
return ParseObject();
case TOKEN.SQUARED_OPEN:
return ParseArray();
case TOKEN.TRUE:
return true;
case TOKEN.FALSE:
return false;
case TOKEN.NULL:
return null;
default:
return null;
}
}
string ParseString()
{
StringBuilder s = new StringBuilder();
char c;
// ditch opening quote
json.Read();
bool parsing = true;
while (parsing)
{
if (json.Peek() == -1)
{
parsing = false;
break;
}
c = NextChar;
switch (c)
{
case '"':
parsing = false;
break;
case '\\':
if (json.Peek() == -1)
{
parsing = false;
break;
}
c = NextChar;
switch (c)
{
case '"':
case '\\':
case '/':
s.Append(c);
break;
case 'b':
s.Append('\b');
break;
case 'f':
s.Append('\f');
break;
case 'n':
s.Append('\n');
break;
case 'r':
s.Append('\r');
break;
case 't':
s.Append('\t');
break;
case 'u':
var hex = new char[4];
for (int i = 0; i < 4; i++)
{
hex[i] = NextChar;
}
s.Append((char)Convert.ToInt32(new string(hex), 16));
break;
}
break;
default:
s.Append(c);
break;
}
}
return s.ToString();
}
object ParseNumber()
{
string number = NextWord;
if (number.IndexOf('.') == -1)
{
long parsedInt;
Int64.TryParse(number, out parsedInt);
return parsedInt;
}
double parsedDouble;
if (!Double.TryParse(number, System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign, System.Globalization.CultureInfo.InvariantCulture, out parsedDouble))
{
Double.TryParse(number, System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign, System.Globalization.CultureInfo.CreateSpecificCulture("es-ES"), out parsedDouble);
}
return parsedDouble;
}
void EatWhitespace()
{
while (Char.IsWhiteSpace(PeekChar))
{
json.Read();
if (json.Peek() == -1)
{
break;
}
}
}
char PeekChar
{
get
{
return Convert.ToChar(json.Peek());
}
}
char NextChar
{
get
{
return Convert.ToChar(json.Read());
}
}
string NextWord
{
get
{
StringBuilder word = new StringBuilder();
while (!IsWordBreak(PeekChar))
{
word.Append(NextChar);
if (json.Peek() == -1)
{
break;
}
}
return word.ToString();
}
}
TOKEN NextToken
{
get
{
EatWhitespace();
if (json.Peek() == -1)
{
return TOKEN.NONE;
}
switch (PeekChar)
{
case '{':
return TOKEN.CURLY_OPEN;
case '}':
json.Read();
return TOKEN.CURLY_CLOSE;
case '[':
return TOKEN.SQUARED_OPEN;
case ']':
json.Read();
return TOKEN.SQUARED_CLOSE;
case ',':
json.Read();
return TOKEN.COMMA;
case '"':
return TOKEN.STRING;
case ':':
return TOKEN.COLON;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
return TOKEN.NUMBER;
}
switch (NextWord)
{
case "false":
return TOKEN.FALSE;
case "true":
return TOKEN.TRUE;
case "null":
return TOKEN.NULL;
}
return TOKEN.NONE;
}
}
}
/// <summary>
/// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string
/// </summary>
/// <param name="json">A Dictionary&lt;string, object&gt; / List&lt;object&gt;</param>
/// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
public static string Serialize(object obj, Func<DateTime, string> func = null)
{
return Serializer.Serialize(obj, func);
}
sealed class Serializer
{
StringBuilder builder;
Func<DateTime, string> func;
Serializer()
{
builder = new StringBuilder();
}
public static string Serialize(object obj, Func<DateTime, string> func)
{
var instance = new Serializer();
instance.func = func;
instance.SerializeValue(obj);
return instance.builder.ToString();
}
void SerializeValue(object value)
{
IList asList;
IDictionary asDict;
string asStr;
if (value == null)
{
builder.Append("null");
}
else if ((asStr = value as string) != null)
{
SerializeString(asStr);
}
else if (value is bool)
{
builder.Append((bool)value ? "true" : "false");
}
else if ((asList = value as IList) != null)
{
SerializeArray(asList);
}
else if ((asDict = value as IDictionary) != null)
{
SerializeObject(asDict);
}
else if (value is char)
{
SerializeString(new string((char)value, 1));
}
else
{
SerializeOther(value);
}
}
void SerializeObject(IDictionary obj)
{
bool first = true;
builder.Append('{');
foreach (object e in obj.Keys)
{
if (!first)
{
builder.Append(',');
}
SerializeString(e.ToString());
builder.Append(':');
SerializeValue(obj[e]);
first = false;
}
builder.Append('}');
}
void SerializeArray(IList anArray)
{
builder.Append('[');
bool first = true;
foreach (object obj in anArray)
{
if (!first)
{
builder.Append(',');
}
SerializeValue(obj);
first = false;
}
builder.Append(']');
}
void SerializeString(string str)
{
builder.Append('\"');
char[] charArray = str.ToCharArray();
foreach (var c in charArray)
{
switch (c)
{
case '"':
builder.Append("\\\"");
break;
case '\\':
builder.Append("\\\\");
break;
case '\b':
builder.Append("\\b");
break;
case '\f':
builder.Append("\\f");
break;
case '\n':
builder.Append("\\n");
break;
case '\r':
builder.Append("\\r");
break;
case '\t':
builder.Append("\\t");
break;
default:
int codepoint = Convert.ToInt32(c);
if ((codepoint >= 32) && (codepoint <= 126))
{
builder.Append(c);
}
else
{
builder.Append("\\u");
builder.Append(codepoint.ToString("x4"));
}
break;
}
}
builder.Append('\"');
}
void SerializeOther(object value)
{
// NOTE: decimals lose precision during serialization.
// They always have, I'm just letting you know.
// Previously floats and doubles lost precision too.
if (value is float)
{
builder.Append(((float)value).ToString("R", System.Globalization.CultureInfo.InvariantCulture));
}
else if (value is int
|| value is uint
|| value is long
|| value is sbyte
|| value is byte
|| value is short
|| value is ushort
|| value is ulong)
{
builder.Append(value);
}
else if (value is double)
{
builder.Append(Convert.ToDouble(value).ToString("R", System.Globalization.CultureInfo.InvariantCulture));
}
else if (value is decimal) {
builder.Append(Convert.ToDecimal(value).ToString("G", System.Globalization.CultureInfo.InvariantCulture));
}
else if (value is DateTime)
{
builder.Append('\"');
DateTime dateTime = (DateTime)value;
if (null != func)
{
builder.Append(func((DateTime)value));
}
else
{
builder.Append(dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture));
}
builder.Append('\"');
}
else
{
SerializeString(value.ToString());
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f521a02d525fd485c93a25ce7f330b0d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
using System;
using System.IO;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Config;
using UnityEngine;
namespace ThinkingSDK.PC.Utils
{
public class ThinkingSDKLogger
{
public ThinkingSDKLogger()
{
}
public static void Print(string str)
{
if (ThinkingSDKPublicConfig.IsPrintLog())
{
Debug.Log("[ThinkingData] Info: " + str);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7003bc870a4644632aa259a02b235ec6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ThinkingSDK.PC.Utils
{
public class ThinkingSDKTimeUtil
{
public static string Time()
{
return "";
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb171e9f7fda1436a83fc7be10687f92
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,199 @@
using UnityEngine;
using System;
using System.Xml;
using System.Collections.Generic;
using ThinkingSDK.PC.Config;
using ThinkingSDK.PC.Constant;
using ThinkingSDK.PC.Storage;
namespace ThinkingSDK.PC.Utils
{
public class ThinkingSDKUtil
{
private static Dictionary<string, object> deviceInfo = null;
public ThinkingSDKUtil()
{
}
public static List<string> DisPresetProperties = ThinkingSDKUtil.GetDisPresetProperties();
/*
* Check if the URL is valid
*/
public static bool IsValiadURL(string url)
{
return !(url == null || url.Length == 0 || !url.Contains("http") || !url.Contains("https"));
}
/*
* Check if the string is empty
*/
public static bool IsEmptyString(string str)
{
return (str == null || str.Length == 0);
}
public static Dictionary<string, object> DeviceInfo()
{
if (deviceInfo == null)
{
deviceInfo = new Dictionary<string, object>();
deviceInfo[ThinkingSDKConstant.DEVICE_ID] = ThinkingSDKDeviceInfo.DeviceID();
//deviceInfo[ThinkingSDKConstant.CARRIER] = ThinkingSDKDeviceInfo.Carrier(); //PC端不采集
deviceInfo[ThinkingSDKConstant.OS] = ThinkingSDKDeviceInfo.OS();
deviceInfo[ThinkingSDKConstant.OS_VERSION] = ThinkingSDKDeviceInfo.OSVersion();
deviceInfo[ThinkingSDKConstant.SCREEN_HEIGHT] = ThinkingSDKDeviceInfo.ScreenHeight();
deviceInfo[ThinkingSDKConstant.SCREEN_WIDTH] = ThinkingSDKDeviceInfo.ScreenWidth();
deviceInfo[ThinkingSDKConstant.MANUFACTURE] = ThinkingSDKDeviceInfo.Manufacture();
deviceInfo[ThinkingSDKConstant.DEVICE_MODEL] = ThinkingSDKDeviceInfo.DeviceModel();
deviceInfo[ThinkingSDKConstant.APP_VERSION] = ThinkingSDKAppInfo.AppVersion();
deviceInfo[ThinkingSDKConstant.APP_BUNDLEID] = ThinkingSDKAppInfo.AppIdentifier();
deviceInfo[ThinkingSDKConstant.LIB] = ThinkingSDKAppInfo.LibName();
deviceInfo[ThinkingSDKConstant.LIB_VERSION] = ThinkingSDKAppInfo.LibVersion();
}
deviceInfo[ThinkingSDKConstant.SYSTEM_LANGUAGE] = ThinkingSDKDeviceInfo.MachineLanguage();
deviceInfo[ThinkingSDKConstant.NETWORK_TYPE] = ThinkingSDKDeviceInfo.NetworkType();
return deviceInfo;
}
// Get disabled preset properties
private static List<string> GetDisPresetProperties()
{
List<string> properties = new List<string>();
TextAsset textAsset = Resources.Load<TextAsset>("ta_public_config");
if (textAsset != null && textAsset.text != null)
{
XmlDocument xmlDoc = new XmlDocument();
// xmlDoc.Load(srcPath);
xmlDoc.LoadXml(textAsset.text);
XmlNode root = xmlDoc.SelectSingleNode("resources");
for (int i=0; i<root.ChildNodes.Count; i++)
{
XmlNode x1 = root.ChildNodes[i];
if (x1.NodeType == XmlNodeType.Element)
{
XmlElement e1 = x1 as XmlElement;
if (e1.HasAttributes)
{
string name = e1.GetAttribute("name");
if (name == "TDDisPresetProperties" && e1.HasChildNodes)
{
for (int j=0; j<e1.ChildNodes.Count; j++)
{
XmlNode x2 = e1.ChildNodes[j];
if (x2.NodeType == XmlNodeType.Element)
{
properties.Add(x2.InnerText);
}
}
}
}
}
}
}
return properties;
}
// A persistent random number, used as an alternative to the distinct ID
public static string RandomID(bool persistent = true)
{
string randomID = null;
if (persistent)
{
randomID = (string)ThinkingSDKFile.GetData(ThinkingSDKConstant.RANDOM_ID, typeof(string));
}
if (string.IsNullOrEmpty(randomID))
{
randomID = System.Guid.NewGuid().ToString("N");
if (persistent)
{
ThinkingSDKFile.SaveData(ThinkingSDKConstant.RANDOM_ID, randomID);
}
}
return randomID;
}
// Get time zone offset
public static double ZoneOffset(DateTime dateTime, TimeZoneInfo timeZone)
{
bool success = true;
TimeSpan timeSpan = new TimeSpan();
try
{
timeSpan = timeZone.BaseUtcOffset;
}
catch (Exception)
{
success = false;
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("ZoneOffset: TimeSpan get failed : " + e.Message);
}
try
{
if (timeZone.IsDaylightSavingTime(dateTime))
{
TimeSpan timeSpan1 = TimeSpan.FromHours(1);
timeSpan = timeSpan.Add(timeSpan1);
}
}
catch (Exception)
{
success = false;
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("ZoneOffset: IsDaylightSavingTime get failed : " + e.Message);
}
if (success == false)
{
timeSpan = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
}
return timeSpan.TotalHours;
}
// time formatting
public static string FormatDate(DateTime dateTime, TimeZoneInfo timeZone)
{
bool success = true;
DateTime univDateTime = dateTime.ToUniversalTime();
TimeSpan timeSpan = new TimeSpan();
try
{
timeSpan = timeZone.BaseUtcOffset;
}
catch (Exception)
{
success = false;
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("FormatDate - TimeSpan get failed : " + e.Message);
}
try
{
if (timeZone.IsDaylightSavingTime(dateTime))
{
TimeSpan timeSpan1 = TimeSpan.FromHours(1);
timeSpan = timeSpan.Add(timeSpan1);
}
}
catch (Exception)
{
success = false;
//if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("FormatDate: IsDaylightSavingTime get failed : " + e.Message);
}
if (success == false)
{
timeSpan = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
}
DateTime dateNew = univDateTime + timeSpan;
return dateNew.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture);
}
// add Dictionary to Dictionary
public static void AddDictionary(Dictionary<string, object> originalDic, Dictionary<string, object> subDic)
{
if (originalDic != subDic)
{
foreach (KeyValuePair<string, object> kv in subDic)
{
originalDic[kv.Key] = kv.Value;
}
}
}
//get timestamp
public static long GetTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalMilliseconds);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ed8643f4a1b924df991677307901a014
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More