diff --git a/Assets/Editor.meta b/Assets/Editor.meta new file mode 100644 index 0000000..9fa18b1 --- /dev/null +++ b/Assets/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1c3596aacf52e4dce91260e35b40c684 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/TDInspectors.cs b/Assets/Editor/TDInspectors.cs new file mode 100644 index 0000000..2f69826 --- /dev/null +++ b/Assets/Editor/TDInspectors.cs @@ -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(); + } + } +} diff --git a/Assets/Editor/TDInspectors.cs.meta b/Assets/Editor/TDInspectors.cs.meta new file mode 100644 index 0000000..d24fd67 --- /dev/null +++ b/Assets/Editor/TDInspectors.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9e175a5169e2c4de78d15b28f2ce6520 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/TDPostprocessBuild.cs b/Assets/Editor/TDPostprocessBuild.cs new file mode 100644 index 0000000..ae5271d --- /dev/null +++ b/Assets/Editor/TDPostprocessBuild.cs @@ -0,0 +1,124 @@ +#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_OPENHARMONY +using System.IO; +using UnityEditor; +using UnityEditor.Callbacks; + +namespace ThinkingData.Analytics.Editors +{ + public class TD_PostProcessBuild + { + [PostProcessBuildAttribute(88)] + public static void OnPostProcessBuild(BuildTarget target, string targetPath) + { + string path = Path.Combine(targetPath, "entry/oh-package.json5"); + string jsonContent = File.ReadAllText(path); + jsonContent = jsonContent.Replace("\"TDAnalytics\"", "\"@thinkingdata/analytics\""); + File.WriteAllText(path, jsonContent); + } + } +} +#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("ta_public_config"); + if (textAsset != null && textAsset.bytes != null) + { + File.WriteAllBytes(desPath, textAsset.bytes); + } + } + } +} +#endif diff --git a/Assets/Editor/TDPostprocessBuild.cs.meta b/Assets/Editor/TDPostprocessBuild.cs.meta new file mode 100644 index 0000000..340f92a --- /dev/null +++ b/Assets/Editor/TDPostprocessBuild.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75476b67117c64ab1a25a2b94db96dcb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GoogleMobileAds/Resources.meta b/Assets/GoogleMobileAds/Resources.meta new file mode 100644 index 0000000..62ebf0d --- /dev/null +++ b/Assets/GoogleMobileAds/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6e99afc9a5a55e343b5eb579656b88d4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GoogleMobileAds/Resources/GoogleMobileAdsSettings.asset b/Assets/GoogleMobileAds/Resources/GoogleMobileAdsSettings.asset new file mode 100644 index 0000000..f04c964 --- /dev/null +++ b/Assets/GoogleMobileAds/Resources/GoogleMobileAdsSettings.asset @@ -0,0 +1,22 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a187246822bbb47529482707f3e0eff8, type: 3} + m_Name: GoogleMobileAdsSettings + m_EditorClassIdentifier: + adMobAndroidAppId: + adMobIOSAppId: + enableKotlinXCoroutinesPackagingOption: 1 + enableGradleBuildPreProcessor: 1 + disableOptimizeInitialization: 0 + disableOptimizeAdLoading: 0 + userTrackingUsageDescription: + userLanguage: en diff --git a/Assets/GoogleMobileAds/Resources/GoogleMobileAdsSettings.asset.meta b/Assets/GoogleMobileAds/Resources/GoogleMobileAdsSettings.asset.meta new file mode 100644 index 0000000..4919efd --- /dev/null +++ b/Assets/GoogleMobileAds/Resources/GoogleMobileAdsSettings.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7496f258105db1c44adb5eb28724b41f +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Android/FirebaseApp.androidlib.meta b/Assets/Plugins/Android/FirebaseApp.androidlib.meta new file mode 100644 index 0000000..82b7b01 --- /dev/null +++ b/Assets/Plugins/Android/FirebaseApp.androidlib.meta @@ -0,0 +1,32 @@ +fileFormatVersion: 2 +guid: ac5dc49959b8d094ba069fb641fc914d +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: diff --git a/Assets/Plugins/Android/FirebaseApp.androidlib/AndroidManifest.xml b/Assets/Plugins/Android/FirebaseApp.androidlib/AndroidManifest.xml new file mode 100644 index 0000000..fa692b9 --- /dev/null +++ b/Assets/Plugins/Android/FirebaseApp.androidlib/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/Assets/Plugins/Android/FirebaseApp.androidlib/project.properties b/Assets/Plugins/Android/FirebaseApp.androidlib/project.properties new file mode 100644 index 0000000..37b95ed --- /dev/null +++ b/Assets/Plugins/Android/FirebaseApp.androidlib/project.properties @@ -0,0 +1,2 @@ +target=android-9 +android.library=true \ No newline at end of file diff --git a/Assets/Plugins/Android/FirebaseApp.androidlib/res/values/google-services.xml b/Assets/Plugins/Android/FirebaseApp.androidlib/res/values/google-services.xml new file mode 100644 index 0000000..a67beb5 --- /dev/null +++ b/Assets/Plugins/Android/FirebaseApp.androidlib/res/values/google-services.xml @@ -0,0 +1,9 @@ + + + 601745472008 + ag787cd54047-e0ac1-gp.firebasestorage.app + ag787cd54047-e0ac1-gp + AIzaSyCbVg7dxQbatGTDomrKq4AkQAP4aH1vr4Y + AIzaSyCbVg7dxQbatGTDomrKq4AkQAP4aH1vr4Y + 1:601745472008:android:768b7c2f79e2e93725afbd + diff --git a/Assets/Plugins/Android/FirebaseCrashlytics.androidlib.meta b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib.meta new file mode 100644 index 0000000..b363c21 --- /dev/null +++ b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib.meta @@ -0,0 +1,32 @@ +fileFormatVersion: 2 +guid: 0126fce90148f434a8ead1dd4d008662 +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: diff --git a/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/AndroidManifest.xml b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/AndroidManifest.xml new file mode 100644 index 0000000..5284571 --- /dev/null +++ b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/project.properties b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/project.properties new file mode 100644 index 0000000..37b95ed --- /dev/null +++ b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/project.properties @@ -0,0 +1,2 @@ +target=android-9 +android.library=true \ No newline at end of file diff --git a/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/res/values/crashlytics_build_id.xml b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/res/values/crashlytics_build_id.xml new file mode 100644 index 0000000..debd291 --- /dev/null +++ b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/res/values/crashlytics_build_id.xml @@ -0,0 +1 @@ +c1e37c92-6bd2-4451-a40c-88a57f3343f3 diff --git a/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/res/values/crashlytics_unity_version.xml b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/res/values/crashlytics_unity_version.xml new file mode 100644 index 0000000..21af423 --- /dev/null +++ b/Assets/Plugins/Android/FirebaseCrashlytics.androidlib/res/values/crashlytics_unity_version.xml @@ -0,0 +1 @@ +2022.3.62f1 diff --git a/Assets/Plugins/Android/TDAnalytics.aar b/Assets/Plugins/Android/TDAnalytics.aar new file mode 100644 index 0000000..33e6c04 Binary files /dev/null and b/Assets/Plugins/Android/TDAnalytics.aar differ diff --git a/Assets/Plugins/Android/TDAnalytics.aar.meta b/Assets/Plugins/Android/TDAnalytics.aar.meta new file mode 100644 index 0000000..7abadc3 --- /dev/null +++ b/Assets/Plugins/Android/TDAnalytics.aar.meta @@ -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: diff --git a/Assets/Plugins/Android/TDCore.aar b/Assets/Plugins/Android/TDCore.aar new file mode 100644 index 0000000..72e3ff7 Binary files /dev/null and b/Assets/Plugins/Android/TDCore.aar differ diff --git a/Assets/Plugins/Android/TDCore.aar.meta b/Assets/Plugins/Android/TDCore.aar.meta new file mode 100644 index 0000000..42467fe --- /dev/null +++ b/Assets/Plugins/Android/TDCore.aar.meta @@ -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: diff --git a/Assets/Plugins/Android/ThinkingAnalyticsProxy.java b/Assets/Plugins/Android/ThinkingAnalyticsProxy.java new file mode 100644 index 0000000..2b2bf2d --- /dev/null +++ b/Assets/Plugins/Android/ThinkingAnalyticsProxy.java @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2024 ThinkingData + */ +package cn.thinkingdata.analytics; + +import android.content.Context; +import android.text.TextUtils; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import cn.thinkingdata.analytics.TDAnalytics; +import cn.thinkingdata.analytics.TDAnalyticsAPI; +import cn.thinkingdata.analytics.TDConfig; +import cn.thinkingdata.analytics.TDFirstEvent; +import cn.thinkingdata.analytics.TDOverWritableEvent; +import cn.thinkingdata.analytics.TDUpdatableEvent; +import cn.thinkingdata.analytics.ThinkingAnalyticsSDK; + +public class ThinkingAnalyticsProxy { + public static void setCustomerLibInfo(String libName, String libVersion) { + TDAnalytics.setCustomerLibInfo(libName, libVersion); + } + + public static void enableTrackLog(boolean enableLog) { + TDAnalytics.enableLog(enableLog); + } + + public static void calibrateTime(long timeStampMillis) { + TDAnalytics.calibrateTime(timeStampMillis); + } + + public static void calibrateTimeWithNtp(String ntpServer) { + TDAnalytics.calibrateTimeWithNtp(ntpServer); + } + + public static void init(Context context, String appId, String serverUrl, int mode, String name, String timeZone, int version, String publicKey) { + try { + if (context == null || TextUtils.isEmpty(appId) || TextUtils.isEmpty(serverUrl)) { + return; + } + String instanceName = ""; + if (TextUtils.isEmpty(name)) { + instanceName = appId; + } else { + instanceName = name; + } + TDConfig tdConfig = TDConfig.getInstance(context, appId, serverUrl, instanceName); + if (!TextUtils.isEmpty(timeZone)) { + tdConfig.setDefaultTimeZone(TimeZone.getTimeZone(timeZone)); + } + if (mode == 1 || mode == 2) { + tdConfig.setMode(TDConfig.TDMode.values()[mode]); + } + if (version > 0 && !TextUtils.isEmpty(publicKey)) { + tdConfig.enableEncrypt(version, publicKey); + } + TDAnalytics.init(tdConfig); + } catch (Exception ignore) { + + } + } + + public static void track(String eventName, String properties, long time, String timeZoneId, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + JSONObject pJson = null; + try { + pJson = new JSONObject(properties); + } catch (JSONException ignore) { + } + if (time < 0 || TextUtils.isEmpty(timeZoneId)) { + instance.track(eventName, pJson); + } else { + TimeZone timeZone = null; + if (TextUtils.equals(timeZoneId, "Local")) { + timeZone = TimeZone.getDefault(); + } else { + timeZone = TimeZone.getTimeZone(timeZoneId); + } + instance.track(eventName, pJson, new Date(time), timeZone); + } + } + } catch (Exception ignore) { + } + } + + public static void trackEvent(int type, String eventName, String properties, String eventId, long time, String timeZoneId, String appId) { + try { + Date date = null; + if (time > 0) { + date = new Date(time); + } + TimeZone timeZone = null; + if (TextUtils.equals(timeZoneId, "Local")) { + timeZone = TimeZone.getDefault(); + } else { + timeZone = TimeZone.getTimeZone(timeZoneId); + } + JSONObject pJson = null; + try { + pJson = new JSONObject(properties); + } catch (JSONException ignore) { + } + if (type == 0) { + TDFirstEvent firstEvent = new TDFirstEvent(eventName, pJson); + firstEvent.setFirstCheckId(eventId); + firstEvent.setEventTime(date, timeZone); + TDAnalyticsAPI.track(firstEvent, appId); + } else if (type == 1) { + TDUpdatableEvent updatableEvent = new TDUpdatableEvent(eventName, pJson, eventId); + updatableEvent.setEventTime(date, timeZone); + TDAnalyticsAPI.track(updatableEvent, appId); + } else if (type == 2) { + TDOverWritableEvent overWritableEvent = new TDOverWritableEvent(eventName, pJson, eventId); + overWritableEvent.setEventTime(date, timeZone); + TDAnalyticsAPI.track(overWritableEvent, appId); + } + } catch (Exception ignore) { + } + } + + + public static void timeEvent(String eventName, String appId) { + TDAnalyticsAPI.timeEvent(eventName, appId); + } + + public static void login(String accountId, String appId) { + TDAnalyticsAPI.login(accountId, appId); + } + + public static void logout(String appId) { + TDAnalyticsAPI.logout(appId); + } + + public static void identify(String distinctId, String appId) { + TDAnalyticsAPI.setDistinctId(distinctId, appId); + } + + public static String getDistinctId(String appId) { + return TDAnalyticsAPI.getDistinctId(appId); + } + + public static void userSet(String properties, long time, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + Date date = null; + if (time > 0) { + date = new Date(time); + } + instance.user_set(new JSONObject(properties), date); + } + } catch (Exception ignore) { + } + } + + public static void userUnset(String properties, long time, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + Date date = null; + if (time > 0) { + date = new Date(time); + } + instance.user_unset(new JSONObject(properties), date); + } + } catch (Exception ignore) { + } + } + + public static void userSetOnce(String properties, long time, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + Date date = null; + if (time > 0) { + date = new Date(time); + } + instance.user_setOnce(new JSONObject(properties), date); + } + } catch (Exception ignore) { + + } + } + + public static void userAdd(String properties, long time, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + Date date = null; + if (time > 0) { + date = new Date(time); + } + instance.user_add(new JSONObject(properties), date); + } + } catch (Exception ignore) { + + } + } + + public static void userDel(long time, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + Date date = null; + if (time > 0) { + date = new Date(time); + } + instance.user_delete(date); + } + } catch (Exception ignore) { + } + } + + public static void userAppend(String properties, long time, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + Date date = null; + if (time > 0) { + date = new Date(time); + } + instance.user_append(new JSONObject(properties), date); + } + } catch (Exception ignore) { + } + } + + public static void userUniqAppend(String properties, long time, String appId) { + try { + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + if (null != instance) { + Date date = null; + if (time > 0) { + date = new Date(time); + } + instance.user_uniqAppend(new JSONObject(properties), date); + } + } catch (Exception ignore) { + } + } + + public static void setSuperProperties(String properties, String appId) { + try { + TDAnalyticsAPI.setSuperProperties(new JSONObject(properties), appId); + } catch (Exception ignore) { + } + } + + public static void unsetSuperProperty(String property, String appId) { + TDAnalyticsAPI.unsetSuperProperty(property, appId); + } + + public static void clearSuperProperties(String appId) { + TDAnalyticsAPI.clearSuperProperties(appId); + } + + public static String getSuperProperties(String appId) { + return TDAnalyticsAPI.getSuperProperties(appId).toString(); + } + + public static String getPresetProperties(String appId) { + return TDAnalyticsAPI.getPresetProperties(appId).toEventPresetProperties().toString(); + } + + public static void flush(String appId) { + TDAnalyticsAPI.flush(appId); + } + + public static String getDeviceId() { + return TDAnalytics.getDeviceId(); + } + + public static void setTrackStatus(int status, String appId) { + TDAnalytics.TDTrackStatus trackStatus = TDAnalytics.TDTrackStatus.NORMAL; + if (status == 1) { + trackStatus = TDAnalytics.TDTrackStatus.PAUSE; + } else if (status == 2) { + trackStatus = TDAnalytics.TDTrackStatus.STOP; + } else if (status == 3) { + trackStatus = TDAnalytics.TDTrackStatus.SAVE_ONLY; + } + TDAnalyticsAPI.setTrackStatus(trackStatus, appId); + } + + public static String createLightInstance(String appId) { + return TDAnalyticsAPI.lightInstance(appId); + } + + public static void setNetworkType(int type, String appId) { + if (type == 0 || type == 2) { + TDAnalyticsAPI.setNetworkType(TDAnalytics.TDNetworkType.ALL, appId); + } else if (type == 1) { + TDAnalyticsAPI.setNetworkType(TDAnalytics.TDNetworkType.WIFI, appId); + } + } + + public static void enableThirdPartySharing(int types, String params, String appId) { + Map maps = new HashMap<>(); + try { + JSONObject json = new JSONObject(params); + for (Iterator it = json.keys(); it.hasNext(); ) { + String key = it.next(); + maps.put(key, json.opt(key)); + } + } catch (JSONException ignore) { + } + if (maps.isEmpty()) { + TDAnalyticsAPI.enableThirdPartySharing(types, appId); + } else { + TDAnalyticsAPI.enableThirdPartySharing(types, maps, appId); + } + } + + public static void setDynamicSuperPropertiesTrackerListener(String appId, DynamicSuperPropertiesTrackerListener listener) { + ThinkingAnalyticsSDK ta = TDAnalyticsAPI.getInstance(appId); + if (null == ta) return; + ta.setAutoTrackDynamicProperties(new ThinkingAnalyticsSDK.AutoTrackDynamicProperties() { + @Override + public JSONObject getAutoTrackDynamicProperties() { + try { + String pStr = listener.getDynamicSuperPropertiesString(); + if (pStr != null) { + return new JSONObject(pStr); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return new JSONObject(); + } + }); + } + + public static void enableAutoTrack(int types, String properties, String appId) { + JSONObject json = null; + try { + json = new JSONObject(properties); + } catch (JSONException ignore) { + } + TDAnalyticsAPI.enableAutoTrack(types, json, appId); + } + + public static void setAutoTrackProperties(int types, String properties, String appId) { + JSONObject json = null; + try { + json = new JSONObject(properties); + } catch (JSONException ignore) { + } + if (json == null) return; + ThinkingAnalyticsSDK instance = TDAnalyticsAPI.getInstance(appId); + List eventTypeList = new ArrayList<>(); + if ((types & TDAnalytics.TDAutoTrackEventType.APP_START) > 0) { + eventTypeList.add(ThinkingAnalyticsSDK.AutoTrackEventType.APP_START); + } + if ((types & TDAnalytics.TDAutoTrackEventType.APP_END) > 0) { + eventTypeList.add(ThinkingAnalyticsSDK.AutoTrackEventType.APP_END); + } + + if ((types & TDAnalytics.TDAutoTrackEventType.APP_INSTALL) > 0) { + eventTypeList.add(ThinkingAnalyticsSDK.AutoTrackEventType.APP_INSTALL); + } + if ((types & TDAnalytics.TDAutoTrackEventType.APP_CRASH) > 0) { + eventTypeList.add(ThinkingAnalyticsSDK.AutoTrackEventType.APP_CRASH); + } + instance.setAutoTrackProperties(eventTypeList, json); + } + + public static void enableAutoTrack(int types, AutoTrackEventTrackerListener listener, String appId) { + TDAnalyticsAPI.enableAutoTrack(types, new TDAnalytics.TDAutoTrackEventHandler() { + @Override + public JSONObject getAutoTrackEventProperties(int i, JSONObject jsonObject) { + try { + String name = appId; + if (TextUtils.isEmpty(name)) { + name = TDAnalytics.instance.mConfig.getName(); + } + String eStr = listener.eventCallback(i, name, jsonObject.toString()); + if (eStr != null) { + return new JSONObject(eStr); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return new JSONObject(); + } + }, appId); + } + + public interface DynamicSuperPropertiesTrackerListener { + String getDynamicSuperPropertiesString(); + } + + public interface AutoTrackEventTrackerListener { + /** + * Callback event name and current properties and get dynamic properties + * + * @return dynamic properties String + */ + String eventCallback(int type, String appId, String properties); + } +} diff --git a/Assets/Plugins/Android/ThinkingAnalyticsProxy.java.meta b/Assets/Plugins/Android/ThinkingAnalyticsProxy.java.meta new file mode 100644 index 0000000..c97f5e1 --- /dev/null +++ b/Assets/Plugins/Android/ThinkingAnalyticsProxy.java.meta @@ -0,0 +1,32 @@ +fileFormatVersion: 2 +guid: 2eaec3210b47f473c8e023bc9410f6e2 +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: diff --git a/Assets/Plugins/Android/ThinkingSDK-thirdparty.aar b/Assets/Plugins/Android/ThinkingSDK-thirdparty.aar new file mode 100644 index 0000000..a1c7c4e Binary files /dev/null and b/Assets/Plugins/Android/ThinkingSDK-thirdparty.aar differ diff --git a/Assets/Plugins/Android/ThinkingSDK-thirdparty.aar.meta b/Assets/Plugins/Android/ThinkingSDK-thirdparty.aar.meta new file mode 100644 index 0000000..8b74aaa --- /dev/null +++ b/Assets/Plugins/Android/ThinkingSDK-thirdparty.aar.meta @@ -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: diff --git a/Assets/Plugins/Android/gradleTemplate.properties b/Assets/Plugins/Android/gradleTemplate.properties new file mode 100644 index 0000000..4cfad19 --- /dev/null +++ b/Assets/Plugins/Android/gradleTemplate.properties @@ -0,0 +1,10 @@ +org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M +org.gradle.parallel=true +unityStreamingAssets=**STREAMING_ASSETS** +# Android Resolver Properties Start +android.useAndroidX=true +android.enableJetifier=true +# Android Resolver Properties End +**ADDITIONAL_PROPERTIES** + +android.jetifier.ignorelist=annotation-experimental-1.4.0.aar diff --git a/Assets/Plugins/Android/gradleTemplate.properties.meta b/Assets/Plugins/Android/gradleTemplate.properties.meta new file mode 100644 index 0000000..0ae1473 --- /dev/null +++ b/Assets/Plugins/Android/gradleTemplate.properties.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d19bf1415603c584ebc742afa3d23b8e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Android/mainTemplate.gradle b/Assets/Plugins/Android/mainTemplate.gradle new file mode 100644 index 0000000..5ed1629 --- /dev/null +++ b/Assets/Plugins/Android/mainTemplate.gradle @@ -0,0 +1,98 @@ +apply plugin: 'com.android.library' +**APPLY_PLUGINS** + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +// Android Resolver Dependencies Start + implementation 'androidx.annotation:annotation:1.2.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai/Editor/Dependencies.xml:8 + implementation 'androidx.appcompat:appcompat:1.6.1' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai/Editor/Dependencies.xml:6 + implementation 'androidx.browser:browser:1.4.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/Editor/Dependencies.xml:4 + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' // Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:12 + implementation 'androidx.lifecycle:lifecycle-process:2.6.2' // Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:17 + implementation 'androidx.media3:media3-exoplayer:1.0.0-alpha01' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai/Editor/Dependencies.xml:5 + // implementation 'androidx.recyclerview:recyclerview:1.1.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/gtm/Editor/Dependencies.xml:7 + implementation 'androidx.recyclerview:recyclerview:1.2.1' // Assets/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml:9 + implementation 'com.applovin.mediation:bigoads-adapter:5.5.1.2' // Assets/MaxSdk/Mediation/BigoAds/Editor/Dependencies.xml:4 + implementation 'com.applovin.mediation:bytedance-adapter:7.5.0.3.0' // Assets/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml:8 + implementation 'com.applovin.mediation:fyber-adapter:8.3.8.0' // Assets/MaxSdk/Mediation/Fyber/Editor/Dependencies.xml:4 + implementation 'com.applovin.mediation:google-adapter:[24.5.0.0]' // Assets/MaxSdk/Mediation/Google/Editor/Dependencies.xml:5 + implementation 'com.applovin.mediation:google-ad-manager-adapter:[24.5.0.0]' // Assets/MaxSdk/Mediation/GoogleAdManager/Editor/Dependencies.xml:5 + implementation 'com.applovin.mediation:mintegral-adapter:16.9.91.0' // Assets/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml:8 + implementation 'com.applovin.mediation:moloco-adapter:4.0.0.0' // Assets/MaxSdk/Mediation/Moloco/Editor/Dependencies.xml:4 + implementation 'com.applovin.mediation:unityads-adapter:4.16.1.0' // Assets/MaxSdk/Mediation/UnityAds/Editor/Dependencies.xml:4 + implementation 'com.applovin.mediation:vungle-adapter:7.5.1.0' // Assets/MaxSdk/Mediation/Vungle/Editor/Dependencies.xml:4 + implementation 'com.applovin:applovin-sdk:13.3.1' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/applovin/Editor/Dependencies.xml:3 + // implementation 'com.bigossp:bigo-ads:5.0.0' // Assets/BigoSDK/Editor/Dependencies.xml:11 + implementation 'com.bigossp:bigo-ads:5.3.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/bigo/Editor/Dependencies.xml:3 + implementation 'com.fyber:marketplace-sdk:8.3.7' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/fyber/Editor/Dependencies.xml:3 + // implementation 'com.google.android.gms:play-services-ads:24.4.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/admob/Editor/Dependencies.xml:3 + implementation 'com.google.android.gms:play-services-ads:24.5.0' // Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:7 + // implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/vungle/Editor/Dependencies.xml:5 + implementation 'com.google.android.gms:play-services-ads-identifier:18.2.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/pangle/Editor/Dependencies.xml:7 + implementation 'com.google.android.gms:play-services-base:18.7.2' // Assets/rd3/Firebase/Editor/AppDependencies.xml:17 + implementation 'com.google.android.gms:play-services-basement:18.1.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/vungle/Editor/Dependencies.xml:4 + implementation 'com.google.android.material:material:1.2.1' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai/Editor/Dependencies.xml:7 + implementation 'com.google.android.ump:user-messaging-platform:3.2.0' // Assets/GoogleMobileAds/Editor/GoogleUmpDependencies.xml:7 + implementation 'com.google.firebase:firebase-analytics:23.0.0' // Assets/rd3/Firebase/Editor/RemoteConfigDependencies.xml:15 + implementation 'com.google.firebase:firebase-analytics-unity:13.1.0' // Assets/rd3/Firebase/Editor/AnalyticsDependencies.xml:18 + implementation 'com.google.firebase:firebase-app-unity:13.1.0' // Assets/rd3/Firebase/Editor/AppDependencies.xml:22 + implementation 'com.google.firebase:firebase-common:22.0.0' // Assets/rd3/Firebase/Editor/AppDependencies.xml:13 + implementation 'com.google.firebase:firebase-config:23.0.0' // Assets/rd3/Firebase/Editor/RemoteConfigDependencies.xml:13 + implementation 'com.google.firebase:firebase-config-unity:13.1.0' // Assets/rd3/Firebase/Editor/RemoteConfigDependencies.xml:20 + implementation 'com.google.firebase:firebase-crashlytics-ndk:20.0.0' // Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml:13 + implementation 'com.google.firebase:firebase-crashlytics-unity:13.1.0' // Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml:20 + implementation 'com.mbridge.msdk.oversea:mbridge_android_sdk:16.9.71' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/gtm/Editor/Dependencies.xml:6 + implementation 'com.pangle.global:pag-sdk:7.2.0.6' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/pangle/Editor/Dependencies.xml:6 + implementation 'com.unity3d.ads:unity-ads:4.14.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/unityads/Editor/Dependencies.xml:3 + implementation 'com.vungle:vungle-ads:7.5.0' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/vungle/Editor/Dependencies.xml:3 + implementation 'io.github.kwainetwork:adApi:1.2.19' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai/Editor/Dependencies.xml:3 + implementation 'io.github.kwainetwork:adImpl:1.2.19' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai/Editor/Dependencies.xml:4 + implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.10' // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai/Editor/Dependencies.xml:9 +// Android Resolver Dependencies End +**DEPS**} + +// Android Resolver Exclusions Start +android { + packagingOptions { + exclude ('/lib/armeabi/*' + '*') + exclude ('/lib/mips/*' + '*') + exclude ('/lib/mips64/*' + '*') + exclude ('/lib/x86/*' + '*') + exclude ('/lib/x86_64/*' + '*') + } +} +// Android Resolver Exclusions End +android { + namespace "com.unity3d.player" + ndkPath "**NDKPATH**" + compileSdkVersion **APIVERSION** + buildToolsVersion '**BUILDTOOLS**' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + + defaultConfig { + minSdkVersion **MINSDKVERSION** + targetSdkVersion **TARGETSDKVERSION** + ndk { + abiFilters **ABIFILTERS** + } + versionCode **VERSIONCODE** + versionName '**VERSIONNAME**' + consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD** + } + + lintOptions { + abortOnError false + } + + aaptOptions { + noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ') + ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~" + }**PACKAGING_OPTIONS** +} +**IL_CPP_BUILD_SETUP** +**SOURCE_BUILD_SETUP** +**EXTERNAL_SOURCES** diff --git a/Assets/Plugins/Android/mainTemplate.gradle.meta b/Assets/Plugins/Android/mainTemplate.gradle.meta new file mode 100644 index 0000000..54243cf --- /dev/null +++ b/Assets/Plugins/Android/mainTemplate.gradle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d0ce803953bb6b144b9dced384d6d358 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/Android/settingsTemplate.gradle b/Assets/Plugins/Android/settingsTemplate.gradle new file mode 100644 index 0000000..815e48e --- /dev/null +++ b/Assets/Plugins/Android/settingsTemplate.gradle @@ -0,0 +1,42 @@ +pluginManagement { + repositories { + **ARTIFACTORYREPOSITORY** + gradlePluginPortal() + google() + mavenCentral() + } +} + +include ':launcher', ':unityLibrary' +**INCLUDES** + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + repositories { + **ARTIFACTORYREPOSITORY** + google() + mavenCentral() +// Android Resolver Repos Start + def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/") + maven { + url "https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea" // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/gtm/Editor/Dependencies.xml:5, Assets/MaxSdk/Mediation/Mintegral/Editor/Dependencies.xml:8 + } + maven { + url "https://artifact.bytedance.com/repository/pangle" // Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/pangle/Editor/Dependencies.xml:5, Assets/MaxSdk/Mediation/ByteDance/Editor/Dependencies.xml:8 + } + maven { + url "https://repo1.maven.org/maven2/" // Assets/BigoSDK/Editor/Dependencies.xml:11 + } + maven { + url "https://maven.google.com/" // Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:7, Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:12, Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml:17, Assets/GoogleMobileAds/Editor/GoogleUmpDependencies.xml:7 + } + maven { + url (unityProjectPath + "/Assets/Firebase/m2repository") // Assets/rd3/Firebase/Editor/AnalyticsDependencies.xml:18, Assets/rd3/Firebase/Editor/AppDependencies.xml:22, Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml:20, Assets/rd3/Firebase/Editor/RemoteConfigDependencies.xml:20 + } + mavenLocal() +// Android Resolver Repos End + flatDir { + dirs "${project(':unityLibrary').projectDir}/libs" + } + } +} diff --git a/Assets/Plugins/Android/settingsTemplate.gradle.meta b/Assets/Plugins/Android/settingsTemplate.gradle.meta new file mode 100644 index 0000000..05bba80 --- /dev/null +++ b/Assets/Plugins/Android/settingsTemplate.gradle.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b7bd8993c4f1e6242a9cfbe9355ae1d0 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/OpenHarmony.meta b/Assets/Plugins/OpenHarmony.meta new file mode 100644 index 0000000..c827a59 --- /dev/null +++ b/Assets/Plugins/OpenHarmony.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 15e16f29589354e96963bf14c4beda9f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/OpenHarmony/NativeBridge.tslib b/Assets/Plugins/OpenHarmony/NativeBridge.tslib new file mode 100644 index 0000000..6aa30f6 --- /dev/null +++ b/Assets/Plugins/OpenHarmony/NativeBridge.tslib @@ -0,0 +1,6 @@ +import { TDOpenHarmonyProxy } from "./TDOpenHarmonyProxy.ts"; +export function RegisterNativeBridge(){ + var register = { } + register["TDOpenHarmonyProxy"] = TDOpenHarmonyProxy; + return register +} diff --git a/Assets/Plugins/OpenHarmony/NativeBridge.tslib.meta b/Assets/Plugins/OpenHarmony/NativeBridge.tslib.meta new file mode 100644 index 0000000..425318d --- /dev/null +++ b/Assets/Plugins/OpenHarmony/NativeBridge.tslib.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 15b10eae4ecca486aa372841269de824 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/OpenHarmony/TDAnalytics.har b/Assets/Plugins/OpenHarmony/TDAnalytics.har new file mode 100644 index 0000000..a1180b6 Binary files /dev/null and b/Assets/Plugins/OpenHarmony/TDAnalytics.har differ diff --git a/Assets/Plugins/OpenHarmony/TDAnalytics.har.meta b/Assets/Plugins/OpenHarmony/TDAnalytics.har.meta new file mode 100644 index 0000000..622f6d9 --- /dev/null +++ b/Assets/Plugins/OpenHarmony/TDAnalytics.har.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7bb46bcdc1562464698344aedabc6ad9 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/OpenHarmony/TDOpenHarmonyProxy.ts b/Assets/Plugins/OpenHarmony/TDOpenHarmonyProxy.ts new file mode 100644 index 0000000..2355dba --- /dev/null +++ b/Assets/Plugins/OpenHarmony/TDOpenHarmonyProxy.ts @@ -0,0 +1,273 @@ +import { TDAnalytics, TDConfig, TDMode, TDNetworkType } from '@thinkingdata/analytics'; +import I18n from '@ohos.i18n'; +export class TDOpenHarmonyProxy { + + static init(appId: string, serverUrl: string, mode: number, timeZone: string, version: number, publicKey: string) { + let config = new TDConfig() + config.appId = appId + config.serverUrl = serverUrl + if (mode == 1) { + config.mode = TDMode.DEBUG + } else if (mode == 2) { + config.mode = TDMode.DEBUG_ONLY + } else { + config.mode = TDMode.NORMAL + } + if (timeZone) { + config.defaultTimeZone = I18n.getTimeZone(timeZone) + } + if (publicKey && version > 0) { + config.enableEncrypt(version, publicKey) + } + TDAnalytics.initWithConfig(globalThis.context, config) + } + + static enableLog(enable: boolean) { + TDAnalytics.enableLog(enable) + } + + static setLibraryInfo(libName: string, libVersion: string) { + TDAnalytics.setCustomerLibInfo(libName, libVersion) + } + + static setDistinctId(distinctId: string, appId: string) { + TDAnalytics.setDistinctId(distinctId, appId) + } + + static getDistinctId(appId: string): string { + return TDAnalytics.getDistinctId(appId) + } + + static login(accountId: string, appId: string) { + TDAnalytics.login(accountId, appId) + } + + static logout(appId: string) { + TDAnalytics.logout(appId) + } + + static track(eventName: string, properties: string, timeStamp: number, timeZoneId: string, appId: string) { + try { + let time: Date = null; + let timeZone: I18n.TimeZone = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + if (timeZoneId) { + if (timeZoneId === 'Local') { + timeZone = I18n.getTimeZone() + } else { + timeZone = I18n.getTimeZone(timeZoneId) + } + } + } + TDAnalytics.track({ + eventName: eventName, + properties: this.parseJsonStrict(properties), + time: time, + timeZone: timeZone + }, appId) + } catch (e) { + } + } + + static trackEvent(eventType: number, eventName: string, properties: string, eventId: string, timeStamp: number, + timezoneId: string, appId: string) { + try { + let time: Date = null; + let timeZone: I18n.TimeZone = null; + if (timeStamp > 0) { + time = new Date(timeStamp); + if (timezoneId) { + if (timezoneId == 'Local') { + timeZone = I18n.getTimeZone() + } else { + timeZone = I18n.getTimeZone(timezoneId) + } + } + } + if (eventType == 1) { + TDAnalytics.trackFirst({ + eventName: eventName, + properties: this.parseJsonStrict(properties), + firstCheckId: eventId, + time: time, + timeZone: timeZone + }, appId) + } else if (eventType == 2) { + TDAnalytics.trackUpdate({ + eventName: eventName, + properties: this.parseJsonStrict(properties), + eventId: eventId, + time: time, + timeZone: timeZone + }, appId) + } else if (eventType == 3) { + TDAnalytics.trackOverwrite({ + eventName: eventName, + properties: this.parseJsonStrict(properties), + eventId: eventId, + time: time, + timeZone: timeZone + }, appId) + } + } catch (e) { + } + } + + + static setSuperProperties(superProperties: string, appId: string) { + try { + TDAnalytics.setSuperProperties(this.parseJsonStrict(superProperties), appId) + } catch (e) { + } + } + + static unsetSuperProperty(property: string, appId: string) { + TDAnalytics.unsetSuperProperty(property, appId) + } + + static clearSuperProperties(appId: string) { + TDAnalytics.clearSuperProperties(appId) + } + + static getSuperProperties(appId: string): string { + return TDAnalytics.getSuperProperties(appId) + } + + static getPresetProperties(appId: string): string { + return TDAnalytics.getPresetProperties(appId) + } + + static flush(appId: string) { + TDAnalytics.flush(appId) + } + + static userSet(properties: string, timeStamp: number, appId: string) { + try { + let time: Date = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + } + TDAnalytics.userSet({ + properties: this.parseJsonStrict(properties), + time: time + }, appId) + } catch (e) { + } + } + + static userSetOnce(properties: string, timeStamp: number, appId: string) { + try { + let time: Date = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + } + TDAnalytics.userSetOnce({ + properties: this.parseJsonStrict(properties), + time: time + }, appId) + } catch (e) { + } + } + + static userUnset(property: string, timeStamp: number, appId: string) { + let time: Date = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + } + TDAnalytics.userUnset({ + property: property, + time: time + }, appId) + } + + static userAdd(properties: string, timeStamp: number, appId: string) { + try { + let time: Date = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + } + TDAnalytics.userAdd({ + properties: this.parseJsonStrict(properties), + time: time + }, appId) + } catch (e) { + } + } + + static userAppend(properties: string, timeStamp: number, appId: string) { + try { + let time: Date = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + } + TDAnalytics.userAppend({ + properties: this.parseJsonStrict(properties), + time: time + }, appId) + } catch (e) { + } + } + + static userUniqAppend(properties: string, timeStamp: number, appId: string) { + try { + let time: Date = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + } + TDAnalytics.userUniqAppend({ + properties: this.parseJsonStrict(properties), + time: time + }, appId) + } catch (e) { + } + } + + + static userDelete(timeStamp: number, appId: string) { + let time: Date = null; + if (timeStamp > 0) { + time = new Date(timeStamp) + } + TDAnalytics.userDelete({ + time: time + }, appId) + } + + static getDeviceId(): string { + return TDAnalytics.getDeviceId() + } + + static setNetWorkType(type: number) { + if (type == 2) { + TDAnalytics.setNetworkType(TDNetworkType.WIFI) + } else { + TDAnalytics.setNetworkType(TDNetworkType.ALL) + } + } + + static enableAutoTrack(autoTypes: number, appId: string) { + TDAnalytics.enableAutoTrack(globalThis.context, autoTypes, null, appId) + } + + static timeEvent(eventName: string, appId: string) { + TDAnalytics.timeEvent(eventName, appId) + } + + static calibrateTime(timestamp: number) { + TDAnalytics.calibrateTime(timestamp) + } + + private static parseJsonStrict(jsonString: string): object { + try { + const parsed = JSON.parse(jsonString); + if (typeof parsed !== 'object' || parsed === null) { + return {}; + } + return parsed; + } catch (error) { + return {}; + } + } + +} \ No newline at end of file diff --git a/Assets/Plugins/OpenHarmony/TDOpenHarmonyProxy.ts.meta b/Assets/Plugins/OpenHarmony/TDOpenHarmonyProxy.ts.meta new file mode 100644 index 0000000..215c1eb --- /dev/null +++ b/Assets/Plugins/OpenHarmony/TDOpenHarmonyProxy.ts.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c7ac184e05351426197404368d11c8d2 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC.meta b/Assets/Plugins/PC.meta new file mode 100644 index 0000000..bbe9ed9 --- /dev/null +++ b/Assets/Plugins/PC.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b5e64871c9af447029fea9ebb8a01507 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/AutoTrack.meta b/Assets/Plugins/PC/AutoTrack.meta new file mode 100644 index 0000000..ca4fbe3 --- /dev/null +++ b/Assets/Plugins/PC/AutoTrack.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eefcaefb9c6534ae78d8e6d4345a9531 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/AutoTrack/ThinkingSDKAutoTrack.cs b/Assets/Plugins/PC/AutoTrack/ThinkingSDKAutoTrack.cs new file mode 100644 index 0000000..5aceb94 --- /dev/null +++ b/Assets/Plugins/PC/AutoTrack/ThinkingSDKAutoTrack.cs @@ -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> mAutoTrackProperties = new Dictionary>(); + 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 properties = new Dictionary(); + 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 properties = new Dictionary(); + 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 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 mProperties = new Dictionary(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 mProperties = new Dictionary(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 properties = null; + if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_INSTALL)) + { + properties = mAutoTrackProperties[TDAutoTrackEventType_APP_INSTALL]; + } + else + { + properties = new Dictionary(); + } + 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 properties = null; + if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_START)) + { + properties = mAutoTrackProperties[TDAutoTrackEventType_APP_START]; + } + else + { + properties = new Dictionary(); + } + 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 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; + } + } + +} diff --git a/Assets/Plugins/PC/AutoTrack/ThinkingSDKAutoTrack.cs.meta b/Assets/Plugins/PC/AutoTrack/ThinkingSDKAutoTrack.cs.meta new file mode 100644 index 0000000..5401f4e --- /dev/null +++ b/Assets/Plugins/PC/AutoTrack/ThinkingSDKAutoTrack.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0ac1f96dfbfb046e79d0e2f5c3d94261 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Config.meta b/Assets/Plugins/PC/Config.meta new file mode 100644 index 0000000..0d08ab0 --- /dev/null +++ b/Assets/Plugins/PC/Config.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 255aaff7c590d43c0893234eb5279770 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Config/ThinkingSDKConfig.cs b/Assets/Plugins/PC/Config/ThinkingSDKConfig.cs new file mode 100644 index 0000000..fc04f3f --- /dev/null +++ b/Assets/Plugins/PC/Config/ThinkingSDKConfig.cs @@ -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 mDisableEvents = new List(); + private static Dictionary sInstances = new Dictionary(); + 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 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 result) + { + try + { + if (result != null && result["code"] != null + && int.Parse(result["code"].ToString()) == 0) + { + Dictionary data = (Dictionary)result["data"]; + if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Get remote config success: " + ThinkingSDKJSON.Serialize(data)); + foreach (KeyValuePair 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)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 param, ResponseHandle responseHandle) { + yield return ThinkingSDKBaseRequest.GetWithFORM_2(this.mConfigUrl,this.mToken,param,responseHandle); + } + } +} diff --git a/Assets/Plugins/PC/Config/ThinkingSDKConfig.cs.meta b/Assets/Plugins/PC/Config/ThinkingSDKConfig.cs.meta new file mode 100644 index 0000000..243dc8d --- /dev/null +++ b/Assets/Plugins/PC/Config/ThinkingSDKConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 472854a90c78a4dd4a16616ba3d3437d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Config/ThinkingSDKPublicConfig.cs b/Assets/Plugins/PC/Config/ThinkingSDKPublicConfig.cs new file mode 100644 index 0000000..9c95ea9 --- /dev/null +++ b/Assets/Plugins/PC/Config/ThinkingSDKPublicConfig.cs @@ -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; + } + + } +} diff --git a/Assets/Plugins/PC/Config/ThinkingSDKPublicConfig.cs.meta b/Assets/Plugins/PC/Config/ThinkingSDKPublicConfig.cs.meta new file mode 100644 index 0000000..d514b1a --- /dev/null +++ b/Assets/Plugins/PC/Config/ThinkingSDKPublicConfig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 47e9c09a25d664062bd8264d072b2f34 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Constant.meta b/Assets/Plugins/PC/Constant.meta new file mode 100644 index 0000000..416a115 --- /dev/null +++ b/Assets/Plugins/PC/Constant.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e5cb18d25c15d4fca82ba5c10c117b9e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Constant/ThinkingSDKConstant.cs b/Assets/Plugins/PC/Constant/ThinkingSDKConstant.cs new file mode 100644 index 0000000..679f81e --- /dev/null +++ b/Assets/Plugins/PC/Constant/ThinkingSDKConstant.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; + +namespace ThinkingSDK.PC.Constant +{ + public delegate void ResponseHandle(Dictionary 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"; + + + + + + + + } +} diff --git a/Assets/Plugins/PC/Constant/ThinkingSDKConstant.cs.meta b/Assets/Plugins/PC/Constant/ThinkingSDKConstant.cs.meta new file mode 100644 index 0000000..0271e3a --- /dev/null +++ b/Assets/Plugins/PC/Constant/ThinkingSDKConstant.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 361e81159859b41d797fc238c8f55f17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/DataModel.meta b/Assets/Plugins/PC/DataModel.meta new file mode 100644 index 0000000..48cac20 --- /dev/null +++ b/Assets/Plugins/PC/DataModel.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a138ac43e601b433093a111aff909263 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKBaseData.cs b/Assets/Plugins/PC/DataModel/ThinkingSDKBaseData.cs new file mode 100644 index 0000000..4fceb96 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKBaseData.cs @@ -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 mProperties = new Dictionary(); + public Dictionary 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 properties):this(time,eventName) + { + if (properties != null) + { + this.SetProperties(properties); + } + } + + abstract public Dictionary ToDictionary(); + public void SetProperties(Dictionary properties,bool isOverwrite = true) + { + if (isOverwrite) + { + foreach (KeyValuePair kv in properties) + { + mProperties[kv.Key] = kv.Value; + + } + } + else + { + foreach (KeyValuePair kv in properties) + { + if (!mProperties.ContainsKey(kv.Key)) + { + mProperties[kv.Key] = kv.Value; + } + + } + } + + } + + } +} diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKBaseData.cs.meta b/Assets/Plugins/PC/DataModel/ThinkingSDKBaseData.cs.meta new file mode 100644 index 0000000..bf4ed94 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKBaseData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69b1ae68ce0724b4290b99fb1920ffca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKEventData.cs b/Assets/Plugins/PC/DataModel/ThinkingSDKEventData.cs new file mode 100644 index 0000000..3d90731 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKEventData.cs @@ -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 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 properties):base(time,eventName,properties) + { + } + public override string GetDataType() + { + return "track"; + } + public void SetDuration(float duration) + { + this.mDuration = duration; + } + + public override Dictionary ToDictionary() + { + if (mData == null) + { + mData = new Dictionary(); + } + 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 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; + } + } +} diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKEventData.cs.meta b/Assets/Plugins/PC/DataModel/ThinkingSDKEventData.cs.meta new file mode 100644 index 0000000..f3b1fa0 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKEventData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3d815c0c9730f473387bb0c0cd83098c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKFirstEvent.cs b/Assets/Plugins/PC/DataModel/ThinkingSDKFirstEvent.cs new file mode 100644 index 0000000..b4b0669 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKFirstEvent.cs @@ -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 ToDictionary() + { + Dictionary dictionary = base.ToDictionary(); + dictionary[ThinkingSDKConstant.FIRST_CHECK_ID] = FirstCheckId(); + return dictionary; + } + } +} diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKFirstEvent.cs.meta b/Assets/Plugins/PC/DataModel/ThinkingSDKFirstEvent.cs.meta new file mode 100644 index 0000000..e177423 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKFirstEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 285f00076791947c8a99103da1a2653d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKOverWritableEvent.cs b/Assets/Plugins/PC/DataModel/ThinkingSDKOverWritableEvent.cs new file mode 100644 index 0000000..ec2c1b2 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKOverWritableEvent.cs @@ -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 ToDictionary() + { + Dictionary dictionary = base.ToDictionary(); + dictionary[ThinkingSDKConstant.EVENT_ID] = mEventID; + return dictionary; + } + } +} diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKOverWritableEvent.cs.meta b/Assets/Plugins/PC/DataModel/ThinkingSDKOverWritableEvent.cs.meta new file mode 100644 index 0000000..b4ba599 --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKOverWritableEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9609b6c1610254c6795e60fe0ce7a92b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKUpdateEvent.cs b/Assets/Plugins/PC/DataModel/ThinkingSDKUpdateEvent.cs new file mode 100644 index 0000000..da8139c --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKUpdateEvent.cs @@ -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 ToDictionary() + { + Dictionary dictionary = base.ToDictionary(); + dictionary[ThinkingSDKConstant.EVENT_ID] = mEventID; + return dictionary; + } + } +} diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKUpdateEvent.cs.meta b/Assets/Plugins/PC/DataModel/ThinkingSDKUpdateEvent.cs.meta new file mode 100644 index 0000000..a6ac63d --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKUpdateEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25db2db9cd0d24311b5c5db04b42a604 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKUserData.cs b/Assets/Plugins/PC/DataModel/ThinkingSDKUserData.cs new file mode 100644 index 0000000..652721d --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKUserData.cs @@ -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 properties) + { + this.SetEventType(eventType); + this.SetTime(time); + this.SetBaseData(null); + this.SetProperties(properties); + } + override public Dictionary ToDictionary() + { + Dictionary data = new Dictionary(); + 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; + } + } +} diff --git a/Assets/Plugins/PC/DataModel/ThinkingSDKUserData.cs.meta b/Assets/Plugins/PC/DataModel/ThinkingSDKUserData.cs.meta new file mode 100644 index 0000000..74880bb --- /dev/null +++ b/Assets/Plugins/PC/DataModel/ThinkingSDKUserData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 890bcbb20acb741689b72692aaf6f60a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Main.meta b/Assets/Plugins/PC/Main.meta new file mode 100644 index 0000000..7a6a436 --- /dev/null +++ b/Assets/Plugins/PC/Main.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3166be662c1c1445387662fcb7118be5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Main/LightThinkingSDKInstance.cs b/Assets/Plugins/PC/Main/LightThinkingSDKInstance.cs new file mode 100644 index 0000000..b5e421a --- /dev/null +++ b/Assets/Plugins/PC/Main/LightThinkingSDKInstance.cs @@ -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 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 SuperProperties() + { + return this.mSupperProperties; + } + public override void ClearSuperProperties() + { + if (IsPaused()) + { + return; + } + this.mSupperProperties.Clear(); + } + public override void EnableAutoTrack(TDAutoTrackEventType events, Dictionary properties) + { + } + public override void SetAutoTrackProperties(TDAutoTrackEventType events, Dictionary properties) + { + } + public override void Flush() + { + } + } + +} \ No newline at end of file diff --git a/Assets/Plugins/PC/Main/LightThinkingSDKInstance.cs.meta b/Assets/Plugins/PC/Main/LightThinkingSDKInstance.cs.meta new file mode 100644 index 0000000..9fba05a --- /dev/null +++ b/Assets/Plugins/PC/Main/LightThinkingSDKInstance.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7bff4ee40c5ed4a0cb4e4afe060d03c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Main/ThinkingPCSDK.cs b/Assets/Plugins/PC/Main/ThinkingPCSDK.cs new file mode 100644 index 0000000..21b038f --- /dev/null +++ b/Assets/Plugins/PC/Main/ThinkingPCSDK.cs @@ -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 Instances = new Dictionary(); + private static readonly Dictionary LightInstances = new Dictionary(); + 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; + } + /// + /// Sets distinct ID + /// + /// + /// + public static void Identifiy(string distinctID, string appId = "") + { + GetInstance(appId).Identifiy(distinctID); + } + + /// + /// Gets distinct ID + /// + /// + /// + public static string DistinctId(string appId = "") + { + return GetInstance(appId).DistinctId(); + } + /// + /// Sets account ID + /// + /// + /// + public static void Login(string accountID,string appId = "") + { + GetInstance(appId).Login(accountID); + } + /// + /// Gets account ID + /// + /// + /// + public static string AccountID(string appId = "") + { + return GetInstance(appId).AccountID(); + } + /// + /// Clear account ID + /// + public static void Logout(string appId = "") + { + GetInstance(appId).Logout(); + } + + /// + /// Enable Auto-tracking Events + /// + /// + /// + public static void EnableAutoTrack(TDAutoTrackEventType events, Dictionary 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 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 properties, string appId = "") + { + GetInstance(appId).Track(eventName,properties); + } + public static void Track(string eventName, Dictionary properties, DateTime date, string appId = "") + { + GetInstance(appId).Track(eventName, properties, date); + } + public static void Track(string eventName, Dictionary properties, DateTime date, TimeZoneInfo timeZone, string appId = "") + { + GetInstance(appId).Track(eventName, properties, date, timeZone); + } + public static void TrackForAll(string eventName, Dictionary 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 superProperties,string appId = "") + { + GetInstance(appId).SetSuperProperties(superProperties); + } + public static void UnsetSuperProperty(string propertyKey, string appId = "") + { + GetInstance(appId).UnsetSuperProperty(propertyKey); + } + public static Dictionary SuperProperties(string appId="") + { + return GetInstance(appId).SuperProperties(); + } + + public static Dictionary 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); + } + } + /// + /// Pause Event timing + /// + /// ture: puase timing, false: resume timing + /// event name (null or empty is for all event) + public static void PauseTimeEvent(bool status, string eventName = "", string appId = "") + { + GetInstance(appId).PauseTimeEvent(status, eventName); + } + public static void UserSet(Dictionary properties, string appId = "") + { + GetInstance(appId).UserSet(properties); + } + public static void UserSet(Dictionary 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 propertyKeys, string appId = "") + { + GetInstance(appId).UserUnset(propertyKeys); + } + public static void UserUnset(List propertyKeys, DateTime dateTime, string appId = "") + { + GetInstance(appId).UserUnset(propertyKeys,dateTime); + } + public static void UserSetOnce(Dictionary properties,string appId = "") + { + GetInstance(appId).UserSetOnce(properties); + } + public static void UserSetOnce(Dictionary properties, DateTime dateTime, string appId = "") + { + GetInstance(appId).UserSetOnce(properties,dateTime); + } + public static void UserAdd(Dictionary properties, string appId = "") + { + GetInstance(appId).UserAdd(properties); + } + public static void UserAdd(Dictionary properties, DateTime dateTime, string appId = "") + { + GetInstance(appId).UserAdd(properties,dateTime); + } + public static void UserAppend(Dictionary properties, string appId = "") + { + GetInstance(appId).UserAppend(properties); + } + public static void UserAppend(Dictionary properties, DateTime dateTime, string appId = "") + { + GetInstance(appId).UserAppend(properties,dateTime); + } + public static void UserUniqAppend(Dictionary properties, string appId = "") + { + GetInstance(appId).UserUniqAppend(properties); + } + public static void UserUniqAppend(Dictionary 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); + } + } +} diff --git a/Assets/Plugins/PC/Main/ThinkingPCSDK.cs.meta b/Assets/Plugins/PC/Main/ThinkingPCSDK.cs.meta new file mode 100644 index 0000000..0cb66c0 --- /dev/null +++ b/Assets/Plugins/PC/Main/ThinkingPCSDK.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee46cd65b236c4202a800c812df46325 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Main/ThinkingSDKInstance.cs b/Assets/Plugins/PC/Main/ThinkingSDKInstance.cs new file mode 100644 index 0000000..fdf463c --- /dev/null +++ b/Assets/Plugins/PC/Main/ThinkingSDKInstance.cs @@ -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 GetDynamicSuperProperties_PC(); + } + public interface TDAutoTrackEventHandler_PC + { + Dictionary AutoTrackEventCallback_PC(int type, Dictionaryproperties); + } + public class ThinkingSDKInstance + { + private string mAppid; + private string mServer; + protected string mDistinctID; + protected string mAccountID; + private bool mOptTracking = true; + private Dictionary mTimeEvents = new Dictionary(); + private Dictionary mTimeEventsBefore = new Dictionary(); + private bool mEnableTracking = true; + private bool mEventSaveOnly = false; //data stores in the cache, but not be reported + protected Dictionary mSupperProperties = new Dictionary(); + protected Dictionary> mAutoTrackProperties = new Dictionary>(); + 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 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 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 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 properties) + { + this.mAutoTrack.SetAutoTrackProperties(events, properties); + } + public void Track(string eventName) + { + Track(eventName, null, DateTime.MinValue); + } + public void Track(string eventName, Dictionary properties) + { + Track(eventName, properties, DateTime.MinValue); + } + public void Track(string eventName, Dictionary properties, DateTime date) + { + Track(eventName, properties, date, null, false); + } + public void Track(string eventName, Dictionary properties, DateTime date, TimeZoneInfo timeZone) + { + Track(eventName, properties, date, timeZone, false); + } + public void Track(string eventName, Dictionary 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 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 dataDic = data.ToDictionary(); + this.mMono.StartCoroutine(mRequest.SendData_2(null, ThinkingSDKJSON.Serialize(dataDic), 1)); + } + else + { + Dictionary 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(); + } + } + + /// + /// flush events data + /// + 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 superProperties) + { + if (IsPaused()) + { + return; + } + Dictionary properties = new Dictionary(); + string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string)); + if (!string.IsNullOrEmpty(propertiesStr)) + { + properties = ThinkingSDKJSON.Deserialize(propertiesStr); + } + ThinkingSDKUtil.AddDictionary(properties, superProperties); + this.mSupperProperties = properties; + ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, ThinkingSDKJSON.Serialize(this.mSupperProperties)); + } + public virtual void UnsetSuperProperty(string propertyKey) + { + if (IsPaused()) + { + return; + } + Dictionary properties = new Dictionary(); + string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string)); + if (!string.IsNullOrEmpty(propertiesStr)) + { + properties = ThinkingSDKJSON.Deserialize(propertiesStr); + } + if (properties.ContainsKey(propertyKey)) + { + properties.Remove(propertyKey); + } + this.mSupperProperties = properties; + ThinkingSDKFile.SaveData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, ThinkingSDKJSON.Serialize(this.mSupperProperties)); + } + public virtual Dictionary SuperProperties() + { + string propertiesStr = (string)ThinkingSDKFile.GetData(this.mAppid, ThinkingSDKConstant.SUPER_PROPERTY, typeof(string)); + if (!string.IsNullOrEmpty(propertiesStr)) + { + this.mSupperProperties = ThinkingSDKJSON.Deserialize(propertiesStr); + } + return this.mSupperProperties; + } + public Dictionary PresetProperties() + { + Dictionary presetProperties = new Dictionary(); + presetProperties[ThinkingSDKConstant.DEVICE_ID] = ThinkingSDKDeviceInfo.DeviceID(); + presetProperties[ThinkingSDKConstant.CARRIER] = ThinkingSDKDeviceInfo.Carrier(); + presetProperties[ThinkingSDKConstant.OS] = ThinkingSDKDeviceInfo.OS(); + presetProperties[ThinkingSDKConstant.SCREEN_HEIGHT] = ThinkingSDKDeviceInfo.ScreenHeight(); + presetProperties[ThinkingSDKConstant.SCREEN_WIDTH] = ThinkingSDKDeviceInfo.ScreenWidth(); + presetProperties[ThinkingSDKConstant.MANUFACTURE] = ThinkingSDKDeviceInfo.Manufacture(); + presetProperties[ThinkingSDKConstant.DEVICE_MODEL] = ThinkingSDKDeviceInfo.DeviceModel(); + presetProperties[ThinkingSDKConstant.SYSTEM_LANGUAGE] = ThinkingSDKDeviceInfo.MachineLanguage(); + presetProperties[ThinkingSDKConstant.OS_VERSION] = ThinkingSDKDeviceInfo.OSVersion(); + presetProperties[ThinkingSDKConstant.NETWORK_TYPE] = ThinkingSDKDeviceInfo.NetworkType(); + presetProperties[ThinkingSDKConstant.APP_BUNDLEID] = ThinkingSDKAppInfo.AppIdentifier(); + presetProperties[ThinkingSDKConstant.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); + } + } + /// + /// Pause Event timing + /// + /// ture: puase timing, false: resume timing + /// event name (null or empty is for all event) + 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 properties) + { + UserSet(properties, DateTime.MinValue); + } + public void UserSet(Dictionary properties,DateTime dateTime) + { + ThinkingSDKTimeInter time = GetTime(dateTime); + ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_SET, properties); + SendData(data); + } + public void UserUnset(string propertyKey) + { + UserUnset(propertyKey, DateTime.MinValue); + } + public void UserUnset(string propertyKey, DateTime dateTime) + { + ThinkingSDKTimeInter time = GetTime(dateTime); + Dictionary properties = new Dictionary(); + properties[propertyKey] = 0; + ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties); + SendData(data); + } + public void UserUnset(List propertyKeys) + { + UserUnset(propertyKeys,DateTime.MinValue); + } + public void UserUnset(List propertyKeys, DateTime dateTime) + { + ThinkingSDKTimeInter time = GetTime(dateTime); + Dictionary properties = new Dictionary(); + foreach (string key in propertyKeys) + { + properties[key] = 0; + } + ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_UNSET, properties); + SendData(data); + } + public void UserSetOnce(Dictionary properties) + { + UserSetOnce(properties, DateTime.MinValue); + } + public void UserSetOnce(Dictionary properties, DateTime dateTime) + { + ThinkingSDKTimeInter time = GetTime(dateTime); + ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_SETONCE, properties); + SendData(data); + } + public void UserAdd(Dictionary properties) + { + UserAdd(properties, DateTime.MinValue); + } + public void UserAdd(Dictionary properties, DateTime dateTime) + { + ThinkingSDKTimeInter time = GetTime(dateTime); + ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_ADD, properties); + SendData(data); + } + public void UserAppend(Dictionary properties) + { + UserAppend(properties, DateTime.MinValue); + } + public void UserAppend(Dictionary properties, DateTime dateTime) + { + ThinkingSDKTimeInter time = GetTime(dateTime); + ThinkingSDKUserData data = new ThinkingSDKUserData(time, ThinkingSDKConstant.USER_APPEND, properties); + SendData(data); + } + public void UserUniqAppend(Dictionary properties) + { + UserUniqAppend(properties, DateTime.MinValue); + } + public void UserUniqAppend(Dictionary 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 properties = new Dictionary(); + 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(); + 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()); + } + } +} + diff --git a/Assets/Plugins/PC/Main/ThinkingSDKInstance.cs.meta b/Assets/Plugins/PC/Main/ThinkingSDKInstance.cs.meta new file mode 100644 index 0000000..02bd125 --- /dev/null +++ b/Assets/Plugins/PC/Main/ThinkingSDKInstance.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8287bb3311be54f52be240639203175f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Request.meta b/Assets/Plugins/PC/Request.meta new file mode 100644 index 0000000..4d9cce4 --- /dev/null +++ b/Assets/Plugins/PC/Request.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: db5e3ec02eff54121adead1f781264b7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Request/ThinkingSDKBaseRequest.cs b/Assets/Plugins/PC/Request/ThinkingSDKBaseRequest.cs new file mode 100644 index 0000000..9a67146 --- /dev/null +++ b/Assets/Plugins/PC/Request/ThinkingSDKBaseRequest.cs @@ -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 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 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); + } + } + } + } +} + diff --git a/Assets/Plugins/PC/Request/ThinkingSDKBaseRequest.cs.meta b/Assets/Plugins/PC/Request/ThinkingSDKBaseRequest.cs.meta new file mode 100644 index 0000000..c52a4c1 --- /dev/null +++ b/Assets/Plugins/PC/Request/ThinkingSDKBaseRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b31966af44764a508681ee9d6e24f7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Request/ThinkingSDKDebugRequest.cs b/Assets/Plugins/PC/Request/ThinkingSDKDebugRequest.cs new file mode 100644 index 0000000..8aeb9b2 --- /dev/null +++ b/Assets/Plugins/PC/Request/ThinkingSDKDebugRequest.cs @@ -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 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); + } + } + } + } +} diff --git a/Assets/Plugins/PC/Request/ThinkingSDKDebugRequest.cs.meta b/Assets/Plugins/PC/Request/ThinkingSDKDebugRequest.cs.meta new file mode 100644 index 0000000..e8c9592 --- /dev/null +++ b/Assets/Plugins/PC/Request/ThinkingSDKDebugRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7849691904f3c426e81a91572a027863 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Request/ThinkingSDKNormalRequest.cs b/Assets/Plugins/PC/Request/ThinkingSDKNormalRequest.cs new file mode 100644 index 0000000..082d158 --- /dev/null +++ b/Assets/Plugins/PC/Request/ThinkingSDKNormalRequest.cs @@ -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 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); + } + } + + } +} diff --git a/Assets/Plugins/PC/Request/ThinkingSDKNormalRequest.cs.meta b/Assets/Plugins/PC/Request/ThinkingSDKNormalRequest.cs.meta new file mode 100644 index 0000000..b1ff204 --- /dev/null +++ b/Assets/Plugins/PC/Request/ThinkingSDKNormalRequest.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 992a71ad5ae554eb98a712f6a65b3a7f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Storage.meta b/Assets/Plugins/PC/Storage.meta new file mode 100644 index 0000000..56bae73 --- /dev/null +++ b/Assets/Plugins/PC/Storage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 21f73e209611b40d3a1c87e9418529b2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Storage/ThinkingSDKFile.cs b/Assets/Plugins/PC/Storage/ThinkingSDKFile.cs new file mode 100644 index 0000000..caca170 --- /dev/null +++ b/Assets/Plugins/PC/Storage/ThinkingSDKFile.cs @@ -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); + } + } +} + diff --git a/Assets/Plugins/PC/Storage/ThinkingSDKFile.cs.meta b/Assets/Plugins/PC/Storage/ThinkingSDKFile.cs.meta new file mode 100644 index 0000000..8ad1e33 --- /dev/null +++ b/Assets/Plugins/PC/Storage/ThinkingSDKFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be6ada75d19854acca2314015d2c6376 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Storage/ThinkingSDKFileJson.cs b/Assets/Plugins/PC/Storage/ThinkingSDKFileJson.cs new file mode 100644 index 0000000..18e9cd7 --- /dev/null +++ b/Assets/Plugins/PC/Storage/ThinkingSDKFileJson.cs @@ -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 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> tempDataList = new List>(); + 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> batch, string prefix) { + // foreach(Dictionary 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 eventKeysPrefix = new Dictionary() { }; + private static Dictionary eventIndexIDKeys = new Dictionary() { }; + private static Dictionary eventAutoIncrementingIDKeys = new Dictionary() { }; + + 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; + } + } + } +} diff --git a/Assets/Plugins/PC/Storage/ThinkingSDKFileJson.cs.meta b/Assets/Plugins/PC/Storage/ThinkingSDKFileJson.cs.meta new file mode 100644 index 0000000..b08277c --- /dev/null +++ b/Assets/Plugins/PC/Storage/ThinkingSDKFileJson.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d4bedacbe272d46bda26db9388665562 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/TaskManager.meta b/Assets/Plugins/PC/TaskManager.meta new file mode 100644 index 0000000..bd2f83f --- /dev/null +++ b/Assets/Plugins/PC/TaskManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 372921461f6fe4648827f1a91a1759e1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/TaskManager/ThinkingSDKTask.cs b/Assets/Plugins/PC/TaskManager/ThinkingSDKTask.cs new file mode 100644 index 0000000..3d1380e --- /dev/null +++ b/Assets/Plugins/PC/TaskManager/ThinkingSDKTask.cs @@ -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 requestList = new List(); + private List responseHandleList = new List(); + private List batchSizeList = new List(); + private List appIdList = new List(); + + + 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(); + //} + + /// + /// hold signal + /// + public void WaitOne() + { + isWaiting = true; + } + /// + /// release signal + /// + 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); + } + } +} + diff --git a/Assets/Plugins/PC/TaskManager/ThinkingSDKTask.cs.meta b/Assets/Plugins/PC/TaskManager/ThinkingSDKTask.cs.meta new file mode 100644 index 0000000..ce3d9c5 --- /dev/null +++ b/Assets/Plugins/PC/TaskManager/ThinkingSDKTask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb96ead89c0c544608be4e0ad781de78 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/ThinkingSDK.asmdef b/Assets/Plugins/PC/ThinkingSDK.asmdef new file mode 100644 index 0000000..4c20b5e --- /dev/null +++ b/Assets/Plugins/PC/ThinkingSDK.asmdef @@ -0,0 +1,3 @@ +{ + "name": "ThinkingSDK" +} diff --git a/Assets/Plugins/PC/ThinkingSDK.asmdef.meta b/Assets/Plugins/PC/ThinkingSDK.asmdef.meta new file mode 100644 index 0000000..a78dc3e --- /dev/null +++ b/Assets/Plugins/PC/ThinkingSDK.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0a958a7eb80a248e1b8bc4553787c209 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time.meta b/Assets/Plugins/PC/Time.meta new file mode 100644 index 0000000..ee5221a --- /dev/null +++ b/Assets/Plugins/PC/Time.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c859b53e53b824a2aa36430c980862cf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/TDTimeout.cs b/Assets/Plugins/PC/Time/TDTimeout.cs new file mode 100644 index 0000000..3c2de2c --- /dev/null +++ b/Assets/Plugins/PC/Time/TDTimeout.cs @@ -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 action, object obj) + { + GameObject gameObject = new GameObject("TDTimeout"); + var tdTimeout = gameObject.AddComponent(); + tdTimeout._setTimeout(timeout, action, obj); + } + + private void _setTimeout(int timeout, Action action, object obj) + { + StartCoroutine(_wait(timeout, action, obj)); + } + + private IEnumerator _wait(int timeout, Action action, object obj) + { + yield return new WaitForSeconds(timeout); + if (action != null) + { + action(obj); + } + Destroy(gameObject); + } + } +} diff --git a/Assets/Plugins/PC/Time/TDTimeout.cs.meta b/Assets/Plugins/PC/Time/TDTimeout.cs.meta new file mode 100644 index 0000000..81367bd --- /dev/null +++ b/Assets/Plugins/PC/Time/TDTimeout.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c4b6a31edd864c43a12c23d11ac6ddd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/ThinkingSDKCalibratedTime.cs b/Assets/Plugins/PC/Time/ThinkingSDKCalibratedTime.cs new file mode 100644 index 0000000..cd24363 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKCalibratedTime.cs @@ -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); + } + } + } + +} diff --git a/Assets/Plugins/PC/Time/ThinkingSDKCalibratedTime.cs.meta b/Assets/Plugins/PC/Time/ThinkingSDKCalibratedTime.cs.meta new file mode 100644 index 0000000..4d4dc14 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKCalibratedTime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46014ab35934a4a90b8329f357801cdf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/ThinkingSDKDefinedTime.cs b/Assets/Plugins/PC/Time/ThinkingSDKDefinedTime.cs new file mode 100644 index 0000000..654a19e --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKDefinedTime.cs @@ -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; + } + } +} + diff --git a/Assets/Plugins/PC/Time/ThinkingSDKDefinedTime.cs.meta b/Assets/Plugins/PC/Time/ThinkingSDKDefinedTime.cs.meta new file mode 100644 index 0000000..7cdf3fa --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKDefinedTime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86eabc3f1cff146f89092cd516702db9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/ThinkingSDKNTPCalibration.cs b/Assets/Plugins/PC/Time/ThinkingSDKNTPCalibration.cs new file mode 100644 index 0000000..647b7c6 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKNTPCalibration.cs @@ -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(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; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/PC/Time/ThinkingSDKNTPCalibration.cs.meta b/Assets/Plugins/PC/Time/ThinkingSDKNTPCalibration.cs.meta new file mode 100644 index 0000000..09d2677 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKNTPCalibration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 610a0d13d17714116b2d436c4daf69a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTime.cs b/Assets/Plugins/PC/Time/ThinkingSDKTime.cs new file mode 100644 index 0000000..4f15c55 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTime.cs @@ -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); + } + } + } + +} diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTime.cs.meta b/Assets/Plugins/PC/Time/ThinkingSDKTime.cs.meta new file mode 100644 index 0000000..97d6856 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 482ba0db5b92b4f9e9475acfda6e496c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTimeCalibration.cs b/Assets/Plugins/PC/Time/ThinkingSDKTimeCalibration.cs new file mode 100644 index 0000000..a4096a0 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTimeCalibration.cs @@ -0,0 +1,32 @@ +using System; + +namespace ThinkingSDK.PC.Time +{ + public class ThinkingSDKTimeCalibration + { + /// + /// Timestamp when time was calibrated + /// + public long mStartTime; + /// + /// System boot time when calibrating time + /// + 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; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTimeCalibration.cs.meta b/Assets/Plugins/PC/Time/ThinkingSDKTimeCalibration.cs.meta new file mode 100644 index 0000000..202b812 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTimeCalibration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9bb8b764cd4d47bd91702ea2c9a5ad5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTimeInter.cs b/Assets/Plugins/PC/Time/ThinkingSDKTimeInter.cs new file mode 100644 index 0000000..82c17fa --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTimeInter.cs @@ -0,0 +1,9 @@ +using System; +namespace ThinkingSDK.PC.Time +{ + public interface ThinkingSDKTimeInter + { + string GetTime(TimeZoneInfo timeZone); + Double GetZoneOffset(TimeZoneInfo timeZone); + } +} diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTimeInter.cs.meta b/Assets/Plugins/PC/Time/ThinkingSDKTimeInter.cs.meta new file mode 100644 index 0000000..1671847 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTimeInter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0cc5c74f7de224d3aa2fa4668ae7a9f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTimestampCalibration.cs b/Assets/Plugins/PC/Time/ThinkingSDKTimestampCalibration.cs new file mode 100644 index 0000000..d3da381 --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTimestampCalibration.cs @@ -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")); + } + } +} + diff --git a/Assets/Plugins/PC/Time/ThinkingSDKTimestampCalibration.cs.meta b/Assets/Plugins/PC/Time/ThinkingSDKTimestampCalibration.cs.meta new file mode 100644 index 0000000..f2bbbca --- /dev/null +++ b/Assets/Plugins/PC/Time/ThinkingSDKTimestampCalibration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aef0ebc4f720643f3878a26fc71b6ddd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Utils.meta b/Assets/Plugins/PC/Utils.meta new file mode 100644 index 0000000..570e5c6 --- /dev/null +++ b/Assets/Plugins/PC/Utils.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0ff15ea6a25e04a79b1289cb0664ef16 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKAppInfo.cs b/Assets/Plugins/PC/Utils/ThinkingSDKAppInfo.cs new file mode 100644 index 0000000..12b4eb5 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKAppInfo.cs @@ -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; + } + + } +} \ No newline at end of file diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKAppInfo.cs.meta b/Assets/Plugins/PC/Utils/ThinkingSDKAppInfo.cs.meta new file mode 100644 index 0000000..eee0a1f --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKAppInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85a9d7d4b192d42fb826f9620d01ef01 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKDeviceInfo.cs b/Assets/Plugins/PC/Utils/ThinkingSDKDeviceInfo.cs new file mode 100644 index 0000000..153ced7 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKDeviceInfo.cs @@ -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 ""; + } + } +} + diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKDeviceInfo.cs.meta b/Assets/Plugins/PC/Utils/ThinkingSDKDeviceInfo.cs.meta new file mode 100644 index 0000000..e9931ec --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKDeviceInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c84fe92f43c114ba7ad64250db8e124e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKJSON.cs b/Assets/Plugins/PC/Utils/ThinkingSDKJSON.cs new file mode 100644 index 0000000..b3d844f --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKJSON.cs @@ -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. + */ + /// + /// 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. + /// + public class ThinkingSDKJSON + { + /// + /// Parses the string json into a value + /// + /// A JSON string. + /// An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false + public static Dictionary Deserialize(string json) + { + // save the string for debug information + if (json == null) + { + return null; + } + + return Parser.Parse(json); + } + + // Use caution! + public static List 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 Parse(string jsonString) + { + using (var instance = new Parser(jsonString)) + { + return instance.ParseObject(); + } + } + + public static List ParseArray(string jsonString) + { + using (var instance = new Parser(jsonString)) + { + return instance.ParseArray(); + } + } + + public void Dispose() + { + json.Dispose(); + json = null; + } + + Dictionary ParseObject() + { + Dictionary table = new Dictionary(); + + // 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 ParseArray() + { + List array = new List(); + + // 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; + } + } + } + + /// + /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string + /// + /// A Dictionary<string, object> / List<object> + /// A JSON encoded string, or null if object 'json' is not serializable + public static string Serialize(object obj, Func func = null) + { + return Serializer.Serialize(obj, func); + } + + sealed class Serializer + { + StringBuilder builder; + Func func; + + Serializer() + { + builder = new StringBuilder(); + } + + public static string Serialize(object obj, Func 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()); + } + } + } + } +} diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKJSON.cs.meta b/Assets/Plugins/PC/Utils/ThinkingSDKJSON.cs.meta new file mode 100644 index 0000000..de5cd85 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKJSON.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f521a02d525fd485c93a25ce7f330b0d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKLogger.cs b/Assets/Plugins/PC/Utils/ThinkingSDKLogger.cs new file mode 100644 index 0000000..aaebf35 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKLogger.cs @@ -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); + } + } + } +} diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKLogger.cs.meta b/Assets/Plugins/PC/Utils/ThinkingSDKLogger.cs.meta new file mode 100644 index 0000000..4de59a8 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKLogger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7003bc870a4644632aa259a02b235ec6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKTimeUtil.cs b/Assets/Plugins/PC/Utils/ThinkingSDKTimeUtil.cs new file mode 100644 index 0000000..2bbb844 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKTimeUtil.cs @@ -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 ""; + } + } +} + diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKTimeUtil.cs.meta b/Assets/Plugins/PC/Utils/ThinkingSDKTimeUtil.cs.meta new file mode 100644 index 0000000..8371099 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKTimeUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb171e9f7fda1436a83fc7be10687f92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKUtil.cs b/Assets/Plugins/PC/Utils/ThinkingSDKUtil.cs new file mode 100644 index 0000000..4a47bf1 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKUtil.cs @@ -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 deviceInfo = null; + public ThinkingSDKUtil() + { + + } + public static List 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 DeviceInfo() + { + if (deviceInfo == null) + { + deviceInfo = new Dictionary(); + 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 GetDisPresetProperties() + { + List properties = new List(); + + TextAsset textAsset = Resources.Load("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 originalDic, Dictionary subDic) + { + if (originalDic != subDic) + { + foreach (KeyValuePair 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); + } + } +} diff --git a/Assets/Plugins/PC/Utils/ThinkingSDKUtil.cs.meta b/Assets/Plugins/PC/Utils/ThinkingSDKUtil.cs.meta new file mode 100644 index 0000000..5e83b32 --- /dev/null +++ b/Assets/Plugins/PC/Utils/ThinkingSDKUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed8643f4a1b924df991677307901a014 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a b/Assets/Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a new file mode 100644 index 0000000..27a9c31 Binary files /dev/null and b/Assets/Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a differ diff --git a/Assets/Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a.meta b/Assets/Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a.meta new file mode 100644 index 0000000..3dabf11 --- /dev/null +++ b/Assets/Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: c9a5f5c47ed44459ae2c09b918d44344 +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a +timeCreated: 1480838400 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 0 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 0 + settings: + CPU: None + Linux64: + enabled: 0 + settings: + CPU: None + LinuxUniversal: + enabled: 0 + settings: + CPU: None + OSXIntel: + enabled: 0 + settings: + CPU: None + OSXIntel64: + enabled: 0 + settings: + CPU: None + OSXUniversal: + enabled: 0 + settings: + CPU: None + Web: + enabled: 0 + settings: {} + WebStreamed: + enabled: 0 + settings: {} + Win: + enabled: 0 + settings: + CPU: None + Win64: + enabled: 0 + settings: + CPU: None + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + iOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + tvOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty.meta b/Assets/Plugins/iOS/TAThirdParty.meta new file mode 100644 index 0000000..1864472 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc9f548d434094d83b1c00e0cd0895ae +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.h new file mode 100644 index 0000000..111feeb --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.h @@ -0,0 +1,16 @@ +// +// TAAdjustSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAAdjustSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.h.meta new file mode 100644 index 0000000..09f2839 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5c2ee17250bf74b279745e7b20324386 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.m new file mode 100644 index 0000000..3dfe260 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.m @@ -0,0 +1,39 @@ +// +// TAAdjustSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TAAdjustSyncData.h" + +@implementation TAAdjustSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSString *accountID = [taInstance getAccountId] ? [taInstance getAccountId] : @""; + NSString *distinctId = [taInstance getDistinctId] ? [taInstance getDistinctId] : @""; + + Class cls = NSClassFromString(@"Adjust"); + SEL selectorV4 = NSSelectorFromString(@"addSessionCallbackParameter:value:"); + SEL selectorV5 = NSSelectorFromString(@"addGlobalCallbackParameter:forKey:"); + if (cls != nil) { + if ([cls respondsToSelector:selectorV4]) { + [cls performSelector:selectorV4 withObject:TA_ACCOUNT_ID withObject:accountID]; + [cls performSelector:selectorV4 withObject:TA_DISTINCT_ID withObject:distinctId]; + } else if ([cls respondsToSelector:selectorV5]) { + [cls performSelector:selectorV5 withObject:accountID withObject:TA_ACCOUNT_ID]; + [cls performSelector:selectorV5 withObject:distinctId withObject:TA_DISTINCT_ID]; + } + } +} +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.m.meta new file mode 100644 index 0000000..3733857 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAdjustSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5eb03a70bd3e04ffaa297aa9944119ab +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.h new file mode 100644 index 0000000..74e9db6 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.h @@ -0,0 +1,16 @@ +// +// TAAppLovinSyncData.h +// ThinkingSDK.default-Base-Core-Extension-Util-iOS +// +// Created by wwango on 2022/9/28. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAAppLovinSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.h.meta new file mode 100644 index 0000000..d193490 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bef7b8a1ee5a94c378327f8cc1fbd2c2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.m new file mode 100644 index 0000000..a155bfb --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.m @@ -0,0 +1,62 @@ +// +// TAAppLovinSyncData.m +// ThinkingSDK.default-Base-Core-Extension-Util-iOS +// +// Created by wwango on 2022/9/28. +// + +#import "TAAppLovinSyncData.h" + +@implementation TAAppLovinSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSString *distinctId = [taInstance getDistinctId] ? [taInstance getDistinctId] : @""; + + static dispatch_once_t onceToken; + Class cls = NSClassFromString(@"ALSdk"); + SEL sel1 = NSSelectorFromString(@"shared"); + SEL sel2 = NSSelectorFromString(@"setUserIdentifier:"); + __block id instance; + dispatch_once(&onceToken, ^{ + if (cls && [cls respondsToSelector:sel1]) { + instance = [cls performSelector:sel1]; + if ([instance respondsToSelector:sel2]) { + [instance performSelector:sel2 withObject:distinctId]; + } + } + }); + + + if ([property isKindOfClass:[NSDictionary class]] && [property.allKeys containsObject:TASyncDataKey]) { + id customData = property[TASyncDataKey]; + Class cls = NSClassFromString(@"MAAd"); + if ([customData isKindOfClass:cls]) { + double revenue = [(NSNumber *)[customData performSelector:@selector(revenue)] doubleValue]; + NSString *networkName = [customData performSelector:@selector(networkName)]; + NSString *placement = [customData performSelector:@selector(placement)]; + NSString *adUnitId = [customData performSelector:@selector(adUnitIdentifier)]; + NSString *format = [[customData performSelector:@selector(format)] performSelector:@selector(label)]; + NSString *countryCode = [instance valueForKeyPath:@"configuration.countryCode"]; + + [taInstance track:@"appLovin_sdk_ad_revenue" properties:@{ + @"revenue":@(revenue), + @"networkName":networkName, + @"placement":placement, + @"adUnitId":adUnitId, + @"format":format, + @"countryCode":countryCode}]; + } + } + +} +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.m.meta new file mode 100644 index 0000000..462e5bd --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppLovinSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6acd01cb07ff941398f5ac76b64d668b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.h new file mode 100644 index 0000000..3e2e4da --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.h @@ -0,0 +1,16 @@ +// +// TAAppsFlyerSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/2/14. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAAppsFlyerSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.h.meta new file mode 100644 index 0000000..4f45d34 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b808938d5a4ef44cd9417fcaa09304a4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.m new file mode 100644 index 0000000..75b7171 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.m @@ -0,0 +1,39 @@ +// +// TAAppsFlyerSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/2/14. +// + +#import "TAAppsFlyerSyncData.h" + +@implementation TAAppsFlyerSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSMutableDictionary * datas = [NSMutableDictionary dictionaryWithDictionary:property]; + NSString *accountID = [taInstance getAccountId]; + NSString *distinctId = [taInstance getDistinctId]; + [datas setObject:(accountID ? accountID : @"") forKey:TA_ACCOUNT_ID]; + [datas setObject:distinctId ? distinctId : @"" forKey:TA_DISTINCT_ID]; + + Class cls = NSClassFromString(@"AppsFlyerLib"); + SEL sel1 = NSSelectorFromString(@"shared"); + SEL sel2 = NSSelectorFromString(@"setAdditionalData:"); + if (cls && [cls respondsToSelector:sel1]) { + id instance = [cls performSelector:sel1]; + if ([instance respondsToSelector:sel2]) { + [instance performSelector:sel2 withObject:datas]; + } + } +} +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.m.meta new file mode 100644 index 0000000..701459b --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAAppsFlyerSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b373ccef5fc814dd3b5cca3544ef6d2e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.h new file mode 100644 index 0000000..99e9b02 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.h @@ -0,0 +1,76 @@ +// +// TABaseSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/2/14. +// + +#import +#import +#import "TAThirdPartySyncProtocol.h" + +#define TA_DISTINCT_ID @"ta_distinct_id" +#define TA_ACCOUNT_ID @"ta_account_id" + + +#define td_force_inline __inline__ __attribute__((always_inline)) + + +#define TASyncDataKey @"TASyncDataKey" + + +NS_ASSUME_NONNULL_BEGIN + +static td_force_inline void __td_td__swizzleWithClassMethod(Class c, NSString *oriSELStr, SEL newSel, IMP newIMP) { + SEL orig = NSSelectorFromString(oriSELStr); + Method origMethod = class_getClassMethod(c, orig); + c = object_getClass((id)c); + + class_addMethod(c, newSel, newIMP, method_getTypeEncoding(origMethod)); + + + if(class_addMethod(c, orig, newIMP, method_getTypeEncoding(origMethod))) { + class_replaceMethod(c, newSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); + } else { + Method newMethod = class_getClassMethod(c, newSel); + method_exchangeImplementations(origMethod, newMethod); + } +} + + +static td_force_inline void __td_td_swizzleWithOriSELStr(id target, NSString *oriSELStr, SEL newSEL, IMP newIMP) { + SEL origSEL = NSSelectorFromString(oriSELStr); + Method origMethod = class_getInstanceMethod([target class], origSEL); + + if ([target respondsToSelector:origSEL]) { + + class_addMethod([target class], newSEL, newIMP, method_getTypeEncoding(origMethod)); + + + Method origMethod = class_getInstanceMethod([target class], origSEL); + + Method newMethod = class_getInstanceMethod([target class], newSEL); + + + if(class_addMethod([target class], origSEL, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) { + + class_replaceMethod([target class], newSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); + } else { + + method_exchangeImplementations(origMethod, newMethod); + } + } else { + + class_addMethod([target class], origSEL, newIMP, method_getTypeEncoding(origMethod)); + } +} + +@interface TABaseSyncData : NSObject + +@property (nonatomic, weak) id taInstance; +@property (nonatomic, strong) NSDictionary *customPropety; +@property (nonatomic, assign) BOOL isSwizzleMethod; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.h.meta new file mode 100644 index 0000000..d3bdabb --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 65771a2840d484c718e6166b779b5d9b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.m new file mode 100644 index 0000000..b276be8 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.m @@ -0,0 +1,21 @@ +// +// TABaseSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/2/14. +// + +#import "TABaseSyncData.h" + +@implementation TABaseSyncData + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + self.taInstance = taInstance; + self.customPropety = property; +} + +- (void)syncThirdData:(id)taInstance { + [self syncThirdData:taInstance property:@{}]; +} + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.m.meta new file mode 100644 index 0000000..d1fe240 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABaseSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 517862af209ce4ad4bd8002a327fed73 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.h new file mode 100644 index 0000000..0d11db3 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.h @@ -0,0 +1,16 @@ +// +// TABranchSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TABranchSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.h.meta new file mode 100644 index 0000000..adf2d92 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ca22a7263ae5145cba856e4bd480b2bb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.m new file mode 100644 index 0000000..c810dd0 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.m @@ -0,0 +1,37 @@ +// +// TABranchSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TABranchSyncData.h" + +@implementation TABranchSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSString *accountID = [taInstance getAccountId]; + NSString *distinctId = [taInstance getDistinctId]; + + Class cls = NSClassFromString(@"Branch"); + SEL sel1 = NSSelectorFromString(@"getInstance"); + SEL sel2 = NSSelectorFromString(@"setRequestMetadataKey:value:"); + if (cls && [cls respondsToSelector:sel1]) { + id instance = [cls performSelector:sel1]; + if ([instance respondsToSelector:sel2]) { + [instance performSelector:sel2 withObject:TA_ACCOUNT_ID withObject:accountID]; + [instance performSelector:sel2 withObject:TA_DISTINCT_ID withObject:distinctId]; + } + } +} +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.m.meta new file mode 100644 index 0000000..f0dcbb7 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TABranchSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 14d24e07c10e04914806b65a10266790 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.h new file mode 100644 index 0000000..346faca --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.h @@ -0,0 +1,16 @@ +// +// TAFirebaseSyncData.h +// ThinkingSDK.default-Base-Core-Extension-Util-iOS +// +// Created by wwango on 2022/9/28. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAFirebaseSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.h.meta new file mode 100644 index 0000000..2ddc6b2 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 05884726aff3f4d0a8705c380924ac0f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.m new file mode 100644 index 0000000..668090b --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.m @@ -0,0 +1,181 @@ +// +// TAFirebaseSyncData.m +// ThinkingSDK.default-Base-Core-Extension-Util-iOS +// +// Created by wwango on 2022/9/28. +// + +#import "TAFirebaseSyncData.h" +#import +//#import + +@implementation TAFirebaseSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + +// NSString *distinctId = [taInstance getDistinctId] ? [taInstance getDistinctId] : @""; +// +// Class cls = NSClassFromString(@"FIRAnalytics"); +// SEL sel = NSSelectorFromString(@"setUserID:"); +// if (cls && [cls respondsToSelector:sel]) { +// [cls performSelector:sel withObject:distinctId]; +// } + + [self registTDMethods]; +} + + +#pragma mark - Firebase Analytics + +//// 原始方法实现 +//void (*ori_method_logEventWithOrigin_IMP)(id, SEL, id, BOOL, id, id); +//// 交换方法实现 +//void method_td_logEventWithOrigin_IMP(id self, SEL _cmd, id orgin, BOOL isPublicEvent, id name, id parameters) { +// NSLog(@"This is a dynamic method: [%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); +// if(ori_method_logEventWithOrigin_IMP) { +// ori_method_logEventWithOrigin_IMP(self, _cmd, orgin, isPublicEvent, name, parameters); +// } +//} + +//// 原始方法实现 +//void (*ori_method_queueOperationWithBlock_IMP)(id, SEL, id); +//// 交换方法实现 +//void method_td_queueOperationWithBlock_IMP(id self, SEL _cmd, id block) { +// NSLog(@"This is a dynamic method: [%@ %@]", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); +// if(ori_method_queueOperationWithBlock_IMP) { +// ori_method_queueOperationWithBlock_IMP(self, _cmd, block); +// } +//} + +// 原始方法实现 +void (*ori_method_notifyEventListeners_IMP)(id, SEL, id); +// 交换方法实现 +void method_td_notifyEventListeners_IMP(id self, SEL _cmd, id notify) { + NSString *name = [notify valueForKey:@"_name"]; + //NSString *origin = [notify valueForKey:@"_origin"]; + NSDictionary *parameters = [notify valueForKey:@"_parameters"]; + [NSClassFromString(@"TDAnalytics") performSelector:NSSelectorFromString(@"track:properties:") withObject:name withObject:parameters]; + if(ori_method_notifyEventListeners_IMP) { + ori_method_notifyEventListeners_IMP(self, _cmd, notify); + } +} + + + +// 原始方法实现 +void (*ori_method_setUserPropertyString_IMP)(id, SEL, id, id); +// 交换方法实现 +void method_td_setUserPropertyString_IMP(id self, SEL _cmd, id value, id name) { + [NSClassFromString(@"TDAnalytics") performSelector:NSSelectorFromString(@"setSuperProperties:") withObject:[NSDictionary dictionaryWithObject:value forKey:name]]; + if(ori_method_setUserPropertyString_IMP) { + ori_method_setUserPropertyString_IMP(self, _cmd, value, name); + } +} + +// 原始方法实现 +void (*ori_method_setUserID_IMP)(id, SEL, id); +// 交换方法实现 +void method_td_setUserID_IMP(id self, SEL _cmd, id userId) { + [NSClassFromString(@"TDAnalytics") performSelector:NSSelectorFromString(@"setSuperProperties:") withObject:[NSDictionary dictionaryWithObject:userId forKey:@"userId"]]; + if(ori_method_setUserID_IMP) { + ori_method_setUserID_IMP(self, _cmd, userId); + } +} + + +// 原始方法实现 +void (*ori_method_setDefaultEventParameters_IMP)(id, SEL, id); +// 交换方法实现 +void method_td_setDefaultEventParameters_IMP(id self, SEL _cmd, id parameters) { + [NSClassFromString(@"TDAnalytics") performSelector:NSSelectorFromString(@"setSuperProperties:") withObject:parameters]; + if(ori_method_setDefaultEventParameters_IMP) { + ori_method_setDefaultEventParameters_IMP(self, _cmd, parameters); + } +} + +- (void)registTDMethods { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + + // APMAnalytics method exchange + Class desClass_APMAnalytics = objc_getClass("APMAnalytics"); + Class metaClass_APMAnalytics = object_getClass(desClass_APMAnalytics); + bool ret = NO; + //ret = class_addMethod(metaClass_APMAnalytics, NSSelectorFromString(@"td_logEventWithOrigin:isPublicEvent:name:parameters:"), (IMP)(method_td_logEventWithOrigin_IMP), "v@:@B@@"); + //if (ret) { + // Method method_logEventWithOrigin = class_getClassMethod(metaClass_APMAnalytics, NSSelectorFromString(@"logEventWithOrigin:isPublicEvent:name:parameters:")); + // Method method_td_logEventWithOrigin = class_getClassMethod(metaClass_APMAnalytics, NSSelectorFromString(@"td_logEventWithOrigin:isPublicEvent:name:parameters:")); + // //保存原始实现 + // ori_method_logEventWithOrigin_IMP = (void(*)(id, SEL, id, BOOL, id, id))method_getImplementation(method_logEventWithOrigin); + // //交换方法实现 + // method_exchangeImplementations(method_logEventWithOrigin, method_td_logEventWithOrigin); + //} + + //ret = class_addMethod(metaClass_APMAnalytics, NSSelectorFromString(@"td_queueOperationWithBlock:"), (IMP)(method_td_queueOperationWithBlock_IMP), "v@:@"); + //if (ret) { + // Method method_queueOperationWithBlock = class_getClassMethod(metaClass_APMAnalytics, NSSelectorFromString(@"queueOperationWithBlock:")); + // Method method_td_queueOperationWithBlock = class_getClassMethod(metaClass_APMAnalytics, NSSelectorFromString(@"td_queueOperationWithBlock:")); + // //保存原始实现 + // ori_method_queueOperationWithBlock_IMP = (void(*)(id, SEL, id))method_getImplementation(method_queueOperationWithBlock); + // //交换方法实现 + // method_exchangeImplementations(method_queueOperationWithBlock, method_td_queueOperationWithBlock); + //} + + ret = class_addMethod(metaClass_APMAnalytics, NSSelectorFromString(@"td_notifyEventListeners:"), (IMP)(method_td_notifyEventListeners_IMP), "v@:@"); + if (ret) { + Method method_notifyEventListeners = class_getClassMethod(metaClass_APMAnalytics, NSSelectorFromString(@"notifyEventListeners:")); + Method method_td_notifyEventListeners = class_getClassMethod(metaClass_APMAnalytics, NSSelectorFromString(@"td_notifyEventListeners:")); + //保存原始实现 + ori_method_notifyEventListeners_IMP = (void(*)(id, SEL, id))method_getImplementation(method_notifyEventListeners); + //交换方法实现 + method_exchangeImplementations(method_notifyEventListeners, method_td_notifyEventListeners); + } + + + // FIRAnalytics method exchange + Class desClass_FIRAnalytics = objc_getClass("FIRAnalytics"); + Class metaClass_FIRAnalytics = object_getClass(desClass_FIRAnalytics); + ret = class_addMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"td_setUserPropertyString:forName:"), (IMP)(method_td_setUserPropertyString_IMP), "v@:@@"); + if (ret) { + Method method_setUserPropertyString = class_getClassMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"setUserPropertyString:forName:")); + Method method_td_setUserPropertyString = class_getClassMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"td_setUserPropertyString:forName:")); + //保存原始实现 + ori_method_setUserPropertyString_IMP = (void(*)(id, SEL, id, id))method_getImplementation(method_setUserPropertyString); + //交换方法实现 + method_exchangeImplementations(method_setUserPropertyString, method_td_setUserPropertyString); + } + + + ret = class_addMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"td_setUserID:"), (IMP)(method_td_setUserID_IMP), "v@:@"); + if (ret) { + Method method_setUserID = class_getClassMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"setUserID:")); + Method method_td_setUserID = class_getClassMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"td_setUserID:")); + //保存原始实现 + ori_method_setUserID_IMP = (void(*)(id, SEL, id))method_getImplementation(method_setUserID); + //交换方法实现 + method_exchangeImplementations(method_setUserID, method_td_setUserID); + } + + + ret = class_addMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"td_setDefaultEventParameters:"), (IMP)(method_td_setDefaultEventParameters_IMP), "v@:@"); + if (ret) { + Method method_setDefaultEventParameters = class_getClassMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"setDefaultEventParameters:")); + Method method_td_setDefaultEventParameters = class_getClassMethod(metaClass_FIRAnalytics, NSSelectorFromString(@"td_setDefaultEventParameters:")); + //保存原始实现 + ori_method_setDefaultEventParameters_IMP = (void(*)(id, SEL, id))method_getImplementation(method_setDefaultEventParameters); + //交换方法实现 + method_exchangeImplementations(method_setDefaultEventParameters, method_td_setDefaultEventParameters); + } + }); +} + +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.m.meta new file mode 100644 index 0000000..19ec555 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAFirebaseSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f55372f8b0d004744a0d5601f3bdf1e5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.h new file mode 100644 index 0000000..e89d705 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.h @@ -0,0 +1,16 @@ +// +// TAIronSourceSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/2/16. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAIronSourceSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.h.meta new file mode 100644 index 0000000..2a8fcc8 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7fccbd96cdae8450181ef923883295d9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.m new file mode 100644 index 0000000..99c24f8 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.m @@ -0,0 +1,61 @@ +// +// TAIronSourceSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/2/16. +// + +#import "TAIronSourceSyncData.h" + +@implementation TAIronSourceSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +static id _td_last_IronSource_delegate; + +- (void)syncThirdData:(id)taInstance { + + [super syncThirdData:taInstance]; + + if (self.isSwizzleMethod) return; + + Class class = NSClassFromString(@"IronSource"); + NSString *oriSELString = @"addImpressionDataDelegate:"; + SEL newSel = NSSelectorFromString([NSString stringWithFormat:@"td_%@", oriSELString]); + IMP newIMP = imp_implementationWithBlock(^(id _self, id delegate) { + if ([_self respondsToSelector:newSel]) { + [_self performSelector:newSel withObject:delegate]; + _td_last_IronSource_delegate = delegate; + } + + id class1 = delegate; + NSString *oriSELString1 = @"impressionDataDidSucceed:"; + SEL newSel1 = NSSelectorFromString([NSString stringWithFormat:@"td_%@", oriSELString1]); + IMP newIMP1 = imp_implementationWithBlock(^(id _self1, id impressionData) { + if ([_self1 respondsToSelector:newSel1]) { + [_self1 performSelector:newSel1 withObject:impressionData]; + } + + NSDictionary *all_data; + SEL sel = NSSelectorFromString(@"all_data"); + if ([impressionData respondsToSelector:sel]) { + all_data = [impressionData performSelector:sel]; + } + + if (_td_last_IronSource_delegate == _self1) { + [self.taInstance track:@"ta_ironSource_callback" properties:all_data]; + } + }); + __td_td_swizzleWithOriSELStr(class1, oriSELString1, newSel1, newIMP1); + }); + + __td_td__swizzleWithClassMethod(class, oriSELString, newSel, newIMP); + + self.isSwizzleMethod = YES; +} + +#pragma clang diagnostic pop + +@end + diff --git a/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.m.meta new file mode 100644 index 0000000..ad8bfa8 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAIronSourceSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 50723cb7b78a24331b43bba7ee34caf4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.h new file mode 100644 index 0000000..ada1929 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.h @@ -0,0 +1,16 @@ +// +// TAKochavaSyncData.h +// ThinkingSDK.default-Base-Core-Extension-Util-iOS +// +// Created by wwango on 2022/9/28. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAKochavaSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.h.meta new file mode 100644 index 0000000..771248a --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5908d2c27b80a489dae892a870b74de1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.m new file mode 100644 index 0000000..29a1fc2 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.m @@ -0,0 +1,42 @@ +// +// TAKochavaSyncData.m +// ThinkingSDK.default-Base-Core-Extension-Util-iOS +// +// Created by wwango on 2022/9/28. +// + +#import "TAKochavaSyncData.h" + +@implementation TAKochavaSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSString *accountID = [taInstance getAccountId]; + NSString *distinctId = [taInstance getDistinctId]; + + Class cls = NSClassFromString(@"KVATracker"); + SEL sel = NSSelectorFromString(@"shared"); + SEL sel1 = NSSelectorFromString(@"identityLink"); + SEL sel2 = NSSelectorFromString(@"registerWithNameString:identifierString:"); + if (cls && [cls respondsToSelector:sel]) { + id shared = [cls performSelector:sel]; + if (shared && [shared respondsToSelector:sel1]) { + id identityLink = [shared performSelector:sel1]; + if (identityLink && [identityLink respondsToSelector:sel2]) { + [identityLink performSelector:sel2 withObject:TA_ACCOUNT_ID withObject:(accountID ? accountID : @"")]; + [identityLink performSelector:sel2 withObject:TA_DISTINCT_ID withObject:(distinctId ? distinctId : @"")]; + } + } + } +} +#pragma clang diagnostic pop + + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.m.meta new file mode 100644 index 0000000..a0d4ea4 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAKochavaSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9dfff7df542cd401fa7592b206725a02 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.h new file mode 100644 index 0000000..516410d --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.h @@ -0,0 +1,16 @@ +// +// TAReYunSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAReYunSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.h.meta new file mode 100644 index 0000000..a55686a --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: e64632bcc60a04ad78c1baa60002266c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.m new file mode 100644 index 0000000..d26258e --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.m @@ -0,0 +1,31 @@ +// +// TAReYunSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TAReYunSyncData.h" + +@implementation TAReYunSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSString *distinctId = [taInstance getDistinctId] ? [taInstance getDistinctId] : @""; + + Class cls = NSClassFromString(@"Tracking"); + SEL sel = NSSelectorFromString(@"setRegisterWithAccountID:"); + if (cls && [cls respondsToSelector:sel]) { + [cls performSelector:sel withObject: distinctId]; + } +} +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.m.meta new file mode 100644 index 0000000..5182f8a --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAReYunSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: fb3609527c6d545288b56199264a3800 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdParty.h b/Assets/Plugins/iOS/TAThirdParty/TAThirdParty.h new file mode 100644 index 0000000..6df5b8e --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdParty.h @@ -0,0 +1,13 @@ +// +// TAThirdParty.h +// TAThirdParty +// +// Created by Charles on 9.1.23. +// + +#import + +// version = 0.3.5 +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdParty.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAThirdParty.h.meta new file mode 100644 index 0000000..9e9c6b8 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdParty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 97f6ec784b7384c92ac47dcd94bf5d5a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.h b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.h new file mode 100644 index 0000000..01bd1c6 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.h @@ -0,0 +1,20 @@ +// +// TAThirdPartyManager.h +// ThinkingSDK +// +// Created by wwango on 2022/2/11. +// + +#import +#import "TAThirdPartySyncProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TAThirdPartyManager : NSObject + +- (void)enableThirdPartySharing:(NSNumber *)type instance:(id)instance; +- (void)enableThirdPartySharing:(NSNumber *)type instance:(id)instance property:(NSDictionary *)property; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.h.meta new file mode 100644 index 0000000..bd46834 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 17cf558a565af4f988f6a4a875217e78 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.m b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.m new file mode 100644 index 0000000..7e07b03 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.m @@ -0,0 +1,175 @@ +// +// TAThirdPartyManager.m +// ThinkingSDK +// +// Created by wwango on 2022/2/11. +// + +#import "TAThirdPartyManager.h" +#import "TAAppsFlyerSyncData.h" +#import "TAIronSourceSyncData.h" +#import "TAAdjustSyncData.h" +#import "TABranchSyncData.h" +#import "TATopOnSyncData.h" +#import "TAReYunSyncData.h" +#import "TATradPlusSyncData.h" +#import "TAKochavaSyncData.h" + + +typedef NS_OPTIONS(NSInteger, TDThirdPartyType) { + TDThirdPartyTypeNone = 0, + TDThirdPartyTypeAppsFlyer = 1 << 0, + TDThirdPartyTypeIronSource = 1 << 1, + TDThirdPartyTypeAdjust = 1 << 2, + TDThirdPartyTypeBranch = 1 << 3, + TDThirdPartyTypeTopOn = 1 << 4, + TDThirdPartyTypeTracking = 1 << 5, + TDThirdPartyTypeTradPlus = 1 << 6, + TDThirdPartyTypeAppLovin = 1 << 7, + TDThirdPartyTypeKochava = 1 << 8, + TDThirdPartyTypeTalkingData = 1 << 9, + TDThirdPartyTypeFirebase = 1 << 10, +}; + +static NSMutableDictionary *_thirdPartyManagerMap; + +static NSString * const KEY_THIRD_PARTY_CLASS_NAME = @"libClass"; +static NSString * const KEY_TA_PLUGIN_CLASS_NAME = @"taThirdClass"; +static NSString * const KEY_ERROR_MESSAGE = @"errorMes"; + +char * kThinkingServices_service __attribute((used, section("__DATA, ThinkingServices"))) = "{ \"TAThirdPartyProtocol\" : \"TAThirdPartyManager\"}"; +@interface TAThirdPartyManager() + +@end + + +@implementation TAThirdPartyManager + +- (instancetype)init +{ + self = [super init]; + if (self) { + _thirdPartyManagerMap = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)enableThirdPartySharing:(NSNumber *)type instance:(id)instance +{ + [self enableThirdPartySharing:type instance:instance property:@{}]; +} + +- (void)enableThirdPartySharing:(NSNumber *)type instance:(id)instance property:(NSDictionary *)property +{ + NSArray *thirdPartyList = [self _getThridInfoWithType:type]; + + for (NSInteger i = 0; i < thirdPartyList.count; i++) { + NSDictionary *info = thirdPartyList[i]; + + NSString *libClass = info[KEY_THIRD_PARTY_CLASS_NAME]; + NSString *taThirdClass = info[KEY_TA_PLUGIN_CLASS_NAME]; + NSString *errorMes = info[KEY_ERROR_MESSAGE]; + + if (!NSClassFromString(libClass)) { + NSLog(@"[ThinkingData][Error] %@", errorMes); + } else { + id syncData = [_thirdPartyManagerMap objectForKey:taThirdClass]; + if (!syncData) { + syncData = [NSClassFromString(taThirdClass) new]; + [_thirdPartyManagerMap setObject:syncData forKey:taThirdClass]; + } + [syncData syncThirdData:instance property:[property copy]]; + NSLog(@"[ThinkingData][Info] %@ , SyncThirdData Success", NSClassFromString(libClass)); + } + } +} + +- (NSArray *)_getThridInfoWithType:(NSNumber *)type { + NSInteger typeNum = type.integerValue; + + NSMutableArray *mutableArray = [NSMutableArray array]; + + if (typeNum & TDThirdPartyTypeAppsFlyer) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"AppsFlyerLib", + KEY_TA_PLUGIN_CLASS_NAME: @"TAAppsFlyerSyncData", + KEY_ERROR_MESSAGE: @"AppsFlyer Data synchronization exception: not installed AppsFlyer SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeIronSource) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"IronSource", + KEY_TA_PLUGIN_CLASS_NAME:@"TAIronSourceSyncData", + KEY_ERROR_MESSAGE: @"IronSource Data synchronization exception: not installed IronSource SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeAdjust) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"Adjust", + KEY_TA_PLUGIN_CLASS_NAME:@"TAAdjustSyncData", + KEY_ERROR_MESSAGE: @"Adjust Data synchronization exception: not installed Adjust SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeBranch) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"Branch", + KEY_TA_PLUGIN_CLASS_NAME:@"TABranchSyncData", + KEY_ERROR_MESSAGE: @"Branch Data synchronization exception: not installed Branch SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeTopOn) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"ATAPI", + KEY_TA_PLUGIN_CLASS_NAME:@"TATopOnSyncData", + KEY_ERROR_MESSAGE: @"TopOn Data synchronization exception: not installed TopOn SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeTracking) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"Tracking", + KEY_TA_PLUGIN_CLASS_NAME:@"TAReYunSyncData", + KEY_ERROR_MESSAGE: @"ReYun Data synchronization exception: Data synchronization exception: not installed SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeTradPlus) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"TradPlus", + KEY_TA_PLUGIN_CLASS_NAME:@"TATradPlusSyncData", + KEY_ERROR_MESSAGE: @"TradPlus Data synchronization exception: not installed TradPlus SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeAppLovin) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"ALSdk", + KEY_TA_PLUGIN_CLASS_NAME:@"TAAppLovinSyncData", + KEY_ERROR_MESSAGE: @"AppLovin Data synchronization exception: not installed AppLovin SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeKochava) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"KVATracker", + KEY_TA_PLUGIN_CLASS_NAME:@"TAKochavaSyncData", + KEY_ERROR_MESSAGE: @"Kochava Data synchronization exception: not installed Kochava SDK" + }]; + } + + if (typeNum & TDThirdPartyTypeFirebase) { + [mutableArray addObject:@{ + KEY_THIRD_PARTY_CLASS_NAME: @"FIRAnalytics", + KEY_TA_PLUGIN_CLASS_NAME:@"TAFirebaseSyncData", + KEY_ERROR_MESSAGE: @"FIREBASE Data synchronization exception: not installed FIRAnalytics SDK" + }]; + } + + return [mutableArray copy]; +} + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.m.meta b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.m.meta new file mode 100644 index 0000000..e7583c8 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartyManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6a1080195ae5b4aea9bc7c1589134f3f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdPartySyncProtocol.h b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartySyncProtocol.h new file mode 100644 index 0000000..3f78b17 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartySyncProtocol.h @@ -0,0 +1,36 @@ +// +// TAThirdPartySyncProtocol.h +// ThinkingSDKDEMO +// +// Created by wwango on 2022/2/17. +// Copyright © 2022 thinking. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol TAThinkingTrackProtocol + +- (void)track:(NSString *)event properties:(nullable NSDictionary *)propertieDict; +- (NSString *)getDistinctId; +- (NSString *)getAccountId; + +@end + + +@protocol TAThirdPartySyncProtocol + +- (void)syncThirdData:(id)taInstance; +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property; + +@end + +@protocol TAThirdPartyProtocol + +- (void)enableThirdPartySharing:(NSNumber *)type instance:(id)instance; +- (void)enableThirdPartySharing:(NSNumber *)type instance:(id)instance property:(NSDictionary *)property; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TAThirdPartySyncProtocol.h.meta b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartySyncProtocol.h.meta new file mode 100644 index 0000000..c0c3540 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TAThirdPartySyncProtocol.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d31a489f12eb54653b5cf6444e4245d6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.h new file mode 100644 index 0000000..e3eb68b --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.h @@ -0,0 +1,16 @@ +// +// TATopOnSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TATopOnSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.h.meta new file mode 100644 index 0000000..c512ac3 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9cb377c463bc14281934790c36a376c0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.m new file mode 100644 index 0000000..b383cd6 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.m @@ -0,0 +1,39 @@ +// +// TATopOnSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TATopOnSyncData.h" + +@implementation TATopOnSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSMutableDictionary * datas = [NSMutableDictionary dictionaryWithDictionary:property]; + NSString *accountID = [taInstance getAccountId]; + NSString *distinctId = [taInstance getDistinctId]; + [datas setObject:(accountID ? accountID : @"") forKey:TA_ACCOUNT_ID]; + [datas setObject:distinctId ? distinctId : @"" forKey:TA_DISTINCT_ID]; + + Class cls = NSClassFromString(@"ATAPI"); + SEL sel1 = NSSelectorFromString(@"sharedInstance"); + SEL sel2 = NSSelectorFromString(@"setCustomData:"); + if (cls && [cls respondsToSelector:sel1]) { + id instance = [cls performSelector:sel1]; + if ([instance respondsToSelector:sel2]) { + [instance performSelector:sel2 withObject:datas]; + } + } +} +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.m.meta new file mode 100644 index 0000000..8020cdd --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATopOnSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: dbca3c50b30be4ef88f32c10856288c8 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.h b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.h new file mode 100644 index 0000000..5d94ce6 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.h @@ -0,0 +1,16 @@ +// +// TATradPlusSyncData.h +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TABaseSyncData.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TATradPlusSyncData : TABaseSyncData + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.h.meta b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.h.meta new file mode 100644 index 0000000..3152340 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f0682c1aaffe14280b29c0bd11d0954e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.m b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.m new file mode 100644 index 0000000..1603792 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.m @@ -0,0 +1,39 @@ +// +// TATradPlusSyncData.m +// ThinkingSDK +// +// Created by wwango on 2022/3/25. +// + +#import "TATradPlusSyncData.h" + +@implementation TATradPlusSyncData + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + +- (void)syncThirdData:(id)taInstance property:(NSDictionary *)property { + + if (!self.customPropety || [self.customPropety isKindOfClass:[NSDictionary class]]) { + self.customPropety = @{}; + } + + NSMutableDictionary * datas = [NSMutableDictionary dictionaryWithDictionary:property]; +// NSString *accountID = [taInstance getAccountId]; + NSString *distinctId = [taInstance getDistinctId]; +// [datas setObject:(accountID ? accountID : @"") forKey:TA_ACCOUNT_ID]; + [datas setObject:distinctId ? distinctId : @"" forKey:TA_DISTINCT_ID]; + + Class cls = NSClassFromString(@"TradPlus"); + SEL sel1 = NSSelectorFromString(@"sharedInstance"); + SEL sel2 = NSSelectorFromString(@"setDicCustomValue:"); + if (cls && [cls respondsToSelector:sel1]) { + id instance = [cls performSelector:sel1]; + if ([instance respondsToSelector:sel2]) { + [instance performSelector:sel2 withObject:datas]; + } + } +} +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.m.meta b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.m.meta new file mode 100644 index 0000000..d64d6f4 --- /dev/null +++ b/Assets/Plugins/iOS/TAThirdParty/TATradPlusSyncData.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: e00d06dbb27e94407b943499f2d08daf +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingAnalytics.m b/Assets/Plugins/iOS/ThinkingAnalytics.m new file mode 100644 index 0000000..4ea1cea --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingAnalytics.m @@ -0,0 +1,520 @@ +#if __has_include() +#import +#import +#else +#import "ThinkingSDK.h" +#import "TDDeviceInfo.h" +#endif +#import + +#define NETWORK_TYPE_DEFAULT 1 +#define NETWORK_TYPE_WIFI 2 +#define NETWORK_TYPE_ALL 3 + +typedef const char * (*ResultHandler) (const char *type, const char *jsonData); +static ResultHandler resultHandler; +void RegisterRecieveGameCallback(ResultHandler handlerPointer) +{ + resultHandler = handlerPointer; +} + +static NSMutableDictionary *light_instances; +static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; + +ThinkingAnalyticsSDK* ta_getInstance(NSString *app_id) { + ThinkingAnalyticsSDK *result = nil; + + if (app_id == nil || [app_id isEqualToString:@""]) { + return [ThinkingAnalyticsSDK sharedInstance]; + } + + pthread_rwlock_rdlock(&rwlock); + if (light_instances[app_id] != nil) { + result = light_instances[app_id]; + } + pthread_rwlock_unlock(&rwlock); + + if (result != nil) return result; + + return [ThinkingAnalyticsSDK sharedInstanceWithAppid: app_id]; +} + +void ta_convertToDictionary(const char *json, NSDictionary **properties_dict) { + NSString *json_string = json != NULL ? [NSString stringWithUTF8String:json] : nil; + if (json_string) { + *properties_dict = [NSJSONSerialization JSONObjectWithData:[json_string dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil]; + } +} + +NSDictionary * ta_parse_date(NSDictionary *properties_dict) { + NSMutableDictionary *properties = [NSMutableDictionary dictionary]; + for (NSString *key in properties_dict.allKeys) { + id value = properties_dict[key]; + if ([value isKindOfClass:[NSDate class]]) { + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS"; + NSString *dateStr = [formatter stringFromDate:(NSDate *)value]; + properties[key] = dateStr; + } else if ([value isKindOfClass:[NSDictionary class]]) { + properties[key] = ta_parse_date((NSDictionary *)value); + } else { + properties[key] = value; + } + } + return properties; +} + +char* ta_strdup(const char* string) { + if (string == NULL) + return NULL; + char* res = (char*)malloc(strlen(string) + 1); + strcpy(res, string); + return res; +} + + +void ta_start(const char *app_id, const char *url, int mode, const char *timezone_id, bool enable_encrypt, int encrypt_version, const char *encrypt_public_key, int pinning_mode, bool allow_invalid_certificates, bool validates_domain_name, const char *instance_name) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *url_string = url != NULL ? [NSString stringWithUTF8String:url] : nil; + NSString *instance_name_string = instance_name != NULL ? [NSString stringWithUTF8String:instance_name] : nil; + TDConfig *config = [[TDConfig alloc] init]; + config.appid = app_id_string; + config.configureURL = url_string; + if (instance_name) { + [config setName:instance_name_string]; + } + if (mode == 1) { + // DEBUG + config.debugMode = ThinkingAnalyticsDebug; + } else if (mode == 2) { + // DEBUG_ONLY + config.debugMode = ThinkingAnalyticsDebugOnly; + } + NSString *timezone_id_string = timezone_id != NULL ? [NSString stringWithUTF8String:timezone_id] : nil; + NSTimeZone *timezone = [NSTimeZone timeZoneWithName:timezone_id_string]; + if (timezone) { + config.defaultTimeZone = timezone; + } + if (enable_encrypt == YES) { + NSString *encrypt_public_key_string = encrypt_public_key != NULL ? [NSString stringWithUTF8String:encrypt_public_key] : nil; + // Enable data encryption + config.enableEncrypt = YES; + // Set public key and version + config.secretKey = [[TDSecretKey alloc] initWithVersion:encrypt_version publicKey:encrypt_public_key_string]; + } + + [ThinkingAnalyticsSDK startWithConfig:config]; +} + +void ta_enable_log(BOOL enable_log) { + if (enable_log) { + [ThinkingAnalyticsSDK setLogLevel:TDLoggingLevelDebug]; + } else { + [ThinkingAnalyticsSDK setLogLevel:TDLoggingLevelNone]; + } +} + +void ta_set_network_type(int type) { + switch (type) { + case NETWORK_TYPE_DEFAULT: + [ta_getInstance(nil) setNetworkType:TDNetworkTypeDefault]; + break; + case NETWORK_TYPE_WIFI: + [ta_getInstance(nil) setNetworkType:TDNetworkTypeOnlyWIFI]; + break; + case NETWORK_TYPE_ALL: + [ta_getInstance(nil) setNetworkType:TDNetworkTypeALL]; + break; + } +} + +void ta_identify(const char *app_id, const char *unique_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *id_string = unique_id != NULL ? [NSString stringWithUTF8String:unique_id] : nil; + [ta_getInstance(app_id_string) identify:id_string]; +} + +const char *ta_get_distinct_id(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *distinct_id =[ta_getInstance(app_id_string) getDistinctId]; + return ta_strdup([distinct_id UTF8String]); +} + +const char *ta_get_account_id(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *account_id = [TDAnalytics getAccountIdWithAppId:app_id_string]; + return ta_strdup([account_id UTF8String]); +} + +void ta_login(const char *app_id, const char *account_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *id_string = account_id != NULL ? [NSString stringWithUTF8String:account_id] : nil; + [ta_getInstance(app_id_string) login:id_string]; +} + +void ta_logout(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) logout]; +} + +void ta_config_custom_lib_info(const char *lib_name, const char *lib_version) { + NSString *lib_name_string = lib_name != NULL ? [NSString stringWithUTF8String:lib_name] : nil; + NSString *lib_version_string = lib_version != NULL ? [NSString stringWithUTF8String:lib_version] : nil; + [ThinkingAnalyticsSDK setCustomerLibInfoWithLibName:lib_name_string libVersion:lib_version_string]; +} + +void ta_track_event(const char *app_id, int type,const char *event_name,const char *properties,const char *event_id,long long time_stamp_millis, const char *timezone) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *event_name_string = event_name != NULL ? [NSString stringWithUTF8String:event_name] : nil; + NSString *event_id_string = event_id != NULL ? [NSString stringWithUTF8String:event_id] : nil; + TDEventModel *eventModel; + if(type == 0){ + eventModel = [[TDFirstEventModel alloc] initWithEventName:event_name_string firstCheckID:event_id_string]; + }else if(type == 1){ + eventModel = [[TDUpdateEventModel alloc] initWithEventName:event_name_string eventID:event_id_string]; + }else if(type == 2){ + eventModel = [[TDOverwriteEventModel alloc] initWithEventName:event_name_string eventID:event_id_string]; + } + if(eventModel == NULL) return; + NSDictionary *evevent_properties = nil; + ta_convertToDictionary(properties, &evevent_properties); + eventModel.properties = evevent_properties; + NSString *timezoneString = timezone != NULL ? [NSString stringWithUTF8String:timezone] : nil; + NSTimeZone *tz; + if ([@"Local" isEqualToString:timezoneString]) { + tz = [NSTimeZone localTimeZone]; + } else { + tz = [NSTimeZone timeZoneWithName:timezoneString]; + } + if (time_stamp_millis > 0) { + NSDate *date = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis/1000.0]; + [eventModel configTime:date timeZone:tz]; + } + [ta_getInstance(app_id_string) trackWithEventModel:eventModel]; +} + +void ta_track(const char *app_id, const char *event_name, const char *properties, long long time_stamp_millis, const char *timezone) { + NSString *event_name_string = event_name != NULL ? [NSString stringWithUTF8String:event_name] : nil; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + + NSString *time_zone_string = timezone != NULL ? [NSString stringWithUTF8String:timezone] : nil; + NSTimeZone *tz; + if ([@"Local" isEqualToString:time_zone_string]) { + tz = [NSTimeZone localTimeZone]; + } else { + tz = [NSTimeZone timeZoneWithName:time_zone_string]; + } + + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + + if (tz) { + [ta_getInstance(app_id_string) track:event_name_string properties:properties_dict time:time timeZone:tz]; + } else { + if (time_stamp_millis > 0) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [ta_getInstance(app_id_string) track:event_name_string properties:properties_dict time:time]; +#pragma clang diagnostic pop + } else { + [ta_getInstance(app_id_string) track:event_name_string properties:properties_dict]; + } + } +} + +void ta_flush(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) flush]; +} + +void ta_set_super_properties(const char *app_id, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) setSuperProperties:properties_dict]; + } +} + +void ta_unset_super_property(const char *app_id, const char *property_name) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *property_name_string = property_name != NULL ? [NSString stringWithUTF8String:property_name] : nil; + [ta_getInstance(app_id_string) unsetSuperProperty:property_name_string]; +} + +void ta_clear_super_properties(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) clearSuperProperties]; +} + +const char *ta_get_super_properties(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *property_dict = [ta_getInstance(app_id_string) currentSuperProperties]; + // nsdictionary --> nsdata + NSData *data = [NSJSONSerialization dataWithJSONObject:property_dict options:kNilOptions error:nil]; + // nsdata -> nsstring + NSString *jsonString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; + return ta_strdup([jsonString UTF8String]); +} + +const char *ta_get_preset_properties(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *property_dict = [[ta_getInstance(app_id_string) getPresetProperties] toEventPresetProperties]; + // nsdate => nsstring + property_dict = ta_parse_date(property_dict); + // nsdictionary --> nsdata + NSData *data = [NSJSONSerialization dataWithJSONObject:property_dict options:kNilOptions error:nil]; + // nsdata -> nsstring + NSString *jsonString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; + return ta_strdup([jsonString UTF8String]); +} + +void ta_time_event(const char *app_id, const char *event_name) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *event_name_string = event_name != NULL ? [NSString stringWithUTF8String:event_name] : nil; + [ta_getInstance(app_id_string) timeEvent:event_name_string]; +} + +void ta_user_set(const char *app_id, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_set:properties_dict]; + } +} + +void ta_user_set_with_time(const char *app_id, const char *properties, long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_set:properties_dict withTime:time]; + } +} + +void ta_user_unset(const char *app_id, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *properties_string = properties != NULL ? [NSString stringWithUTF8String:properties] : nil; + [ta_getInstance(app_id_string) user_unset:properties_string]; +} + +void ta_user_unset_with_time(const char *app_id, const char *properties, long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSString *properties_string = properties != NULL ? [NSString stringWithUTF8String:properties] : nil; + [ta_getInstance(app_id_string) user_unset:properties_string withTime:time]; +} + +void ta_user_set_once(const char *app_id, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_setOnce:properties_dict]; + } +} + +void ta_user_set_once_with_time(const char *app_id, const char *properties, long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_setOnce:properties_dict withTime:time]; + } +} + +void ta_user_add(const char *app_id, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_add:properties_dict]; + } +} + +void ta_user_add_with_time(const char *app_id, const char *properties, long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_add:properties_dict withTime:time]; + } +} + +void ta_user_delete(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) user_delete]; +} + +void ta_user_delete_with_time(const char *app_id, long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) user_delete:time]; +} + +void ta_user_append(const char *app_id, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_append:properties_dict]; + } +} + +void ta_user_append_with_time(const char *app_id, const char *properties, long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_append:properties_dict withTime:time]; + } +} + +void ta_user_uniq_append(const char *app_id, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_uniqAppend:properties_dict]; + } +} + +void ta_user_uniq_append_with_time(const char *app_id, const char *properties, long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) user_uniqAppend:properties_dict withTime:time]; + } +} + +const char *ta_get_device_id() { + NSString *distinct_id = [ta_getInstance(nil) getDeviceId]; + return ta_strdup([distinct_id UTF8String]); +} + +void ta_set_dynamic_super_properties(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) setAutoTrackDynamicProperties:^NSDictionary * _Nonnull{ + const char *ret = resultHandler("DynamicSuperProperties", nil); + NSDictionary *dynamicSuperProperties = nil; + ta_convertToDictionary(ret, &dynamicSuperProperties); + return dynamicSuperProperties; + }]; +} + +void ta_set_track_status(const char *app_id, int status) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + ThinkingAnalyticsSDK* instance = ta_getInstance(app_id_string); + switch (status) { + case 1: + [instance setTrackStatus:TATrackStatusPause]; + break; + case 2: + [instance setTrackStatus:TATrackStatusStop]; + break; + case 3: + [instance setTrackStatus:TATrackStatusSaveOnly]; + break; + case 4: + default: + [instance setTrackStatus:TATrackStatusNormal]; + } +} + +void ta_enable_tracking(const char *app_id, BOOL enabled) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) enableTracking:enabled]; +} + +void ta_opt_out_tracking(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) optOutTracking]; +} + +void ta_opt_out_tracking_and_delete_user(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) optOutTrackingAndDeleteUser]; +} + +void ta_opt_in_tracking(const char *app_id) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + [ta_getInstance(app_id_string) optInTracking]; +} + +void ta_create_light_instance(const char *delegate_app_id) { + NSString *delegate_app_id_string = delegate_app_id != NULL ? [NSString stringWithUTF8String:delegate_app_id] : nil; + ThinkingAnalyticsSDK *light = [ta_getInstance(nil) createLightInstance]; + + pthread_rwlock_wrlock(&rwlock); + if (light_instances == nil) { + light_instances = [NSMutableDictionary dictionary]; + } + + [light_instances setObject:light forKey:delegate_app_id_string]; + pthread_rwlock_unlock(&rwlock); +} + +void ta_enable_autoTrack(const char *app_id, int autoTrackEvents, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + [ta_getInstance(app_id_string) enableAutoTrack: autoTrackEvents properties:properties_dict]; +} + +void ta_enable_autoTrack_with_callback(const char *app_id, int autoTrackEvents) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + __block NSString * w_app_id_string = app_id_string; + [ta_getInstance(app_id_string) enableAutoTrack: autoTrackEvents callback:^NSDictionary * _Nonnull(ThinkingAnalyticsAutoTrackEventType eventType, NSDictionary * _Nonnull properties) { + NSMutableDictionary *callbackProperties = [NSMutableDictionary dictionaryWithDictionary:properties]; + [callbackProperties setObject:@(eventType) forKey:@"EventType"]; + [callbackProperties setObject:w_app_id_string forKey:@"AppID"]; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:ta_parse_date(callbackProperties) options:NSJSONWritingPrettyPrinted error:nil]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + const char *ret = resultHandler("AutoTrackProperties", [jsonString UTF8String]); + NSDictionary *autoTrackProperties = nil; + ta_convertToDictionary(ret, &autoTrackProperties); + return autoTrackProperties; + }]; +} + +void ta_set_autoTrack_properties(const char *app_id, int autoTrackEvents, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + [ta_getInstance(app_id_string) setAutoTrackProperties: autoTrackEvents properties:properties_dict]; +} + +const char *ta_get_time_string(long long time_stamp_millis) { + NSDate *time = [NSDate dateWithTimeIntervalSince1970:time_stamp_millis / 1000.0]; + NSString *time_string = [ta_getInstance(nil) getTimeString:time]; + return ta_strdup([time_string UTF8String]); +} + +void ta_calibrate_time(long long time_stamp_millis) { + [ThinkingAnalyticsSDK calibrateTime:time_stamp_millis]; +} + +void ta_calibrate_time_with_ntp(const char *ntp_server) { + NSString *ntp_server_string = ntp_server != NULL ? [NSString stringWithUTF8String:ntp_server] : nil; + [ThinkingAnalyticsSDK calibrateTimeWithNtp:ntp_server_string]; +} + +void ta_enable_third_party_sharing(const char *app_id, int share_type, const char *properties) { + NSString *app_id_string = app_id != NULL ? [NSString stringWithUTF8String:app_id] : nil; + NSDictionary *properties_dict = nil; + ta_convertToDictionary(properties, &properties_dict); + if (properties_dict) { + [ta_getInstance(app_id_string) enableThirdPartySharing:share_type customMap:properties_dict]; + } else { + [ta_getInstance(app_id_string) enableThirdPartySharing:share_type]; + } +} diff --git a/Assets/Plugins/iOS/ThinkingAnalytics.m.meta b/Assets/Plugins/iOS/ThinkingAnalytics.m.meta new file mode 100644 index 0000000..3fff6fd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingAnalytics.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4a3a74316bafb412290585db3ac5a04e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore.meta b/Assets/Plugins/iOS/ThinkingDataCore.meta new file mode 100644 index 0000000..578f28d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc9ce7e195a034b4383e3fc6dac4de33 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes.meta new file mode 100644 index 0000000..4973e99 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00c57f8b45eef4696976079b9f2a9b9d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime.meta new file mode 100644 index 0000000..7d07547 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a43ba7904865402dab9870feb41b38f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.h new file mode 100644 index 0000000..d86eaf4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.h @@ -0,0 +1,17 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCalibratedTime : NSObject +@property (atomic, assign, readonly) BOOL hasBeenCalibrated; + ++ (instancetype)sharedInstance; + ++ (NSDate *)now; + +- (void)recalibrationWithTimeInterval:(NSTimeInterval)timestamp; +- (void)recalibrationWithNtps:(NSArray *)ntpServers; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.h.meta new file mode 100644 index 0000000..bcc019a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8c2f861958ac24d76bcd736e04612643 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.m new file mode 100644 index 0000000..94bd8be --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.m @@ -0,0 +1,87 @@ +#import "TDCalibratedTime.h" +#import "TDCoreDeviceInfo.h" +#import "TDNTPServer.h" +#import "TDNotificationManager+Core.h" +#import "TDCoreLog.h" + +@interface TDCalibratedTime () +@property (atomic, assign) NSTimeInterval deviceBootTime; +@property (atomic, assign) NSTimeInterval serverTime; +@property (atomic, assign) BOOL hasBeenCalibrated; + +@end + + +@implementation TDCalibratedTime + ++ (instancetype)sharedInstance { + static dispatch_once_t once; + static id sharedInstance; + dispatch_once(&once, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init { + if (self = [super init]) { + self.hasBeenCalibrated = NO; + } + return self; +} + ++ (NSDate *)now { + NSDate *date = nil; + TDCalibratedTime *calibrated = [TDCalibratedTime sharedInstance]; + if (calibrated.hasBeenCalibrated) { + NSTimeInterval outTime = [TDCoreDeviceInfo bootTime] - calibrated.deviceBootTime; + date = [NSDate dateWithTimeIntervalSince1970:(calibrated.serverTime + outTime)]; + } else { + date = [NSDate date]; + } + return date; +} + +- (void)recalibrationWithTimeInterval:(NSTimeInterval)timestamp { + if (timestamp > 0) { + NSTimeInterval nowInterval = [[NSDate date] timeIntervalSince1970]; + TDCORELOG(@"SDK calibrateTime success. Timestamp(%lf), diff = %lfms", timestamp * 1000, (timestamp - nowInterval) * 1000); + self.hasBeenCalibrated = YES; + self.serverTime = timestamp; + self.deviceBootTime = [TDCoreDeviceInfo bootTime]; + [TDNotificationManager postCoreNotificationCalibratedTimeSuccess:[TDCalibratedTime now]]; + } +} + +- (void)recalibrationWithNtps:(NSArray *)ntpServers { + dispatch_async(dispatch_get_main_queue(), ^{ + [self startNtp:ntpServers]; + }); +} + +- (void)startNtp:(NSArray *)ntpServerHost { + NSError *err; + for (NSString *host in ntpServerHost) { + if (!([host isKindOfClass:[NSString class]] && host.length > 0)) { + continue; + } + + err = nil; + TDNTPServer *server = [[TDNTPServer alloc] initWithHostname:host port:123]; + NSTimeInterval offset = [server dateWithError:&err]; + [server disconnect]; + + if (err) { + TDCORELOG(@"ntp failed. host: %@ error: %@", host, err); + } else { + TDCORELOG(@"SDK calibrateTime success. NTP(%@), diff = %lfms", host, (NSTimeInterval)(offset * 1000)); + self.deviceBootTime = [TDCoreDeviceInfo bootTime]; + self.serverTime = [[NSDate dateWithTimeIntervalSinceNow:offset] timeIntervalSince1970]; + self.hasBeenCalibrated = YES; + [TDNotificationManager postCoreNotificationCalibratedTimeSuccess:[TDCalibratedTime now]]; + break; + } + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.m.meta new file mode 100644 index 0000000..3fa3387 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDCalibratedTime.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 90f87ceef86a64eb39462916cd27385f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.h new file mode 100644 index 0000000..fbae756 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.h @@ -0,0 +1,28 @@ + +#import + +@interface TDNTPServer : NSObject + +NS_ASSUME_NONNULL_BEGIN + +@property (readonly, strong, nonatomic) NSString *hostname; + +@property (readonly, assign, nonatomic) NSUInteger port; + +@property (assign, atomic) NSTimeInterval timeout; + +@property (readonly, atomic, getter=isConnected) BOOL connected; + +@property (class, readonly, nonatomic) TDNTPServer *defaultServer; + +- (instancetype)initWithHostname:(NSString *)hostname port:(NSUInteger)port NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithHostname:(NSString *)hostname; +- (instancetype)init; +- (BOOL)connectWithError:(NSError *__autoreleasing _Nullable *_Nullable)error NS_REQUIRES_SUPER; +- (void)disconnect NS_REQUIRES_SUPER; +- (BOOL)syncWithError:(NSError *__autoreleasing _Nullable *_Nullable)error NS_REQUIRES_SUPER; +- (NSTimeInterval)dateWithError:(NSError *__autoreleasing _Nullable *_Nullable)error; + +NS_ASSUME_NONNULL_END + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.h.meta new file mode 100644 index 0000000..45a7d60 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f8035ad4199a142fe9b8abb4cb1a5a38 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.m new file mode 100644 index 0000000..f9492d8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.m @@ -0,0 +1,211 @@ +#import "TDNTPServer.h" +#import "TDNTPTypes.h" +#import +#import +#import +#import + +@implementation TDNTPServer { + NSTimeInterval _timeout; + int _socket; + + NSTimeInterval _offset; +} + +static const uint32_t kSecondsFrom1900To1970 = 2208988800UL; + +static ufixed64_t ntp_localtime_get_ufixed64(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return ufixed64((uint32_t)tv.tv_sec + kSecondsFrom1900To1970, tv.tv_usec * (pow(2, 32) / USEC_PER_SEC)); +} + ++ (TDNTPServer *)defaultServer { + static TDNTPServer *server = nil; + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + server = [[TDNTPServer alloc] init]; + }); + return server; +} + +- (instancetype)initWithHostname:(NSString *)hostname port:(NSUInteger)port { + self = [super init]; + if (self) { + _hostname = [hostname copy]; + _port = port; + _timeout = 3.0; + _socket = -1; + + _offset = NAN; + } + return self; +} + +- (instancetype)initWithHostname:(NSString *)hostname { + return [self initWithHostname:hostname port:123]; +} + +- (instancetype)init { + return [self initWithHostname:@"pool.ntp.org"]; +} + +- (void)dealloc { + [self disconnect]; +} + +- (void)setTimeout:(NSTimeInterval)timeout { + assert(timeout > 0 && isfinite(timeout)); + @synchronized (self) { + _timeout = timeout; + if (_socket >= 0) { + struct timeval tv = { .tv_sec = _timeout, .tv_usec = (_timeout - trunc(_timeout)) * USEC_PER_SEC }; + setsockopt(_socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + } + + } +} + +- (NSTimeInterval)timeout { + @synchronized (self) { + return _timeout; + } +} + +- (BOOL)isConnected { + @synchronized (self) { + return _socket >= 0; + } +} + +- (BOOL)connectWithError:(NSError *__autoreleasing _Nullable *_Nullable)error { + @synchronized (self) { + if (_socket >= 0) { + return YES; + } + + struct addrinfo hints = {0}, *addrinfo = NULL; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + + NSString *port = [[NSString alloc] initWithFormat:@"%lu", (unsigned long) _port]; + + int getaddrinfo_err = getaddrinfo(_hostname.UTF8String, port.UTF8String, &hints, &addrinfo); + if (getaddrinfo_err != 0) { + if (error) { + NSString *errorDescription = [[NSString alloc] initWithUTF8String:gai_strerror(getaddrinfo_err)]; + NSDictionary *errorInfo = [[NSDictionary alloc] initWithObjectsAndKeys:errorDescription, NSLocalizedDescriptionKey, nil]; + *error = [NSError errorWithDomain:@"netdb" code:getaddrinfo_err userInfo:errorInfo]; + } + return NO; + } + + const int sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); + if (sock < 0) { + if (error) { + *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:nil]; + } + freeaddrinfo(addrinfo); + return NO; + } + + fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK); + + struct timeval timeout = { .tv_sec = _timeout, .tv_usec = (_timeout - trunc(_timeout)) * USEC_PER_SEC }; + int connect_err = connect(sock, addrinfo->ai_addr, addrinfo->ai_addrlen) ? errno : 0; + if (connect_err == EINPROGRESS) { + fd_set fd; + FD_ZERO(&fd); + FD_SET(sock, &fd); + + const int select_err = select(sock + 1, &fd, &fd, NULL, &timeout); + if (select_err <= 0) { + connect_err = select_err ? errno : ETIMEDOUT; + } else { + socklen_t optlen = sizeof(connect_err); + getsockopt(sock, SOL_SOCKET, SO_ERROR, &connect_err, &optlen); + } + } + freeaddrinfo(addrinfo); + if (connect_err) { + if (error) { + *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:connect_err userInfo:nil]; + } + close(sock); + return NO; + } + + fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK); + + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + [self willChangeValueForKey:@"connected"]; + _socket = sock; + [self didChangeValueForKey:@"connected"]; + + return YES; + } +} + +- (void)disconnect { + @synchronized (self) { + if (_socket >= 0) { + close(_socket); + + [self willChangeValueForKey:@"connected"]; + _socket = -1; + [self didChangeValueForKey:@"connected"]; + } + } +} + +- (BOOL)syncWithError:(NSError *__autoreleasing _Nullable *_Nullable)error { + @synchronized (self) { + if (![self connectWithError:error]) { + return NO; + } + + ntp_packet_t packet = {0}; + packet.version_number = 4; + packet.mode = 3; + packet.transmit_timestamp = ntp_localtime_get_ufixed64(); + packet = hton_ntp_packet(packet); + const ssize_t send_s = send(_socket, &packet, sizeof(packet), 0); + const int send_err = send_s == sizeof(packet) ? 0 : send_s >= 0 ? EIO : errno; + if (send_err) { + if (error) { + *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:send_err userInfo:nil]; + } + return NO; + } + + const ssize_t recv_s = recv(_socket, &packet, sizeof(packet), 0); + const int recv_err = recv_s == sizeof(packet) ? 0 : recv_s >= 0 ? EIO : errno; + if (recv_err) { + if (error) { + *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:recv_err userInfo:nil]; + } + return NO; + } + + packet = ntoh_ntp_packet(packet); + const double T[4] = { + ufixed64_as_double(packet.originate_timestamp), + ufixed64_as_double(packet.receive_timestamp), + ufixed64_as_double(packet.transmit_timestamp), + ufixed64_as_double(ntp_localtime_get_ufixed64()), + }; + _offset = ((T[1] - T[0]) + (T[2] - T[3])) / 2.0; + return YES; + } +} + +- (NSTimeInterval)dateWithError:(NSError *__autoreleasing _Nullable *_Nullable)error { + @synchronized (self) { + return isfinite(_offset) || [self syncWithError:error] ? _offset : 0; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.m.meta new file mode 100644 index 0000000..137fbaf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPServer.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 06c07a9cbd7e6406c94518066eb75005 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.c b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.c new file mode 100644 index 0000000..d09df8b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.c @@ -0,0 +1,61 @@ +#include "TDNTPTypes.h" + +#include +#include +#include + +ufixed32_t ufixed32(uint16_t whole, uint16_t fraction) { + return (struct ufixed32) { .whole = whole, .fraction = fraction }; +} + +ufixed64_t ufixed64(uint32_t whole, uint32_t fraction) { + return (struct ufixed64) { .whole = whole, .fraction = fraction }; +} + +double ufixed64_as_double(ufixed64_t uf64) { + return uf64.whole + uf64.fraction * pow(2, -32); +} + +ufixed64_t ufixed64_with_double(double value) { + assert(value >= 0); + return ufixed64(value, (value - trunc(value) * pow(2, 32))); +} + +ufixed32_t hton_ufixed32(ufixed32_t uf32) { + return ufixed32(htons(uf32.whole), htons(uf32.fraction)); +} +ufixed32_t ntoh_ufixed32(ufixed32_t uf32) { + return ufixed32(ntohs(uf32.whole), ntohs(uf32.fraction)); +} + +ufixed64_t hton_ufixed64(ufixed64_t uf64) { + return ufixed64(htonl(uf64.whole), htonl(uf64.fraction)); +} +ufixed64_t ntoh_ufixed64(ufixed64_t uf64) { + return ufixed64(ntohl(uf64.whole), ntohl(uf64.fraction)); +} + +ntp_packet_t hton_ntp_packet(ntp_packet_t p) { + p.root_delay = hton_ufixed32(p.root_delay); + p.root_dispersion = hton_ufixed32(p.root_dispersion); + + p.reference_timestamp = hton_ufixed64(p.reference_timestamp); + p.originate_timestamp = hton_ufixed64(p.originate_timestamp); + p.receive_timestamp = hton_ufixed64(p.receive_timestamp); + p.transmit_timestamp = hton_ufixed64(p.transmit_timestamp); + + return p; +} + +ntp_packet_t ntoh_ntp_packet(ntp_packet_t p) { + p.root_delay = ntoh_ufixed32(p.root_delay); + p.root_dispersion = ntoh_ufixed32(p.root_dispersion); + + p.reference_timestamp = ntoh_ufixed64(p.reference_timestamp); + p.originate_timestamp = ntoh_ufixed64(p.originate_timestamp); + p.receive_timestamp = ntoh_ufixed64(p.receive_timestamp); + p.transmit_timestamp = ntoh_ufixed64(p.transmit_timestamp); + + return p; +} + diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.c.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.c.meta new file mode 100644 index 0000000..b2558eb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.c.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ac2ad1998c80d45f2ac718ddf4883224 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.h new file mode 100644 index 0000000..cab6a44 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.h @@ -0,0 +1,51 @@ +#ifndef NTPTypes_h +#define NTPTypes_h + +#include + +typedef struct ufixed32 { + uint16_t whole, fraction; +} ufixed32_t; + +ufixed32_t ufixed32(uint16_t whole, uint16_t fraction); + +typedef struct ufixed64 { + uint32_t whole, fraction; +} ufixed64_t; + +ufixed64_t ufixed64(uint32_t whole, uint32_t fraction); + +double ufixed64_as_double(ufixed64_t); +ufixed64_t ufixed64_with_double(double); + +typedef struct ntp_packet_t { + uint8_t mode : 3; + uint8_t version_number : 3; + uint8_t leap_indicator : 2; + + uint8_t stratum; + uint8_t poll; + uint8_t precision; + + ufixed32_t root_delay; + ufixed32_t root_dispersion; + uint8_t reference_identifier[4]; + + ufixed64_t reference_timestamp; + ufixed64_t originate_timestamp; + ufixed64_t receive_timestamp; + ufixed64_t transmit_timestamp; +} ntp_packet_t; + + + +ufixed32_t hton_ufixed32(ufixed32_t); +ufixed32_t ntoh_ufixed32(ufixed32_t); + +ufixed64_t hton_ufixed64(ufixed64_t); +ufixed64_t ntoh_ufixed64(ufixed64_t); + +ntp_packet_t hton_ntp_packet(ntp_packet_t); +ntp_packet_t ntoh_ntp_packet(ntp_packet_t); + +#endif diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.h.meta new file mode 100644 index 0000000..4389162 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/CalibratedTime/TDNTPTypes.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 18f02ba86c91f4567b793beb5b04b96f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category.meta new file mode 100644 index 0000000..de618d5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0b5be36e8a2f94699b5a6bfe5519acd3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData.meta new file mode 100644 index 0000000..a2a4c37 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 89219b76e4d614e66a9a62e15056467c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.h new file mode 100644 index 0000000..1ad6f18 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.h @@ -0,0 +1,9 @@ +#import + +@interface NSData (TDGzip) + ++ (NSData *)td_gzipData:(NSData *)dataa; + ++ (NSData *)td_gunzipData:(NSData *)data; + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.h.meta new file mode 100644 index 0000000..6f04029 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 250dc854c27ee411e85b664779a0ef8b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.m new file mode 100644 index 0000000..b43e083 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.m @@ -0,0 +1,82 @@ +#import "NSData+TDGzip.h" +#import +#import "TDCoreLog.h" + +@implementation NSData (TDGzip) + ++ (NSData *)td_gzipData:(NSData *)dataa { + if (!dataa || [dataa length] == 0) { + TDCORELOG(@"gzip error, return nil "); + return nil; + } + + z_stream zlibStreamStruct; + zlibStreamStruct.zalloc = Z_NULL; + zlibStreamStruct.zfree = Z_NULL; + zlibStreamStruct.opaque = Z_NULL; + zlibStreamStruct.total_out = 0; + zlibStreamStruct.next_in = (Bytef *)[dataa bytes]; + zlibStreamStruct.avail_in = (uInt)[dataa length]; + + int initError = deflateInit2(&zlibStreamStruct, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY); + + if (initError != Z_OK) return nil; + + NSMutableData *gzipData = [NSMutableData dataWithLength:[dataa length] * 1.01 + 21]; + int deflateStatus; + + do { + zlibStreamStruct.next_out = [gzipData mutableBytes] + zlibStreamStruct.total_out; + zlibStreamStruct.avail_out = (uInt)([gzipData length] - zlibStreamStruct.total_out); + deflateStatus = deflate(&zlibStreamStruct, Z_FINISH); + } while (deflateStatus == Z_OK); + + if (deflateStatus != Z_STREAM_END) return nil; + deflateEnd(&zlibStreamStruct); + [gzipData setLength:zlibStreamStruct.total_out]; + return gzipData; +} + ++ (NSData *)td_gunzipData:(NSData *)compressedData { + if ([compressedData length] == 0) { + return compressedData; + } + NSUInteger full_length = [compressedData length]; + NSUInteger half_length = [compressedData length] / 2; + NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; + BOOL done = NO; + int status; + z_stream strm; + strm.next_in = (Bytef *)[compressedData bytes]; + strm.avail_in = (uint)[compressedData length]; + strm.total_out = 0; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; + while (!done) { + // Make sure we have enough room and reset the lengths. + if (strm.total_out >= [decompressed length]) { + [decompressed increaseLengthBy: half_length]; + } + // chadeltu 加了(Bytef *) + strm.next_out = (Bytef *)[decompressed mutableBytes] + strm.total_out; + strm.avail_out = (uint)[decompressed length] - (uint)(strm.total_out); + // Inflate another chunk. + status = inflate (&strm, Z_SYNC_FLUSH); + if (status == Z_STREAM_END) { + done = YES; + } else if (status != Z_OK) { + break; + } + } + if (inflateEnd (&strm) != Z_OK) return nil; + // Set real length. + if (done) { + [decompressed setLength: strm.total_out]; + return [NSData dataWithData: decompressed]; + } else { + return nil; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.m.meta new file mode 100644 index 0000000..ec16761 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSData/NSData+TDGzip.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 043f08397cddf4cf3be299df2a6306e7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate.meta new file mode 100644 index 0000000..4a74a23 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 415d0262871ef428d836be26dfb73bae +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.h new file mode 100644 index 0000000..bfc55a0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.h @@ -0,0 +1,22 @@ +// +// NSDate+TDCore.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/13. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDate (TDCore) + ++ (nullable NSDate *)td_dateWithString:(nonnull NSString *)dateString formatter:(nullable NSString *)formatter timeZone:(nullable NSTimeZone *)timeZone; + +- (double)td_timeZoneOffset:(NSTimeZone *)timeZone; + +- (NSString *)td_formatWithTimeZone:(NSTimeZone *)timeZone formatString:(NSString *)formatString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.h.meta new file mode 100644 index 0000000..2cc499d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f390bd929a9b6486e8c29e0765f64d5f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.m new file mode 100644 index 0000000..ffb2ba6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.m @@ -0,0 +1,55 @@ +// +// NSDate+TDCore.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/13. +// + +#import "NSDate+TDCore.h" +#import "NSString+TDCore.h" + +@implementation NSDate (TDCore) + ++ (NSDate *)td_dateWithString:(NSString *)dateString formatter:(NSString *)formatter timeZone:(nullable NSTimeZone *)timeZone { + if ([NSString td_isEmpty:dateString]) { + return nil; + } + NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; + [dateFormatter setTimeZone:timeZone]; + NSDate *date = nil; + if (![NSString td_isEmpty:formatter]) { + [dateFormatter setDateFormat:formatter]; + date = [dateFormatter dateFromString:dateString]; + } + if (!date) { + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm"]; + date = [dateFormatter dateFromString:dateString]; + } + if (!date) { + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; + date = [dateFormatter dateFromString:dateString]; + } + if (!date) { + [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; + date = [dateFormatter dateFromString:dateString]; + } + return date; +} + +- (double)td_timeZoneOffset:(NSTimeZone *)timeZone { + if (!timeZone) { + return 0; + } + NSInteger sourceGMTOffset = [timeZone secondsFromGMTForDate:self]; + return (double)(sourceGMTOffset/3600.0); +} + +- (NSString *)td_formatWithTimeZone:(NSTimeZone *)timeZone formatString:(NSString *)formatString { + NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init]; + timeFormatter.dateFormat = formatString; + timeFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; + timeFormatter.timeZone = timeZone; + return [timeFormatter stringFromDate:self]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.m.meta new file mode 100644 index 0000000..db3f49a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDate/NSDate+TDCore.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3b7fd59f9c46f4069ac9b50f3817a82e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary.meta new file mode 100644 index 0000000..095ad06 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dbdf0181d841d4e09b52692a864a163d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.h new file mode 100644 index 0000000..5077390 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.h @@ -0,0 +1,17 @@ +// +// NSDictionary+TDCore.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/14. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDictionary (TDCore) + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.h.meta new file mode 100644 index 0000000..19083ba --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c0c6aa0f7b8d248bea475ed0f1eaa79a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.m new file mode 100644 index 0000000..caf41b0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.m @@ -0,0 +1,12 @@ +// +// NSDictionary+TDCore.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/14. +// + +#import "NSDictionary+TDCore.h" + +@implementation NSDictionary (TDCore) + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.m.meta new file mode 100644 index 0000000..8573b53 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSDictionary/NSDictionary+TDCore.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9d16a1aeb5773473996d37b09ea03390 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber.meta new file mode 100644 index 0000000..3f38ecf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 337a597cf28a34bab862b501fe4760a7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.h new file mode 100644 index 0000000..e82d07b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.h @@ -0,0 +1,18 @@ +// +// NSNumber+TDCore.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/7/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSNumber (TDCore) + +- (BOOL)td_isBool; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.h.meta new file mode 100644 index 0000000..3cc1672 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f07b8f2c0543c4f268d5e6613300f0f1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.m new file mode 100644 index 0000000..2607862 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.m @@ -0,0 +1,20 @@ +// +// NSNumber+TDCore.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/7/24. +// + +#import "NSNumber+TDCore.h" + +@implementation NSNumber (TDCore) + +- (BOOL)td_isBool { + const char *type = [self objCType]; + if (strcmp(type, "c") == 0 && ([self isEqualToNumber:@YES] || [self isEqualToNumber:@NO])) { + return YES; + } + return NO; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.m.meta new file mode 100644 index 0000000..f2646db --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSNumber/NSNumber+TDCore.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 33818e5f49cef4d6a8cba12f8444a3ca +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject.meta new file mode 100644 index 0000000..c9b5b40 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 09bd2089163174d488265abcd4374fb4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.h new file mode 100644 index 0000000..a6a6012 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.h @@ -0,0 +1,20 @@ +// +// NSObject+TDCore.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/13. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (TDCore) + +- (nullable instancetype)td_filterNull; +- (nullable NSString *)td_string; +- (nullable NSNumber *)td_number; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.h.meta new file mode 100644 index 0000000..7b1e58a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 90748d10279ff43bebc11eb1ca6d6d84 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.m new file mode 100644 index 0000000..0c2fb7a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.m @@ -0,0 +1,45 @@ +// +// NSObject+TDCore.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/13. +// + +#import "NSObject+TDCore.h" + +@implementation NSObject (TDCore) + +- (instancetype)td_filterNull { + if ([self isKindOfClass:NSNull.class]) { + return nil; + } + return self; +} + +- (NSString *)td_string { + NSObject *target = [self td_filterNull]; + if ([target isKindOfClass:NSString.class]) { + return (NSString *)target; + } + if ([target isKindOfClass:NSNumber.class]) { + return [NSString stringWithFormat:@"%@", target]; + } + return nil; +} + +- (NSNumber *)td_number { + NSObject *target = [self td_filterNull]; + if ([target isKindOfClass:NSString.class]) { + NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; + formatter.numberStyle = NSNumberFormatterDecimalStyle; + NSNumber *number = [formatter numberFromString:(NSString *)target]; + return number; + } + if ([target isKindOfClass:NSNumber.class]) { + return (NSNumber *)target; + } + return nil; +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.m.meta new file mode 100644 index 0000000..0974971 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSObject/NSObject+TDCore.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ff9148ad56bcb4b368da4b4527a1cea1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString.meta new file mode 100644 index 0000000..aef009a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a21e12f3026b44ef3b93d5bb48cbd1f6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.h new file mode 100644 index 0000000..1767b2c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.h @@ -0,0 +1,28 @@ +// +// NSString+TDCore.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/12. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSString (TDCore) + ++ (BOOL)td_isEmpty:(NSString *)str; + +- (nullable id)td_jsonObject; + +- (NSString *)td_trim; + ++ (nullable NSString *)td_jsonStringWithJsonObject:(id)jsonObj; + ++ (BOOL)td_isEqualWithString1:(nullable NSString *)string1 string2:(nullable NSString *)string2; + +- (NSString *)td_sha256AndBase64; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.h.meta new file mode 100644 index 0000000..3d3b22c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: e7d7a60dbd110438aaf23abaede6603e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.m new file mode 100644 index 0000000..daf3877 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.m @@ -0,0 +1,71 @@ +// +// NSString+TDCore.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/12. +// + +#import "NSString+TDCore.h" +#import "TDJSONUtil.h" +#import + +@implementation NSString (TDCore) + ++ (BOOL)td_isEmpty:(NSString *)str { + if (str == nil) { + return YES; + } else { + if ([str isKindOfClass:NSString.class]) { + return str.length <= 0; + } else { + return YES; + } + } +} + +- (id)td_jsonObject { + NSData *jsonData = [self dataUsingEncoding:NSUTF8StringEncoding]; + return [TDJSONUtil jsonForData:jsonData]; +} + +- (NSString *)td_trim { + NSString *string = [self stringByReplacingOccurrencesOfString:@" " withString:@""]; + string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@""]; + string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + return string; +} + ++ (NSString *)td_jsonStringWithJsonObject:(id)jsonObj { + if ([jsonObj isKindOfClass:NSArray.class] || [jsonObj isKindOfClass:NSDictionary.class]) { + @try { + NSError *jsonSeralizeError = nil; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonObj options:NSJSONWritingPrettyPrinted error:&jsonSeralizeError]; + if (jsonSeralizeError == nil && jsonData != nil) { + NSString *str = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + return str; + } + } @catch (NSException *exception) { + return nil; + } + } + return nil; +} + ++ (BOOL)td_isEqualWithString1:(NSString *)string1 string2:(NSString *)string2 { + if (string1 == nil && string2 == nil) { + return YES; + } else if ([string1 isEqualToString:string2]) { + return YES; + } + return NO; +} + +- (NSString *)td_sha256AndBase64 { + NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; + uint8_t digest[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(data.bytes, (CC_LONG)data.length, digest); + NSData *output = [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH]; + return [output base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.m.meta new file mode 100644 index 0000000..c992dec --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSString/NSString+TDCore.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 436015ca91e1b4b2e9f24086708dee8a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL.meta new file mode 100644 index 0000000..c4ec003 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e890e9aae12964f8a8010a887558ed5d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.h new file mode 100644 index 0000000..1c12e5d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.h @@ -0,0 +1,18 @@ +// +// NSURL+TDCore.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/5/27. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSURL (TDCore) + ++ (NSString *)td_baseUrlStringWithString:(NSString *)urlString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.h.meta new file mode 100644 index 0000000..1bba781 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: cbfa02ae02dbe4b27ae637627ca00279 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.m new file mode 100644 index 0000000..5a4157f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.m @@ -0,0 +1,30 @@ +// +// NSURL+TDCore.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/5/27. +// + +#import "NSURL+TDCore.h" + +@implementation NSURL (TDCore) + ++ (NSString *)td_baseUrlStringWithString:(NSString *)urlString { + NSString *formatString = [urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + + NSURL *url = [NSURL URLWithString:formatString]; + NSString *scheme = [url scheme]; + NSString *host = [url host]; + NSNumber *port = [url port]; + + if (scheme && scheme.length > 0 && host && host.length > 0) { + formatString = [NSString stringWithFormat:@"%@://%@", scheme, host]; + if (port && [port stringValue]) { + formatString = [formatString stringByAppendingFormat:@":%@", [port stringValue]]; + } + } + return formatString; +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.m.meta new file mode 100644 index 0000000..a4f29ae --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Category/NSURL/NSURL+TDCore.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: eb909be83eecc4518a575faa8c9f0e10 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database.meta new file mode 100644 index 0000000..1fd0f08 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 01f60e644d49441d6b44973a1da98f3d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.h new file mode 100644 index 0000000..068c417 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.h @@ -0,0 +1,21 @@ +// +// TDCoreDatabase.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/14. +// + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCoreDatabase : NSObject + ++ (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt; + ++ (NSString *)stringForColumnIndex:(int)columnIdx inStatement:(sqlite3_stmt *)pStmt; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.h.meta new file mode 100644 index 0000000..0f8fdf1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 36f88fea675524447950a6779f19adb7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.m new file mode 100644 index 0000000..c8011b2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.m @@ -0,0 +1,92 @@ +// +// TDCoreDatabase.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/3/14. +// + +#import "TDCoreDatabase.h" + +@implementation TDCoreDatabase + ++ (void)bindObject:(id)obj toColumn:(int)idx inStatement:(sqlite3_stmt*)pStmt { + if ((!obj) || ((NSNull *)obj == [NSNull null])) { + sqlite3_bind_null(pStmt, idx); + } + + // FIXME - someday check the return codes on these binds. + else if ([obj isKindOfClass:[NSData class]]) { + const void *bytes = [obj bytes]; + if (!bytes) { + // it's an empty NSData object, aka [NSData data]. + // Don't pass a NULL pointer, or sqlite will bind a SQL null instead of a blob. + bytes = ""; + } + sqlite3_bind_blob(pStmt, idx, bytes, (int)[obj length], SQLITE_TRANSIENT); + } + else if ([obj isKindOfClass:[NSDate class]]) { + sqlite3_bind_double(pStmt, idx, [obj timeIntervalSince1970]); + } + else if ([obj isKindOfClass:[NSNumber class]]) { + + if (strcmp([obj objCType], @encode(char)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj charValue]); + } + else if (strcmp([obj objCType], @encode(unsigned char)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj unsignedCharValue]); + } + else if (strcmp([obj objCType], @encode(short)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj shortValue]); + } + else if (strcmp([obj objCType], @encode(unsigned short)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj unsignedShortValue]); + } + else if (strcmp([obj objCType], @encode(int)) == 0) { + sqlite3_bind_int(pStmt, idx, [obj intValue]); + } + else if (strcmp([obj objCType], @encode(unsigned int)) == 0) { + sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedIntValue]); + } + else if (strcmp([obj objCType], @encode(long)) == 0) { + sqlite3_bind_int64(pStmt, idx, [obj longValue]); + } + else if (strcmp([obj objCType], @encode(unsigned long)) == 0) { + sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedLongValue]); + } + else if (strcmp([obj objCType], @encode(long long)) == 0) { + sqlite3_bind_int64(pStmt, idx, [obj longLongValue]); + } + else if (strcmp([obj objCType], @encode(unsigned long long)) == 0) { + sqlite3_bind_int64(pStmt, idx, (long long)[obj unsignedLongLongValue]); + } + else if (strcmp([obj objCType], @encode(float)) == 0) { + sqlite3_bind_double(pStmt, idx, [obj floatValue]); + } + else if (strcmp([obj objCType], @encode(double)) == 0) { + sqlite3_bind_double(pStmt, idx, [obj doubleValue]); + } + else if (strcmp([obj objCType], @encode(BOOL)) == 0) { + sqlite3_bind_int(pStmt, idx, ([obj boolValue] ? 1 : 0)); + } + else { + sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_TRANSIENT); + } + } + else { + sqlite3_bind_text(pStmt, idx, [[obj description] UTF8String], -1, SQLITE_TRANSIENT); + } +} + ++ (NSString *)stringForColumnIndex:(int)columnIdx inStatement:(sqlite3_stmt *)pStmt { + if (sqlite3_column_type(pStmt, columnIdx) == SQLITE_NULL || (columnIdx < 0) || columnIdx >= sqlite3_column_count(pStmt)) { + return nil; + } + const char *c = (const char *)sqlite3_column_text(pStmt, columnIdx); + if (!c) { + // null row. + return nil; + } + return [NSString stringWithUTF8String:c]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.m.meta new file mode 100644 index 0000000..ab080bc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Database/TDCoreDatabase.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 30390506a2f3444a2ab1fbb114438c6d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo.meta new file mode 100644 index 0000000..cab1f69 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 415368d8b93784505985b8f697e6199c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.h new file mode 100644 index 0000000..8447398 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.h @@ -0,0 +1,39 @@ +// +// TDCoreDeviceInfo.h +// Pods +// +// Created by 杨雄 on 2024/4/23. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCoreDeviceInfo : NSObject + ++ (NSTimeInterval)bootTime; ++ (NSString *)manufacturer; ++ (nullable NSString *)systemLanguage; ++ (NSString *)bundleId; ++ (NSString *)deviceId; ++ (NSDate *)installTime; ++ (NSString *)ram; ++ (NSString *)disk; ++ (NSString *)appVersion; ++ (NSString *)os; ++ (NSString *)osVersion; ++ (NSString *)deviceModel; ++ (NSString *)deviceType; ++ (BOOL)isSimulator; + +#if TARGET_OS_IOS ++ (NSNumber *)fps; ++ (NSNumber *)screenWidth; ++ (NSNumber *)screenHeight; ++ (NSString *)networkType; ++ (nullable NSString *)carrier; +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.h.meta new file mode 100644 index 0000000..8cc3889 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 0b0729b1f4eea40e9a71dab018e636ef +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.m new file mode 100644 index 0000000..88f6d47 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.m @@ -0,0 +1,417 @@ +// +// TDCoreDeviceInfo.m +// Pods +// +// Created by 杨雄 on 2024/4/23. +// + +#import "TDCoreDeviceInfo.h" +#import +#include +#import "TDCoreKeychainHelper.h" +#import + +#if TARGET_OS_WATCH +#import +#endif + +#if TARGET_OS_IOS || TARGET_OS_VISION +#import +#endif + +#if TARGET_OS_IOS +#import "TDNetworkReachability.h" +#import "TDCoreFPSMonitor.h" +#endif + +@implementation TDCoreDeviceInfo + +#if TARGET_OS_IOS ++ (void)load { + [[TDNetworkReachability shareInstance] startMonitoring]; +} +#endif + ++ (NSTimeInterval)bootTime { + struct timeval boottime; + int mib[2] = {CTL_KERN, KERN_BOOTTIME}; + size_t size = sizeof(boottime); + + struct timeval now; + struct timezone tz; + gettimeofday(&now, &tz); + + double uptime = -1; + + if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) + { + uptime = now.tv_sec - boottime.tv_sec; + uptime += (double)(now.tv_usec - boottime.tv_usec) / 1000000.0; + } + return uptime; +} + ++ (NSString *)manufacturer { + return @"Apple"; +} + ++ (nullable NSString *)systemLanguage { + NSString *preferredLanguages = [[NSLocale preferredLanguages] firstObject]; + if (preferredLanguages && preferredLanguages.length > 0) { + return [[preferredLanguages componentsSeparatedByString:@"-"] firstObject];; + } + return nil; +} + ++ (NSString *)bundleId { + return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]; +} + +#if (TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_VISION || TARGET_OS_TV) + ++ (NSString *)deviceId { + NSString *deviceId = nil; + @synchronized (self) { + NSString *keyDeviceId = @"thinking_data_device_id"; + deviceId = [TDCoreKeychainHelper readDeviceId]; + if (!([deviceId isKindOfClass:NSString.class] && deviceId.length > 0)) { + deviceId = [[NSUserDefaults standardUserDefaults] stringForKey:keyDeviceId]; + } + if (!deviceId) { + deviceId = [self defaultIdentifier]; + } + [[NSUserDefaults standardUserDefaults] setObject:deviceId forKey:keyDeviceId]; + [TDCoreKeychainHelper saveDeviceId:deviceId]; + } + return deviceId; +} + +#define kDeviceClass @"XY2HU4AX3JI2JJW5MDhjm6wea2x6ymvm28ylmiyh7jkc8axy9mw3em8w" +#define kCurrentDevice @"0a223h444j555cm666uw77722rh985jrj323ae44y5xn5ll5tm5mD5wm6e8y9m0vm32y46i7a89x0yl32c44ml4ye5a3a5" +#define kIdfv @"hj23kik4343j545dk656ke43434hhn534536jj7676tx323423yyx547657iy7678yxf7654hhl32342im3424ww4235w546ew64645w76ll57rx67yF434hj323ao343aa546rk76l323Vx32y32y32x32e3m43w656m76nxy657k657lmd65y657yx5o323aa34kk45rk76k76lm87" +#define kUUIDStr @"323J342J342K342U657K675A87A87U879H0943AX908IJ214KWD54WW87SX98XY3425At769k93l2l548m7r32xyx76769im3234ww6576n8ax89g98k9l97m1w31242" ++ (NSString *)defaultIdentifier { + NSString *anonymityId = NULL; + Class deviceCls = NSClassFromString([self dealStringWithRegExp:kDeviceClass]); + if (deviceCls) { + SEL currentDve = NSSelectorFromString([self dealStringWithRegExp:kCurrentDevice]); + SEL idfvor = NSSelectorFromString([self dealStringWithRegExp:kIdfv]); + SEL uuidStr = NSSelectorFromString([self dealStringWithRegExp:kUUIDStr]); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + if ([deviceCls respondsToSelector:currentDve]) { + id cls1 = [deviceCls performSelector:currentDve]; + if (cls1 && [cls1 respondsToSelector:idfvor]) { + id cls2 = [cls1 performSelector:idfvor]; + if (cls2 && [cls2 respondsToSelector:uuidStr]) { + id tempAnonymityId = [cls2 performSelector:uuidStr]; + if ([tempAnonymityId isKindOfClass:[NSString class]]) { + anonymityId = tempAnonymityId; + } + } + } + } +#pragma clang diagnostic pop + } + if (!anonymityId) { + anonymityId = [[NSUUID UUID] UUIDString]; + } + return anonymityId; +} + +#elif TARGET_OS_OSX + ++ (NSString *)deviceId { + NSString *keyDeviceId = @"thinking_data_device_id"; + NSString *deviceId = [[NSUserDefaults standardUserDefaults] stringForKey:keyDeviceId]; + if (!deviceId) { + deviceId = [self getSystemSerialNumber]; + if (deviceId == nil) { + deviceId = [[NSUUID UUID] UUIDString]; + } + [[NSUserDefaults standardUserDefaults] setObject:deviceId forKey:keyDeviceId]; + } + return deviceId; +} + ++ (nullable NSString *)getSystemSerialNumber { + io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); + if (platformExpert) { + CFTypeRef serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0); + IOObjectRelease(platformExpert); + if (serialNumberAsCFString) { + NSString *serialNumber = (__bridge_transfer NSString *)serialNumberAsCFString; + return serialNumber; + } + } + return nil; +} + +#endif + ++ (NSString *)dealStringWithRegExp:(NSString *)string { + NSRegularExpression *regExp = [[NSRegularExpression alloc]initWithPattern:@"[0-9AXYHJKLMW]" options:NSRegularExpressionCaseInsensitive error:nil]; + return [regExp stringByReplacingMatchesInString:string options:NSMatchingReportProgress range:NSMakeRange(0, string.length) withTemplate:@""]; +} + ++ (NSDate *)installTime { + NSURL *urlToDocumentsFolder = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; + NSError *error = nil; + NSDate *installDate = [[[NSFileManager defaultManager] attributesOfItemAtPath:urlToDocumentsFolder.path error:&error] objectForKey:NSFileCreationDate]; + if (!error) { + return installDate; + } + return [NSDate date]; +} + +#define TD_PM_UNIT_KB 1024.0 +#define TD_PM_UNIT_MB (1024.0 * TD_PM_UNIT_KB) +#define TD_PM_UNIT_GB (1024.0 * TD_PM_UNIT_MB) ++ (NSString *)ram { + NSString *ram = [NSString stringWithFormat:@"%.1f/%.1f", [self td_pm_func_getFreeMemory]*1.0/TD_PM_UNIT_GB, [self td_pm_func_getRamSize]*1.0/TD_PM_UNIT_GB]; + return ram; +} ++ (NSString *)disk { + NSString *disk = [NSString stringWithFormat:@"%.1f/%.1f", [self td_get_disk_free_size]*1.0/TD_PM_UNIT_GB, [self td_get_storage_size]*1.0/TD_PM_UNIT_GB]; + return disk; +} + ++ (int64_t)td_pm_func_getFreeMemory { + size_t length = 0; + int mib[6] = {0}; + + int pagesize = 0; + mib[0] = CTL_HW; + mib[1] = HW_PAGESIZE; + length = sizeof(pagesize); + if (sysctl(mib, 2, &pagesize, &length, NULL, 0) < 0){ + return -1; + } + mach_msg_type_number_t count = HOST_VM_INFO_COUNT; + vm_statistics_data_t vmstat; + if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat, &count) != KERN_SUCCESS){ + return -1; + } + + int64_t freeMem = vmstat.free_count * pagesize; + int64_t inactiveMem = vmstat.inactive_count * pagesize; + return freeMem + inactiveMem; +} + ++ (int64_t)td_pm_func_getRamSize{ + int mib[2]; + size_t length = 0; + + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + long ram; + length = sizeof(ram); + if (sysctl(mib, 2, &ram, &length, NULL, 0) < 0) { + return -1; + } + return ram; +} + ++ (NSDictionary *)td_pm_getFileAttributeDic { + NSError *error; + NSDictionary *directory = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error]; + if (error) { + return nil; + } + return directory; +} + ++ (long long)td_get_disk_free_size { + NSDictionary *directory = [self td_pm_getFileAttributeDic]; + if (directory) { + return [[directory objectForKey:NSFileSystemFreeSize] unsignedLongLongValue]; + } + return -1; +} + ++ (long long)td_get_storage_size { + NSDictionary *directory = [self td_pm_getFileAttributeDic]; + return directory ? ((NSNumber *)[directory objectForKey:NSFileSystemSize]).unsignedLongLongValue:-1; +} + ++ (NSString *)appVersion { + return [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"]; +} + ++ (BOOL)isSimulator { + BOOL result = NO; +#if TARGET_IPHONE_SIMULATOR + result = YES; +#elif TARGET_OS_SIMULATOR + result = YES; +#else + result = NO; +#endif + return result; +} + +#if TARGET_OS_IOS + ++ (NSNumber *)fps { + static TDCoreFPSMonitor *fpsMonitor = nil; + if (!fpsMonitor) { + fpsMonitor = [[TDCoreFPSMonitor alloc] init]; + [fpsMonitor setEnable:YES]; + } + return [fpsMonitor getPFS]; +} + ++ (NSNumber *)screenWidth { + CGSize size = [UIScreen mainScreen].bounds.size; + return @((NSInteger)size.width); +} + ++ (NSNumber *)screenHeight { + CGSize size = [UIScreen mainScreen].bounds.size; + return @((NSInteger)size.height); +} + ++ (NSString *)networkType { + return [[TDNetworkReachability shareInstance] networkState]; +} + ++ (nullable NSString *)carrier { + return [[TDNetworkReachability shareInstance] carrier]; +} +#endif + +/* ========================================================================================================== + Warning: The following code cannot be modified, otherwise it will result in inaccurate data analysis!!! + ============================================================================================================ + */ ++ (NSString *)deviceModel { +#if (TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_VISION || TARGET_OS_TV) + struct utsname systemInfo; + uname(&systemInfo); + NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding]; + if ([platform isEqualToString:@"iPhone1,1"]) return @"iPhone 2G"; + if ([platform isEqualToString:@"iPhone1,2"]) return @"iPhone 3G"; + if ([platform isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS"; + if ([platform isEqualToString:@"iPhone3,1"]) return @"iPhone 4"; + if ([platform isEqualToString:@"iPhone3,2"]) return @"iPhone 4"; + if ([platform isEqualToString:@"iPhone3,3"]) return @"iPhone 4"; + if ([platform isEqualToString:@"iPhone4,1"]) return @"iPhone 4S"; + if ([platform isEqualToString:@"iPhone5,1"]) return @"iPhone 5"; + if ([platform isEqualToString:@"iPhone5,2"]) return @"iPhone 5"; + if ([platform isEqualToString:@"iPhone5,3"]) return @"iPhone 5c"; + if ([platform isEqualToString:@"iPhone5,4"]) return @"iPhone 5c"; + if ([platform isEqualToString:@"iPhone6,1"]) return @"iPhone 5s"; + if ([platform isEqualToString:@"iPhone6,2"]) return @"iPhone 5s"; + if ([platform isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus"; + if ([platform isEqualToString:@"iPhone7,2"]) return @"iPhone 6"; + if ([platform isEqualToString:@"iPhone8,1"]) return @"iPhone 6s"; + if ([platform isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus"; + if ([platform isEqualToString:@"iPhone8,4"]) return @"iPhone SE"; + if ([platform isEqualToString:@"iPhone9,1"]) return @"iPhone 7"; + if ([platform isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus"; + if ([platform isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G"; + if ([platform isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G"; + if ([platform isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G"; + if ([platform isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G"; + if ([platform isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G"; + if ([platform isEqualToString:@"iPad1,1"]) return @"iPad 1G"; + if ([platform isEqualToString:@"iPad2,1"]) return @"iPad 2"; + if ([platform isEqualToString:@"iPad2,2"]) return @"iPad 2"; + if ([platform isEqualToString:@"iPad2,3"]) return @"iPad 2"; + if ([platform isEqualToString:@"iPad2,4"]) return @"iPad 2"; + if ([platform isEqualToString:@"iPad2,5"]) return @"iPad Mini 1G"; + if ([platform isEqualToString:@"iPad2,6"]) return @"iPad Mini 1G"; + if ([platform isEqualToString:@"iPad2,7"]) return @"iPad Mini 1G"; + if ([platform isEqualToString:@"iPad3,1"]) return @"iPad 3"; + if ([platform isEqualToString:@"iPad3,2"]) return @"iPad 3"; + if ([platform isEqualToString:@"iPad3,3"]) return @"iPad 3"; + if ([platform isEqualToString:@"iPad3,4"]) return @"iPad 4"; + if ([platform isEqualToString:@"iPad3,5"]) return @"iPad 4"; + if ([platform isEqualToString:@"iPad3,6"]) return @"iPad 4"; + if ([platform isEqualToString:@"iPad4,1"]) return @"iPad Air"; + if ([platform isEqualToString:@"iPad4,2"]) return @"iPad Air"; + if ([platform isEqualToString:@"iPad4,3"]) return @"iPad Air"; + if ([platform isEqualToString:@"iPad4,4"]) return @"iPad Mini 2G"; + if ([platform isEqualToString:@"iPad4,5"]) return @"iPad Mini 2G"; + if ([platform isEqualToString:@"iPad4,6"]) return @"iPad Mini 2G"; + if ([platform isEqualToString:@"i386"]) return @"iPhone Simulator"; + if ([platform isEqualToString:@"x86_64"]) return @"iPhone Simulator"; + return platform; +#elif TARGET_OS_OSX + struct utsname systemInfo; + uname(&systemInfo); + NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding]; + return platform; +#endif +} + ++ (NSString *)os { +#if TARGET_OS_IOS + return @"iOS"; +#elif TARGET_OS_WATCH + return [WKInterfaceDevice currentDevice].systemName; +#elif TARGET_OS_TV + return @"tvOS"; +#elif TARGET_OS_VISION + return [UIDevice currentDevice].systemName; +#elif TARGET_OS_OSX + return @"OSX"; +#endif +} + ++ (NSString *)osVersion { +#if TARGET_OS_IOS || TARGET_OS_VISION || TARGET_OS_TV + return [[UIDevice currentDevice] systemVersion]; +#elif TARGET_OS_WATCH + return [WKInterfaceDevice currentDevice].systemVersion; +#elif TARGET_OS_OSX + NSDictionary *sv = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; + NSString *versionString = [sv objectForKey:@"ProductVersion"]; + return versionString; +#endif + return @""; +} + ++ (NSString *)deviceType { +#if TARGET_OS_IOS + NSString *typeName = @"unknown"; + switch ([[UIDevice currentDevice] userInterfaceIdiom]) { + case UIUserInterfaceIdiomPad: { + typeName = @"iPad"; + } break; + case UIUserInterfaceIdiomPhone: { + typeName = @"iPhone"; + } break; + case UIUserInterfaceIdiomTV: { + typeName = @"TV"; + } break; + case UIUserInterfaceIdiomCarPlay: { + typeName = @"CarPlay"; + } break; +#ifdef __IPHONE_14_0 + case UIUserInterfaceIdiomMac: { + typeName = @"Mac"; + } break; +#endif +#ifdef __IPHONE_17_0 + case UIUserInterfaceIdiomVision: { + typeName = @"Vision"; + } break; +#endif + default: + break; + } + return typeName; +#elif TARGET_OS_OSX + return @"Mac"; +#elif TARGET_OS_WATCH + return @"AppleWatch"; +#elif TARGET_OS_VISION + return @"VisionPro"; +#elif TARGET_OS_TV + return @"AppleTV"; +#endif + return @""; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.m.meta new file mode 100644 index 0000000..93f9117 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreDeviceInfo.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 98760b88a7a5f46128e9d1846136dbd9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.h new file mode 100644 index 0000000..f42ad3c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.h @@ -0,0 +1,19 @@ +// +// TDCoreFPSMonitor.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCoreFPSMonitor : NSObject +@property (nonatomic, assign, getter=isEnable) BOOL enable; + +- (NSNumber *)getPFS; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.h.meta new file mode 100644 index 0000000..238191b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 56117c2f6c43f4a3bbe88ef03e338924 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.m new file mode 100644 index 0000000..702b706 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.m @@ -0,0 +1,72 @@ +// +// TDCoreFPSMonitor.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/24. +// + +#import "TDCoreFPSMonitor.h" +#import +#import "TDCoreWeakProxy.h" + +@interface TDCoreFPSMonitor () +@property (nonatomic, strong) CADisplayLink *link; +@property (nonatomic, assign) NSUInteger count; +@property (nonatomic, assign) NSTimeInterval lastTime; +@property (nonatomic, assign) int thinkingdata_fps; + +@end + +@implementation TDCoreFPSMonitor + +- (void)setEnable:(BOOL)enable { + _enable = enable; + if (_enable) { + [self startDisplay]; + } else { + [self stopDisplay]; + } +} + +- (NSNumber *)getPFS { + return [NSNumber numberWithInt:[NSString stringWithFormat:@"%d", _thinkingdata_fps].intValue]; +} + +- (void)dealloc { + if (_link) { + [_link invalidate]; + } +} + +- (void)startDisplay { + + if (_link) return; + + _thinkingdata_fps = 60; + _link = [CADisplayLink displayLinkWithTarget:[TDCoreWeakProxy proxyWithTarget:self] selector:@selector(tick:)]; +// _link.preferredFrameRateRange = CAFrameRateRangeMake(60, 120, 120); + [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; +} + +- (void)stopDisplay { + if (_link) { + [_link invalidate]; + _link= nil; + } +} + +- (void)tick:(CADisplayLink *)link { + if (_lastTime == 0) { + _lastTime = link.timestamp; + return; + } + + _count++; + NSTimeInterval delta = link.timestamp - _lastTime; + if (delta < 1.0) return; + _lastTime = link.timestamp; + _thinkingdata_fps = _count / delta; + _count = 0; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.m.meta new file mode 100644 index 0000000..22f129e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCoreFPSMonitor.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 02553d30dbe3a497592fe37e155561c5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.h new file mode 100644 index 0000000..c16ad62 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.h @@ -0,0 +1,56 @@ +// +// TDCorePresetDisableConfig.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/25. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCorePresetDisableConfig : NSObject + +@property(class, nonatomic, readonly) BOOL disableOpsReceiptProperties; +@property(class, nonatomic, readonly) BOOL disableStartReason; +@property(class, nonatomic, readonly) BOOL disableDisk; +@property(class, nonatomic, readonly) BOOL disableRAM; +@property(class, nonatomic, readonly) BOOL disableFPS; +@property(class, nonatomic, readonly) BOOL disableSimulator; +@property(class, nonatomic, readonly) BOOL disableAppVersion; +@property(class, nonatomic, readonly) BOOL disableOsVersion; +@property(class, nonatomic, readonly) BOOL disableManufacturer; +@property(class, nonatomic, readonly) BOOL disableDeviceModel; +@property(class, nonatomic, readonly) BOOL disableScreenHeight; +@property(class, nonatomic, readonly) BOOL disableScreenWidth; +@property(class, nonatomic, readonly) BOOL disableCarrier; +@property(class, nonatomic, readonly) BOOL disableDeviceId; +@property(class, nonatomic, readonly) BOOL disableSystemLanguage; +@property(class, nonatomic, readonly) BOOL disableLib; +@property(class, nonatomic, readonly) BOOL disableLibVersion; +@property(class, nonatomic, readonly) BOOL disableBundleId; +@property(class, nonatomic, readonly) BOOL disableOs; +@property(class, nonatomic, readonly) BOOL disableInstallTime; +@property(class, nonatomic, readonly) BOOL disableDeviceType; +@property(class, nonatomic, readonly) BOOL disableSessionID; +@property(class, nonatomic, readonly) BOOL disableCalibratedTime; + +@property(class, nonatomic, readonly) BOOL disableNetworkType; +@property(class, nonatomic, readonly) BOOL disableZoneOffset; +@property(class, nonatomic, readonly) BOOL disableDuration; +@property(class, nonatomic, readonly) BOOL disableBackgroundDuration; +@property(class, nonatomic, readonly) BOOL disableAppCrashedReason; +@property(class, nonatomic, readonly) BOOL disableResumeFromBackground; +@property(class, nonatomic, readonly) BOOL disableElementId; +@property(class, nonatomic, readonly) BOOL disableElementType; +@property(class, nonatomic, readonly) BOOL disableElementContent; +@property(class, nonatomic, readonly) BOOL disableElementPosition; +@property(class, nonatomic, readonly) BOOL disableElementSelector; +@property(class, nonatomic, readonly) BOOL disableScreenName; +@property(class, nonatomic, readonly) BOOL disableTitle; +@property(class, nonatomic, readonly) BOOL disableUrl; +@property(class, nonatomic, readonly) BOOL disableReferrer; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.h.meta new file mode 100644 index 0000000..3e3829e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4852319f96f674a85bc9d9d6eb0b8d37 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.m new file mode 100644 index 0000000..aab1478 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.m @@ -0,0 +1,317 @@ +// +// TDCorePresetDisableConfig.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/25. +// + +#import "TDCorePresetDisableConfig.h" + +static BOOL _td_disableOpsReceiptProperties; +static BOOL _td_disableStartReason; +static BOOL _td_disableDisk; +static BOOL _td_disableRAM; +static BOOL _td_disableFPS; +static BOOL _td_disableSimulator; +static BOOL _td_disableAppVersion; +static BOOL _td_disableOsVersion; +static BOOL _td_disableManufacturer; +static BOOL _td_disableDeviceModel; +static BOOL _td_disableScreenHeight; +static BOOL _td_disableScreenWidth; +static BOOL _td_disableCarrier; +static BOOL _td_disableDeviceId; +static BOOL _td_disableSystemLanguage; +static BOOL _td_disableLib; +static BOOL _td_disableLibVersion; +static BOOL _td_disableBundleId; +static BOOL _td_disableOs; +static BOOL _td_disableInstallTime; +static BOOL _td_disableDeviceType; +static BOOL _td_disableSessionID; +static BOOL _td_disableCalibratedTime; + +static BOOL _td_disableNetworkType; +static BOOL _td_disableZoneOffset; +static BOOL _td_disableDuration; +static BOOL _td_disableBackgroundDuration; +static BOOL _td_disableAppCrashedReason; +static BOOL _td_disableResumeFromBackground; +static BOOL _td_disableElementId; +static BOOL _td_disableElementType; +static BOOL _td_disableElementContent; +static BOOL _td_disableElementPosition; +static BOOL _td_disableElementSelector; +static BOOL _td_disableScreenName; +static BOOL _td_disableTitle; +static BOOL _td_disableUrl; +static BOOL _td_disableReferrer; + +// - 禁用功能并过滤字段拼接 +static const NSString *kTDPresentOpsReceiptProperties = @"#ops_receipt_properties"; +static const NSString *kTDStartReason = @"#start_reason"; +static const NSString *kTDPerformanceRAM = @"#ram"; +static const NSString *kTDPerformanceDISK = @"#disk"; +static const NSString *kTDPerformanceSIM = @"#simulator"; +static const NSString *kTDPerformanceFPS = @"#fps"; +static const NSString *kTDPresentAppVersion = @"#app_version"; +static const NSString *kTDPresentOsVersion = @"#os_version"; +static const NSString *kTDPresentManufacturer = @"#manufacturer"; +static const NSString *kTDPresentDeviceModel = @"#device_model"; +static const NSString *kTDPresentScreenHeight = @"#screen_height"; +static const NSString *kTDPresentScreenWidth = @"#screen_width"; +static const NSString *kTDPresentCarrier = @"#carrier"; +static const NSString *kTDPresentDeviceId = @"#device_id"; +static const NSString *kTDPresentSystemLanguage = @"#system_language"; +static const NSString *kTDPresentLib = @"#lib"; +static const NSString *kTDPresentLibVersion = @"#lib_version"; +static const NSString *kTDPresentOs = @"#os"; +static const NSString *kTDPresentBundleId = @"#bundle_id"; +static const NSString *kTDPresentInstallTime = @"#install_time"; +static const NSString *kTDPresentDeviceType = @"#device_type"; +static const NSString *kTDPresentSessionID = @"#session_id"; +static const NSString *kTDPresentCalibratedTime = @"#time_calibration"; + +// - 只过滤字段 +static const NSString *kTDPresentNETWORKTYPE = @"#network_type"; +static const NSString *kTDPresentZONEOFFSET = @"#zone_offset"; +static const NSString *kTDPresentDURATION = @"#duration"; +static const NSString *kTDPresentBACKGROUNDDURATION = @"#background_duration"; +static const NSString *kTDPresentCRASHREASON = @"#app_crashed_reason"; +static const NSString *kTDPresentRESUMEFROMBACKGROUND = @"#resume_from_background"; +static const NSString *kTDPresentELEMENTID = @"#element_id"; +static const NSString *kTDPresentELEMENTTYPE = @"#element_type"; +static const NSString *kTDPresentELEMENTCONTENT = @"#element_content"; +static const NSString *kTDPresentELEMENTPOSITION = @"#element_position"; +static const NSString *kTDPresentELEMENTSELECTOR = @"#element_selector"; +static const NSString *kTDPresentSCREENNAME = @"#screen_name"; +static const NSString *kTDPresentTITLE = @"#title"; +static const NSString *kTDPresentURL = @"#url"; +static const NSString *kTDPresentREFERRER = @"#referrer"; + +#define TD_MAIM_INFO_PLIST_DISPRESTPRO_KEY @"TDDisPresetProperties" + +@implementation TDCorePresetDisableConfig + +static NSMutableArray *__td_disPresetProperties; + ++ (void)initialize { + [self loadDisPresetProperties]; +} + ++ (NSArray *)loadDisPresetProperties { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + + NSArray *disPresetProperties = (NSArray *)[[[NSBundle mainBundle] infoDictionary] objectForKey:TD_MAIM_INFO_PLIST_DISPRESTPRO_KEY]; + + if (disPresetProperties && disPresetProperties.count) { + __td_disPresetProperties = [NSMutableArray arrayWithArray:disPresetProperties]; + + if ([__td_disPresetProperties containsObject:kTDPresentZONEOFFSET]) { + [__td_disPresetProperties removeObject:kTDPresentZONEOFFSET]; + } + + _td_disableStartReason = [__td_disPresetProperties containsObject:kTDStartReason]; + _td_disableDisk = [__td_disPresetProperties containsObject:kTDPerformanceDISK]; + _td_disableRAM = [__td_disPresetProperties containsObject:kTDPerformanceRAM]; + _td_disableFPS = [__td_disPresetProperties containsObject:kTDPerformanceFPS]; + _td_disableSimulator = [__td_disPresetProperties containsObject:kTDPerformanceSIM]; + + _td_disableAppVersion = [__td_disPresetProperties containsObject:kTDPresentAppVersion]; + _td_disableOsVersion = [__td_disPresetProperties containsObject:kTDPresentOsVersion]; + _td_disableManufacturer = [__td_disPresetProperties containsObject:kTDPresentManufacturer]; + _td_disableDeviceModel = [__td_disPresetProperties containsObject:kTDPresentDeviceModel]; + _td_disableScreenHeight = [__td_disPresetProperties containsObject:kTDPresentScreenHeight]; + _td_disableScreenWidth = [__td_disPresetProperties containsObject:kTDPresentScreenWidth]; + _td_disableCarrier = [__td_disPresetProperties containsObject:kTDPresentCarrier]; + _td_disableDeviceId = [__td_disPresetProperties containsObject:kTDPresentDeviceId]; + _td_disableSystemLanguage = [__td_disPresetProperties containsObject:kTDPresentSystemLanguage]; + _td_disableLib = [__td_disPresetProperties containsObject:kTDPresentLib]; + _td_disableLibVersion = [__td_disPresetProperties containsObject:kTDPresentLibVersion]; + _td_disableBundleId = [__td_disPresetProperties containsObject:kTDPresentBundleId]; + _td_disableOs = [__td_disPresetProperties containsObject:kTDPresentOs]; + _td_disableInstallTime = [__td_disPresetProperties containsObject:kTDPresentInstallTime]; + _td_disableDeviceType = [__td_disPresetProperties containsObject:kTDPresentDeviceType]; + //_td_disableSessionID = [__td_disPresetProperties containsObject:kTDPresentSessionID]; + //_td_disableCalibratedTime = [__td_disPresetProperties containsObject:kTDPresentCalibratedTime]; + _td_disableSessionID = YES; + _td_disableCalibratedTime = YES; + + _td_disableNetworkType = [__td_disPresetProperties containsObject:kTDPresentNETWORKTYPE]; + _td_disableZoneOffset = [__td_disPresetProperties containsObject:kTDPresentZONEOFFSET]; + _td_disableDuration = [__td_disPresetProperties containsObject:kTDPresentDURATION]; + _td_disableBackgroundDuration = [__td_disPresetProperties containsObject:kTDPresentBACKGROUNDDURATION]; + _td_disableAppCrashedReason = [__td_disPresetProperties containsObject:kTDPresentCRASHREASON]; + _td_disableResumeFromBackground = [__td_disPresetProperties containsObject:kTDPresentRESUMEFROMBACKGROUND]; + _td_disableElementId = [__td_disPresetProperties containsObject:kTDPresentELEMENTID]; + _td_disableElementType = [__td_disPresetProperties containsObject:kTDPresentELEMENTTYPE]; + _td_disableElementContent = [__td_disPresetProperties containsObject:kTDPresentELEMENTCONTENT]; + _td_disableElementPosition = [__td_disPresetProperties containsObject:kTDPresentELEMENTPOSITION]; + _td_disableElementSelector = [__td_disPresetProperties containsObject:kTDPresentELEMENTSELECTOR]; + _td_disableScreenName = [__td_disPresetProperties containsObject:kTDPresentSCREENNAME]; + _td_disableTitle = [__td_disPresetProperties containsObject:kTDPresentTITLE]; + _td_disableUrl = [__td_disPresetProperties containsObject:kTDPresentURL]; + _td_disableReferrer = [__td_disPresetProperties containsObject:kTDPresentREFERRER]; + _td_disableOpsReceiptProperties = [__td_disPresetProperties containsObject:kTDPresentOpsReceiptProperties]; + } + }); + return __td_disPresetProperties; +} + ++ (BOOL)disableOpsReceiptProperties { + return _td_disableOpsReceiptProperties; +} + ++ (BOOL)disableStartReason { + return _td_disableStartReason; +} + ++ (BOOL)disableDisk { + return _td_disableDisk; +} + ++ (BOOL)disableRAM { + return _td_disableRAM; +} + ++ (BOOL)disableFPS { + return _td_disableFPS; +} + ++ (BOOL)disableSimulator { + return _td_disableSimulator; +} + + + + ++ (BOOL)disableAppVersion { + return _td_disableAppVersion; +} + ++ (BOOL)disableOsVersion { + return _td_disableOsVersion; +} + ++ (BOOL)disableManufacturer { + return _td_disableManufacturer; +} + ++ (BOOL)disableDeviceId { + return _td_disableDeviceId; +} + ++ (BOOL)disableDeviceModel { + return _td_disableDeviceModel; +} + ++ (BOOL)disableScreenHeight { + return _td_disableScreenHeight; +} + ++ (BOOL)disableScreenWidth { + return _td_disableScreenWidth; +} + ++ (BOOL)disableCarrier { + return _td_disableCarrier; +} + ++ (BOOL)disableSystemLanguage { + return _td_disableSystemLanguage; +} + ++ (BOOL)disableLib { + return _td_disableLib; +} + ++ (BOOL)disableLibVersion { + return _td_disableLibVersion; +} + ++ (BOOL)disableOs { + return _td_disableOs; +} + ++ (BOOL)disableBundleId { + return _td_disableBundleId; +} + ++ (BOOL)disableInstallTime { + return _td_disableInstallTime; +} + ++ (BOOL)disableDeviceType { + return _td_disableDeviceType; +} + ++ (BOOL)disableNetworkType { + return _td_disableNetworkType; +} + ++ (BOOL)disableZoneOffset { + return _td_disableZoneOffset; +} + ++ (BOOL)disableDuration { + return _td_disableDuration; +} + ++ (BOOL)disableBackgroundDuration { + return _td_disableBackgroundDuration; +} + ++ (BOOL)disableAppCrashedReason { + return _td_disableAppCrashedReason; +} + ++ (BOOL)disableResumeFromBackground { + return _td_disableResumeFromBackground; +} + ++ (BOOL)disableElementId { + return _td_disableElementId; +} + ++ (BOOL)disableElementType { + return _td_disableElementType; +} + ++ (BOOL)disableElementContent { + return _td_disableElementContent; +} + ++ (BOOL)disableElementPosition { + return _td_disableElementPosition; +} + ++ (BOOL)disableElementSelector { + return _td_disableElementSelector; +} + ++ (BOOL)disableScreenName { + return _td_disableScreenName; +} + ++ (BOOL)disableTitle { + return _td_disableTitle; +} + ++ (BOOL)disableUrl { + return _td_disableUrl; +} + ++ (BOOL)disableReferrer { + return _td_disableReferrer; +} + ++ (BOOL)disableSessionID { + return _td_disableSessionID; +} + ++ (BOOL)disableCalibratedTime { + return _td_disableCalibratedTime; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.m.meta new file mode 100644 index 0000000..2cd1f72 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetDisableConfig.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4d45d78e5506a4395a0eb7656ce51256 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.h new file mode 100644 index 0000000..e4188e5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.h @@ -0,0 +1,22 @@ +// +// TDCorePresetProperty.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCorePresetProperty : NSObject + ++ (NSDictionary *)staticProperties; + ++ (NSDictionary *)dynamicProperties; + ++ (NSDictionary *)allPresetProperties; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.h.meta new file mode 100644 index 0000000..881e9cd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 01aef1e4616454ee7be4d15184c63ccc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.m new file mode 100644 index 0000000..0c4015e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.m @@ -0,0 +1,145 @@ +// +// TDCorePresetProperty.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/26. +// + +#import "TDCorePresetProperty.h" +#import "TDCoreDeviceInfo.h" +#import "TDCorePresetDisableConfig.h" + +@implementation TDCorePresetProperty + ++ (NSDictionary *)staticProperties { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (![TDCorePresetDisableConfig disableBundleId]) { + NSString *value = [TDCoreDeviceInfo bundleId]; + if (value) { + dict[@"#bundle_id"] = value; + } + } + if (![TDCorePresetDisableConfig disableInstallTime]) { + NSDate *value = [TDCoreDeviceInfo installTime]; + if (value) { + dict[@"#install_time"] = value; + } + } + if (![TDCorePresetDisableConfig disableDeviceId]) { + NSString *value = [TDCoreDeviceInfo deviceId]; + if (value) { + dict[@"#device_id"] = value; + } + } + if (![TDCorePresetDisableConfig disableAppVersion]) { + NSString *value = [TDCoreDeviceInfo appVersion]; + if (value) { + dict[@"#app_version"] = value; + } + } + if (![TDCorePresetDisableConfig disableOs]) { + NSString *value = [TDCoreDeviceInfo os]; + if (value) { + dict[@"#os"] = value; + } + } + if (![TDCorePresetDisableConfig disableOsVersion]) { + NSString *value = [TDCoreDeviceInfo osVersion]; + if (value) { + dict[@"#os_version"] = value; + } + } + if (![TDCorePresetDisableConfig disableDeviceModel]) { + NSString *value = [TDCoreDeviceInfo deviceModel]; + if (value) { + dict[@"#device_model"] = value; + } + } + if (![TDCorePresetDisableConfig disableDeviceType]) { + NSString *value = [TDCoreDeviceInfo deviceType]; + if (value) { + dict[@"#device_type"] = value; + } + } + if (![TDCorePresetDisableConfig disableManufacturer]) { + NSString *value = [TDCoreDeviceInfo manufacturer]; + if (value) { + dict[@"#manufacturer"] = value; + } + } + if (![TDCorePresetDisableConfig disableSimulator]) { + dict[@"#simulator"] = [TDCoreDeviceInfo isSimulator] ? @(YES) : @(NO); + } +#if TARGET_OS_IOS + + if (![TDCorePresetDisableConfig disableScreenWidth]) { + NSNumber *value = [TDCoreDeviceInfo screenWidth]; + if (value) { + dict[@"#screen_width"] = value; + } + } + if (![TDCorePresetDisableConfig disableScreenHeight]) { + NSNumber *value = [TDCoreDeviceInfo screenHeight]; + if (value) { + dict[@"#screen_height"] = value; + } + } +#endif + return dict; +} + ++ (NSDictionary *)dynamicProperties { + NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; + + if (![TDCorePresetDisableConfig disableRAM]) { + NSString *value = [TDCoreDeviceInfo ram]; + if (value) { + mutableDict[@"#ram"] = value; + } + } + if (![TDCorePresetDisableConfig disableDisk]) { + NSString *value = [TDCoreDeviceInfo disk]; + if (value) { + mutableDict[@"#disk"] = value; + } + } + if (![TDCorePresetDisableConfig disableSystemLanguage]) { + NSString *value = [TDCoreDeviceInfo systemLanguage]; + if (value) { + mutableDict[@"#system_language"] = value; + } + } +#if TARGET_OS_IOS + if (![TDCorePresetDisableConfig disableCarrier]) { + NSString *value = [TDCoreDeviceInfo carrier]; + if (value) { + mutableDict[@"#carrier"] = value; + } + } + if (![TDCorePresetDisableConfig disableNetworkType]) { + NSString *value = [TDCoreDeviceInfo networkType]; + if (value) { + mutableDict[@"#network_type"] = value; + } + } + if (![TDCorePresetDisableConfig disableFPS]) { + NSNumber *value = [TDCoreDeviceInfo fps]; + if (value) { + mutableDict[@"#fps"] = value; + } + } +#endif + return mutableDict; +} + ++ (NSDictionary *)allPresetProperties { + NSDictionary *staticDict = [self staticProperties]; + NSDictionary *dynamicDict = [self dynamicProperties]; + + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [dict addEntriesFromDictionary:staticDict]; + [dict addEntriesFromDictionary:dynamicDict]; + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.m.meta new file mode 100644 index 0000000..1064c4e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/DeviceInfo/TDCorePresetProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 518d2743a150b42d88db013fb0311fa5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain.meta new file mode 100644 index 0000000..ef39dda --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4e836d9003e714cf1bd690fd380a447a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.h new file mode 100644 index 0000000..20df298 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.h @@ -0,0 +1,20 @@ +// +// TDCoreKeychainHelper.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCoreKeychainHelper : NSObject + ++ (void)saveDeviceId:(NSString *)string; + ++ (NSString *)readDeviceId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.h.meta new file mode 100644 index 0000000..5df7c3f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f09db69b8fe434562848fb6bf12d5695 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.m new file mode 100644 index 0000000..8999e8f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.m @@ -0,0 +1,34 @@ +// +// TDCoreKeychainHelper.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/24. +// + +#import "TDCoreKeychainHelper.h" +#import "TDKeychainManager.h" + +static NSString * const kTDDeviceIDOld = @"com.thinkingddata.analytics.deviceid"; +static NSString * const kTDDeviceIDNew = @"com.thinkingddata.analytics.deviceid_1"; + +@implementation TDCoreKeychainHelper + ++ (void)saveDeviceId:(NSString *)string { + [TDKeychainManager saveItem:string forKey:kTDDeviceIDNew]; + + // Compatibility handles the case of jumping back and forth between old and new SDK versions + [TDKeychainManager oldSaveItem:string forKey:kTDDeviceIDOld]; +} + ++ (NSString *)readDeviceId { + NSString *data = [TDKeychainManager itemForKey:kTDDeviceIDNew]; + if (data == nil) { + data = [TDKeychainManager oldItemForKey:kTDDeviceIDOld]; + if (data) { + [TDKeychainManager saveItem:data forKey:kTDDeviceIDNew]; + } + } + return data; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.m.meta new file mode 100644 index 0000000..4da5635 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDCoreKeychainHelper.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 23267f5a227e440279b4d3f360848880 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.h new file mode 100644 index 0000000..9c5e5f7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.h @@ -0,0 +1,21 @@ +// +// TDKeychainManager.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/1/23. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDKeychainManager : NSObject ++ (void)saveItem:(nonnull NSString *)value forKey:(nonnull NSString *)key; ++ (void)oldSaveItem:(nonnull NSString *)value forKey:(nonnull NSString *)key; ++ (nullable NSString *)itemForKey:(nonnull NSString *)key; ++ (BOOL)deleteItemWithKey:(nonnull NSString *)key; ++ (nullable NSString *)oldItemForKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.h.meta new file mode 100644 index 0000000..b83a705 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ea66356f7b752448da1f6da14a70b0bc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.m new file mode 100644 index 0000000..16365fe --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.m @@ -0,0 +1,149 @@ +// +// TDKeychainManager.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/1/23. +// + +#import "TDKeychainManager.h" +#import "TDOSLog.h" + +static NSString * const TDKeychainService = @"com.thinkingddata.analytics.service"; + +@interface TDKeychainManager () + +@end + +@implementation TDKeychainManager + ++ (void)saveItem:(nonnull NSString *)value forKey:(nonnull NSString *)key { + if (!key || !value) { + return; + } + NSData *encodeData = [value dataUsingEncoding:NSUTF8StringEncoding]; + @synchronized (self) { + NSString *originPassword = [self itemForKey:key]; + if (originPassword.length > 0) { + NSMutableDictionary *updateAttributes = [NSMutableDictionary dictionary]; + updateAttributes[(__bridge id)kSecValueData] = encodeData; + NSMutableDictionary *query = [self keychainQueryWithAccount:key]; + OSStatus statusCode = SecItemUpdate((__bridge CFDictionaryRef)query,(__bridge CFDictionaryRef)updateAttributes); + if (statusCode != noErr) { + [TDOSLog logMessage:@"Keychain Update Error" prefix:@"TDCore" type:TDLogTypeError asynchronous:NO]; + } + } else { + NSMutableDictionary *attributes = [self keychainQueryWithAccount:key]; + attributes[(__bridge id)kSecValueData] = encodeData; + OSStatus statusCode = SecItemAdd((__bridge CFDictionaryRef)attributes, nil); + if (statusCode != noErr) { + [TDOSLog logMessage:@"Keychain Add Error" prefix:@"TDCore" type:TDLogTypeError asynchronous:NO]; + } + } + } +} + ++ (void)oldSaveItem:(nonnull NSString *)value forKey:(nonnull NSString *)key { + if (!key || !value) { + return; + } + NSData *encodeData = [value dataUsingEncoding:NSUTF8StringEncoding]; + @synchronized (self) { + NSString *originPassword = [self oldItemForKey:key]; + if (originPassword.length > 0) { + NSMutableDictionary *updateAttributes = [NSMutableDictionary dictionary]; + updateAttributes[(__bridge id)kSecValueData] = encodeData; + NSMutableDictionary *query = [self oldKeychainQueryWithAccount:key]; + OSStatus statusCode = SecItemUpdate((__bridge CFDictionaryRef)query,(__bridge CFDictionaryRef)updateAttributes); + if (statusCode != noErr) { + [TDOSLog logMessage:@"Keychain Update Error" prefix:@"TDCore" type:TDLogTypeError asynchronous:NO]; + } + } else { + NSMutableDictionary *attributes = [self oldKeychainQueryWithAccount:key]; + attributes[(__bridge id)kSecValueData] = encodeData; + OSStatus statusCode = SecItemAdd((__bridge CFDictionaryRef)attributes, nil); + if (statusCode != noErr) { + [TDOSLog logMessage:@"Keychain Add Error" prefix:@"TDCore" type:TDLogTypeError asynchronous:NO]; + } + } + } +} + ++ (nullable NSString *)itemForKey:(NSString *)key { + if (!key) { + return nil; + } + NSMutableDictionary *attributes = [self keychainQueryWithAccount:key]; + attributes[(__bridge id)kSecMatchLimit] = (__bridge id)(kSecMatchLimitOne); + attributes[(__bridge id)kSecReturnData] = (__bridge id)(kCFBooleanTrue); + NSString *result = nil; + @synchronized (self) { + CFTypeRef data = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)attributes,(CFTypeRef *)&data); + if (status == errSecSuccess) { + NSData *encodeData = [NSData dataWithData:(__bridge NSData *)data]; + if (data) { + CFRelease(data); + } + if (encodeData) { + result = [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding]; + } + } + } + return result; +} + ++ (nullable NSString *)oldItemForKey:(NSString *)key { + if (!key) { + return nil; + } + NSMutableDictionary *attributes = [self oldKeychainQueryWithAccount:key]; + attributes[(__bridge id)kSecMatchLimit] = (__bridge id)(kSecMatchLimitOne); + attributes[(__bridge id)kSecReturnData] = (__bridge id)(kCFBooleanTrue); + NSString *result = nil; + @synchronized (self) { + CFTypeRef data = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)attributes,(CFTypeRef *)&data); + if (status == errSecSuccess) { + NSData *encodeData = [NSData dataWithData:(__bridge NSData *)data]; + if (data) { + CFRelease(data); + } + if (encodeData) { + result = [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding]; + } + } + } + return result; +} + ++ (BOOL)deleteItemWithKey:(nonnull NSString *)key { + if (!key) { + return NO; + } + NSMutableDictionary *query = [self keychainQueryWithAccount:key]; + BOOL result = NO; + @synchronized (self) { + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query); + result = (status == errSecSuccess); + } + return result; +} + ++ (NSMutableDictionary *)keychainQueryWithAccount:(NSString *)account { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; + query[(__bridge id)kSecAttrService] = TDKeychainService; + query[(__bridge id)kSecAttrAccount] = account; + query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAfterFirstUnlock; + return query; +} + ++ (NSMutableDictionary *)oldKeychainQueryWithAccount:(NSString *)account { + NSMutableDictionary *query = [NSMutableDictionary dictionary]; + query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; + query[(__bridge id)kSecAttrService] = TDKeychainService; + query[(__bridge id)kSecAttrAccount] = account; + return query; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.m.meta new file mode 100644 index 0000000..29dc888 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Keychain/TDKeychainManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c874dd0d4a6a441dfa75ff9c52fccc71 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log.meta new file mode 100644 index 0000000..ec6afd8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6e4ed24660e144ff9a6c9eeefa27b193 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.h new file mode 100644 index 0000000..5b9ebcf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.h @@ -0,0 +1,22 @@ +// +// TDCoreLog.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/7/17. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +#define TDCORELOG(format, ...) [TDCoreLog printLog:(format), ##__VA_ARGS__] + +@interface TDCoreLog : NSObject + ++ (void)enableLog:(BOOL)enable; + ++ (void)printLog:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2); + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.h.meta new file mode 100644 index 0000000..be2b8ab --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 540badeeb1b654ce5b8152bfc867a074 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.m new file mode 100644 index 0000000..01609b5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.m @@ -0,0 +1,33 @@ +// +// TDCoreLog.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/7/17. +// + +#import "TDCoreLog.h" +#import "TDOSLog.h" + +static BOOL _logOn = YES; + +@implementation TDCoreLog + ++ (void)enableLog:(BOOL)enable { + _logOn = enable; +} + ++ (void)printLog:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { + if (_logOn == YES) { + if (format) { + va_list args; + va_start(args, format); + NSString *output = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + + NSString *prefix = @"TDCore"; + [TDOSLog logMessage:output prefix:prefix type:TDLogTypeInfo asynchronous:YES]; + } + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.m.meta new file mode 100644 index 0000000..7151b8f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDCoreLog.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: cb3ca0d5a513643c0ab3ef79ffc773fe +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.h new file mode 100644 index 0000000..7ae72da --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.h @@ -0,0 +1,17 @@ +// +// TDLogChannelConsole.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/22. +// + +#import +#import "TDLogChannelProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDLogChannelConsole : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.h.meta new file mode 100644 index 0000000..9eccbc9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: cb390acbdcf6d4214895f4dd81d23657 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.m new file mode 100644 index 0000000..c9bee94 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.m @@ -0,0 +1,62 @@ +// +// TDLogChannelConsole.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/22. +// + +#import "TDLogChannelConsole.h" +#import + +@interface TDLogChannelConsole () +@property (strong, nonatomic) os_log_t logger; + +@end + +@implementation TDLogChannelConsole + +- (instancetype)init +{ + self = [super init]; + if (self) { +#ifdef __IPHONE_10_0 + self.logger = os_log_create("cn.thinkingdata.analytics.log", "ThinkingData"); +#endif + } + return self; +} + +- (void)printMessage:(NSString *)message type:(TDLogType)type { + if (message == nil) { + return; + } + +#ifdef __IPHONE_10_0 + if (@available(iOS 10.0, *)) { + const char *msg = [message UTF8String]; + os_log_t logger = self.logger; + switch (type) { + case TDLogTypeDebug: + os_log_debug(logger, "%{public}s", msg); + break; + case TDLogTypeInfo: + os_log_info(logger, "%{public}s", msg); + break; + case TDLogTypeWarning: + os_log_error(logger, "%{public}s", msg); + break; + case TDLogTypeError: + os_log_error(logger, "%{public}s", msg); + break; + case TDLogTypeOff: + default: + break; + } + } +#else + NSLog(@"%@", message); +#endif +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.m.meta new file mode 100644 index 0000000..c69fb76 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelConsole.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 648394274314f4bd5bc062ae6b6bb6f4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelProtocol.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelProtocol.h new file mode 100644 index 0000000..499a524 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelProtocol.h @@ -0,0 +1,20 @@ +// +// TDLogChannelProtocol.h +// Pods +// +// Created by 杨雄 on 2024/1/22. +// + +#ifndef TDLogChannelProtocol_h +#define TDLogChannelProtocol_h + +#import +#import "TDLogConstant.h" + +@protocol TDLogChannleProtocol + +- (void)printMessage:(NSString *)message type:(TDLogType)type; + +@end + +#endif /* TDLogChannelProtocol_h */ diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelProtocol.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelProtocol.h.meta new file mode 100644 index 0000000..0d7c82a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogChannelProtocol.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4d09e21e074214737a1156d0f799d7b7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogConstant.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogConstant.h new file mode 100644 index 0000000..34eda2a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogConstant.h @@ -0,0 +1,21 @@ +// +// TDLogConstant.h +// Pods +// +// Created by 杨雄 on 2024/1/22. +// + +#ifndef TDLogConstant_h +#define TDLogConstant_h + +#import + +typedef NS_ENUM(NSUInteger, TDLogType) { + TDLogTypeOff = 0, + TDLogTypeError = 1 << 0, + TDLogTypeWarning = 1 << 1, + TDLogTypeInfo = 1 << 2, + TDLogTypeDebug = 1 << 3, +}; + +#endif /* TDLogConstant_h */ diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogConstant.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogConstant.h.meta new file mode 100644 index 0000000..916f501 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogConstant.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 76d3e619d0dd1413aa666c1dd25f9aa4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.h new file mode 100644 index 0000000..93af964 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.h @@ -0,0 +1,22 @@ +// +// TDLogMessage.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/22. +// + +#import +#import "TDLogConstant.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDLogMessage : NSObject +@property (nonatomic, copy) NSString *prefix; +@property (nonatomic, copy) NSString *message; +@property (nonatomic, assign) TDLogType type; + +- (TDLogMessage *)initWithMessage:(NSString *)message prefix:(nullable NSString *)prefix type:(TDLogType)type; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.h.meta new file mode 100644 index 0000000..3e35a26 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a17b2cd01a7304682bc8baabfb55f265 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.m new file mode 100644 index 0000000..2b22e0c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.m @@ -0,0 +1,21 @@ +// +// TDLogMessage.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/22. +// + +#import "TDLogMessage.h" + +@implementation TDLogMessage + +- (TDLogMessage *)initWithMessage:(NSString *)message prefix:(NSString *)prefix type:(TDLogType)type { + if (self = [super init]) { + self.prefix = prefix; + self.message = message; + self.type = type; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.m.meta new file mode 100644 index 0000000..840619d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDLogMessage.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9251627353083411db8d7bca9d8f8146 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.h new file mode 100644 index 0000000..e0f6cef --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.h @@ -0,0 +1,32 @@ +// +// TDOSLog.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/1/22. +// + +#import + +#if __has_include() +#import +#else +#import "TDLogChannelProtocol.h" +#endif + +#if __has_include() +#import +#else +#import "TDLogConstant.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDOSLog : NSObject + ++ (void)addLogConsumer:(id)consumer; + ++ (void)logMessage:(NSString *)message prefix:(nullable NSString *)prefix type:(TDLogType)type asynchronous:(BOOL)asynchronous; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.h.meta new file mode 100644 index 0000000..97aa235 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 92906c2bd1b4046979de56b5c6cc91bc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.m new file mode 100644 index 0000000..a1a935d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.m @@ -0,0 +1,117 @@ +// +// TDOSLog.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/1/22. +// + +#import "TDOSLog.h" +#import "TDLogChannelConsole.h" +#import "TDLogMessage.h" + +#ifndef DDLOG_MAX_QUEUE_SIZE + #define DDLOG_MAX_QUEUE_SIZE 1000 +#endif + +static dispatch_queue_t g_loggingQueue; +static dispatch_semaphore_t g_queueSemaphore; +static void *const GlobalLoggingQueueIdentityKey = (void *)&GlobalLoggingQueueIdentityKey; + +@interface TDOSLog () +@property (atomic, strong) NSMutableArray> *logConsumers; +@property (nonatomic, strong) dispatch_queue_t consoleLogQueue; +@property (nonatomic, strong) NSDateFormatter *dateFormatter; +@end + +@implementation TDOSLog + ++ (instancetype)sharedInstance { + static id sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + ++ (void)initialize { + static dispatch_once_t TDLogOnceToken; + dispatch_once(&TDLogOnceToken, ^{ + g_loggingQueue = dispatch_queue_create("cn.thinking.log", NULL); + + void *nonNullValue = GlobalLoggingQueueIdentityKey; + dispatch_queue_set_specific(g_loggingQueue, GlobalLoggingQueueIdentityKey, nonNullValue, NULL); + g_queueSemaphore = dispatch_semaphore_create(DDLOG_MAX_QUEUE_SIZE); + }); +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.logConsumers = [NSMutableArray array]; + [self.logConsumers addObject:[[TDLogChannelConsole alloc] init]]; + + self.dateFormatter = [[NSDateFormatter alloc] init]; + [self.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; + + const char *loggerQueueName = [@"cn.thinkingdata.analytics.osLogger" UTF8String]; + dispatch_queue_t loggerQueue = dispatch_queue_create(loggerQueueName, NULL); + self.consoleLogQueue = loggerQueue; + } + return self; +} + +// MARK: - Public method + ++ (void)addLogConsumer:(id)consumer { + dispatch_async(g_loggingQueue, ^{ + if ([consumer conformsToProtocol:@protocol(TDLogChannleProtocol)]) { + [[TDOSLog sharedInstance].logConsumers addObject:consumer]; + } + }); +} + ++ (void)logMessage:(NSString *)message prefix:(NSString *)prefix type:(TDLogType)type asynchronous:(BOOL)asynchronous { + TDLogMessage *logMessage = [[TDLogMessage alloc] initWithMessage:message prefix:prefix type:type]; + [self.sharedInstance queueLogMessage:logMessage asynchronously:asynchronous]; +} + +//MARK: - Private method + +- (void)queueLogMessage:(TDLogMessage *)logMessage asynchronously:(BOOL)asyncFlag { + dispatch_block_t logBlock = ^{ + dispatch_semaphore_wait(g_queueSemaphore, DISPATCH_TIME_FOREVER); + @autoreleasepool { + [self lt_log:logMessage]; + } + dispatch_semaphore_signal(g_queueSemaphore); + }; + + if (asyncFlag) { + dispatch_async(g_loggingQueue, logBlock); + } else if (dispatch_get_specific(GlobalLoggingQueueIdentityKey)) { + logBlock(); + } else { + dispatch_sync(g_loggingQueue, logBlock); + } +} + +- (void)lt_log:(TDLogMessage *)logMessage { + NSAssert(dispatch_get_specific(GlobalLoggingQueueIdentityKey), + @"This method should only be run on the logging thread/queue"); + + NSMutableString *logText = [[NSMutableString alloc] init]; + NSString *timeString = [self.dateFormatter stringFromDate:[NSDate date]]; + [logText appendFormat:@"[%@]", timeString]; + if (logMessage.prefix) { + [logText appendFormat:@"[%@]", logMessage.prefix]; + } + [logText appendFormat:@" %@", logMessage.message]; + + for (id consumer in self.logConsumers) { + [consumer printMessage:logText type:logMessage.type]; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.m.meta new file mode 100644 index 0000000..5b7337c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Log/TDOSLog.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: e9865184e38294362b713291b48f06b7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network.meta new file mode 100644 index 0000000..9b8d86e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2f04524b7ddbe4f50b01e03a4b14893a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.h new file mode 100644 index 0000000..21093ab --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.h @@ -0,0 +1,26 @@ +// +// TDNetworkReachability.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDNetworkReachability : NSObject + ++ (instancetype)shareInstance; + +- (void)startMonitoring; + +- (void)stopMonitoring; + +- (NSString *)networkState; + +- (nullable NSString *)carrier; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.h.meta new file mode 100644 index 0000000..10cc8c4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 232bba0170c5e4894aac72664982367f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.m new file mode 100644 index 0000000..7f4d4e7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.m @@ -0,0 +1,180 @@ +// +// TDNetworkReachability.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/15. +// + +#import "TDNetworkReachability.h" +#import +#import +#import +#import "TDNotificationManager+Networking.h" + +@interface TDNetworkReachability () +@property (atomic, assign) SCNetworkReachabilityRef reachability; +@property (nonatomic, assign) BOOL isWifi; +@property (nonatomic, assign) BOOL isWwan; +@property (nonatomic, strong) CTTelephonyNetworkInfo *td_TelephonyNetworkInfo; + +@end + +@implementation TDNetworkReachability + +#if TARGET_OS_IOS +static void ThinkingReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) { + TDNetworkReachability *instance = (__bridge TDNetworkReachability *)info; + if (instance && [instance isKindOfClass:[TDNetworkReachability class]]) { + [instance reachabilityChanged:flags]; + [TDNotificationManager postNetworkStatusChanged:[instance networkState]]; + } +} +#endif + +//MARK: - Public Methods + ++ (instancetype)shareInstance { + static dispatch_once_t onceToken; + static TDNetworkReachability *reachability = nil; + dispatch_once(&onceToken, ^{ + reachability = [[TDNetworkReachability alloc] init]; + }); + return reachability; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.td_TelephonyNetworkInfo = [[CTTelephonyNetworkInfo alloc] init]; + } + return self; +} + +- (NSString *)networkState { + if (self.isWifi) { + return @"WIFI"; + } else if (self.isWwan) { + return [self currentRadio]; + } else { + return @"NULL"; + } +} + +- (void)startMonitoring { + [self stopMonitoring]; + + SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL,"thinkingdata.cn"); + self.reachability = reachability; + + if (self.reachability != NULL) { + SCNetworkReachabilityFlags flags; + BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(self.reachability, &flags); + if (didRetrieveFlags) { + self.isWifi = (flags & kSCNetworkReachabilityFlagsReachable) && !(flags & kSCNetworkReachabilityFlagsIsWWAN); + self.isWwan = (flags & kSCNetworkReachabilityFlagsIsWWAN); + } + + SCNetworkReachabilityContext context = {0, (__bridge void *)self, NULL, NULL, NULL}; + if (SCNetworkReachabilitySetCallback(self.reachability, ThinkingReachabilityCallback, &context)) { + if (!SCNetworkReachabilityScheduleWithRunLoop(self.reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes)) { + SCNetworkReachabilitySetCallback(self.reachability, NULL, NULL); + } + } + } +} + +- (void)stopMonitoring { + if (!self.reachability) { + return; + } + SCNetworkReachabilityUnscheduleFromRunLoop(self.reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); +} + +//MARK: - Private Methods + +- (void)reachabilityChanged:(SCNetworkReachabilityFlags)flags { + self.isWifi = (flags & kSCNetworkReachabilityFlagsReachable) && !(flags & kSCNetworkReachabilityFlagsIsWWAN); + self.isWwan = (flags & kSCNetworkReachabilityFlagsIsWWAN); +} + +- (NSString *)currentRadio { + NSString *networkType = @"NULL"; + @try { + NSString *currentRadio = nil; +#ifdef __IPHONE_12_0 + if (@available(iOS 12.0, *)) { + NSDictionary *serviceCurrentRadio = [self.td_TelephonyNetworkInfo serviceCurrentRadioAccessTechnology]; + if ([serviceCurrentRadio isKindOfClass:[NSDictionary class]] && serviceCurrentRadio.allValues.count>0) { + currentRadio = serviceCurrentRadio.allValues[0]; + } + } +#endif + if (currentRadio == nil && [self.td_TelephonyNetworkInfo.currentRadioAccessTechnology isKindOfClass:[NSString class]]) { + currentRadio = self.td_TelephonyNetworkInfo.currentRadioAccessTechnology; + } + + if ([currentRadio isEqualToString:CTRadioAccessTechnologyLTE]) { + networkType = @"4G"; + } else if ([currentRadio isEqualToString:CTRadioAccessTechnologyeHRPD] || + [currentRadio isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] || + [currentRadio isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] || + [currentRadio isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] || + [currentRadio isEqualToString:CTRadioAccessTechnologyCDMA1x] || + [currentRadio isEqualToString:CTRadioAccessTechnologyHSUPA] || + [currentRadio isEqualToString:CTRadioAccessTechnologyHSDPA] || + [currentRadio isEqualToString:CTRadioAccessTechnologyWCDMA]) { + networkType = @"3G"; + } else if ([currentRadio isEqualToString:CTRadioAccessTechnologyEdge] || + [currentRadio isEqualToString:CTRadioAccessTechnologyGPRS]) { + networkType = @"2G"; + } +#ifdef __IPHONE_14_1 + else if (@available(iOS 14.1, *)) { + if ([currentRadio isKindOfClass:[NSString class]]) { + if([currentRadio isEqualToString:CTRadioAccessTechnologyNRNSA] || + [currentRadio isEqualToString:CTRadioAccessTechnologyNR]) { + networkType = @"5G"; + } + } + } +#endif + } @catch (NSException *exception) { +// TDLogError(@"%@: %@", self, exception); + } + + return networkType; +} + +- (nullable NSString *)carrier { +#ifdef __IPHONE_16_0 + return nil; +#else + CTCarrier *carrier = nil; + NSString *carrierName = @""; +#ifdef __IPHONE_12_0 + if (@available(iOS 12.0, *)) { + NSArray *carrierKeysArray = [self.td_TelephonyNetworkInfo.serviceSubscriberCellularProviders.allKeys sortedArrayUsingSelector:@selector(compare:)]; + carrier = self.td_TelephonyNetworkInfo.serviceSubscriberCellularProviders[carrierKeysArray.firstObject]; + if (!carrier.mobileNetworkCode) { + carrier = self.td_TelephonyNetworkInfo.serviceSubscriberCellularProviders[carrierKeysArray.lastObject]; + } + } +#endif + if (!carrier) { + carrier = [self.td_TelephonyNetworkInfo subscriberCellularProvider]; + } + + // System characteristics, when the SIM is not installed, the carrierName also has a value, here additionally add the judgment of whether MCC and MNC have values + // MCC, MNC, and isoCountryCode are nil when no SIM card is installed and not within the cellular service range + if (carrier.carrierName && + carrier.carrierName.length > 0 && + carrier.mobileNetworkCode && + carrier.mobileNetworkCode.length > 0) { + carrierName = carrier.carrierName; + } + return carrierName; +#endif +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.m.meta new file mode 100644 index 0000000..3b30514 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Network/TDNetworkReachability.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 94d9f886cb2114d6db9f5881a5bc6ed0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage.meta new file mode 100644 index 0000000..75cb000 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7e20b11921d6b4135899c0c8c7f122ee +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.h new file mode 100644 index 0000000..5fdf305 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.h @@ -0,0 +1,63 @@ +// +// TDNotificationManager+Analytics.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/12. +// + +#if __has_include() +#import +#else +#import "TDNotificationManager.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// init +extern NSString * const kAnalyticsNotificationNameInit; +// login +extern NSString * const kAnalyticsNotificationNameLogin; +// logout +extern NSString * const kAnalyticsNotificationNameLogout; +// set distinct id +extern NSString * const kAnalyticsNotificationNameSetDistinctId; +// app install event +extern NSString * const kAnalyticsNotificationNameAppInstall; +// track event +extern NSString * const kAnalyticsNotificationNameTrack; + +// params +extern NSString * const kAnalyticsNotificationParamsAppId; +extern NSString * const kAnalyticsNotificationParamsServerUrl; +extern NSString * const kAnalyticsNotificationParamsAccountId; +extern NSString * const kAnalyticsNotificationParamsDistinctId; +extern NSString * const kAnalyticsNotificationParamsEvent; + +@interface TDNotificationManager (Analytics) + +/// analytics init event +/// Observer will receive data: e.g. {"appId": "", "serverUrl": ""} ++ (void)postAnalyticsInitEventWithAppId:(nonnull NSString *)appId serverUrl:(nonnull NSString *)serverUrl; + +/// analytics login event +/// Observer will receive data: e.g. {"appId": "", "accountId": "", "distinctId": ""} ++ (void)postAnalyticsLoginEventWithAppId:(nonnull NSString *)appId accountId:(nonnull NSString *)accountId distinctId:(nonnull NSString *)distinctId; + +/// analytics logout event +/// Observer will receive data: e.g. {"appId": "", "distinctId": ""} ++ (void)postAnalyticsLogoutEventWithAppId:(nonnull NSString *)appId distinctId:(nonnull NSString *)distinctId; + +/// analytics set distinct id event +/// Observer will receive data: e.g. {"appId": "", "accountId": "", "distinctId": ""} ++ (void)postAnalyticsSetDistinctIdEventWithAppId:(nonnull NSString *)appId accountId:(nullable NSString *)accountId distinctId:(nonnull NSString *)distinctId; + +/// analytics app install event ++ (void)postAnalyticsAppInstallEventWithAppId:(NSString *)appId; + +/// analytics track event +/// Observer will receive data: e.g. {"appId": "", "event": ""} ++ (void)postAnalyticsTrackWithAppId:(nonnull NSString *)appId event:(nonnull NSDictionary *)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.h.meta new file mode 100644 index 0000000..21ae223 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5da19ae19dfaf4e589bf7453079d580c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.m new file mode 100644 index 0000000..8c7f205 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.m @@ -0,0 +1,101 @@ +// +// TDNotificationManager+Analytics.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/12. +// + +#import "TDNotificationManager+Analytics.h" + +NSString * const kAnalyticsNotificationNameInit = @"kAnalyticsNotificationNameInit"; +NSString * const kAnalyticsNotificationNameLogin = @"kAnalyticsNotificationNameLogin"; +NSString * const kAnalyticsNotificationNameLogout = @"kAnalyticsNotificationNameLogout"; +NSString * const kAnalyticsNotificationNameSetDistinctId = @"kAnalyticsNotificationNameSetDistinctId"; +NSString * const kAnalyticsNotificationNameAppInstall = @"kAnalyticsNotificationNameAppInstall"; +NSString * const kAnalyticsNotificationNameTrack = @"kAnalyticsNotificationNameTrack"; + +NSString * const kAnalyticsNotificationParamsAppId = @"appId"; +NSString * const kAnalyticsNotificationParamsServerUrl = @"serverUrl"; +NSString * const kAnalyticsNotificationParamsAccountId = @"accountId"; +NSString * const kAnalyticsNotificationParamsDistinctId = @"distinctId"; +NSString * const kAnalyticsNotificationParamsEvent = @"event"; + + +@implementation TDNotificationManager (Analytics) + ++ (void)postAnalyticsInitEventWithAppId:(NSString *)appId serverUrl:(NSString *)serverUrl { + if (appId.length == 0 || serverUrl.length == 0) { + return; + } + NSDictionary *userInfo = @{ + kAnalyticsNotificationParamsAppId: appId, + kAnalyticsNotificationParamsServerUrl: serverUrl + }; + [self postNotificationName:kAnalyticsNotificationNameInit object:nil userInfo:userInfo]; +} + ++ (void)postAnalyticsLoginEventWithAppId:(NSString *)appId accountId:(NSString *)accountId distinctId:(NSString *)distinctId { + if (appId.length == 0 || accountId.length == 0) { + return; + } + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:@{ + kAnalyticsNotificationParamsAppId: appId, + kAnalyticsNotificationParamsAccountId: accountId, + }]; + if (distinctId.length) { + userInfo[kAnalyticsNotificationParamsDistinctId] = distinctId; + } + [self postNotificationName:kAnalyticsNotificationNameLogin object:nil userInfo:userInfo]; +} + ++ (void)postAnalyticsLogoutEventWithAppId:(NSString *)appId distinctId:(NSString *)distinctId { + if (appId.length == 0) { + return; + } + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:@{ + kAnalyticsNotificationParamsAppId: appId, + }]; + if (distinctId.length) { + userInfo[kAnalyticsNotificationParamsDistinctId] = distinctId; + } + + [self postNotificationName:kAnalyticsNotificationNameLogout object:nil userInfo:userInfo]; +} + ++ (void)postAnalyticsSetDistinctIdEventWithAppId:(NSString *)appId accountId:(NSString *)accountId distinctId:(NSString *)distinctId { + if (appId.length == 0 || distinctId.length == 0) { + return; + } + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:@{ + kAnalyticsNotificationParamsAppId: appId, + kAnalyticsNotificationParamsDistinctId: distinctId, + }]; + if (accountId.length) { + userInfo[kAnalyticsNotificationParamsAccountId] = accountId; + } + + [self postNotificationName:kAnalyticsNotificationNameSetDistinctId object:nil userInfo:userInfo]; +} + ++ (void)postAnalyticsAppInstallEventWithAppId:(NSString *)appId { + if (appId.length == 0) { + return; + } + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:@{ + kAnalyticsNotificationParamsAppId: appId, + }]; + [self postNotificationName:kAnalyticsNotificationNameAppInstall object:nil userInfo:userInfo]; +} + ++ (void)postAnalyticsTrackWithAppId:(NSString *)appId event:(NSDictionary *)event { + if (appId.length == 0 || event.count == 0) { + return; + } + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:@{ + kAnalyticsNotificationParamsAppId: appId, + kAnalyticsNotificationParamsEvent: event, + }]; + [self postNotificationName:kAnalyticsNotificationNameTrack object:nil userInfo:userInfo]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.m.meta new file mode 100644 index 0000000..4aea6d1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Analytics.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 73e405d08084948cdb5b992f92d751f1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.h new file mode 100644 index 0000000..15e255e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.h @@ -0,0 +1,25 @@ +// +// TDNotificationManager+Core.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/6/27. +// + +#if __has_include() +#import +#else +#import "TDNotificationManager.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const kCoreNotificationNameCalibratedTimeSuccess; +extern NSString * const kCoreNotificationParamsCalibratedTimeNow; + +@interface TDNotificationManager (Core) + ++ (void)postCoreNotificationCalibratedTimeSuccess:(NSDate *)now; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.h.meta new file mode 100644 index 0000000..b408784 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 72056eed9d556463bb4cf7066654cd3d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.m new file mode 100644 index 0000000..96afdd4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.m @@ -0,0 +1,24 @@ +// +// TDNotificationManager+Core.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/6/27. +// + +#import "TDNotificationManager+Core.h" + +NSString * const kCoreNotificationNameCalibratedTimeSuccess = @"kCoreNotificationNameCalibratedTimeSuccess"; +NSString * const kCoreNotificationParamsCalibratedTimeNow = @"now"; + +@implementation TDNotificationManager (Core) + ++ (void)postCoreNotificationCalibratedTimeSuccess:(NSDate *)now { + if (![now isKindOfClass:NSDate.class]) { + return; + } + [self postNotificationName:kCoreNotificationNameCalibratedTimeSuccess object:nil userInfo:@{ + kCoreNotificationParamsCalibratedTimeNow: now + }]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.m.meta new file mode 100644 index 0000000..bb61440 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Core.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3157b4a348b8e466b9b0e1efe26fcae6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.h new file mode 100644 index 0000000..1c453bb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.h @@ -0,0 +1,25 @@ +// +// TDNotificationManager+Networking.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/15. +// + +#if __has_include() +#import +#else +#import "TDNotificationManager.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const kNetworkNotificationNameStatusChange; +extern NSString * const kNetworkNotificationParamsNetworkType; + +@interface TDNotificationManager (Networking) + ++ (void)postNetworkStatusChanged:(NSString *)networkStatus; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.h.meta new file mode 100644 index 0000000..d911015 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 47fd1e3d199b24b04bd6f24e8e1a9b61 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.m new file mode 100644 index 0000000..1fbef97 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.m @@ -0,0 +1,24 @@ +// +// TDNotificationManager+Networking.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/1/15. +// + +#import "TDNotificationManager+Networking.h" + +NSString * const kNetworkNotificationNameStatusChange = @"kNetworkNotificationNameStatusChange"; +NSString * const kNetworkNotificationParamsNetworkType = @"network"; + +@implementation TDNotificationManager (Networking) + ++ (void)postNetworkStatusChanged:(NSString *)networkStatus { + if (networkStatus.length == 0) { + return; + } + [self postNotificationName:kNetworkNotificationNameStatusChange object:nil userInfo:@{ + kNetworkNotificationParamsNetworkType: networkStatus + }]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.m.meta new file mode 100644 index 0000000..f4cd03b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+Networking.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1d9b5e7f0230b4d3dbee64255faf24c8 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.h new file mode 100644 index 0000000..9606a6c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.h @@ -0,0 +1,42 @@ +// +// TDNotificationManager+RemoteConfig.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/2. +// + +#if __has_include() +#import +#else +#import "TDNotificationManager.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const kRemoteConfigNotificationNameTemplateWillStop; +extern NSString * const kRemoteConfigNotificationNameTemplateFetchSuccess; +extern NSString * const kRemoteConfigNotificationNameTemplateFetchFailed; +extern NSString * const kRemoteConfigNotificationParamAppId; +extern NSString * const kRemoteConfigNotificationParamTemplateCode; +extern NSString * const kRemoteConfigNotificationParamClientUserId; +extern NSString * const kRemoteConfigNotificationParamTemplateInfo; +extern NSString * const kRemoteConfigNotificationParamErrorCode; +extern NSString * const kRemoteConfigNotificationParamIsDebug; + +extern NSString * const kRemoteConfigNotificationNameSystemConfigFetchSuccess; +extern NSString * const kRemoteConfigNotificationParamSystemConfig; + +@interface TDNotificationManager (RemoteConfig) + ++ (void)postRemoteConfigWillStopTemplateCode:(nonnull NSString *)templateCode appId:(nonnull NSString *)appId clientUserId:(nonnull NSString *)clientUserId; + ++ (void)postRemoteConfigFetchTemplateSuccessIsDebug:(BOOL)isDebug templateCode:(nonnull NSString *)templateCode appId:(nonnull NSString *)appId clientUserId:(nonnull NSString *)clientUserId templateInfo:(nonnull NSDictionary *)templateInfo; + ++ (void)postRemoteConfigFetchTemplateFailedIsDebug:(BOOL)isDebug templateCode:(nonnull NSString *)templateCode appId:(nonnull NSString *)appId clientUserId:(nonnull NSString *)clientUserId errorCode:(NSNumber *)errorCode; + ++ (void)postRemoteConfigFetchSystemConfigSuccessWithAppId:(nonnull NSString *)appId systemConfig:(nullable NSDictionary *)systemConfig; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.h.meta new file mode 100644 index 0000000..9e32820 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8e985713547844520bae1181966c0aed +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.m new file mode 100644 index 0000000..5f63c8f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.m @@ -0,0 +1,78 @@ +// +// TDNotificationManager+RemoteConfig.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/2. +// + +#import "TDNotificationManager+RemoteConfig.h" + +NSString * const kRemoteConfigNotificationNameTemplateWillStop = @"kRemoteConfigNotificationNameTemplateWillStop"; +NSString * const kRemoteConfigNotificationNameTemplateFetchSuccess = @"kRemoteConfigNotificationNameTemplateFetchSuccess"; +NSString * const kRemoteConfigNotificationNameTemplateFetchFailed = @"kRemoteConfigNotificationNameTemplateFetchFailed"; +NSString * const kRemoteConfigNotificationParamAppId = @"appId"; +NSString * const kRemoteConfigNotificationParamTemplateCode = @"templateCode"; +NSString * const kRemoteConfigNotificationParamClientUserId = @"clientUserId"; +NSString * const kRemoteConfigNotificationParamTemplateInfo = @"templateInfo"; +NSString * const kRemoteConfigNotificationParamErrorCode = @"errorCode"; +NSString * const kRemoteConfigNotificationParamIsDebug = @"isDebug"; + +NSString * const kRemoteConfigNotificationNameSystemConfigFetchSuccess = @"kRemoteConfigNotificationNameSystemConfigFetchSuccess"; +NSString * const kRemoteConfigNotificationParamSystemConfig = @"kRemoteConfigNotificationParamSystemConfig"; + +@implementation TDNotificationManager (RemoteConfig) + ++ (void)postRemoteConfigWillStopTemplateCode:(NSString *)templateCode appId:(NSString *)appId clientUserId:(NSString *)clientUserId { + if (templateCode.length == 0 || appId.length == 0 || clientUserId.length == 0) { + return; + } + NSDictionary *userInfo = @{ + kRemoteConfigNotificationParamAppId: appId, + kRemoteConfigNotificationParamTemplateCode: templateCode, + kRemoteConfigNotificationParamClientUserId: clientUserId + }; + [self postNotificationName:kRemoteConfigNotificationNameTemplateWillStop object:nil userInfo:userInfo]; +} + ++ (void)postRemoteConfigFetchTemplateSuccessIsDebug:(BOOL)isDebug templateCode:(NSString *)templateCode appId:(NSString *)appId clientUserId:(NSString *)clientUserId templateInfo:(NSDictionary *)templateInfo { + if (templateCode.length == 0 || appId.length == 0 || clientUserId.length == 0 || templateInfo.count == 0) { + return; + } + NSDictionary *userInfo = @{ + kRemoteConfigNotificationParamAppId: appId, + kRemoteConfigNotificationParamTemplateCode: templateCode, + kRemoteConfigNotificationParamClientUserId: clientUserId, + kRemoteConfigNotificationParamTemplateInfo: templateInfo, + kRemoteConfigNotificationParamIsDebug: @(isDebug), + }; + [self postNotificationName:kRemoteConfigNotificationNameTemplateFetchSuccess object:nil userInfo:userInfo]; +} + ++ (void)postRemoteConfigFetchTemplateFailedIsDebug:(BOOL)isDebug templateCode:(NSString *)templateCode appId:(NSString *)appId clientUserId:(NSString *)clientUserId errorCode:(NSNumber *)errorCode { + if (templateCode.length == 0 || appId.length == 0 || clientUserId.length == 0 || errorCode == nil) { + return; + } + NSDictionary *userInfo = @{ + kRemoteConfigNotificationParamAppId: appId, + kRemoteConfigNotificationParamTemplateCode: templateCode, + kRemoteConfigNotificationParamClientUserId: clientUserId, + kRemoteConfigNotificationParamErrorCode: errorCode, + kRemoteConfigNotificationParamIsDebug: @(isDebug), + }; + [self postNotificationName:kRemoteConfigNotificationNameTemplateFetchFailed object:nil userInfo:userInfo]; +} + ++ (void)postRemoteConfigFetchSystemConfigSuccessWithAppId:(NSString *)appId systemConfig:(nullable NSDictionary *)systemConfig { + if (appId.length == 0) { + return; + } + NSMutableDictionary *userInfo = [@{ + kRemoteConfigNotificationParamAppId: appId, + } mutableCopy]; + if ([systemConfig isKindOfClass:NSDictionary.class]) { + userInfo[kRemoteConfigNotificationParamSystemConfig] = systemConfig; + } + [self postNotificationName:kRemoteConfigNotificationNameSystemConfigFetchSuccess object:nil userInfo:userInfo]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.m.meta new file mode 100644 index 0000000..7588048 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager+RemoteConfig.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 00da302b023aa425480f00bb781ae32b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.h new file mode 100644 index 0000000..a9b7576 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.h @@ -0,0 +1,18 @@ +// +// TDNotificationManager.h +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/1/12. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDNotificationManager : NSObject + ++ (void)postNotificationName:(nonnull NSString *)name object:(nullable id)object userInfo:(nullable NSDictionary *)userInfo; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.h.meta new file mode 100644 index 0000000..58268f3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d85a39f4be406485fbbf889af81cf5dc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.m new file mode 100644 index 0000000..cbabd52 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.m @@ -0,0 +1,16 @@ +// +// TDNotificationManager.m +// Pods-DevelopProgram +// +// Created by 杨雄 on 2024/1/12. +// + +#import "TDNotificationManager.h" + +@implementation TDNotificationManager + ++ (void)postNotificationName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo { + [[NSNotificationCenter defaultCenter] postNotificationName:name object:object userInfo:userInfo]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.m.meta new file mode 100644 index 0000000..4fc2182 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/NotificationManage/TDNotificationManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: aa7107ac4deee4cd2af0bc5c04521c4d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router.meta new file mode 100644 index 0000000..17d63dd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 46a327f0a2cb94432b1db1cfb4047bd4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.h new file mode 100644 index 0000000..d13db7a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.h @@ -0,0 +1,48 @@ +// +// TDMediator+Analytics.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/6. +// + +#if __has_include() +#import +#else +#import "TDMediator.h" +#endif + +#if __has_include() +#import +#else +#import "TDSettings.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const kTDMediatorTargetAnalytics; + +@interface TDMediator (Analytics) + +- (void)tdAnalyticsInitWithSettings:(nullable TDSettings *)settings; + +- (nullable NSString *)tdAnalyticsGetAccountIdWithAppId:(nullable NSString *)appId; + +- (nullable NSString *)tdAnalyticsGetDistinctIdWithAppId:(nullable NSString *)appId; + +- (void)tdAnalyticsTrackEvent:(nonnull NSString *)eventName properties:(nullable NSDictionary *)properties appId:(nullable NSString *)appId; + +- (void)tdAnalyticsUserSetProperties:(nonnull NSDictionary *)properties appId:(nullable NSString *)appId; + +- (nullable NSDictionary *)tdAnalyticsGetPresetPropertiesWithAppId:(nullable NSString *)appId; + +- (void)tdAnalyticsTrackDebugEvent:(nonnull NSString *)eventName properties:(nullable NSDictionary *)properties appId:(nullable NSString *)appId; + +- (BOOL)tdAnalyticsGetEnableAutoPushWithAppId:(nullable NSString *)appId; + +- (NSArray *)tdAnalyticsGetAllAppIds; + +- (nullable NSString *)tdAnalyticsGetSDKVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.h.meta new file mode 100644 index 0000000..d32f3f6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ce32dad599f8d4f3bbff213ed9c9750b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.m new file mode 100644 index 0000000..eca78b5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.m @@ -0,0 +1,118 @@ +// +// TDMediator+Analytics.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/6. +// + +#import "TDMediator+Analytics.h" + +NSString * const kTDMediatorTargetAnalytics = @"Analytics"; + +NSString * const kTDMediatorTargetAnalyticsActionNativeInit = @"nativeInitWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeGetAccountId = @"nativeGetAccountIdWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeGetDistinctId = @"nativeGetDistinctIdWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeGetPresetProperties = @"nativeGetPresetPropertiesWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeTrackEvent = @"nativeTrackEventWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeUserSet = @"nativeUserSetWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeTrackDebugEvent = @"nativeTrackDebugEventWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeGetEnableAutoPush = @"nativeGetEnableAutoPushWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeGetAllAppIds = @"nativeGetAllAppIdsWithParams"; +NSString * const kTDMediatorTargetAnalyticsActionNativeGetSDKVersion = @"nativeGetSDKVersionWithParams"; + +@implementation TDMediator (Analytics) + +- (void)tdAnalyticsInitWithSettings:(TDSettings *)settings { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (settings) { + params[@"settings"] = settings; + } + [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeInit params:params shouldCacheTarget:NO]; +} + +- (nullable NSString *)tdAnalyticsGetAccountIdWithAppId:(nullable NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId) { + params[@"appId"] = appId; + } + NSString *accountId = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeGetAccountId params:params shouldCacheTarget:NO]; + return accountId; +} + +- (nullable NSString *)tdAnalyticsGetDistinctIdWithAppId:(nullable NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId) { + params[@"appId"] = appId; + } + NSString *distinctId = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeGetDistinctId params:params shouldCacheTarget:NO]; + return distinctId; +} + +- (void)tdAnalyticsTrackEvent:(nonnull NSString *)eventName properties:(nullable NSDictionary *)properties appId:(nullable NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId) { + params[@"appId"] = appId; + } + if (eventName) { + params[@"eventName"] = eventName; + } + if (properties) { + params[@"properties"] = properties; + } + [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeTrackEvent params:params shouldCacheTarget:NO needModuleReady:YES]; +} + +- (void)tdAnalyticsUserSetProperties:(nonnull NSDictionary *)properties appId:(nullable NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId) { + params[@"appId"] = appId; + } + if (properties) { + params[@"properties"] = properties; + } + [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeUserSet params:params shouldCacheTarget:NO needModuleReady:YES]; +} + +- (nullable NSDictionary *)tdAnalyticsGetPresetPropertiesWithAppId:(NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId) { + params[@"appId"] = appId; + } + NSDictionary *dict = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeGetPresetProperties params:params shouldCacheTarget:NO]; + return dict; +} + +- (void)tdAnalyticsTrackDebugEvent:(NSString *)eventName properties:(NSDictionary *)properties appId:(NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId) { + params[@"appId"] = appId; + } + if (eventName) { + params[@"eventName"] = eventName; + } + if (properties) { + params[@"properties"] = properties; + } + [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeTrackDebugEvent params:params shouldCacheTarget:NO needModuleReady:YES]; +} + +- (BOOL)tdAnalyticsGetEnableAutoPushWithAppId:(NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId) { + params[@"appId"] = appId; + } + BOOL enableAutoPush = [[[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeGetEnableAutoPush params:params shouldCacheTarget:NO] boolValue]; + return enableAutoPush; +} + +- (NSArray *)tdAnalyticsGetAllAppIds { + NSArray *appIds = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeGetAllAppIds params:nil shouldCacheTarget:NO]; + return appIds; +} + +- (nullable NSString *)tdAnalyticsGetSDKVersion { + NSString *version = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetAnalytics action:kTDMediatorTargetAnalyticsActionNativeGetSDKVersion params:nil shouldCacheTarget:NO]; + return version; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.m.meta new file mode 100644 index 0000000..904ee0b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Analytics.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: de92d976bf5b745ab83a18249cdc4c61 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.h new file mode 100644 index 0000000..9eceecd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.h @@ -0,0 +1,39 @@ +// +// TDMediator+RemoteConfig.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/6. +// + +#if __has_include() +#import +#else +#import "TDMediator.h" +#endif + +#if __has_include() +#import +#else +#import "TDSettings.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDMediator (RemoteConfig) + +- (void)tdRemoteConfigInitWithSettings:(nonnull TDSettings *)settings; + +- (nullable NSString *)tdRemoteConfigGetClientUserIdWithAccountId:(nullable NSString *)accountId distinctId:(nullable NSString *)distinctId appId:(nonnull NSString *)appId; + +- (nullable NSDictionary *)tdRemoteConfigGetApplyValueWithAppId:(nonnull NSString *)appId templateCode:(nullable NSString *)code; + +- (nullable NSDictionary *)tdRemoteConfigGetSystemConfigWithAppId:(nonnull NSString *)appId; + +- (BOOL)tdRemoteConfigIsSDKCloseWithAppId:(nonnull NSString *)appId; + +- (void)tdRemoteConfigFetchTemplateWithAppId:(nonnull NSString *)appId templateCode:(nullable NSString *)code; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.h.meta new file mode 100644 index 0000000..31b5a18 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9f7b2aeb76f62465f920e18fcb4be56d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.m new file mode 100644 index 0000000..5bcbb58 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.m @@ -0,0 +1,85 @@ +// +// TDMediator+RemoteConfig.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/6. +// + +#import "TDMediator+RemoteConfig.h" + +NSString * const kTDMediatorTargetRemoteConfig = @"RemoteConfig"; + +NSString * const kTDMediatorTargetRemoteConfigActionNativeInit = @"nativeInitWithParams"; +NSString * const kTDMediatorTargetRemoteConfigActionNativeGetClientUserId = @"nativeGetClientUserIdWithParams"; +NSString * const kTDMediatorTargetRemoteConfigActionNativeGetApplyValue = @"nativeGetApplyValueWithParams"; +NSString * const kTDMediatorTargetRemoteConfigActionNativeGetSystemConfig = @"nativeGetSystemConfigWithParams"; +NSString * const kTDMediatorTargetRemoteConfigActionNativeIsSDKClose = @"nativeIsSDKCloseWithParams"; +NSString * const kTDMediatorTargetRemoteConfigActionNativeFetchTemplateInfo = @"nativeFetchTemplateInfoWithParams"; + +@implementation TDMediator (RemoteConfig) + +- (void)tdRemoteConfigInitWithSettings:(TDSettings *)settings { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (settings) { + params[@"settings"] = settings; + } + [[TDMediator sharedInstance] performTarget:kTDMediatorTargetRemoteConfig action:kTDMediatorTargetRemoteConfigActionNativeInit params:params shouldCacheTarget:NO]; +} + +- (NSString *)tdRemoteConfigGetClientUserIdWithAccountId:(NSString *)accountId distinctId:(NSString *)distinctId appId:(nonnull NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (accountId.length) { + params[@"accountId"] = accountId; + } + if (distinctId.length) { + params[@"distinctId"] = distinctId; + } + if (appId.length) { + params[@"appId"] = appId; + } + NSString *userId = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetRemoteConfig action:kTDMediatorTargetRemoteConfigActionNativeGetClientUserId params:params shouldCacheTarget:NO]; + return userId; +} + +- (NSDictionary *)tdRemoteConfigGetApplyValueWithAppId:(NSString *)appId templateCode:(NSString *)code { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId.length) { + params[@"appId"] = appId; + } + if (code.length) { + params[@"templateCode"] = code; + } + NSDictionary *dict = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetRemoteConfig action:kTDMediatorTargetRemoteConfigActionNativeGetApplyValue params:params shouldCacheTarget:NO]; + return dict; +} + +- (NSDictionary *)tdRemoteConfigGetSystemConfigWithAppId:(NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId.length) { + params[@"appId"] = appId; + } + NSDictionary *dict = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetRemoteConfig action:kTDMediatorTargetRemoteConfigActionNativeGetSystemConfig params:params shouldCacheTarget:NO]; + return dict; +} + +- (BOOL)tdRemoteConfigIsSDKCloseWithAppId:(NSString *)appId { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId.length) { + params[@"appId"] = appId; + } + NSNumber *value = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetRemoteConfig action:kTDMediatorTargetRemoteConfigActionNativeIsSDKClose params:params shouldCacheTarget:NO]; + return value.boolValue; +} + +- (void)tdRemoteConfigFetchTemplateWithAppId:(NSString *)appId templateCode:(NSString *)code { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (appId.length) { + params[@"appId"] = appId; + } + if (code.length) { + params[@"templateCode"] = code; + } + [[TDMediator sharedInstance] performTarget:kTDMediatorTargetRemoteConfig action:kTDMediatorTargetRemoteConfigActionNativeFetchTemplateInfo params:params shouldCacheTarget:NO]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.m.meta new file mode 100644 index 0000000..704c5a1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+RemoteConfig.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: afd38c24134d54299b338eefab26b31d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.h new file mode 100644 index 0000000..c04075d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.h @@ -0,0 +1,30 @@ +// +// TDMediator+Strategy.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/21. +// + +#if __has_include() +#import +#else +#import "TDMediator.h" +#endif + +#if __has_include() +#import +#else +#import "TDSettings.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDMediator (Strategy) + +- (void)tdStrategyInitWithSettings:(nullable TDSettings *)settings; + +- (nullable NSString *)tdStrategyGetSDKVersion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.h.meta new file mode 100644 index 0000000..3fdb841 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8221ed81aecc44d019af92a93708a73c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.m new file mode 100644 index 0000000..dbb05b9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.m @@ -0,0 +1,33 @@ +// +// TDMediator+Strategy.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/21. +// + +#import "TDMediator+Strategy.h" + +NSString * const kTDMediatorTargetStrategy = @"Strategy"; + +NSString * const kTDMediatorTargetStrategyActionNativeInit = @"nativeInitWithParams"; +NSString * const kTDMediatorTargetStrategyActionNativeGetSDKVersion = @"nativeGetSDKVersionWithParams"; + +@implementation TDMediator (Strategy) + +- (void)tdStrategyInitWithSettings:(TDSettings *)settings { + NSMutableDictionary *params = [NSMutableDictionary dictionary]; + if (settings) { + params[@"settings"] = settings; + } + [[TDMediator sharedInstance] performTarget:kTDMediatorTargetStrategy action:kTDMediatorTargetStrategyActionNativeInit params:params shouldCacheTarget:NO]; +} + +- (NSString *)tdStrategyGetSDKVersion { + NSString *version = [[TDMediator sharedInstance] performTarget:kTDMediatorTargetStrategy action:kTDMediatorTargetStrategyActionNativeGetSDKVersion params:nil shouldCacheTarget:NO]; + if ([version isKindOfClass:NSString.class]) { + return version; + } + return nil; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.m.meta new file mode 100644 index 0000000..23391be --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator+Strategy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f40cfaf9c3c9f4aeab983e8a41bcaba6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.h new file mode 100644 index 0000000..e9e71d5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.h @@ -0,0 +1,32 @@ +// +// TDMediator.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * _Nonnull const kTDMediatorParamsKeySwiftTargetModuleName; + +@interface TDMediator : NSObject + ++ (instancetype)sharedInstance; + +- (void)registerSuccessWithTargetName:(nonnull NSString *)targetName; + +- (id _Nullable)performActionWithUrl:(NSURL * _Nullable)url completion:(void(^_Nullable)(NSDictionary * _Nullable info))completion; + +- (id _Nullable)performTarget:(NSString * _Nonnull)targetName action:(NSString * _Nonnull)actionName params:(NSDictionary * _Nullable)params shouldCacheTarget:(BOOL)shouldCacheTarget; + +- (id _Nullable)performTarget:(NSString * _Nonnull)targetName action:(NSString * _Nonnull)actionName params:(NSDictionary * _Nullable)params shouldCacheTarget:(BOOL)shouldCacheTarget needModuleReady:(BOOL)needModuleReady; + +- (void)releaseCachedTargetWithFullTargetName:(NSString * _Nullable)fullTargetName; + +- (BOOL)check:(NSString * _Nullable)targetName moduleName:(NSString * _Nullable)moduleName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.h.meta new file mode 100644 index 0000000..542d315 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6e84f72bcd5974d1e9a335308e8b69eb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.m new file mode 100644 index 0000000..564892a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.m @@ -0,0 +1,289 @@ +// +// TDMediator.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/3/6. +// + +#import "TDMediator.h" +#import "TDCoreLog.h" + +NSString * const kTDMediatorParamsKeySwiftTargetModuleName = @"kTDMediatorParamsKeySwiftTargetModuleName"; + +@interface TDMediatorPerformInstance : NSObject +@property (nonatomic, copy) NSString *targetName; +@property (nonatomic, copy) NSString *actionName; +@property (nonatomic, strong) NSDictionary *params; + +@end + +@implementation TDMediatorPerformInstance +@end + + +@interface TDMediator () +@property (nonatomic, strong) NSMutableDictionary *cachedTarget; +@property (nonatomic, strong) NSMutableArray *registerTargetNames; +@property (nonatomic, strong) NSMutableDictionary *> *cachedPerformInstance; + +@end + +@implementation TDMediator + ++ (instancetype)sharedInstance { + static TDMediator *mediator; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + mediator = [[TDMediator alloc] init]; + }); + return mediator; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.cachedTarget = [[NSMutableDictionary alloc] init]; + self.registerTargetNames = [NSMutableArray array]; + self.cachedPerformInstance = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)registerSuccessWithTargetName:(NSString *)targetName { + if ([targetName isKindOfClass:NSString.class] && targetName.length > 0) { + @synchronized (self) { + [self.registerTargetNames addObject:targetName]; + NSMutableArray *cached = self.cachedPerformInstance[targetName]; + for (TDMediatorPerformInstance *instance in cached) { + [self performTarget:instance.targetName action:instance.actionName params:instance.params shouldCacheTarget:NO]; + } + self.cachedPerformInstance[targetName] = [NSMutableArray array]; + } + } +} + +/// call by url +/// - Parameters: +/// - url: scheme://[target]/[action]?[params] e.g. aaa://targetA/actionB?id=1234 +/// - completion: completion description +- (id)performActionWithUrl:(NSURL *)url completion:(void (^)(NSDictionary * _Nullable))completion { + if (url == nil||![url isKindOfClass:[NSURL class]]) { + return nil; + } + + NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; + NSURLComponents *urlComponents = [[NSURLComponents alloc] initWithString:url.absoluteString]; + [urlComponents.queryItems enumerateObjectsUsingBlock:^(NSURLQueryItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (obj.value&&obj.name) { + [params setObject:obj.value forKey:obj.name]; + } + }]; + + // refuse calls apis which only for local through remote url + NSString *actionName = [url.path stringByReplacingOccurrencesOfString:@"/" withString:@""]; + if ([actionName hasPrefix:@"native"]) { + return @(NO); + } + + id result = [self performTarget:url.host action:actionName params:params shouldCacheTarget:NO]; + if (completion) { + if (result) { + completion(@{@"result":result}); + } else { + completion(nil); + } + } + return result; +} + +- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget { + return [self performTarget:targetName action:actionName params:params shouldCacheTarget:shouldCacheTarget needModuleReady:NO]; +} + +- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget needModuleReady:(BOOL)needModuleReady { + if (targetName == nil || actionName == nil) { + return nil; + } + + if (needModuleReady) { + @synchronized (self) { + if (![self.registerTargetNames containsObject:targetName]) { + NSMutableArray *cached = self.cachedPerformInstance[targetName]; + if (!cached) { + cached = [NSMutableArray array]; + self.cachedPerformInstance[targetName] = cached; + } + TDMediatorPerformInstance *instance = [[TDMediatorPerformInstance alloc] init]; + instance.targetName = targetName; + instance.actionName = actionName; + instance.params = params; + if (cached.count < 100) { + [cached addObject:instance]; + [TDCoreLog printLog:@"Router cache successed. target: %@, action: %@, params: %@", targetName, actionName, params]; + } else { + [TDCoreLog printLog:@"Router Cache fulled. Drop it. target: %@, action: %@, params: %@", targetName, actionName, params]; + } + return nil; + } + } + } + + NSString *swiftModuleName = params[kTDMediatorParamsKeySwiftTargetModuleName]; + + // generate target + NSString *targetClassString = nil; + if (swiftModuleName.length > 0) { + targetClassString = [NSString stringWithFormat:@"%@.Target_%@", swiftModuleName, targetName]; + } else { + targetClassString = [NSString stringWithFormat:@"Target_%@", targetName]; + } + NSObject *target = [self safeFetchCachedTarget:targetClassString]; + if (target == nil) { + Class targetClass = NSClassFromString(targetClassString); + target = [[targetClass alloc] init]; + } + + // generate action + NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName]; + SEL action = NSSelectorFromString(actionString); + + if (target == nil) { + // process no target-action calling + [self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params]; + return nil; + } + + if (shouldCacheTarget) { + [self safeSetCachedTarget:target key:targetClassString]; + } + + if ([target respondsToSelector:action]) { + return [self safePerformAction:action target:target params:params]; + } else { + // call default function "notFound:" in target when action is not found + SEL action = NSSelectorFromString(@"notFound:"); + if ([target respondsToSelector:action]) { + return [self safePerformAction:action target:target params:params]; + } else { + // process no target-action calling + [self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params]; + @synchronized (self) { + [self.cachedTarget removeObjectForKey:targetClassString]; + } + return nil; + } + } +} + +/// release cache +/// - Parameter fullTargetName: OC: e.g. Target_XXX. Swift: e.g. XXXModule.Target_YYY +- (void)releaseCachedTargetWithFullTargetName:(NSString *)fullTargetName { + if (fullTargetName == nil) { + return; + } + @synchronized (self) { + [self.cachedTarget removeObjectForKey:fullTargetName]; + } +} + +- (BOOL)check:(NSString * _Nullable)targetName moduleName:(NSString * _Nullable)moduleName{ + if (moduleName.length > 0) { + return NSClassFromString([NSString stringWithFormat:@"%@.Target_%@", moduleName, targetName]) != nil; + } else { + return NSClassFromString([NSString stringWithFormat:@"Target_%@", targetName]) != nil; + } +} + +- (void)NoTargetActionResponseWithTargetString:(NSString *)targetString selectorString:(NSString *)selectorString originParams:(NSDictionary *)originParams { + SEL action = NSSelectorFromString(@"Action_response:"); + NSObject *target = [[NSClassFromString(@"Target_NoTargetAction") alloc] init]; + + NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; + params[@"originParams"] = originParams; + params[@"targetString"] = targetString; + params[@"selectorString"] = selectorString; + + [self safePerformAction:action target:target params:params]; +} + +- (id)safePerformAction:(SEL)action target:(NSObject *)target params:(NSDictionary *)params { + NSMethodSignature *methodSig = [target methodSignatureForSelector:action]; + if (methodSig == nil) { + return nil; + } + const char *retType = [methodSig methodReturnType]; + + if (strcmp(retType, @encode(void)) == 0) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; + [invocation setArgument:¶ms atIndex:2]; + [invocation setSelector:action]; + [invocation setTarget:target]; + [invocation invoke]; + return nil; + } + + if (strcmp(retType, @encode(NSInteger)) == 0) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; + [invocation setArgument:¶ms atIndex:2]; + [invocation setSelector:action]; + [invocation setTarget:target]; + [invocation invoke]; + NSInteger result = 0; + [invocation getReturnValue:&result]; + return @(result); + } + + if (strcmp(retType, @encode(BOOL)) == 0) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; + [invocation setArgument:¶ms atIndex:2]; + [invocation setSelector:action]; + [invocation setTarget:target]; + [invocation invoke]; + BOOL result = 0; + [invocation getReturnValue:&result]; + return @(result); + } + + if (strcmp(retType, @encode(CGFloat)) == 0) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; + [invocation setArgument:¶ms atIndex:2]; + [invocation setSelector:action]; + [invocation setTarget:target]; + [invocation invoke]; + CGFloat result = 0; + [invocation getReturnValue:&result]; + return @(result); + } + + if (strcmp(retType, @encode(NSUInteger)) == 0) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; + [invocation setArgument:¶ms atIndex:2]; + [invocation setSelector:action]; + [invocation setTarget:target]; + [invocation invoke]; + NSUInteger result = 0; + [invocation getReturnValue:&result]; + return @(result); + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + return [target performSelector:action withObject:params]; +#pragma clang diagnostic pop +} + +#pragma mark - getters and setters + +- (NSObject *)safeFetchCachedTarget:(NSString *)key { + @synchronized (self) { + return self.cachedTarget[key]; + } +} + +- (void)safeSetCachedTarget:(NSObject *)target key:(NSString *)key { + @synchronized (self) { + self.cachedTarget[key] = target; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.m.meta new file mode 100644 index 0000000..dc7d87d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/Router/TDMediator.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 66dbbf5977104487e80cdd049af4d62e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.h new file mode 100644 index 0000000..c3db0e0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.h @@ -0,0 +1,35 @@ +// +// TDApp.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/9/9. +// + +#import + +#if __has_include() +#import +#else +#import "TDSettings.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDApp : NSObject + +/// Initializes from a local file, named 'td_settings.json' ++ (void)start; + +/// Initializes with app id and server url +/// - Parameters: +/// - appId: The app id of your TE project +/// - serverUrl: The server url of your TE project ++ (void)startWithAppId:(NSString *)appId serverUrl:(NSString *)serverUrl; + +/// Initializes with SDK config +/// - Parameter settings: More specific profile ++ (void)startWithSetting:(TDSettings *)settings; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.h.meta new file mode 100644 index 0000000..409ca8e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 77e496978beff4f1282dc47e174c00a5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.m new file mode 100644 index 0000000..813801b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.m @@ -0,0 +1,81 @@ +// +// TDApp.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/9/9. +// + +#import "TDApp.h" +#import "TDJSONUtil.h" +#import "TDMediator+Analytics.h" +#import "TDMediator+RemoteConfig.h" +#import "TDMediator+Strategy.h" +#import "TDSettingsPrivate.h" +#import "TDCoreLog.h" +#import "NSString+TDCore.h" +#import "NSUrl+TDCore.h" + +@implementation TDApp + ++ (void)start { + NSString *path = [[NSBundle mainBundle] pathForResource:@"td_settings" ofType:@"json"]; + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + NSData *data = [NSData dataWithContentsOfFile:path]; + NSArray *array = [TDJSONUtil jsonForData:data]; + if ([array isKindOfClass:NSArray.class]) { + for (NSDictionary *projectInfo in array) { + if ([projectInfo isKindOfClass:NSDictionary.class]) { + TDSettings *settings = [[TDSettings alloc] initWithDictionary:projectInfo]; + [self startWithSetting:settings]; + } + } + } else { + TDCORELOG(@"td_settings.json format is error"); + } + } else { + TDCORELOG(@"td_settings.json is not found"); + } +} + ++ (void)startWithAppId:(NSString *)appId serverUrl:(NSString *)serverUrl { + TDSettings *settings = [[TDSettings alloc] init]; + settings.appId = appId; + settings.serverUrl = serverUrl; + [TDApp startWithSetting:settings]; +} + ++ (void)startWithSetting:(TDSettings *)settings { + // TDCore 日志打印开关 + [TDCoreLog enableLog:settings.enableLog]; + + NSString *appId = nil; + if ([settings.appId isKindOfClass:NSString.class]) { + appId = [settings.appId td_trim]; + } + if (appId.length == 0) { + TDCORELOG(@"The app id is invalid"); + return; + } else { + settings.appId = appId; + } + + NSString *serverUrl = nil; + if ([settings.serverUrl isKindOfClass:NSString.class]) { + serverUrl = [NSURL td_baseUrlStringWithString:settings.serverUrl]; + } + if (serverUrl.length == 0) { + TDCORELOG(@"The server url is invalid"); + return; + } else { + settings.serverUrl = serverUrl; + } + + // 初始化采集SDK + [[TDMediator sharedInstance] tdAnalyticsInitWithSettings:settings]; + // 初始化RemoteConfig SDK + [[TDMediator sharedInstance] tdRemoteConfigInitWithSettings:settings]; + // 初始化策略SDK + [[TDMediator sharedInstance] tdStrategyInitWithSettings:settings]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.m.meta new file mode 100644 index 0000000..b5b374d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDApp.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 165f9a7e1c0184b33995a2c6777d9b2c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.h new file mode 100644 index 0000000..64f00b0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.h @@ -0,0 +1,18 @@ +// +// TDCoreInfo.h +// ThinkingDataCore +// +// Created by 杨雄 on 2023/9/15. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCoreInfo : NSObject + ++ (NSString *)version; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.h.meta new file mode 100644 index 0000000..9c55085 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ae92e38198a86472babcb1379dba240b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.m new file mode 100644 index 0000000..b6491a8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.m @@ -0,0 +1,16 @@ +// +// TDCoreInfo.m +// ThinkingDataCore +// +// Created by 杨雄 on 2023/9/15. +// + +#import "TDCoreInfo.h" + +@implementation TDCoreInfo + ++ (NSString *)version { + return @"1.2.2"; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.m.meta new file mode 100644 index 0000000..908e004 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDCoreInfo.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a2ab9250aec7f4b4988a2f3681f595b6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.h new file mode 100644 index 0000000..c3e087c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.h @@ -0,0 +1,17 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDJSONUtil : NSObject + ++ (NSString *)JSONStringForObject:(id)object; + ++ (NSData *)JSONSerializeForObject:(id)object; + ++ (nullable id)jsonForData:(nonnull NSData *)data; + ++ (nullable NSMutableDictionary *)formatDateWithFormatter:(nonnull NSDateFormatter *)dateFormatter dict:(NSDictionary *)dict; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.h.meta new file mode 100644 index 0000000..609a237 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: dcb73703e86044804b77901c0f38bfab +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.m new file mode 100644 index 0000000..6878602 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.m @@ -0,0 +1,170 @@ +#import "TDJSONUtil.h" + +@implementation TDJSONUtil + ++ (NSString *)JSONStringForObject:(id)obj { + NSData *data = [self JSONSerializeForObject:obj]; + if (!data) { + return nil; + } + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; +} + ++ (NSData *)JSONSerializeForObject:(id)object { + id obj = [TDJSONUtil JSONSerializableObjectForObject:object]; + NSData *data = nil; + @try { + if ([NSJSONSerialization isValidJSONObject:obj]) { + NSError *error = nil; + data = [NSJSONSerialization dataWithJSONObject:obj options:NSJSONWritingFragmentsAllowed error:&error]; + if (error != nil) { + return nil; + } + } + } + @catch (NSException *exception) { + + } + return data; +} + ++ (nullable id)jsonForData:(NSData *)data { + if (![data isKindOfClass:NSData.class]) { + return nil; + } + @try { + NSError *jsonSeralizeError = nil; + id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonSeralizeError]; + if (jsonSeralizeError == nil) { + return json; + } + } @catch (NSException *exception) { + // + } + return nil; +} + ++ (id)JSONSerializableObjectForObject:(id)object { + if ([object isKindOfClass:[NSString class]]) { + return object; + } else if ([object isKindOfClass:[NSNumber class]]) { + + if ([object stringValue] && [[object stringValue] rangeOfString:@"."].location != NSNotFound) { + return [NSDecimalNumber decimalNumberWithDecimal:((NSNumber *)object).decimalValue]; + } + if ([object stringValue] && ([[object stringValue] rangeOfString:@"e"].location != NSNotFound || + [[object stringValue] rangeOfString:@"E"].location != NSNotFound )) { + return [NSDecimalNumber decimalNumberWithDecimal:((NSNumber *)object).decimalValue]; + } + return object; + } else if ([object isKindOfClass:[NSArray class]]) { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (id obj in (NSArray *)object) { + id convertedObj = [self JSONSerializableObjectForObject:obj]; + [self array:array addObject:convertedObj]; + } + return array; + } else if ([object isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; + [(NSDictionary *)object enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *dictionaryStop) { + [self dictionary:dictionary + setObject:[self JSONSerializableObjectForObject:obj] + forKey:key]; + }]; + return dictionary; + } else if ([object isKindOfClass:[NSArray class]]) { + NSMutableArray *array = [[NSMutableArray alloc] init]; + for (id obj in (NSArray *)object) { + id convertedObj = [self JSONSerializableObjectForObject:obj]; + [self array:array addObject:convertedObj]; + } + object = array; + } + + NSString *s = [object description]; + return s; +} + ++ (void)array:(NSMutableArray *)array addObject:(id)object { + if (object) { + [array addObject:object]; + } +} + ++ (void)dictionary:(NSMutableDictionary *)dictionary setObject:(id)object forKey:(id)key { + if (object && key) { + dictionary[key] = object; + } +} + ++ (nullable NSMutableDictionary *)formatDateWithFormatter:(nonnull NSDateFormatter *)dateFormatter dict:(NSDictionary *)dict { + if (![dict isKindOfClass:NSDictionary.class] || ![dateFormatter isKindOfClass:NSDateFormatter.class]) { + return nil; + } + NSMutableDictionary *mutableDict = nil; + if ([dict isKindOfClass:NSMutableDictionary.class]) { + mutableDict = (NSMutableDictionary *)dict; + } else { + mutableDict = [dict mutableCopy]; + } + + NSArray *keys = mutableDict.allKeys; + for (NSString *key in keys) { + id value = dict[key]; + + // 处理字典 + if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *newDict = [self formatDateWithFormatter:dateFormatter dict:value]; + mutableDict[key] = newDict; + } + // 处理数组 + else if ([value isKindOfClass:[NSArray class]]) { + NSMutableArray *newArray = [self formatArrayWithFormatter:dateFormatter array:value]; + mutableDict[key] = newArray; + } + // 处理集合 + else if ([value isKindOfClass:[NSSet class]]) { + NSSet *setData = value; + NSArray *newArray = [self formatArrayWithFormatter:dateFormatter array:setData.allObjects]; + mutableDict[key] = newArray; + } + // 处理日期 + else if ([value isKindOfClass:[NSDate class]]) { + NSString *newValue = [dateFormatter stringFromDate:(NSDate *)value]; + mutableDict[key] = newValue; + } + + } + return mutableDict; +} + + ++ (NSMutableArray *)formatArrayWithFormatter:(nonnull NSDateFormatter *)dateFormatter array:(NSArray *)array { + NSMutableArray *mutableArray = nil; + if ([array isKindOfClass:[NSMutableArray class]]) { + mutableArray = (NSMutableArray *)array; + } else { + mutableArray = [array mutableCopy]; + } + + for (int i = 0; i < mutableArray.count; i++) { + id value = mutableArray[i]; + if ([value isKindOfClass:[NSDate class]]) { + NSString *newValue = [dateFormatter stringFromDate:(NSDate *)value]; + mutableArray[i] = newValue; + } else if ([value isKindOfClass:[NSDictionary class]]) { + NSDictionary *newDict = [self formatDateWithFormatter:dateFormatter dict:value]; + mutableArray[i] = newDict; + } else if ([value isKindOfClass:[NSArray class]]) { + NSArray *newArray = [self formatArrayWithFormatter:dateFormatter array:value]; + mutableArray[i] = newArray; + } else if ([value isKindOfClass:[NSSet class]]) { + NSSet *setData = value; + NSArray *newArray = [self formatArrayWithFormatter:dateFormatter array:setData.allObjects]; + mutableArray[i] = newArray; + } + } + return mutableArray; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.m.meta new file mode 100644 index 0000000..a297102 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDJSONUtil.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 493815f68ee2c410bb4576ca8d351557 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime.meta new file mode 100644 index 0000000..a8a5919 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f7f69a4d3619d480992f8158ddbe7764 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle.meta new file mode 100644 index 0000000..e49339a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 75b00bb7e5ca04813934b3580a551b14 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.h new file mode 100644 index 0000000..679aeea --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.h @@ -0,0 +1,10 @@ +#import + +NS_ASSUME_NONNULL_BEGIN +@interface NSObject (TDSwizzle) + ++ (BOOL)td_swizzleMethod:(SEL)origSel withMethod:(SEL)altSel error:(NSError **)error; ++ (BOOL)td_swizzleClassMethod:(SEL)origSel withClassMethod:(SEL)altSel error:(NSError **)error; + +@end +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.h.meta new file mode 100644 index 0000000..83936be --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3de7db2dbee2b4f1cb70bf1133c9cf26 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.m new file mode 100644 index 0000000..7f70f72 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.m @@ -0,0 +1,41 @@ +#import "NSObject+TDSwizzle.h" + +#if TARGET_OS_IPHONE +#import +#import +#else +#import +#endif + +@implementation NSObject (TDSwizzle) + ++ (BOOL)td_swizzleMethod:(SEL)origSel withMethod:(SEL)altSel error:(NSError **)error { + Method origMethod = class_getInstanceMethod(self, origSel); + if (!origMethod) { + return NO; + } + + Method altMethod = class_getInstanceMethod(self, altSel); + if (!altMethod) { + return NO; + } + + class_addMethod(self, + origSel, + class_getMethodImplementation(self, origSel), + method_getTypeEncoding(origMethod)); + class_addMethod(self, + altSel, + class_getMethodImplementation(self, altSel), + method_getTypeEncoding(altMethod)); + + method_exchangeImplementations(class_getInstanceMethod(self, origSel), class_getInstanceMethod(self, altSel)); + + return YES; +} + ++ (BOOL)td_swizzleClassMethod:(SEL)origSel withClassMethod:(SEL)altSel error:(NSError **)error { + return [object_getClass((id)self) td_swizzleMethod:origSel withMethod:altSel error:error]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.m.meta new file mode 100644 index 0000000..0d3ddb6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/NSObject+TDSwizzle.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 28d46c2bdd871409081f8f1e9b0693fc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.h new file mode 100644 index 0000000..48407ce --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.h @@ -0,0 +1,13 @@ +#import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +typedef void (^swizzleBlock)(); +#pragma clang diagnostic pop + +@interface TDSwizzler : NSObject + ++ (void)swizzleSelector:(SEL)aSelector onClass:(Class)aClass withBlock:(swizzleBlock)block named:(NSString *)aName; ++ (void)unswizzleSelector:(SEL)aSelector onClass:(Class)aClass named:(NSString *)aName; + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.h.meta new file mode 100644 index 0000000..36419bf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 70accc43706e14e57840c87b5ca8b5c6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.m new file mode 100644 index 0000000..9616f17 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.m @@ -0,0 +1,240 @@ +#import "TDSwizzler.h" +#import +#import "TDCoreLog.h" + +#define MAPTABLE_ID(x) (__bridge id)((void *)x) + +#define MIN_ARGS 2 +#define MAX_ARGS 4 + +@interface TDSwizzle : NSObject + +@property (nonatomic, assign) Class class; +@property (nonatomic, assign) SEL selector; +@property (nonatomic, assign) IMP originalMethod; +@property (nonatomic, assign) uint numArgs; +@property (nonatomic, copy) NSMapTable *blocks; + +- (instancetype)initWithBlock:(swizzleBlock)aBlock + named:(NSString *)aName + forClass:(Class)aClass + selector:(SEL)aSelector + originalMethod:(IMP)aMethod; + +@end + +static NSMapTable *swizzles; + +static void td_swizzledMethod_2(id self, SEL _cmd) { + Method aMethod = class_getInstanceMethod([self class], _cmd); + TDSwizzle *swizzle = (TDSwizzle *)[swizzles objectForKey:MAPTABLE_ID(aMethod)]; + if (swizzle) { + ((void(*)(id, SEL))swizzle.originalMethod)(self, _cmd); + + NSEnumerator *blocks = [swizzle.blocks objectEnumerator]; + swizzleBlock block; + while((block = [blocks nextObject])) { + + block(self, _cmd); + } + } +} + +static void td_swizzledMethod_3(id self, SEL _cmd, id arg) { + Method aMethod = class_getInstanceMethod([self class], _cmd); + TDSwizzle *swizzle = (TDSwizzle *)[swizzles objectForKey:MAPTABLE_ID(aMethod)]; + if (swizzle) { + ((void(*)(id, SEL, id))swizzle.originalMethod)(self, _cmd, arg); + + NSEnumerator *blocks = [swizzle.blocks objectEnumerator]; + swizzleBlock block; + while((block = [blocks nextObject])) { + block(self, _cmd, arg); + } + } +} + +static void td_swizzledMethod_4(id self, SEL _cmd, id arg, id arg2) { + Method aMethod = class_getInstanceMethod([self class], _cmd); + TDSwizzle *swizzle = (TDSwizzle *)[swizzles objectForKey:(__bridge id)((void *)aMethod)]; + if (swizzle) { + ((void(*)(id, SEL, id, id))swizzle.originalMethod)(self, _cmd, arg, arg2); + + NSEnumerator *blocks = [swizzle.blocks objectEnumerator]; + swizzleBlock block; + while((block = [blocks nextObject])) { + block(self, _cmd, arg, arg2); + } + } +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wstrict-prototypes" +static void (*td_swizzledMethods[MAX_ARGS - MIN_ARGS + 1])() = {td_swizzledMethod_2, td_swizzledMethod_3, td_swizzledMethod_4}; +#pragma clang diagnostic pop + +@implementation TDSwizzler + ++ (void)load { + swizzles = [NSMapTable mapTableWithKeyOptions:(NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality) + valueOptions:(NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality)]; +} + ++ (TDSwizzle *)swizzleForMethod:(Method)aMethod { + return (TDSwizzle *)[swizzles objectForKey:MAPTABLE_ID(aMethod)]; +} + ++ (void)removeSwizzleForMethod:(Method)aMethod { + [swizzles removeObjectForKey:MAPTABLE_ID(aMethod)]; +} + ++ (void)setSwizzle:(TDSwizzle *)swizzle forMethod:(Method)aMethod { + [swizzles setObject:swizzle forKey:MAPTABLE_ID(aMethod)]; +} + ++ (BOOL)isLocallyDefinedMethod:(Method)aMethod onClass:(Class)aClass { + uint count; + BOOL isLocal = NO; + Method *methods = class_copyMethodList(aClass, &count); + for (NSUInteger i = 0; i < count; i++) { + if (aMethod == methods[i]) { + isLocal = YES; + break; + } + } + free(methods); + return isLocal; +} + ++ (void)swizzleSelector:(SEL)aSelector + onClass:(Class)aClass + withBlock:(swizzleBlock)aBlock + named:(NSString *)aName { + Method aMethod = class_getInstanceMethod(aClass, aSelector); + if (!aMethod) { + TDCORELOG(@"Cannot find method for %@ on %@",NSStringFromSelector(aSelector), NSStringFromClass(aClass)); + return; + } + + uint numArgs = method_getNumberOfArguments(aMethod); + if (numArgs < MIN_ARGS || numArgs > MAX_ARGS) { + TDCORELOG(@"Cannot swizzle method with %d args", numArgs); + } + + IMP swizzledMethod = (IMP)td_swizzledMethods[numArgs - 2]; + [TDSwizzler swizzleSelector:aSelector onClass:aClass withBlock:aBlock andSwizzleMethod:swizzledMethod named:aName]; +} + ++ (void)swizzleSelector:(SEL)aSelector + onClass:(Class)aClass + withBlock:(swizzleBlock)aBlock + andSwizzleMethod:(IMP)aSwizzleMethod + named:(NSString *)aName { + Method aMethod = class_getInstanceMethod(aClass, aSelector); + if (!aMethod) { + TDCORELOG(@"Cannot find method for %@ on %@", NSStringFromSelector(aSelector), NSStringFromClass(aClass)); + } + + BOOL isLocal = [self isLocallyDefinedMethod:aMethod onClass:aClass]; + TDSwizzle *swizzle = [self swizzleForMethod:aMethod]; + + if (isLocal) { + if (!swizzle) { + IMP originalMethod = method_getImplementation(aMethod); + + // Replace the local implementation of this method with the swizzled one + method_setImplementation(aMethod, aSwizzleMethod); + + // Create and add the swizzle + @try { + swizzle = [[TDSwizzle alloc] initWithBlock:aBlock named:aName forClass:aClass selector:aSelector originalMethod:originalMethod]; + } @catch (NSException *exception) { + TDCORELOG(@"%@ error: %@", self, exception); + } + [self setSwizzle:swizzle forMethod:aMethod]; + } else { + [swizzle.blocks setObject:aBlock forKey:aName]; + } + } else { + IMP originalMethod = swizzle ? swizzle.originalMethod : method_getImplementation(aMethod); + + // Add the swizzle as a new local method on the class. + if (!class_addMethod(aClass, aSelector, aSwizzleMethod, method_getTypeEncoding(aMethod))) { + TDCORELOG(@"Could not add swizzled for %@::%@, even though it didn't already exist locally", NSStringFromClass(aClass), NSStringFromSelector(aSelector)); + } + // Now re-get the Method, it should be the one we just added. + Method newMethod = class_getInstanceMethod(aClass, aSelector); + if (aMethod == newMethod) { + TDCORELOG(@"Newly added method for %@::%@ was the same as the old method", NSStringFromClass(aClass), NSStringFromSelector(aSelector)); + } + + TDSwizzle *newSwizzle = [[TDSwizzle alloc] initWithBlock:aBlock named:aName forClass:aClass selector:aSelector originalMethod:originalMethod]; + [self setSwizzle:newSwizzle forMethod:newMethod]; + } +} + ++ (void)unswizzleSelector:(SEL)aSelector onClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, aSelector); + TDSwizzle *swizzle = [self swizzleForMethod:aMethod]; + if (swizzle) { + method_setImplementation(aMethod, swizzle.originalMethod); + [self removeSwizzleForMethod:aMethod]; + } +} + +/* + Remove the named swizzle from the given class/selector. If aName is nil, remove all + swizzles for this class/selector + */ ++ (void)unswizzleSelector:(SEL)aSelector onClass:(Class)aClass named:(NSString *)aName { + Method aMethod = class_getInstanceMethod(aClass, aSelector); + TDSwizzle *swizzle = [self swizzleForMethod:aMethod]; + if (swizzle) { + if (aName) { + [swizzle.blocks removeObjectForKey:aName]; + } + if (!aName || [swizzle.blocks count] == 0) { + method_setImplementation(aMethod, swizzle.originalMethod); + [self removeSwizzleForMethod:aMethod]; + } + } +} + +@end + + +@implementation TDSwizzle + +- (instancetype)init { + if ((self = [super init])) { + self.blocks = [NSMapTable mapTableWithKeyOptions:(NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality) + valueOptions:(NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality)]; + } + return self; +} + +- (instancetype)initWithBlock:(swizzleBlock)aBlock + named:(NSString *)aName + forClass:(Class)aClass + selector:(SEL)aSelector + originalMethod:(IMP)aMethod { + if ((self = [self init])) { + self.class = aClass; + self.selector = aSelector; + self.originalMethod = aMethod; + [self.blocks setObject:aBlock forKey:aName]; + } + return self; +} + +- (NSString *)description { + NSString *descriptors = @""; + NSString *key; + NSEnumerator *keys = [self.blocks keyEnumerator]; + while ((key = [keys nextObject])) { + descriptors = [descriptors stringByAppendingFormat:@"\t%@ : %@\n", key, [self.blocks objectForKey:key]]; + } + return [NSString stringWithFormat:@"Swizzle on %@::%@ [\n%@]", NSStringFromClass(self.class), NSStringFromSelector(self.selector), descriptors]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.m.meta new file mode 100644 index 0000000..b5500d9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/Swizzle/TDSwizzler.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9b483538036f74d7795d6d8b163e8914 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.h new file mode 100644 index 0000000..48b0055 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.h @@ -0,0 +1,16 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDClassHelper : NSObject + ++ (Class _Nullable)allocateClassWithObject:(id)object className:(NSString *)className; + ++ (void)registerClass:(Class)cla; + ++ (BOOL)setObject:(id)object toClass:(Class)cla; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.h.meta new file mode 100644 index 0000000..3c0b3b8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 69c6a43721dd64eab8976fe5696ccb12 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.m new file mode 100644 index 0000000..4c7c01a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.m @@ -0,0 +1,36 @@ + +#import "TDClassHelper.h" +#import + +@implementation TDClassHelper + ++ (Class _Nullable)allocateClassWithObject:(id)object className:(NSString *)className { + if (!object || className.length <= 0) { + return nil; + } + Class originalClass = object_getClass(object); + Class subclass = NSClassFromString(className); + if (subclass) { + return nil; + } + subclass = objc_allocateClassPair(originalClass, className.UTF8String, 0); + if (class_getInstanceSize(originalClass) != class_getInstanceSize(subclass)) { + return nil; + } + return subclass; +} + ++ (void)registerClass:(Class)cla { + if (cla) { + objc_registerClassPair(cla); + } +} + ++ (BOOL)setObject:(id)object toClass:(Class)cla { + if (cla && object && object_getClass(object) != cla) { + return object_setClass(object, cla); + } + return NO; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.m.meta new file mode 100644 index 0000000..2de1f82 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDClassHelper.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2c9862bca358a4cb498509a3cd3b7498 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.h new file mode 100644 index 0000000..bf26960 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.h @@ -0,0 +1,22 @@ +// +// TDCoreWeakProxy.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCoreWeakProxy : NSProxy + +@property (nullable, nonatomic, weak, readonly) id target; + +- (instancetype)initWithTarget:(id)target; + ++ (instancetype)proxyWithTarget:(id)target; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.h.meta new file mode 100644 index 0000000..036f476 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 89e1d852d143d458da80377a78a7ab53 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.m new file mode 100644 index 0000000..b496f7f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.m @@ -0,0 +1,78 @@ +// +// TDCoreWeakProxy.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/24. +// + +#import "TDCoreWeakProxy.h" + +@implementation TDCoreWeakProxy + +- (instancetype)initWithTarget:(id)target { + _target = target; + return self; +} + ++ (instancetype)proxyWithTarget:(id)target { + return [[self alloc] initWithTarget:target]; +} + +- (id)forwardingTargetForSelector:(SEL)selector { + return _target; +} + +- (void)forwardInvocation:(NSInvocation *)invocation { + void *null = NULL; + [invocation setReturnValue:&null]; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + return [NSObject instanceMethodSignatureForSelector:@selector(init)]; +} + +- (BOOL)respondsToSelector:(SEL)aSelector { + return [_target respondsToSelector:aSelector]; +} + +- (BOOL)isEqual:(id)object { + return [_target isEqual:object]; +} + +- (NSUInteger)hash { + return [_target hash]; +} + +- (Class)superclass { + return [_target superclass]; +} + +- (Class)class { + return [_target class]; +} + +- (BOOL)isKindOfClass:(Class)aClass { + return [_target isKindOfClass:aClass]; +} + +- (BOOL)isMemberOfClass:(Class)aClass { + return [_target isMemberOfClass:aClass]; +} + +- (BOOL)conformsToProtocol:(Protocol *)aProtocol { + return [_target conformsToProtocol:aProtocol]; +} + +- (BOOL)isProxy { + return YES; +} + +- (NSString *)description { + return [_target description]; +} + +- (NSString *)debugDescription { + return [_target debugDescription]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.m.meta new file mode 100644 index 0000000..f41ad79 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDCoreWeakProxy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a8977a7d9480a4dd189e1ae33999f673 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.h new file mode 100644 index 0000000..68a6211 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.h @@ -0,0 +1,24 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDMethodHelper : NSObject + ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass; + ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector fromClass:(Class)fromClass toClass:(Class)toClass; + ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector sourceSelector:(SEL)sourceSelector fromClass:(Class)fromClass toClass:(Class)toClass; + ++ (void)addClassMethodWithDestinationSelector:(SEL)destinationSelector sourceSelector:(SEL)sourceSelector fromClass:(Class)fromClass toClass:(Class)toClass; + ++ (IMP _Nullable)replaceInstanceMethodWithDestinationSelector:(SEL)destinationSelector sourceSelector:(SEL)sourceSelector fromClass:(Class)fromClass toClass:(Class)toClass; + +/// swizzle respondsToSelector 方法 +/// 用于处理未实现代理方法也能采集事件的逻辑 ++ (void)swizzleRespondsToSelector; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.h.meta new file mode 100644 index 0000000..a91abb3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 661c5f1df62ae4f9aab882fcfd683853 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.m new file mode 100644 index 0000000..bd5d213 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.m @@ -0,0 +1,58 @@ + +#import "TDMethodHelper.h" +#import +#import "TDNewSwizzle.h" + +@implementation TDMethodHelper + ++ (IMP)implementationOfMethodSelector:(SEL)selector fromClass:(Class)aClass { + Method aMethod = class_getInstanceMethod(aClass, selector); + return method_getImplementation(aMethod); +} + ++ (void)addInstanceMethodWithSelector:(SEL)methodSelector fromClass:(Class)fromClass toClass:(Class)toClass { + [self addInstanceMethodWithDestinationSelector:methodSelector sourceSelector:methodSelector fromClass:fromClass toClass:toClass]; +} + ++ (void)addInstanceMethodWithDestinationSelector:(SEL)destinationSelector sourceSelector:(SEL)sourceSelector fromClass:(Class)fromClass toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + if (!method) { + return; + } + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + IMP destinationIMP = [self implementationOfMethodSelector:destinationSelector fromClass:toClass]; + if (destinationIMP == methodIMP) { + return; + } + class_replaceMethod(toClass, destinationSelector, methodIMP, types); + } +} + ++ (void)addClassMethodWithDestinationSelector:(SEL)destinationSelector sourceSelector:(SEL)sourceSelector fromClass:(Class)fromClass toClass:(Class)toClass { + Method method = class_getClassMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + if (!class_addMethod(toClass, destinationSelector, methodIMP, types)) { + class_replaceMethod(toClass, destinationSelector, methodIMP, types); + } +} + ++ (IMP _Nullable)replaceInstanceMethodWithDestinationSelector:(SEL)destinationSelector sourceSelector:(SEL)sourceSelector fromClass:(Class)fromClass toClass:(Class)toClass { + Method method = class_getInstanceMethod(fromClass, sourceSelector); + IMP methodIMP = method_getImplementation(method); + const char *types = method_getTypeEncoding(method); + return class_replaceMethod(toClass, destinationSelector, methodIMP, types); +} + ++ (void)swizzleRespondsToSelector { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [NSObject td_new_swizzleMethod:@selector(respondsToSelector:) + withMethod:@selector(thinkingdata_respondsToSelector:) + error:NULL]; + }); +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.m.meta new file mode 100644 index 0000000..64d86b6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDMethodHelper.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8f09d284d6fbc4e0aaa8a4fb07b94d75 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.h new file mode 100644 index 0000000..cb3c0ff --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.h @@ -0,0 +1,14 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (TDNewSwizzle) + ++ (BOOL)td_new_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError **)error_; ++ (BOOL)td_new_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError **)error_; ++ (BOOL)td_new_swizzleMethod:(SEL)origSel_ withClass:(Class)altCla_ withMethod:(SEL)altSel_ error:(NSError **)error_; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.h.meta new file mode 100644 index 0000000..b24e70f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3c22c4c0fc8b848db9696b6c6a1b7c97 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.m new file mode 100644 index 0000000..219b7d2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.m @@ -0,0 +1,155 @@ + +#import "TDNewSwizzle.h" + +#if (TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_VISION || TARGET_OS_TV) + #import + #import +#elif TARGET_OS_OSX + #import +#endif + +#define TDSetNSErrorFor(FUNC, ERROR_VAR, FORMAT,...) \ + if (ERROR_VAR) { \ + NSString *errStr = [NSString stringWithFormat:@"%s: " FORMAT,FUNC,##__VA_ARGS__]; \ + *ERROR_VAR = [NSError errorWithDomain:@"NSCocoaErrorDomain" \ + code:-1 \ + userInfo:[NSDictionary dictionaryWithObject:errStr forKey:NSLocalizedDescriptionKey]]; \ + } +#define TDSetNSError(ERROR_VAR, FORMAT,...) TDSetNSErrorFor(__func__, ERROR_VAR, FORMAT, ##__VA_ARGS__) + +#if OBJC_API_VERSION >= 2 +#define TDGetClass(obj) object_getClass(obj) +#else +#define TDGetClass(obj) (obj ? obj->isa : Nil) +#endif + +@implementation NSObject (TDNewSwizzle) + ++ (BOOL)td_new_swizzleMethod:(SEL)origSel_ withClass:(Class)altCla_ withMethod:(SEL)altSel_ error:(NSError **)error_ { + Method origMethod = class_getInstanceMethod(self, origSel_); + if (!origMethod) { + TDSetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self class]); + return NO; + } + + Method altMethod = class_getInstanceMethod(altCla_, altSel_); + if (!altMethod) { + TDSetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [altCla_ class]); + return NO; + } + + class_addMethod(self, + origSel_, + class_getMethodImplementation(self, origSel_), + method_getTypeEncoding(origMethod)); + class_addMethod(altCla_, + altSel_, + class_getMethodImplementation(altCla_, altSel_), + method_getTypeEncoding(altMethod)); + + //交换之前,先对自定义方法进行添加 + BOOL didAddMethod = class_addMethod(self, + altSel_, + method_getImplementation(altMethod), + method_getTypeEncoding(altMethod)); + if (didAddMethod) { + method_exchangeImplementations(origMethod, class_getInstanceMethod(self, altSel_)); + } + return didAddMethod; +} + ++ (BOOL)td_new_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError **)error_ { +#if OBJC_API_VERSION >= 2 + Method origMethod = class_getInstanceMethod(self, origSel_); + if (!origMethod) { + TDSetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self class]); + return NO; + } + + Method altMethod = class_getInstanceMethod(self, altSel_); + if (!altMethod) { + TDSetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self class]); + return NO; + } + + class_addMethod(self, + origSel_, + class_getMethodImplementation(self, origSel_), + method_getTypeEncoding(origMethod)); + class_addMethod(self, + altSel_, + class_getMethodImplementation(self, altSel_), + method_getTypeEncoding(altMethod)); + + method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_)); + return YES; +#else + // Scan for non-inherited methods. + Method directOriginalMethod = NULL, directAlternateMethod = NULL; + + void *iterator = NULL; + struct objc_method_list *mlist = class_nextMethodList(self, &iterator); + while (mlist) { + int method_index = 0; + for (; method_index < mlist->method_count; method_index++) { + if (mlist->method_list[method_index].method_name == origSel_) { + assert(!directOriginalMethod); + directOriginalMethod = &mlist->method_list[method_index]; + } + if (mlist->method_list[method_index].method_name == altSel_) { + assert(!directAlternateMethod); + directAlternateMethod = &mlist->method_list[method_index]; + } + } + mlist = class_nextMethodList(self, &iterator); + } + + // If either method is inherited, copy it up to the target class to make it non-inherited. + if (!directOriginalMethod || !directAlternateMethod) { + Method inheritedOriginalMethod = NULL, inheritedAlternateMethod = NULL; + if (!directOriginalMethod) { + inheritedOriginalMethod = class_getInstanceMethod(self, origSel_); + if (!inheritedOriginalMethod) { + TDSetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]); + return NO; + } + } + if (!directAlternateMethod) { + inheritedAlternateMethod = class_getInstanceMethod(self, altSel_); + if (!inheritedAlternateMethod) { + TDSetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]); + return NO; + } + } + + int hoisted_method_count = !directOriginalMethod && !directAlternateMethod ? 2 : 1; + struct objc_method_list *hoisted_method_list = malloc(sizeof(struct objc_method_list) + (sizeof(struct objc_method)*(hoisted_method_count-1))); + hoisted_method_list->obsolete = NULL; // soothe valgrind - apparently ObjC runtime accesses this value and it shows as uninitialized in valgrind + hoisted_method_list->method_count = hoisted_method_count; + Method hoisted_method = hoisted_method_list->method_list; + + if (!directOriginalMethod) { + bcopy(inheritedOriginalMethod, hoisted_method, sizeof(struct objc_method)); + directOriginalMethod = hoisted_method++; + } + if (!directAlternateMethod) { + bcopy(inheritedAlternateMethod, hoisted_method, sizeof(struct objc_method)); + directAlternateMethod = hoisted_method; + } + class_addMethods(self, hoisted_method_list); + } + + // Swizzle. + IMP temp = directOriginalMethod->method_imp; + directOriginalMethod->method_imp = directAlternateMethod->method_imp; + directAlternateMethod->method_imp = temp; + + return YES; +#endif +} + ++ (BOOL)td_new_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError **)error_ { + return [TDGetClass((id)self) td_new_swizzleMethod:origSel_ withMethod:altSel_ error:error_]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.m.meta new file mode 100644 index 0000000..2039597 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDRuntime/TDNewSwizzle.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f8cf632a0323645d7a47f3c099651cb9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.h new file mode 100644 index 0000000..ad7a468 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.h @@ -0,0 +1,36 @@ +// +// TDSettings.h +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/21. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, TDSDKMode) { + TDSDKModeNomal = 0, + TDSDKModeDebug, + TDSDKModeDebugOnly, +}; + +@interface TDSettings : NSObject + +@property (nonatomic, copy) NSString *appId; +@property (nonatomic, copy) NSString *serverUrl; +@property (nonatomic, copy) NSString *instanceName; +@property (nonatomic, assign) TDSDKMode mode; +@property (nonatomic, assign) BOOL enableLog; +/// Set default time zone. +/// You can use this time zone to compare the offset of the current time zone and the default time zone +@property (nonatomic, strong) NSTimeZone *defaultTimeZone; +@property (nonatomic, assign) NSInteger encryptVersion; +@property (nonatomic, copy) NSString *encryptKey; +@property (nonatomic, assign) BOOL enableAutoPush; +@property (nonatomic, assign) BOOL enableAutoCalibrated; +@property (nonatomic, strong) NSDictionary *rccFetchParams; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.h.meta new file mode 100644 index 0000000..afd0643 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c4b7868bdd79b4ce7bbdb2d70e930110 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.m b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.m new file mode 100644 index 0000000..412469f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.m @@ -0,0 +1,36 @@ +// +// TDSettings.m +// ThinkingDataCore +// +// Created by 杨雄 on 2024/5/21. +// + +#import "TDSettings.h" +#import "NSObject+TDCore.h" + +@implementation TDSettings + +- (instancetype)initWithDictionary:(NSDictionary *)dict { + if (self = [self init]) { + self.appId = [dict[@"appId"] td_string]; + self.serverUrl = [dict[@"serverUrl"] td_string]; + NSNumber *timezoneOffset = [dict[@"defaultTimeZone"] td_number]; + if (timezoneOffset) { + self.defaultTimeZone = [NSTimeZone timeZoneForSecondsFromGMT:timezoneOffset.doubleValue * 3600]; + } + self.enableLog = [dict[@"enableLog"] td_number].boolValue; + self.enableAutoCalibrated = [dict[@"enableAutoCalibrated"] td_number].boolValue; + self.enableAutoPush = [dict[@"enableAutoPush"] td_number].boolValue; + self.encryptKey = [dict[@"encryptKey"] td_string]; + self.encryptVersion = [dict[@"encryptVersion"] td_number].integerValue; + self.mode = [dict[@"mode"] td_number].integerValue; + + NSDictionary *rccFetchParams = dict[@"rccFetchParams"]; + if ([rccFetchParams isKindOfClass:NSDictionary.class]) { + self.rccFetchParams = rccFetchParams; + } + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.m.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.m.meta new file mode 100644 index 0000000..857715a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettings.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1dc60b2db11f84574ab73c3552e48bd2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettingsPrivate.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettingsPrivate.h new file mode 100644 index 0000000..b0528cf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettingsPrivate.h @@ -0,0 +1,19 @@ +// +// TDSettingsPrivate.h +// Pods +// +// Created by 杨雄 on 2024/6/20. +// + +#ifndef TDSettingsPrivate_h +#define TDSettingsPrivate_h + +#import + +@interface TDSettings() + +- (instancetype)initWithDictionary:(NSDictionary *)dict; + +@end + +#endif /* TDSettingsPrivate_h */ diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettingsPrivate.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettingsPrivate.h.meta new file mode 100644 index 0000000..2b6688b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/TDSettingsPrivate.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 43830f5bd7e454fec95773da747c55b9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/ThinkingDataCore.h b/Assets/Plugins/iOS/ThinkingDataCore/Classes/ThinkingDataCore.h new file mode 100644 index 0000000..4f0e3d7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/ThinkingDataCore.h @@ -0,0 +1,190 @@ +// +// ThinkingDataCore.h +// ThinkingDataCore +// +// Created by Hale on 2023/7/24. +// + +#import + +// In this header, you should import all the public headers of your framework using statements like #import + +#if __has_include() +#import +#else +#import "TDCoreInfo.h" +#endif + +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif + +#if __has_include() +#import +#else +#import "NSData+TDGzip.h" +#endif + +#if __has_include() +#import +#else +#import "NSDate+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "TDNewSwizzle.h" +#endif + +#if __has_include() +#import +#else +#import "TDClassHelper.h" +#endif + +#if __has_include() +#import +#else +#import "TDMethodHelper.h" +#endif + +#if __has_include() +#import +#else +#import "NSObject+TDSwizzle.h" +#endif + +#if __has_include() +#import +#else +#import "TDSwizzler.h" +#endif + +#if __has_include() +#import +#else +#import "TDOSLog.h" +#endif + +#if __has_include() +#import +#else +#import "NSString+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "TDApp.h" +#endif + +#if __has_include() +#import +#else +#import "TDSettings.h" +#endif + +#if __has_include() +#import +#else +#import "TDLogChannelProtocol.h" +#endif + +#if __has_include() +#import +#else +#import "TDLogConstant.h" +#endif + +#if __has_include() +#import +#else +#import "TDNotificationManager+Core.h" +#endif + +#if __has_include() +#import +#else +#import "TDNotificationManager+Analytics.h" +#endif + +#if __has_include() +#import +#else +#import "TDNotificationManager+Networking.h" +#endif + +#if __has_include() +#import +#else +#import "TDNotificationManager+RemoteConfig.h" +#endif + +#if __has_include() +#import +#else +#import "TDCoreDatabase.h" +#endif + +#if __has_include() +#import +#else +#import "TDCalibratedTime.h" +#endif + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + +#if __has_include() +#import +#else +#import "NSObject+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "NSURL+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "NSNumber+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "TDMediator+RemoteConfig.h" +#endif + +#if __has_include() +#import +#else +#import "TDMediator+Analytics.h" +#endif + +#if __has_include() +#import +#else +#import "TDMediator+Strategy.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetProperty.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif diff --git a/Assets/Plugins/iOS/ThinkingDataCore/Classes/ThinkingDataCore.h.meta b/Assets/Plugins/iOS/ThinkingDataCore/Classes/ThinkingDataCore.h.meta new file mode 100644 index 0000000..44d3df7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingDataCore/Classes/ThinkingDataCore.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: aa73c5c79638f4d95b0dd8f8b4ee212e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK.meta b/Assets/Plugins/iOS/ThinkingSDK.meta new file mode 100644 index 0000000..20bd8ff --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4dd9e7986fe964179ac6733ba24e44fe +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Resources.meta b/Assets/Plugins/iOS/ThinkingSDK/Resources.meta new file mode 100644 index 0000000..d06ca2c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 43f5c01752f5b4a53809f5f68136b6e9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Resources/PrivacyInfo.xcprivacy b/Assets/Plugins/iOS/ThinkingSDK/Resources/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..28ebcf5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,121 @@ + + + + + NSPrivacyTracking + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeProductInteraction + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeCrashData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypePerformanceData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeCoarseLocation + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeUserID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeDeviceID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAnalytics + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + 1C8F.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryDiskSpace + NSPrivacyAccessedAPITypeReasons + + E174.1 + 7D9E.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Resources/PrivacyInfo.xcprivacy.meta b/Assets/Plugins/iOS/ThinkingSDK/Resources/PrivacyInfo.xcprivacy.meta new file mode 100644 index 0000000..7533243 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Resources/PrivacyInfo.xcprivacy.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bf4c1d023317e4cde85c42a9f1f83ada +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source.meta b/Assets/Plugins/iOS/ThinkingSDK/Source.meta new file mode 100644 index 0000000..60de287 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b010dd865139b4ea8b8fe65c815bf3da +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch.meta new file mode 100644 index 0000000..d76daa7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e3aa65556739d487581dcbc33f001e23 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush.meta new file mode 100644 index 0000000..38a9943 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f4211ddaee63483da2cf08a3b9dbed6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.h new file mode 100644 index 0000000..a46db5f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.h @@ -0,0 +1,18 @@ +// +// TDAPPPushParams.h +// ThinkingSDK +// +// Created by Charles on 6.5.23. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +extern id __td_get_userNotificationCenter(void); +extern id __td_get_userNotificationCenter_delegate(void); +extern NSDictionary * __td_get_userNotificationCenterResponse(id response); +extern NSString * __td_get_userNotificationCenterRequestContentTitle(id response); +extern NSString * __td_get_userNotificationCenterRequestContentBody(id response); + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.h.meta new file mode 100644 index 0000000..e574b64 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d606670f7a7c24e1d86b03c1fc6251ac +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.m new file mode 100644 index 0000000..98548ba --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.m @@ -0,0 +1,70 @@ +// +// TDAPPPushParams.m +// ThinkingSDK +// +// Created by Charles on 6.5.23. +// + +#import "TDAPPPushParams.h" + +id __td_get_userNotificationCenter(void) { + Class cls = NSClassFromString(@"UNUserNotificationCenter"); + SEL sel = NSSelectorFromString(@"currentNotificationCenter"); + if ([cls respondsToSelector:sel]) { + id (*getUserNotificationCenterIMP)(id, SEL) = (NSString * (*)(id, SEL))[cls methodForSelector:sel]; + return getUserNotificationCenterIMP(cls, sel); + } + return nil; +} + +id __td_get_userNotificationCenter_delegate(void) { + Class cls = NSClassFromString(@"UNUserNotificationCenter"); + SEL sel = NSSelectorFromString(@"currentNotificationCenter"); + SEL delegateSel = NSSelectorFromString(@"delegate"); + if ([cls respondsToSelector:sel]) { + id (*getUserNotificationCenterIMP)(id, SEL) = (id (*)(id, SEL))[cls methodForSelector:sel]; + id center = getUserNotificationCenterIMP(cls, sel); + if (center) { + id (*getUserNotificationCenterDelegateIMP)(id, SEL) = (id (*)(id, SEL))[center methodForSelector:delegateSel]; + id delegate = getUserNotificationCenterDelegateIMP(center, delegateSel); + return delegate; + } + } + return nil; +} + +NSDictionary * __td_get_userNotificationCenterResponse(id response) { + + @try { + if ([response isKindOfClass:[NSClassFromString(@"UNNotificationResponse") class]]) { + return [response valueForKeyPath:@"notification.request.content.userInfo"]; + } + } @catch (NSException *exception) { + + } + return nil; +} + +NSString * __td_get_userNotificationCenterRequestContentTitle(id response) { + + @try { + if ([response isKindOfClass:[NSClassFromString(@"UNNotificationResponse") class]]) { + return [response valueForKeyPath:@"notification.request.content.title"]; + } + } @catch (NSException *exception) { + + } + return nil; +} + +NSString * __td_get_userNotificationCenterRequestContentBody(id response) { + + @try { + if ([response isKindOfClass:[NSClassFromString(@"UNNotificationResponse") class]]) { + return [response valueForKeyPath:@"notification.request.content.body"]; + } + } @catch (NSException *exception) { + + } + return nil; +} diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.m.meta new file mode 100644 index 0000000..0281b8c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAPPPushParams.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 08ddbde4b0bb44a2781691f28d329404 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.h new file mode 100644 index 0000000..3960b15 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.h @@ -0,0 +1,14 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAppDelegateProxyManager : NSObject + ++ (instancetype)defaultManager; + +- (void)proxyNotifications; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.h.meta new file mode 100644 index 0000000..983e9d2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 0ad802e76f93c418c9419315b8a3d275 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.m new file mode 100644 index 0000000..d1d6c0a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.m @@ -0,0 +1,61 @@ + +#import "TDAppDelegateProxyManager.h" +#import "TDApplicationDelegateProxy.h" +#import "UIApplication+TDPushClick.h" +#import "TDLogging.h" + +#if __has_include() +#import +#else +#import "TDMethodHelper.h" +#endif + +#if __has_include() +#import +#else +#import "TDNewSwizzle.h" +#endif + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +#import "TDUNUserNotificationCenterDelegateProxy.h" +#endif + +@implementation TDAppDelegateProxyManager + ++ (instancetype)defaultManager { + static dispatch_once_t onceToken; + static TDAppDelegateProxyManager *manager = nil; + dispatch_once(&onceToken, ^{ + manager = [[TDAppDelegateProxyManager alloc] init]; + }); + return manager; +} + +- (void)proxyNotifications NS_EXTENSION_UNAVAILABLE_IOS(""){ + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [TDMethodHelper swizzleRespondsToSelector]; + + [TDApplicationDelegateProxy resolveOptionalSelectorsForDelegate:[UIApplication sharedApplication].delegate]; + [TDApplicationDelegateProxy proxyDelegate:[UIApplication sharedApplication].delegate selectors:[NSSet setWithArray:@[@"application:didReceiveLocalNotification:", + @"application:didReceiveRemoteNotification:fetchCompletionHandler:", + @"application:handleOpenURL:", + @"application:openURL:options:", + @"application:continueUserActivity:restorationHandler:", + @"application:performActionForShortcutItem:completionHandler:"]]]; + if (@available(iOS 10.0, *)) { + if ([UNUserNotificationCenter currentNotificationCenter].delegate) { + [TDUNUserNotificationCenterDelegateProxy resolveOptionalSelectorsForDelegate:[UNUserNotificationCenter currentNotificationCenter].delegate]; + [TDUNUserNotificationCenterDelegateProxy proxyDelegate:[UNUserNotificationCenter currentNotificationCenter].delegate selectors:[NSSet setWithArray:@[@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:",@"userNotificationCenter:willPresentNotification:withCompletionHandler:"]]]; + } + NSError *error = NULL; + [UNUserNotificationCenter td_new_swizzleMethod:@selector(setDelegate:) withMethod:@selector(thinkingdata_setDelegate:) error:&error]; + if (error) { + TDLogInfo(@"proxy notification delegate error: %@", error); + } + } + }); +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.m.meta new file mode 100644 index 0000000..0366a4a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDAppDelegateProxyManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ed11ab70d6d6943019d6d3995eeaadc2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.h new file mode 100644 index 0000000..1b1a54c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.h @@ -0,0 +1,10 @@ + +#import "TDDelegateProxy.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDApplicationDelegateProxy : TDDelegateProxy + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.h.meta new file mode 100644 index 0000000..b4fe0cb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 47013b120f73c4885845dbb7dd840189 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.m new file mode 100644 index 0000000..b3e68e8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.m @@ -0,0 +1,131 @@ + +#import "TDApplicationDelegateProxy.h" +#import "NSObject+TDDelegateProxy.h" +#import "UIApplication+TDPushClick.h" +#import +#import "TDAppLaunchReason.h" +#import "TDCommonUtil.h" +#import "TDLogging.h" + +#if __has_include() +#import +#else +#import "TDClassHelper.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + + +@implementation TDApplicationDelegateProxy + +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + SEL selector = @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:); + [TDApplicationDelegateProxy invokeWithTarget:self selector:selector, application, userInfo, completionHandler]; + [TDApplicationDelegateProxy trackEventWithTarget:self application:application remoteNotification:userInfo]; +} + +- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification API_DEPRECATED("Use UserNotifications Framework's -[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:] or -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]", ios(4.0, 10.0)) { + SEL selector = @selector(application:didReceiveLocalNotification:); + [TDApplicationDelegateProxy invokeWithTarget:self selector:selector, application, notification]; + [TDApplicationDelegateProxy trackEventWithTarget:self application:application localNotification:notification]; +} + +- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> * _Nullable))restorationHandler { + SEL selector = @selector(application:continueUserActivity:restorationHandler:); + if (![TDCorePresetDisableConfig disableStartReason]) { + [[TDAppLaunchReason sharedInstance] clearAppLaunchParams]; + [TDAppLaunchReason sharedInstance].appLaunchParams = @{@"url": [TDCommonUtil string: userActivity.webpageURL.absoluteString],@"data":@{}}; + } + return [TDApplicationDelegateProxy invokeReturnBOOLWithTarget:self selector:selector arg1:application arg2:userActivity arg3:restorationHandler]; +} + +- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options { + SEL selector = @selector(application:openURL:options:); + if (![TDCorePresetDisableConfig disableStartReason]) { + [[TDAppLaunchReason sharedInstance] clearAppLaunchParams]; + [TDAppLaunchReason sharedInstance].appLaunchParams = @{@"url": [TDCommonUtil string:url.absoluteString],@"data":@{}}; + } + return [TDApplicationDelegateProxy invokeReturnBOOLWithTarget:self selector:selector arg1:app arg2:url arg3:options]; +} + +- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { + SEL selector = @selector(application:handleOpenURL:); + if (![TDCorePresetDisableConfig disableStartReason]) { + [[TDAppLaunchReason sharedInstance] clearAppLaunchParams]; + [TDAppLaunchReason sharedInstance].appLaunchParams = @{@"url": [TDCommonUtil string:url.absoluteString], @"data":@{}}; + } + return [TDApplicationDelegateProxy invokeReturnBOOLWithTarget:self selector:selector arg1:application arg2:url]; +} + +- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler API_AVAILABLE(ios(9.0)){ + SEL selector = @selector(application:performActionForShortcutItem:completionHandler:); + [TDApplicationDelegateProxy invokeWithTarget:self selector:selector, application, shortcutItem, completionHandler]; + if (![TDCorePresetDisableConfig disableStartReason]) { + [[TDAppLaunchReason sharedInstance] clearAppLaunchParams]; + [TDAppLaunchReason sharedInstance].appLaunchParams = @{@"url": @"",@"data": [TDCommonUtil dictionary:shortcutItem.userInfo]}; + } +} + + ++ (void)trackEventWithTarget:(NSObject *)target application:(UIApplication *)application remoteNotification:(NSDictionary *)userInfo { + + if (target != application.delegate) { + return; + } + + if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) { + TDLogInfo(@"iOS version >= 10.0, callback for %@ was ignored.", @"application:didReceiveRemoteNotification:fetchCompletionHandler:"); + return; + } + + if (application.applicationState != UIApplicationStateInactive) { + return; + } + + if (![TDCorePresetDisableConfig disableStartReason]) { + [[TDAppLaunchReason sharedInstance] clearAppLaunchParams]; + [TDAppLaunchReason sharedInstance].appLaunchParams = @{@"url": @"", @"data": [TDCommonUtil dictionary:userInfo]}; + } + +} + ++ (void)trackEventWithTarget:(NSObject *)target application:(UIApplication *)application localNotification:(UILocalNotification *)notification API_DEPRECATED("Use UserNotifications Framework's -[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:] or -[UNUserNotificationCenterDelegate didReceiveNotificationResponse:withCompletionHandler:]", ios(4.0, 10.0)){ + + if (target != application.delegate) { + return; + } + + BOOL isValidPushClick = NO; + if (application.applicationState == UIApplicationStateInactive) { + isValidPushClick = YES; + } + + if (!isValidPushClick) { + return; + } + + if (![TDCorePresetDisableConfig disableStartReason]) { + NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; + properties[@"alertBody"] = notification.alertBody; + if (@available(iOS 8.2, *)) { + properties[@"alertTitle"] = notification.alertTitle; + } + [[TDAppLaunchReason sharedInstance] clearAppLaunchParams]; + [TDAppLaunchReason sharedInstance].appLaunchParams = @{@"url": @"", @"data": [TDCommonUtil dictionary:properties]}; + } +} + ++ (NSSet *)optionalSelectors { + return [NSSet setWithArray:@[@"application:didReceiveLocalNotification:", + @"application:didReceiveRemoteNotification:fetchCompletionHandler:", + @"application:handleOpenURL:", + @"application:openURL:options:", + @"application:continueUserActivity:restorationHandler:", + @"application:performActionForShortcutItem:completionHandler:"]]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.m.meta new file mode 100644 index 0000000..9994901 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDApplicationDelegateProxy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b2eec12b437e64f6886ebe51d6680b83 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.h new file mode 100644 index 0000000..94be8fc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.h @@ -0,0 +1,16 @@ + +#import "TDDelegateProxy.h" + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUNUserNotificationCenterDelegateProxy : TDDelegateProxy + + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.h.meta new file mode 100644 index 0000000..68c4018 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: dd9eda5b6572748ecaa3313c288c9e16 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.m new file mode 100644 index 0000000..90143d0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.m @@ -0,0 +1,78 @@ + +#import "TDUNUserNotificationCenterDelegateProxy.h" + +#if __has_include() +#import +#else +#import "TDClassHelper.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +#import "NSObject+TDDelegateProxy.h" +#import +#import "TDAPPPushParams.h" +#import "TDAppLaunchReason.h" +#import "TDCommonUtil.h" +#import "ThinkingAnalyticsSDK.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDUNUserNotificationCenterDelegateProxy + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)){ + SEL selector = @selector(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:); + [TDUNUserNotificationCenterDelegateProxy invokeWithTarget:self selector:selector, center, response, completionHandler]; + [TDUNUserNotificationCenterDelegateProxy trackEventWithTarget:self notificationCenter:center notificationResponse:response]; +} + +- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler API_AVAILABLE(ios(10.0)){ + SEL selector = @selector(userNotificationCenter:willPresentNotification:withCompletionHandler:); + [TDUNUserNotificationCenterDelegateProxy invokeWithTarget:self selector:selector, center, notification, completionHandler]; + [TDUNUserNotificationCenterDelegateProxy trackEventWithTarget:self notificationCenter:center notification:notification]; +} + ++ (void)trackEventWithTarget:(NSObject *)target notificationCenter:(UNUserNotificationCenter *)center notification:(UNNotification *)notification API_AVAILABLE(ios(10.0)){ + +} + ++ (void)trackEventWithTarget:(NSObject *)target notificationCenter:(UNUserNotificationCenter *)center notificationResponse:(UNNotificationResponse *)response API_AVAILABLE(ios(10.0)){ + + if (target != center.delegate) { + return; + } + + if (![TDCorePresetDisableConfig disableStartReason]) { + NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; + NSDictionary *userInfo = __td_get_userNotificationCenterResponse(response); + if (userInfo) { + [properties addEntriesFromDictionary:userInfo]; + } + properties[@"title"] = __td_get_userNotificationCenterRequestContentTitle(response); + properties[@"body"] = __td_get_userNotificationCenterRequestContentBody(response); + + [[TDAppLaunchReason sharedInstance] clearAppLaunchParams]; + [TDAppLaunchReason sharedInstance].appLaunchParams = @{@"url": @"", @"data": [TDCommonUtil dictionary:properties]}; + } + + if ([ThinkingAnalyticsSDK defaultInstance].config.enableAutoPush) { + @try { + if ([response isKindOfClass:[NSClassFromString(@"UNNotificationResponse") class]]) { + NSDictionary *userInfo = [response valueForKeyPath:@"notification.request.content.userInfo"]; + [TDAppLaunchReason td_ops_push_click:userInfo]; + } + } @catch (NSException *exception) { + + } + } + +} + ++ (NSSet *)optionalSelectors { + return [NSSet setWithArray:@[@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:", @"userNotificationCenter:willPresentNotification:withCompletionHandler:"]]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.m.meta new file mode 100644 index 0000000..21f49a8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/TDUNUserNotificationCenterDelegateProxy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a8c262d70355c46f38a4fce70eb95cc5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.h new file mode 100644 index 0000000..373abc9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.h @@ -0,0 +1,13 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIApplication (TDPushClick) + +- (void)thinkingdata_setDelegate:(id )delegate; +@property (nonatomic, copy, nullable) NSDictionary *thinkingdata_launchOptions; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.h.meta new file mode 100644 index 0000000..4f9c082 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b039553b9411c4e30b4fc767b7c2714d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.m new file mode 100644 index 0000000..0e24334 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.m @@ -0,0 +1,29 @@ + +#import "UIApplication+TDPushClick.h" +#import "TDApplicationDelegateProxy.h" +#import + +static void *const kSALaunchOptions = (void *)&kSALaunchOptions; + +@implementation UIApplication (TDPushClick) + +- (void)thinkingdata_setDelegate:(id)delegate { + [TDApplicationDelegateProxy resolveOptionalSelectorsForDelegate:delegate]; + + [self thinkingdata_setDelegate:delegate]; + + if (!self.delegate) { + return; + } + [TDApplicationDelegateProxy proxyDelegate:self.delegate selectors:[NSSet setWithArray:@[@"application:didReceiveLocalNotification:", @"application:didReceiveRemoteNotification:fetchCompletionHandler:"]]]; +} + +- (NSDictionary *)thinkingdata_launchOptions { + return objc_getAssociatedObject(self, kSALaunchOptions); +} + +- (void)setThinkingdata_launchOptions:(NSDictionary *)thinkingdata_launchOptions { + objc_setAssociatedObject(self, kSALaunchOptions, thinkingdata_launchOptions, OBJC_ASSOCIATION_COPY); +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.m.meta new file mode 100644 index 0000000..8df4fd6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UIApplication+TDPushClick.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 17463cb6f209545bcbc20aad5129804d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.h new file mode 100644 index 0000000..3b0adc8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.h @@ -0,0 +1,14 @@ + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 +#import +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface UNUserNotificationCenter (TDPushClick) + +- (void)thinkingdata_setDelegate:(id )delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.h.meta new file mode 100644 index 0000000..85d1588 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: dd78c300cef5f4507a13b638ce74c1e5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.m new file mode 100644 index 0000000..c69d6b3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.m @@ -0,0 +1,18 @@ + +#import "UNUserNotificationCenter+TDPushClick.h" +#import "TDUNUserNotificationCenterDelegateProxy.h" + +@implementation UNUserNotificationCenter (TDPushClick) + +- (void)thinkingdata_setDelegate:(id)delegate { + + [TDUNUserNotificationCenterDelegateProxy resolveOptionalSelectorsForDelegate:delegate]; + + [self thinkingdata_setDelegate:delegate]; + if (!self.delegate) { + return; + } + [TDUNUserNotificationCenterDelegateProxy proxyDelegate:self.delegate selectors:[NSSet setWithArray:@[@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:", @"userNotificationCenter:willPresentNotification:withCompletionHandler:"]]]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.m.meta new file mode 100644 index 0000000..b9fff43 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/AppPush/UNUserNotificationCenter+TDPushClick.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 73166a65f020c46e8a3c53cfa301c5f2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.h new file mode 100644 index 0000000..e7b6240 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.h @@ -0,0 +1,31 @@ +// +// TDAppLaunchReason.h +// ThinkingSDK +// +// Created by wwango on 2021/11/17. +// Copyright © 2021 thinkingdata. All rights reserved. + + +#import + +NS_ASSUME_NONNULL_BEGIN + +static NSDictionary *appPushClickDic; + +@interface TDAppLaunchReason : NSObject + +@property(nonatomic, copy) NSDictionary *appLaunchParams; + ++ (TDAppLaunchReason *)sharedInstance; + +- (void)clearAppLaunchParams; + ++ (void)td_ops_push_click:(NSDictionary *)userInfo; + ++ (NSDictionary*)getAppPushDic; + ++ (void)clearAppPushParams; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.h.meta new file mode 100644 index 0000000..3658010 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f37b994396cdc4d7780bcb516fcc6d51 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.m new file mode 100644 index 0000000..f833549 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.m @@ -0,0 +1,181 @@ +// +// TDAppLaunchReason.m +// ThinkingSDK +// +// Created by wwango on 2021/11/17. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDAppLaunchReason.h" +#import +#import "TDCommonUtil.h" +#import "TDAppState.h" +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDAppDelegateProxyManager.h" +#import "TDPushClickEvent.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@implementation TDAppLaunchReason + ++ (void)load { + [[NSNotificationCenter defaultCenter] addObserver:[TDAppLaunchReason sharedInstance] selector:@selector(_applicationDidFinishLaunchingNotification:) name:UIApplicationDidFinishLaunchingNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:[TDAppLaunchReason sharedInstance] selector:@selector(_applicationDidEnterBackgroundNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil]; +} + ++ (void)td_ops_push_click:(NSDictionary *)userInfo { + + @try { + if ([userInfo.allKeys containsObject:@"te_extras"] && [userInfo[@"te_extras"] isKindOfClass:[NSString class]]) { + NSData *jsonData = [userInfo[@"te_extras"] dataUsingEncoding:NSUTF8StringEncoding]; + NSError *err; + NSDictionary *responseDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err]; + NSDictionary *opsReceiptProperties = responseDic[@"#ops_receipt_properties"]; + if ([opsReceiptProperties isKindOfClass:[NSString class]]) { + NSString *opsStr = (NSString *)opsReceiptProperties; + opsReceiptProperties = [NSJSONSerialization JSONObjectWithData:[opsStr dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&err]; + } + if (opsReceiptProperties && [opsReceiptProperties isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *dic = [ThinkingAnalyticsSDK _getAllInstances]; + if(dic == nil || dic.count == 0){ + appPushClickDic = opsReceiptProperties; + }else{ + for (NSString *instanceToken in dic.allKeys) { + ThinkingAnalyticsSDK *instance = dic[instanceToken]; + TDPushClickEvent *pushEvent = [[TDPushClickEvent alloc]initWithName: @"te_ops_push_click"]; + pushEvent.ops = opsReceiptProperties; + [instance autoTrackWithEvent:pushEvent properties:@{}]; + [instance innerFlush]; + } + } + } + } + } @catch (NSException *exception) { + + } +} + ++ (NSDictionary *)getAppPushDic{ + return appPushClickDic; +} + ++ (void)clearAppPushParams{ + appPushClickDic = nil; +} + ++ (TDAppLaunchReason *)sharedInstance { + static dispatch_once_t onceToken; + static TDAppLaunchReason *appLaunchManager; + + dispatch_once(&onceToken, ^{ + appLaunchManager = [TDAppLaunchReason new]; + }); + return appLaunchManager; +} + +- (void)clearAppLaunchParams { + self.appLaunchParams = @{@"url":@"", + @"data":@{}}; +} + +- (void)_applicationDidEnterBackgroundNotification:(NSNotification *)notification { + [self clearAppLaunchParams]; +} + +// 拦截冷启动和热启动的参数 +- (void)_applicationDidFinishLaunchingNotification:(NSNotification *)notification { + + __weak TDAppLaunchReason *weakSelf = self; + + NSDictionary *launchOptions = notification.userInfo; + NSString *url = [self getInitDeeplink:launchOptions]; + NSDictionary *data = [self getInitData:launchOptions]; + + // 发送推送事件 + if ([ThinkingAnalyticsSDK defaultInstance].config.enableAutoPush && launchOptions) { + NSDictionary *remoteNotification = [launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"]; + [TDAppLaunchReason td_ops_push_click:remoteNotification]; + } + + // 记录冷启动启动原因 + if (![TDCorePresetDisableConfig disableStartReason]) { + + if (!launchOptions) { + [weakSelf clearAppLaunchParams]; + } else if ([url isKindOfClass:[NSString class]] && url.length) { + self.appLaunchParams = @{@"url": [TDCommonUtil string:url], + @"data": @{}}; + } else { + self.appLaunchParams = @{@"url": @"", + @"data": [TDCommonUtil dictionary:data]}; + } + } + + UIApplication *application = [TDAppState sharedApplication]; + id applicationDelegate = [application delegate]; + if (applicationDelegate == nil) + { + return; + } + + if (![TDCorePresetDisableConfig disableStartReason]) { + [[TDAppDelegateProxyManager defaultManager] proxyNotifications]; + } + + if (![TDCorePresetDisableConfig disableOpsReceiptProperties]) { + [[TDAppDelegateProxyManager defaultManager] proxyNotifications]; + } +} + +- (NSString *)getInitDeeplink:(NSDictionary *)launchOptions { + + if (!launchOptions || ![launchOptions isKindOfClass:[NSDictionary class]]) { + return @""; + } + + if ([launchOptions isKindOfClass:[NSDictionary class]] && + [launchOptions.allKeys containsObject:UIApplicationLaunchOptionsURLKey]) { + + return launchOptions[UIApplicationLaunchOptionsURLKey]; + + } else if ([launchOptions isKindOfClass:[NSDictionary class]] && + [launchOptions.allKeys containsObject:UIApplicationLaunchOptionsUserActivityDictionaryKey]) { + + NSDictionary *userActivityDictionary = launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey]; + NSString *type = userActivityDictionary[UIApplicationLaunchOptionsUserActivityTypeKey]; + if ([type isEqualToString:NSUserActivityTypeBrowsingWeb]) { + NSUserActivity *userActivity = userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"]; + return userActivity.webpageURL.absoluteString; + } + } + return @""; +} + +- (NSDictionary *)getInitData:(NSDictionary *)launchOptions { + + if (!launchOptions || ![launchOptions isKindOfClass:[NSDictionary class]]) { + return @{}; + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if ([launchOptions.allKeys containsObject:UIApplicationLaunchOptionsLocalNotificationKey]) { + // 本地推送可能会解析不出alertbody,这里特殊处理一下 + UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; + NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; + properties[@"alertBody"] = notification.alertBody; + if (@available(iOS 8.2, *)) { + properties[@"alertTitle"] = notification.alertTitle; + } + return properties; + } +#pragma clang diagnostic pop + + return launchOptions; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.m.meta new file mode 100644 index 0000000..449f7f5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLaunch/TDAppLaunchReason.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2153a11937bd248f793246e3f848aaab +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle.meta new file mode 100644 index 0000000..22b708e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 20131090d388c4844a66a22ba19bcf58 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.h new file mode 100644 index 0000000..31cc68b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.h @@ -0,0 +1,47 @@ +// +// TDAppLifeCycle.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// APP life cycle +typedef NS_ENUM(NSUInteger, TDAppLifeCycleState) { + TDAppLifeCycleStateInit = 1, // init status + TDAppLifeCycleStateBackgroundStart, + TDAppLifeCycleStateStart, + TDAppLifeCycleStateEnd, + TDAppLifeCycleStateTerminate, +}; + +/// When the life cycle status is about to change, this notification will be sent +/// object: The object is the current life cycle object +/// userInfo: Contains two keys kTDAppLifeCycleNewStateKey and kTDAppLifeCycleOldStateKey +extern NSNotificationName const kTDAppLifeCycleStateWillChangeNotification; + +/// When the life cycle status changes, this notification will be sent +/// object: The object is the current lifecycle object +/// userInfo: Contains two keys kTDAppLifeCycleNewStateKey and kTDAppLifeCycleOldStateKey +extern NSNotificationName const kTDAppLifeCycleStateDidChangeNotification; + +/// In the status change notification, get the new status +extern NSString * const kTDAppLifeCycleNewStateKey; + +/// In the status change notification, get the status before the change +extern NSString * const kTDAppLifeCycleOldStateKey; + +@interface TDAppLifeCycle : NSObject + +@property (nonatomic, assign, readonly) TDAppLifeCycleState state; + ++ (void)startMonitor; + ++ (instancetype)shareInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.h.meta new file mode 100644 index 0000000..ffd5aba --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2e9c1fbbacf0f42f2872451f2d22002d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.m new file mode 100644 index 0000000..26ea67b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.m @@ -0,0 +1,248 @@ +// +// TDAppLifeCycle.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/28. +// + +#import "TDAppLifeCycle.h" +#import "TDAppState.h" + +#if TARGET_OS_IOS +#import +#elif TARGET_OS_OSX +#import +#endif + +#if __has_include() +#import +#else +#import "TDLogging.h" +#endif + +NSNotificationName const kTDAppLifeCycleStateWillChangeNotification = @"cn.thinkingdata.TDAppLifeCycleStateWillChange"; +NSNotificationName const kTDAppLifeCycleStateDidChangeNotification = @"cn.thinkingdata.TDAppLifeCycleStateDidChange"; +NSString * const kTDAppLifeCycleNewStateKey = @"new"; +NSString * const kTDAppLifeCycleOldStateKey = @"old"; + + +@interface TDAppLifeCycle () +/// status +@property (nonatomic, assign) TDAppLifeCycleState state; + +@end + +@implementation TDAppLifeCycle + ++ (void)startMonitor { + [TDAppLifeCycle shareInstance]; +} + ++ (instancetype)shareInstance { + static dispatch_once_t onceToken; + static TDAppLifeCycle *appLifeCycle = nil; + dispatch_once(&onceToken, ^{ + appLifeCycle = [[TDAppLifeCycle alloc] init]; + }); + return appLifeCycle; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _state = TDAppLifeCycleStateInit; + [self registerListeners]; + [self setupLaunchedState]; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)registerListeners { + if ([TDAppState runningInAppExtension]) { + return; + } + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; +#if TARGET_OS_IOS + [notificationCenter addObserver:self + selector:@selector(applicationDidBecomeActive:) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + + [notificationCenter addObserver:self + selector:@selector(applicationDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + + [notificationCenter addObserver:self + selector:@selector(applicationWillTerminate:) + name:UIApplicationWillTerminateNotification + object:nil]; + +#elif TARGET_OS_OSX + +// [notificationCenter addObserver:self +// selector:@selector(applicationDidFinishLaunching:) +// name:NSApplicationDidFinishLaunchingNotification +// object:nil]; +// +// [notificationCenter addObserver:self +// selector:@selector(applicationDidBecomeActive:) +// name:NSApplicationDidBecomeActiveNotification +// object:nil]; +// [notificationCenter addObserver:self +// selector:@selector(applicationDidResignActive:) +// name:NSApplicationDidResignActiveNotification +// object:nil]; +// +// [notificationCenter addObserver:self +// selector:@selector(applicationWillTerminate:) +// name:NSApplicationWillTerminateNotification +// object:nil]; +#endif +} + +- (void)setupLaunchedState { + if ([TDAppState runningInAppExtension]) { + return; + } + + dispatch_block_t mainThreadBlock = ^(){ +#if TARGET_OS_IOS + UIApplication *application = [TDAppState sharedApplication]; + BOOL isAppStateBackground = application.applicationState == UIApplicationStateBackground; +#else + BOOL isAppStateBackground = NO; +#endif + [TDAppState shareInstance].relaunchInBackground = isAppStateBackground; + + self.state = isAppStateBackground ? TDAppLifeCycleStateBackgroundStart : TDAppLifeCycleStateStart; + }; + + if (@available(iOS 13.0, *)) { + // The reason why iOS 13 and above modify the status in the block of the asynchronous main queue:+ + // 1. Make sure that the initialization of the SDK has been completed before sending the appstatus change notification. This can ensure that the public properties have been set when the automatic collection management class sends the app_start event (in fact, it can also be achieved by listening to UIApplicationDidFinishLaunchingNotification) + // 2. In a project that contains SceneDelegate, it is accurate to delay obtaining applicationState (obtaining by listening to UIApplicationDidFinishLaunchingNotification is inaccurate) + dispatch_async(dispatch_get_main_queue(), mainThreadBlock); + } else { + // iOS 13 and below handle background wakeup and cold start (non-delayed initialization) by listening to the notification of UIApplicationDidFinishLaunchingNotification: + // 1. When iOS 13 or later wakes up in the background, the block of the asynchronous main queue will not be executed. So you need to listen to UIApplicationDidFinishLaunchingNotification at the same time + // 2. iOS 13 and below will not contain SceneDelegate +#if TARGET_OS_IOS + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applicationDidFinishLaunching:) + name:UIApplicationDidFinishLaunchingNotification + object:nil]; +#endif + // Handle cold start below iOS 13, where the client delays initialization. UIApplicationDidFinishLaunchingNotification notification has been missed when lazy initialization + dispatch_async(dispatch_get_main_queue(), mainThreadBlock); + } +} + +//MARK: - Notification Action + +- (void)applicationDidFinishLaunching:(NSNotification *)notification { +#if TARGET_OS_IOS + UIApplication *application = [TDAppState sharedApplication]; + BOOL isAppStateBackground = application.applicationState == UIApplicationStateBackground; +#else + BOOL isAppStateBackground = NO; +#endif + + [TDAppState shareInstance].relaunchInBackground = isAppStateBackground; + + self.state = isAppStateBackground ? TDAppLifeCycleStateBackgroundStart : TDAppLifeCycleStateStart; +} + +- (void)applicationDidBecomeActive:(NSNotification *)notification { + TDLogDebug(@"application did become active"); + +#if TARGET_OS_IOS + if (![notification.object isKindOfClass:[UIApplication class]]) { + return; + } + + UIApplication *application = (UIApplication *)notification.object; + if (application.applicationState != UIApplicationStateActive) { + return; + } +#elif TARGET_OS_OSX + if (![notification.object isKindOfClass:[NSApplication class]]) { + return; + } + + NSApplication *application = (NSApplication *)notification.object; + if (!application.isActive) { + return; + } +#endif + + [TDAppState shareInstance].relaunchInBackground = NO; + + self.state = TDAppLifeCycleStateStart; +} + +#if TARGET_OS_IOS +- (void)applicationDidEnterBackground:(NSNotification *)notification { + TDLogDebug(@"application did enter background"); + + if (![notification.object isKindOfClass:[UIApplication class]]) { + return; + } + + UIApplication *application = (UIApplication *)notification.object; + if (application.applicationState != UIApplicationStateBackground) { + return; + } + + self.state = TDAppLifeCycleStateEnd; +} + +#elif TARGET_OS_OSX +- (void)applicationDidResignActive:(NSNotification *)notification { + TDLogDebug(@"application did resignActive"); + + if (![notification.object isKindOfClass:[NSApplication class]]) { + return; + } + + NSApplication *application = (NSApplication *)notification.object; + if (application.isActive) { + return; + } + self.state = TDAppLifeCycleStateEnd; +} +#endif + +- (void)applicationWillTerminate:(NSNotification *)notification { + TDLogDebug(@"application will terminate"); + + self.state = TDAppLifeCycleStateTerminate; +} + +//MARK: - Setter + +- (void)setState:(TDAppLifeCycleState)state { + + if (_state == state) { + return; + } + + [TDAppState shareInstance].isActive = (state == TDAppLifeCycleStateStart); + + NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:2]; + userInfo[kTDAppLifeCycleNewStateKey] = @(state); + userInfo[kTDAppLifeCycleOldStateKey] = @(_state); + + [[NSNotificationCenter defaultCenter] postNotificationName:kTDAppLifeCycleStateWillChangeNotification object:self userInfo:userInfo]; + + _state = state; + + [[NSNotificationCenter defaultCenter] postNotificationName:kTDAppLifeCycleStateDidChangeNotification object:self userInfo:userInfo]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.m.meta new file mode 100644 index 0000000..964549e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppLifeCycle.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c2b0cf29c0ac24442b70af08fba39f7f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.h new file mode 100644 index 0000000..c1053ac --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.h @@ -0,0 +1,28 @@ +// +// TDAppState.h +// ThinkingSDK +// +// Created by wwango on 2021/9/24. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAppState : NSObject +/// Whether to start in the background. When the app is woken up by silently pushing the background, or when the location change wakes up the app, value = YES. (thread safe) +@property (atomic, assign) BOOL relaunchInBackground; + +/// Whether the current app is in the foreground +@property (atomic, assign) BOOL isActive; + ++ (instancetype)shareInstance; + ++ (id)sharedApplication; + ++ (BOOL)runningInAppExtension; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.h.meta new file mode 100644 index 0000000..501b9ec --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bfe06ac7bb20d44f4b38427283e52402 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.m new file mode 100644 index 0000000..bd613c3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.m @@ -0,0 +1,46 @@ +// +// TDAppState.m +// ThinkingSDK +// +// Created by wwango on 2021/9/24. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDAppState.h" + +#if TARGET_OS_IOS +#import +#endif + +@implementation TDAppState + ++ (instancetype)shareInstance { + static dispatch_once_t onceToken; + static TDAppState *appState; + dispatch_once(&onceToken, ^{ + appState = [TDAppState new]; + }); + return appState; +} + ++ (id)sharedApplication { + +#if TARGET_OS_IOS + + if ([self runningInAppExtension]) { + return nil; + } + return [[UIApplication class] performSelector:@selector(sharedApplication)]; + +#endif + return nil; +} + ++ (BOOL)runningInAppExtension { +#if TARGET_OS_IOS + return [[[[NSBundle mainBundle] bundlePath] pathExtension] isEqualToString:@"appex"]; +#endif + return NO; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.m.meta new file mode 100644 index 0000000..eb2d9d0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AppLifeCycle/TDAppState.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 439283b9eaf2e4d26883e97a319af143 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack.meta new file mode 100644 index 0000000..db0bd64 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1b5729d7c0b24bddbf39df25636523b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin.meta new file mode 100644 index 0000000..7e08465 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d28aab82ad3e74dbfba611830073cc1f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.h new file mode 100644 index 0000000..ca0756e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.h @@ -0,0 +1,18 @@ +// +// TDAutoPushPlugin.h +// Pods +// +// Created by 廖德生 on 2024/08/26. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAutoPushPlugin : NSObject + ++ (void)enableLog:(BOOL)enable; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.h.meta new file mode 100644 index 0000000..b471411 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: da9a0ad6e1e7e4ac5a30de33a53f43a0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.m new file mode 100644 index 0000000..ce762b0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.m @@ -0,0 +1,189 @@ +// +// TDAutoPushPlugin.m +// TDAutoPushPlugin.m +// Pods +// +// Created by 廖德生 on 2024/08/26. +// + +#import "TDAutoPushPlugin.h" +#import +#import + +#if __has_include() +#import +#else +#import "ThinkingDataCore.h" +#endif + +static BOOL _logOn = YES; +static NSString * _fcm_token = nil; +static NSString * _apns_token = nil; +static NSString * _jpush_token = nil; +static NSString * const TD_FCM_TOKEN = @"fcm_token"; +static NSString * const TD_APNS_TOKEN = @"apns_token"; +static NSString * const TD_JPUSH_TOKEN = @"jiguang_id"; +static NSMutableSet * _pushAppIds; + +@interface TDAutoPushPlugin () + +@end + +@implementation TDAutoPushPlugin + ++ (void)load { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [TDAutoPushPlugin monitorFIRMessagingToken]; + [TDAutoPushPlugin monitorJPUSHServiceToken]; + [TDAutoPushPlugin registerAnalyticsListener]; + [TDAutoPushPlugin registerAppLifeCycleListener]; + _pushAppIds = [NSMutableSet set]; + }); +} + ++ (void)enableLog:(BOOL)enable { + _logOn = enable; +} + +void (*td_fcm_imp_original)(id, SEL, id); +void td_fcm_imp_final(id self, SEL _cmd, id token) { + [TDAutoPushPlugin printLog:@"FCM token: %@", token]; + _fcm_token = token; + for (NSString *appId in _pushAppIds) { + [TDAutoPushPlugin tdUserSetValue:token forKey:TD_FCM_TOKEN appid:appId]; + } + if(td_fcm_imp_original) { + td_fcm_imp_original(self, _cmd, token); + } +} + ++ (void)monitorFIRMessagingToken { + Class desClass_FIRMessaging = objc_getClass("FIRMessaging"); + bool ret = NO; + ret = class_addMethod(desClass_FIRMessaging, NSSelectorFromString(@"td_updateDefaultFCMToken:"), (IMP)(td_fcm_imp_final), "v@:@"); + if (ret) { + Method method_original = class_getInstanceMethod(desClass_FIRMessaging, NSSelectorFromString(@"updateDefaultFCMToken:")); + Method method_final = class_getInstanceMethod(desClass_FIRMessaging, NSSelectorFromString(@"td_updateDefaultFCMToken:")); + td_fcm_imp_original = (void(*)(id, SEL, id))method_getImplementation(method_original); + method_exchangeImplementations(method_original, method_final); + } +} + ++ (void)monitorJPUSHServiceToken { + Class desClass = NSClassFromString(@"JPUSHService"); + void(^_handler)(int resCode, NSString *registrationID) = ^(int resCode, NSString *registrationID) { + [TDAutoPushPlugin printLog:@"JPush registrationID: %@, resCode: %d", registrationID, resCode]; + _jpush_token = registrationID; + for (NSString *appId in _pushAppIds) { + [TDAutoPushPlugin tdUserSetValue:registrationID forKey:TD_JPUSH_TOKEN appid:appId]; + } + }; + SEL _sel = NSSelectorFromString(@"registrationIDCompletionHandler:"); + if ([desClass respondsToSelector:_sel]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [desClass performSelector:_sel withObject:_handler]; +#pragma clang diagnostic pop + } +} + ++ (void)tdUserSetValue:(NSString *)value forKey:(NSString *)key appid:(NSString *)appId { + if (value != nil && value.length > 0) { + if ([[TDMediator sharedInstance] tdAnalyticsGetEnableAutoPushWithAppId: appId]) { + [[TDMediator sharedInstance] tdAnalyticsUserSetProperties:@{key: value} appId:appId]; + } + } +} + ++ (void)registerAnalyticsListener { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pushTokenNotification:) name:kAnalyticsNotificationNameInit object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pushTokenNotification:) name:kAnalyticsNotificationNameLogin object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pushTokenNotification:) name:kAnalyticsNotificationNameSetDistinctId object:nil]; +} + ++ (void)pushTokenNotification:(NSNotification *)notification { + NSDictionary *userInfo = notification.userInfo; + NSString *appId = userInfo[kAnalyticsNotificationParamsAppId]; + if (_fcm_token.length) { + [TDAutoPushPlugin tdUserSetValue:_fcm_token forKey:TD_FCM_TOKEN appid:appId]; + } else { + [_pushAppIds addObject:appId]; + } + + if (_jpush_token.length) { + [TDAutoPushPlugin tdUserSetValue:_jpush_token forKey:TD_JPUSH_TOKEN appid:appId]; + } else { + [_pushAppIds addObject:appId]; + } + + if (_apns_token.length) { + [TDAutoPushPlugin tdUserSetValue:_apns_token forKey:TD_APNS_TOKEN appid:appId]; + } else { + [_pushAppIds addObject:appId]; + } +} + ++ (void)registerAppLifeCycleListener { + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(td_applicationDidFinishLaunching:) + name:UIApplicationDidFinishLaunchingNotification + object:nil]; +} + +static void (*original_didRegisterForRemoteNotificationsWithDeviceToken)(id, SEL, UIApplication *, NSData *); ++ (void)td_applicationDidFinishLaunching:(NSNotification *)notification { + Class delegateClass = [UIApplication sharedApplication].delegate.class; + + SEL originalSelector = @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:); + SEL swizzledSelector = @selector(td_application:didRegisterForRemoteNotificationsWithDeviceToken:); + + Method originalMethod = class_getInstanceMethod(delegateClass, originalSelector); + // 保存原有方法的实现 + original_didRegisterForRemoteNotificationsWithDeviceToken = (void (*)(id, SEL, UIApplication *, NSData *))method_getImplementation(originalMethod); + + Method swizzledMethod = class_getClassMethod([self class], swizzledSelector); + method_exchangeImplementations(originalMethod, swizzledMethod); +} + ++ (void)td_application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { + NSString *tokenStr = [TDAutoPushPlugin formatDeviceTokenToHexStr:deviceToken]; + [TDAutoPushPlugin printLog:@"apns token: %@", tokenStr]; + _apns_token = tokenStr; + for (NSString *appId in _pushAppIds) { + [TDAutoPushPlugin tdUserSetValue:tokenStr forKey:TD_APNS_TOKEN appid:appId]; + } + original_didRegisterForRemoteNotificationsWithDeviceToken(self, _cmd, application, deviceToken); +} + ++ (NSString *)formatDeviceTokenToHexStr:(NSData *)deviceToken { + NSString *tokenStr; + if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 13.0) { + const unsigned *tokenBytes = [deviceToken bytes]; + tokenStr = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x", + ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]), + ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]), + ntohl(tokenBytes[6]), ntohl(tokenBytes[7])]; + } else { + tokenStr = [[deviceToken description] stringByReplacingOccurrencesOfString:@"<" withString:@""]; + tokenStr = [tokenStr stringByReplacingOccurrencesOfString:@">" withString:@""]; + tokenStr = [tokenStr stringByReplacingOccurrencesOfString:@" " withString:@""]; + } + return tokenStr; +} + ++ (void)printLog:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2) { + if (_logOn == YES) { + if (format) { + va_list args; + va_start(args, format); + NSString *output = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + + NSString *prefix = @"TDAutoPushPlugin"; + [TDOSLog logMessage:output prefix:prefix type:TDLogTypeInfo asynchronous:YES]; + } + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.m.meta new file mode 100644 index 0000000..112be99 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/AutoPushPlugin/TDAutoPushPlugin.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7d25bd808566149d399161cc855bd5dc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event.meta new file mode 100644 index 0000000..66b5b3d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 60e81b49c2ab941b48f1746f0b7f409d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.h new file mode 100644 index 0000000..36c9718 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.h @@ -0,0 +1,17 @@ +// +// TDAppEndEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/17. +// + +#import "TDAutoTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAppEndEvent : TDAutoTrackEvent +@property (nonatomic, copy) NSString *screenName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.h.meta new file mode 100644 index 0000000..628c470 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 81d81a9a5ad354dcd957258ac3ed0fba +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.m new file mode 100644 index 0000000..3f8f6d5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.m @@ -0,0 +1,28 @@ +// +// TDAppEndEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/17. +// + +#import "TDAppEndEvent.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@implementation TDAppEndEvent + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + if (![TDCorePresetDisableConfig disableScreenName]) { + self.properties[@"#screen_name"] = self.screenName ?: @""; + } + + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.m.meta new file mode 100644 index 0000000..d713015 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppEndEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3ad91764cd4c84b3cb4d504bd508b9e4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.h new file mode 100644 index 0000000..2ba3263 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.h @@ -0,0 +1,19 @@ +// +// TDAppStartEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/17. +// + +#import "TDAutoTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAppStartEvent : TDAutoTrackEvent +@property (nonatomic, copy) NSString *startReason; +@property (nonatomic, assign) BOOL resumeFromBackground; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.h.meta new file mode 100644 index 0000000..48c32c8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ed6c573fbb49b4b6ead0f48b1cd38739 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.m new file mode 100644 index 0000000..563626e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.m @@ -0,0 +1,35 @@ +// +// TDAppStartEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/17. +// + +#import "TDAppStartEvent.h" +#import + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +static NSString * const TD_RESUME_FROM_BACKGROUND = @"#resume_from_background"; +static NSString * const TD_START_REASON = @"#start_reason"; + +@implementation TDAppStartEvent + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + if (![TDCorePresetDisableConfig disableResumeFromBackground]) { + self.properties[TD_RESUME_FROM_BACKGROUND] = @(self.resumeFromBackground); + } + if (![TDCorePresetDisableConfig disableStartReason]) { + self.properties[TD_START_REASON] = self.startReason; + } + + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.m.meta new file mode 100644 index 0000000..793b960 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAppStartEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 938284553f4844198b92206428da5dac +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.h new file mode 100644 index 0000000..6d65e6e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.h @@ -0,0 +1,22 @@ +// +// TDAutoClickEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/15. +// + +#import "TDAutoTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAutoClickEvent : TDAutoTrackEvent +@property (nonatomic, copy) NSString *elementId; +@property (nonatomic, copy) NSString *elementContent; +@property (nonatomic, copy) NSString *elementType; +@property (nonatomic, copy) NSString *elementPosition; +@property (nonatomic, copy) NSString *pageTitle; +@property (nonatomic, copy) NSString *screenName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.h.meta new file mode 100644 index 0000000..63f3128 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 0993f6afd7ac045cf937be6f152bca5f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.m new file mode 100644 index 0000000..f99c97b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.m @@ -0,0 +1,43 @@ +// +// TDAutoClickEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/15. +// + +#import "TDAutoClickEvent.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@implementation TDAutoClickEvent + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + if (![TDCorePresetDisableConfig disableScreenName]) { + self.properties[@"#screen_name"] = self.screenName; + } + if (![TDCorePresetDisableConfig disableElementId]) { + self.properties[@"#element_id"] = self.elementId; + } + if (![TDCorePresetDisableConfig disableElementType]) { + self.properties[@"#element_type"] = self.elementType; + } + if (![TDCorePresetDisableConfig disableElementContent]) { + self.properties[@"#element_content"] = self.elementContent; + } + if (![TDCorePresetDisableConfig disableElementPosition]) { + self.properties[@"#element_position"] = self.elementPosition; + } + if (![TDCorePresetDisableConfig disableTitle]) { + self.properties[@"#title"] = self.pageTitle; + } + + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.m.meta new file mode 100644 index 0000000..7b7c59f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoClickEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 63f08b37fb6e244eebb84b7c018a1461 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.h new file mode 100644 index 0000000..971ab96 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.h @@ -0,0 +1,20 @@ +// +// TDAutoPageViewEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/15. +// + +#import "TDAutoTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAutoPageViewEvent : TDAutoTrackEvent +@property (nonatomic, copy) NSString *pageUrl; +@property (nonatomic, copy) NSString *referrer; +@property (nonatomic, copy) NSString *pageTitle; +@property (nonatomic, copy) NSString *screenName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.h.meta new file mode 100644 index 0000000..629c22f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a8c18e34dc9cb402eab1b55cb07a9280 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.m new file mode 100644 index 0000000..afcc061 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.m @@ -0,0 +1,36 @@ +// +// TDAutoPageViewEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/15. +// + +#import "TDAutoPageViewEvent.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@implementation TDAutoPageViewEvent + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + if (![TDCorePresetDisableConfig disableScreenName]) { + self.properties[@"#screen_name"] = self.screenName; + } + if (![TDCorePresetDisableConfig disableTitle]) { + self.properties[@"#title"] = self.pageTitle; + } + if (![TDCorePresetDisableConfig disableUrl]) { + self.properties[@"#url"] = self.pageUrl; + } + if (![TDCorePresetDisableConfig disableReferrer]) { + self.properties[@"#referrer"] = self.referrer; + } + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.m.meta new file mode 100644 index 0000000..8583fb6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoPageViewEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d6f6c0e19e8cf4bde97b9f6eec13ff87 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.h new file mode 100644 index 0000000..50b984e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.h @@ -0,0 +1,27 @@ +// +// TDAutoTrackEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/15. +// + +#import "TDTrackEvent.h" +#import "TDConstant.h" +#import "TDAutoTrackConst.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAutoTrackEvent : TDTrackEvent + +/// It is used to record the dynamic public properties of automatic collection events. The dynamic public properties need to be obtained in the current thread where the event occurs +@property (nonatomic, strong) NSDictionary *autoDynamicSuperProperties; + +/// Static public property for logging autocollection events +@property (nonatomic, strong) NSDictionary *autoSuperProperties; + +/// Returns the automatic collection type +- (TDAutoTrackEventType)autoTrackEventType; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.h.meta new file mode 100644 index 0000000..47669fd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4fe43ec71d6ef4d8390b31b12db67986 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.m new file mode 100644 index 0000000..9336e0c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.m @@ -0,0 +1,63 @@ +// +// TDAutoTrackEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/15. +// + +#import "TDAutoTrackEvent.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@implementation TDAutoTrackEvent + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + // Reprocess the duration of automatic collection events, mainly app_start, app_end + // app_start app_end events are collected by the automatic collection management class. There are the following problems: the automatic collection management class and the timeTracker event duration management class are processed by listening to appLifeCycle notifications, so they are not at a precise and unified time point. There will be small errors that need to be eliminated. + // After testing, the error is less than 0.01s. + CGFloat minDuration = 0.01; + if (![TDCorePresetDisableConfig disableDuration]) { + if (self.foregroundDuration > minDuration) { + self.properties[@"#duration"] = @([NSString stringWithFormat:@"%.3f", self.foregroundDuration].floatValue); + } + } + if (![TDCorePresetDisableConfig disableBackgroundDuration]) { + if (self.backgroundDuration > minDuration) { + self.properties[TD_BACKGROUND_DURATION] = @([NSString stringWithFormat:@"%.3f", self.backgroundDuration].floatValue); + } + } + + return dict; +} + +- (TDAutoTrackEventType)autoTrackEventType { + if ([self.eventName isEqualToString:TD_APP_START_EVENT]) { + return TDAutoTrackEventTypeAppStart; + } else if ([self.eventName isEqualToString:TD_APP_START_BACKGROUND_EVENT]) { + return TDAutoTrackEventTypeAppStart; + } else if ([self.eventName isEqualToString:TD_APP_END_EVENT]) { + return TDAutoTrackEventTypeAppEnd; + } else if ([self.eventName isEqualToString:TD_APP_VIEW_EVENT]) { + return TDAutoTrackEventTypeAppViewScreen; + } else if ([self.eventName isEqualToString:TD_APP_CLICK_EVENT]) { + return TDAutoTrackEventTypeAppClick; + } else if ([self.eventName isEqualToString:TD_APP_CRASH_EVENT]) { + return TDAutoTrackEventTypeAppViewCrash; + } else if ([self.eventName isEqualToString:TD_APP_INSTALL_EVENT]) { + return TDAutoTrackEventTypeAppInstall; + } else { + return TDAutoTrackEventTypeNone; + } +} + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError *__autoreleasing _Nullable *)error { + [TDPropertyValidator validateAutoTrackEventPropertyKey:key value:value error:error]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.m.meta new file mode 100644 index 0000000..c4ab0f9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDAutoTrackEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 45745a7908a4e401494b13bf3dd00329 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.h new file mode 100644 index 0000000..f3def1a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.h @@ -0,0 +1,16 @@ +// +// TAPushClickEvent.h +// ThinkingSDK +// +// Created by liulongbing on 2023/5/31. +// +#import "TDAutoTrackEvent.h" +NS_ASSUME_NONNULL_BEGIN + +@interface TDPushClickEvent : TDAutoTrackEvent + +@property (nonatomic, strong) NSDictionary *ops; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.h.meta new file mode 100644 index 0000000..8385545 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 93b8a7c7ab3054230aa69278b0e877c7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.m new file mode 100644 index 0000000..56d7546 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.m @@ -0,0 +1,18 @@ +// +// TAPushClickEvent.m +// ThinkingSDK +// +// Created by liulongbing on 2023/5/31. +// + +#import "TDPushClickEvent.h" + +@implementation TDPushClickEvent + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + self.properties[@"#ops_receipt_properties"] = self.ops; + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.m.meta new file mode 100644 index 0000000..f905bf4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Event/TDPushClickEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9162f41571f16414fba1baab7b4d1929 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackConst.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackConst.h new file mode 100644 index 0000000..f1ccf59 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackConst.h @@ -0,0 +1,32 @@ +// +// TDAutoTrackConst.h +// Pods +// +// Created by 杨雄 on 2023/7/23. +// + +#ifndef TDAutoTrackConst_h +#define TDAutoTrackConst_h + +#import + +typedef NS_OPTIONS(NSInteger, TDAutoTrackEventType) { + TDAutoTrackEventTypeNone = 0, + TDAutoTrackEventTypeAppStart = 1 << 0, + TDAutoTrackEventTypeAppEnd = 1 << 1, + TDAutoTrackEventTypeAppClick = 1 << 2, + TDAutoTrackEventTypeAppViewScreen = 1 << 3, + TDAutoTrackEventTypeAppViewCrash = 1 << 4, + TDAutoTrackEventTypeAppInstall = 1 << 5, + TDAutoTrackEventTypeAll = TDAutoTrackEventTypeAppStart | TDAutoTrackEventTypeAppEnd | TDAutoTrackEventTypeAppClick | TDAutoTrackEventTypeAppInstall | TDAutoTrackEventTypeAppViewCrash | TDAutoTrackEventTypeAppViewScreen +}; + +static NSString * const TD_APP_START_EVENT = @"ta_app_start"; +static NSString * const TD_APP_START_BACKGROUND_EVENT = @"ta_app_bg_start"; +static NSString * const TD_APP_END_EVENT = @"ta_app_end"; +static NSString * const TD_APP_VIEW_EVENT = @"ta_app_view"; +static NSString * const TD_APP_CLICK_EVENT = @"ta_app_click"; +static NSString * const TD_APP_CRASH_EVENT = @"ta_app_crash"; +static NSString * const TD_APP_INSTALL_EVENT = @"ta_app_install"; + +#endif /* TDAutoTrackConst_h */ diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackConst.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackConst.h.meta new file mode 100644 index 0000000..9768fc2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackConst.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bb155137bd66d45fdb2e1e5762541c79 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.h new file mode 100644 index 0000000..4700d23 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.h @@ -0,0 +1,37 @@ +#import "ThinkingAnalyticsSDK.h" +#import "TDColdStartTracker.h" +#import "TDHotStartTracker.h" +#import "TDInstallTracker.h" +#import "TDAutoTrackConst.h" + +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_TITLE; +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_URL_PROPERTY; +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_REFERRER_URL; +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_SCREEN_NAME; +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_ELEMENT_ID; +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_ELEMENT_TYPE; +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_ELEMENT_CONTENT; +FOUNDATION_EXTERN NSString * const TD_EVENT_PROPERTY_ELEMENT_POSITION; + +@interface TDAutoTrackManager : NSObject + ++ (instancetype)sharedManager; + +- (void)trackEventView:(UIView *)view; + +- (void)trackEventView:(UIView *)view withIndexPath:(NSIndexPath *)indexPath; + +- (void)trackWithAppid:(NSString *)appid withOption:(TDAutoTrackEventType)type; + +- (void)viewControlWillAppear:(UIViewController *)controller; + +- (void)trackWithEvent:(TDAutoTrackEvent *)event withProperties:(NSDictionary *)properties; + ++ (UIViewController *)topPresentedViewController; + +#pragma mark - UNAVAILABLE +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.h.meta new file mode 100644 index 0000000..7d42a49 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1625f60723f8542a69466be0231920f5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.m new file mode 100644 index 0000000..29edc8a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.m @@ -0,0 +1,794 @@ +#import "TDAutoTrackManager.h" + +#import "UIViewController+AutoTrack.h" +#import "UIApplication+AutoTrack.h" +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDPublicConfig.h" +#import "TDAutoClickEvent.h" +#import "TDAutoPageViewEvent.h" +#import "TDAppLifeCycle.h" +#import "TDAppState.h" +#import "TDRunTime.h" +#import "TDAppStartEvent.h" +#import "TDAppEndEvent.h" +#import "TDAppEndTracker.h" +#import "TDColdStartTracker.h" +#import "TDInstallTracker.h" +#import "TDAppState.h" + +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif + +#if __has_include() +#import +#else +#import "NSObject+TDSwizzle.h" +#endif + +#if __has_include() +#import +#else +#import "TDSwizzler.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +#ifndef TD_LOCK +#define TD_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); +#endif + +#ifndef TD_UNLOCK +#define TD_UNLOCK(lock) dispatch_semaphore_signal(lock); +#endif + +NSString * const TD_EVENT_PROPERTY_TITLE = @"#title"; +NSString * const TD_EVENT_PROPERTY_URL_PROPERTY = @"#url"; +NSString * const TD_EVENT_PROPERTY_REFERRER_URL = @"#referrer"; +NSString * const TD_EVENT_PROPERTY_SCREEN_NAME = @"#screen_name"; +NSString * const TD_EVENT_PROPERTY_ELEMENT_ID = @"#element_id"; +NSString * const TD_EVENT_PROPERTY_ELEMENT_TYPE = @"#element_type"; +NSString * const TD_EVENT_PROPERTY_ELEMENT_CONTENT = @"#element_content"; +NSString * const TD_EVENT_PROPERTY_ELEMENT_POSITION = @"#element_position"; + +@interface TDAutoTrackManager () +@property (atomic, strong) NSMutableDictionary *autoTrackOptions; +@property (nonatomic, strong, nonnull) dispatch_semaphore_t trackOptionLock; +@property (atomic, copy) NSString *referrerViewControllerUrl; +@property (nonatomic, strong) TDHotStartTracker *appHotStartTracker; +@property (nonatomic, strong) TDAppEndTracker *appEndTracker; +@property (nonatomic, strong) TDColdStartTracker *appColdStartTracker; +@property (nonatomic, strong) TDInstallTracker *appInstallTracker; + +@end + + +@implementation TDAutoTrackManager + +#pragma mark - Public + ++ (instancetype)sharedManager { + static dispatch_once_t once; + static TDAutoTrackManager *manager = nil; + dispatch_once(&once, ^{ + manager = [[[TDAutoTrackManager class] alloc] init]; + manager.autoTrackOptions = [NSMutableDictionary new]; + manager.trackOptionLock = dispatch_semaphore_create(1); + [manager registerAppLifeCycleListener]; + }); + return manager; +} + +- (void)trackEventView:(UIView *)view { + [self trackEventView:view withIndexPath:nil]; +} + +- (void)trackEventView:(UIView *)view withIndexPath:(NSIndexPath *)indexPath { + if (view.thinkingAnalyticsIgnoreView) { + return; + } + + NSString *elementId = nil; + NSString *elementType = nil; + NSString *elementContent = nil; + NSString *elementPosition = nil; + NSString *elementPageTitle = nil; + NSString *elementScreenName = nil; + NSMutableDictionary *customProperties = [NSMutableDictionary dictionary]; + + + elementId = view.thinkingAnalyticsViewID; + elementType = NSStringFromClass([view class]); + + + NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; + properties[TD_EVENT_PROPERTY_ELEMENT_ID] = view.thinkingAnalyticsViewID; + properties[TD_EVENT_PROPERTY_ELEMENT_TYPE] = NSStringFromClass([view class]); + UIViewController *viewController = [self viewControllerForView:view]; + if (viewController != nil) { + NSString *screenName = NSStringFromClass([viewController class]); + properties[TD_EVENT_PROPERTY_SCREEN_NAME] = screenName; + + elementScreenName = screenName; + + NSString *controllerTitle = [self titleFromViewController:viewController]; + if (controllerTitle) { + properties[TD_EVENT_PROPERTY_TITLE] = controllerTitle; + + elementPageTitle = controllerTitle; + } + } + + + NSDictionary *propDict = view.thinkingAnalyticsViewProperties; + if ([propDict isKindOfClass:[NSDictionary class]]) { + [properties addEntriesFromDictionary:propDict]; + + [customProperties addEntriesFromDictionary:propDict]; + } + + UIView *contentView; + NSDictionary *propertyWithAppid; + if (indexPath) { + if ([view isKindOfClass:[UITableView class]]) { + UITableView *tableView = (UITableView *)view; + contentView = [tableView cellForRowAtIndexPath:indexPath]; + if (!contentView) { + [tableView layoutIfNeeded]; + contentView = [tableView cellForRowAtIndexPath:indexPath]; + } + properties[TD_EVENT_PROPERTY_ELEMENT_POSITION] = [NSString stringWithFormat: @"%ld:%ld", (unsigned long)indexPath.section, (unsigned long)indexPath.row]; + + elementPosition = [NSString stringWithFormat: @"%ld:%ld", (unsigned long)indexPath.section, (unsigned long)indexPath.row]; + + if ([tableView.thinkingAnalyticsDelegate conformsToProtocol:@protocol(TDUIViewAutoTrackDelegate)]) { + if ([tableView.thinkingAnalyticsDelegate respondsToSelector:@selector(thinkingAnalytics_tableView:autoTrackPropertiesAtIndexPath:)]) { + NSDictionary *dic = [view.thinkingAnalyticsDelegate thinkingAnalytics_tableView:tableView autoTrackPropertiesAtIndexPath:indexPath]; + if ([dic isKindOfClass:[NSDictionary class]]) { + [properties addEntriesFromDictionary:dic]; + + [customProperties addEntriesFromDictionary:dic]; + + } + } + + if ([tableView.thinkingAnalyticsDelegate respondsToSelector:@selector(thinkingAnalyticsWithAppid_tableView:autoTrackPropertiesAtIndexPath:)]) { + propertyWithAppid = [view.thinkingAnalyticsDelegate thinkingAnalyticsWithAppid_tableView:tableView autoTrackPropertiesAtIndexPath:indexPath]; + } + } + } else if ([view isKindOfClass:[UICollectionView class]]) { + UICollectionView *collectionView = (UICollectionView *)view; + contentView = [collectionView cellForItemAtIndexPath:indexPath]; + if (!contentView) { + [collectionView layoutIfNeeded]; + contentView = [collectionView cellForItemAtIndexPath:indexPath]; + } + properties[TD_EVENT_PROPERTY_ELEMENT_POSITION] = [NSString stringWithFormat: @"%ld:%ld", (unsigned long)indexPath.section, (unsigned long)indexPath.row]; + + elementPosition = [NSString stringWithFormat: @"%ld:%ld", (unsigned long)indexPath.section, (unsigned long)indexPath.row]; + + if ([collectionView.thinkingAnalyticsDelegate conformsToProtocol:@protocol(TDUIViewAutoTrackDelegate)]) { + if ([collectionView.thinkingAnalyticsDelegate respondsToSelector:@selector(thinkingAnalytics_collectionView:autoTrackPropertiesAtIndexPath:)]) { + NSDictionary *dic = [view.thinkingAnalyticsDelegate thinkingAnalytics_collectionView:collectionView autoTrackPropertiesAtIndexPath:indexPath]; + if ([dic isKindOfClass:[NSDictionary class]]) { + [properties addEntriesFromDictionary:dic]; + + [customProperties addEntriesFromDictionary:dic]; + + } + } + if ([collectionView.thinkingAnalyticsDelegate respondsToSelector:@selector(thinkingAnalyticsWithAppid_collectionView:autoTrackPropertiesAtIndexPath:)]) { + propertyWithAppid = [view.thinkingAnalyticsDelegate thinkingAnalyticsWithAppid_collectionView:collectionView autoTrackPropertiesAtIndexPath:indexPath]; + } + } + } + } else { + contentView = view; + properties[TD_EVENT_PROPERTY_ELEMENT_POSITION] = [TDAutoTrackManager getPosition:contentView]; + + elementPosition = [TDAutoTrackManager getPosition:contentView]; + + } + + NSString *content = [TDAutoTrackManager getText:contentView]; + if (content.length > 0) { + properties[TD_EVENT_PROPERTY_ELEMENT_CONTENT] = content; + + elementContent = content; + + } + + + + NSDate *trackDate = [NSDate date]; + for (NSString *appid in self.autoTrackOptions) { + + TDAutoTrackEventType type = (TDAutoTrackEventType)[self.autoTrackOptions[appid] integerValue]; + + if (type & ThinkingAnalyticsEventTypeAppClick) { + + + + + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appid]; + NSMutableDictionary *trackProperties = [properties mutableCopy]; + + NSMutableDictionary *finalProperties = [customProperties mutableCopy]; + + if ([instance innerIsViewTypeIgnored:[view class]]) { + continue; + } + NSDictionary *ignoreViews = view.thinkingAnalyticsIgnoreViewWithAppid; + if (ignoreViews != nil && [[ignoreViews objectForKey:appid] isKindOfClass:[NSNumber class]]) { + BOOL ignore = [[ignoreViews objectForKey:appid] boolValue]; + if (ignore) + continue; + } + + if ([instance isViewControllerIgnored:viewController]) { + continue; + } + + NSDictionary *viewIDs = view.thinkingAnalyticsViewIDWithAppid; + if (viewIDs != nil && [viewIDs objectForKey:appid]) { + trackProperties[TD_EVENT_PROPERTY_ELEMENT_ID] = [viewIDs objectForKey:appid]; + + elementId = [viewIDs objectForKey:appid]; + + } + + NSDictionary *viewProperties = view.thinkingAnalyticsViewPropertiesWithAppid; + if (viewProperties != nil && [viewProperties objectForKey:appid]) { + NSDictionary *properties = [viewProperties objectForKey:appid]; + if ([properties isKindOfClass:[NSDictionary class]]) { + [trackProperties addEntriesFromDictionary:properties]; + + [finalProperties addEntriesFromDictionary:properties]; + } + } + + if (propertyWithAppid) { + NSDictionary *autoTrackproperties = [propertyWithAppid objectForKey:appid]; + if ([autoTrackproperties isKindOfClass:[NSDictionary class]]) { + [trackProperties addEntriesFromDictionary:autoTrackproperties]; + + [finalProperties addEntriesFromDictionary:autoTrackproperties]; + } + } + + TDAutoClickEvent *clickEvent = [[TDAutoClickEvent alloc] initWithName:TD_APP_CLICK_EVENT]; + clickEvent.time = trackDate; + clickEvent.elementId = elementId; + clickEvent.elementType = elementType; + clickEvent.elementContent = elementContent; + clickEvent.elementPosition = elementPosition; + clickEvent.pageTitle = elementPageTitle; + clickEvent.screenName = elementScreenName; + + [instance autoTrackWithEvent:clickEvent properties:finalProperties]; + } + } +} + +- (void)trackWithAppid:(NSString *)appid withOption:(TDAutoTrackEventType)type { + TD_LOCK(self.trackOptionLock); + self.autoTrackOptions[appid] = @(type); + TD_UNLOCK(self.trackOptionLock); + + if (type & ThinkingAnalyticsEventTypeAppClick || type & ThinkingAnalyticsEventTypeAppViewScreen) { + [self swizzleVC]; + } + + if (type & ThinkingAnalyticsEventTypeAppInstall) { + TDAutoTrackEvent *event = [[TDAutoTrackEvent alloc] initWithName:TD_APP_INSTALL_EVENT]; + event.time = [[NSDate date] dateByAddingTimeInterval: -1]; + [self.appInstallTracker trackWithInstanceTag:appid event:event params:nil]; + } + + if (type & ThinkingAnalyticsEventTypeAppEnd) { + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appid]; + [instance innerTimeEvent:TD_APP_END_EVENT]; + } + + if (type & ThinkingAnalyticsEventTypeAppStart) { + dispatch_block_t mainThreadBlock = ^(){ + NSString *eventName = [TDAppState shareInstance].relaunchInBackground ? TD_APP_START_BACKGROUND_EVENT : TD_APP_START_EVENT; + TDAppStartEvent *event = [[TDAppStartEvent alloc] initWithName:eventName]; + event.resumeFromBackground = NO; + if (![TDCorePresetDisableConfig disableStartReason]) { + NSString *reason = [TDRunTime getAppLaunchReason]; + if (reason && reason.length) { + event.startReason = reason; + } + } + [self.appColdStartTracker trackWithInstanceTag:appid event:event params:nil]; + }; + dispatch_async(dispatch_get_main_queue(), mainThreadBlock); + } + + if (type & ThinkingAnalyticsEventTypeAppViewCrash) { + [ThinkingExceptionHandler start]; + } + + TDLogInfo(@"enable auto track: %li", type); +} + +- (void)trackWithEvent:(TDAutoTrackEvent *)event withProperties:(NSDictionary *)properties { + for (NSString *appid in self.autoTrackOptions.allKeys) { + TDAutoTrackEventType type = (TDAutoTrackEventType)[self.autoTrackOptions[appid] integerValue]; + if (type & event.autoTrackEventType) { + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appid]; + [instance autoTrackWithEvent:event properties:properties]; + } + } +} + +- (void)viewControlWillAppear:(UIViewController *)controller { + [self trackViewController:controller]; +} + ++ (UIViewController *)topPresentedViewController { + UIWindow *keyWindow = [self findWindow]; + if (keyWindow != nil && !keyWindow.isKeyWindow) { + [keyWindow makeKeyWindow]; + } + + UIViewController *topController = keyWindow.rootViewController; + if ([topController isKindOfClass:[UINavigationController class]]) { + topController = [(UINavigationController *)topController topViewController]; + } + while (topController.presentedViewController) { + topController = topController.presentedViewController; + } + return topController; +} + +#pragma mark - Private + +- (BOOL)isAutoTrackEventType:(TDAutoTrackEventType)eventType { + BOOL isIgnored = YES; + for (NSString *appid in self.autoTrackOptions) { + TDAutoTrackEventType type = (TDAutoTrackEventType)[self.autoTrackOptions[appid] integerValue]; + isIgnored = !(type & eventType); + if (isIgnored == NO) + break; + } + return !isIgnored; +} + +- (UIViewController *)viewControllerForView:(UIView *)view { + UIResponder *responder = view.nextResponder; + while (responder) { + if ([responder isKindOfClass:[UIViewController class]]) { + if ([responder isKindOfClass:[UINavigationController class]]) { + responder = [(UINavigationController *)responder topViewController]; + continue; + } else if ([responder isKindOfClass:UITabBarController.class]) { + responder = [(UITabBarController *)responder selectedViewController]; + continue; + } + return (UIViewController *)responder; + } + responder = responder.nextResponder; + } + return nil; +} + +- (void)trackViewController:(UIViewController *)controller { + if (![self shouldTrackViewContrller:[controller class]]) { + return; + } + + NSString *pageUrl = nil; + NSString *pageReferrer = nil; + NSString *pageTitle = nil; + NSString *pageScreenName = nil; + NSMutableDictionary *customProperties = [NSMutableDictionary dictionary]; + + NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; + [properties setValue:NSStringFromClass([controller class]) forKey:TD_EVENT_PROPERTY_SCREEN_NAME]; + + pageScreenName = NSStringFromClass([controller class]); + + NSString *controllerTitle = [self titleFromViewController:controller]; + if (controllerTitle) { + [properties setValue:controllerTitle forKey:TD_EVENT_PROPERTY_TITLE]; + + pageTitle = controllerTitle; + } + + NSDictionary *autoTrackerAppidDic; + if ([controller conformsToProtocol:@protocol(TDAutoTracker)]) { + UIViewController *autoTrackerController = (UIViewController *)controller; + NSDictionary *autoTrackerDic; + if ([controller respondsToSelector:@selector(getTrackPropertiesWithAppid)]) + autoTrackerAppidDic = [autoTrackerController getTrackPropertiesWithAppid]; + if ([controller respondsToSelector:@selector(getTrackProperties)]) + autoTrackerDic = [autoTrackerController getTrackProperties]; + + if ([autoTrackerDic isKindOfClass:[NSDictionary class]]) { + [properties addEntriesFromDictionary:autoTrackerDic]; + + [customProperties addEntriesFromDictionary:autoTrackerDic]; + } + } + + NSDictionary *screenAutoTrackerAppidDic; + if ([controller conformsToProtocol:@protocol(TDScreenAutoTracker)]) { + UIViewController *screenAutoTrackerController = (UIViewController *)controller; + if ([screenAutoTrackerController respondsToSelector:@selector(getScreenUrlWithAppid)]) + screenAutoTrackerAppidDic = [screenAutoTrackerController getScreenUrlWithAppid]; + if ([screenAutoTrackerController respondsToSelector:@selector(getScreenUrl)]) { + NSString *currentUrl = [screenAutoTrackerController getScreenUrl]; + [properties setValue:currentUrl forKey:TD_EVENT_PROPERTY_URL_PROPERTY]; + + pageUrl = currentUrl; + + [properties setValue:_referrerViewControllerUrl forKey:TD_EVENT_PROPERTY_REFERRER_URL]; + + pageReferrer = _referrerViewControllerUrl; + + _referrerViewControllerUrl = currentUrl; + } + } + + NSDate *trackDate = [NSDate date]; + for (NSString *appid in self.autoTrackOptions) { + TDAutoTrackEventType type = [self.autoTrackOptions[appid] integerValue]; + if (type & ThinkingAnalyticsEventTypeAppViewScreen) { + + + + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appid]; + NSMutableDictionary *trackProperties = [properties mutableCopy]; + + NSMutableDictionary *finalProperties = [customProperties mutableCopy]; + + if ([instance isViewControllerIgnored:controller] + || [instance innerIsViewTypeIgnored:[controller class]]) { + continue; + } + + if (autoTrackerAppidDic && [autoTrackerAppidDic objectForKey:appid]) { + NSDictionary *dic = [autoTrackerAppidDic objectForKey:appid]; + if ([dic isKindOfClass:[NSDictionary class]]) { + [trackProperties addEntriesFromDictionary:dic]; + + [finalProperties addEntriesFromDictionary:dic]; + } + } + + if (screenAutoTrackerAppidDic && [screenAutoTrackerAppidDic objectForKey:appid]) { + NSString *screenUrl = [screenAutoTrackerAppidDic objectForKey:appid]; + [trackProperties setValue:screenUrl forKey:TD_EVENT_PROPERTY_URL_PROPERTY]; + + pageUrl = screenUrl; + } + + TDAutoPageViewEvent *pageEvent = [[TDAutoPageViewEvent alloc] initWithName:TD_APP_VIEW_EVENT]; + pageEvent.time = trackDate; + pageEvent.pageUrl = pageUrl; + pageEvent.pageTitle = pageTitle; + pageEvent.referrer = pageReferrer; + pageEvent.screenName = pageScreenName; + + [instance autoTrackWithEvent:pageEvent properties:finalProperties]; + } + } +} + +- (BOOL)shouldTrackViewContrller:(Class)aClass { + return ![TDPublicConfig.controllers containsObject:NSStringFromClass(aClass)]; +} + +- (TDAutoTrackEventType)autoTrackOptionForAppid:(NSString *)appid { + return (TDAutoTrackEventType)[[self.autoTrackOptions objectForKey:appid] integerValue]; +} + +- (void)swizzleSelected:(UIView *)view delegate:(id)delegate { + if ([view isKindOfClass:[UITableView class]] + && [delegate conformsToProtocol:@protocol(UITableViewDelegate)]) { + void (^block)(id, SEL, id, id) = ^(id target, SEL command, UITableView *tableView, NSIndexPath *indexPath) { + [self trackEventView:tableView withIndexPath:indexPath]; + }; + + [TDSwizzler swizzleSelector:@selector(tableView:didSelectRowAtIndexPath:) + onClass:[delegate class] + withBlock:block + named:@"td_table_select"]; + } + + if ([view isKindOfClass:[UICollectionView class]] + && [delegate conformsToProtocol:@protocol(UICollectionViewDelegate)]) { + + void (^block)(id, SEL, id, id) = ^(id target, SEL command, UICollectionView *collectionView, NSIndexPath *indexPath) { + [self trackEventView:collectionView withIndexPath:indexPath]; + }; + [TDSwizzler swizzleSelector:@selector(collectionView:didSelectItemAtIndexPath:) + onClass:[delegate class] + withBlock:block + named:@"td_collection_select"]; + } +} + +- (void)swizzleVC { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + void (^tableViewBlock)(UITableView *tableView, + SEL cmd, + id delegate) = + ^(UITableView *tableView, SEL cmd, id delegate) { + if (!delegate) { + return; + } + + [self swizzleSelected:tableView delegate:delegate]; + }; + + [TDSwizzler swizzleSelector:@selector(setDelegate:) + onClass:[UITableView class] + withBlock:tableViewBlock + named:@"td_table_delegate"]; + + void (^collectionViewBlock)(UICollectionView *, SEL, id) = ^(UICollectionView *collectionView, SEL cmd, id delegate) { + if (nil == delegate) { + return; + } + + [self swizzleSelected:collectionView delegate:delegate]; + }; + [TDSwizzler swizzleSelector:@selector(setDelegate:) + onClass:[UICollectionView class] + withBlock:collectionViewBlock + named:@"td_collection_delegate"]; + + + [UIViewController td_swizzleMethod:@selector(viewWillAppear:) + withMethod:@selector(td_autotrack_viewWillAppear:) + error:NULL]; + + [UIApplication td_swizzleMethod:@selector(sendAction:to:from:forEvent:) + withMethod:@selector(td_sendAction:to:from:forEvent:) + error:NULL]; + }); +} + ++ (NSString *)getPosition:(UIView *)view { + NSString *position = nil; + if ([view isKindOfClass:[UIView class]] && view.thinkingAnalyticsIgnoreView) { + return nil; + } + + if ([view isKindOfClass:[UITabBar class]]) { + UITabBar *tabbar = (UITabBar *)view; + position = [NSString stringWithFormat: @"%ld", (long)[tabbar.items indexOfObject:tabbar.selectedItem]]; + } else if ([view isKindOfClass:[UISegmentedControl class]]) { + UISegmentedControl *segment = (UISegmentedControl *)view; + position = [NSString stringWithFormat:@"%ld", (long)segment.selectedSegmentIndex]; + } else if ([view isKindOfClass:[UIProgressView class]]) { + UIProgressView *progress = (UIProgressView *)view; + position = [NSString stringWithFormat:@"%f", progress.progress]; + } else if ([view isKindOfClass:[UIPageControl class]]) { + UIPageControl *pageControl = (UIPageControl *)view; + position = [NSString stringWithFormat:@"%ld", (long)pageControl.currentPage]; + } + + return position; +} + ++ (NSString *)getText:(NSObject *)obj { + NSString *text = nil; + if ([obj isKindOfClass:[UIView class]] && [(UIView *)obj thinkingAnalyticsIgnoreView]) { + return nil; + } + + if ([obj isKindOfClass:[UIButton class]]) { + text = ((UIButton *)obj).currentTitle; + } else if ([obj isKindOfClass:[UITextView class]] || + [obj isKindOfClass:[UITextField class]]) { + //ignore + } else if ([obj isKindOfClass:[UILabel class]]) { + text = ((UILabel *)obj).text; + } else if ([obj isKindOfClass:[UIPickerView class]]) { + UIPickerView *picker = (UIPickerView *)obj; + NSInteger sections = picker.numberOfComponents; + NSMutableArray *titles = [NSMutableArray array]; + + for(NSInteger i = 0; i < sections; i++) { + NSInteger row = [picker selectedRowInComponent:i]; + NSString *title; + if ([picker.delegate + respondsToSelector:@selector(pickerView:titleForRow:forComponent:)]) { + title = [picker.delegate pickerView:picker titleForRow:row forComponent:i]; + } else if ([picker.delegate + respondsToSelector:@selector(pickerView:attributedTitleForRow:forComponent:)]) { + title = [picker.delegate + pickerView:picker + attributedTitleForRow:row forComponent:i].string; + } + [titles addObject:title ?: @""]; + } + if (titles.count > 0) { + text = [titles componentsJoinedByString:@","]; + } + } else if ([obj isKindOfClass:[UIDatePicker class]]) { + UIDatePicker *picker = (UIDatePicker *)obj; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + formatter.dateFormat = kDefaultTimeFormat; + text = [formatter stringFromDate:picker.date]; + } else if ([obj isKindOfClass:[UISegmentedControl class]]) { + UISegmentedControl *segment = (UISegmentedControl *)obj; + text = [NSString stringWithFormat:@"%@", [segment titleForSegmentAtIndex:segment.selectedSegmentIndex]]; + } else if ([obj isKindOfClass:[UISwitch class]]) { + UISwitch *switchItem = (UISwitch *)obj; + text = switchItem.on ? @"on" : @"off"; + } else if ([obj isKindOfClass:[UISlider class]]) { + UISlider *slider = (UISlider *)obj; + text = [NSString stringWithFormat:@"%f", [slider value]]; + } else if ([obj isKindOfClass:[UIStepper class]]) { + UIStepper *step = (UIStepper *)obj; + text = [NSString stringWithFormat:@"%f", [step value]]; + } else { + if ([obj isKindOfClass:[UIView class]]) { + for(UIView *subView in [(UIView *)obj subviews]) { + text = [TDAutoTrackManager getText:subView]; + if ([text isKindOfClass:[NSString class]] && text.length > 0) { + break; + } + } + } + } + return text; +} + +- (NSString *)titleFromViewController:(UIViewController *)viewController { + if (!viewController) { + return nil; + } + + UIView *titleView = viewController.navigationItem.titleView; + NSString *elementContent = nil; + if (titleView) { + elementContent = [TDAutoTrackManager getText:titleView]; + } + + return elementContent.length > 0 ? elementContent : viewController.navigationItem.title; +} + ++ (UIWindow *)findWindow { + UIApplication *application = [TDAppState sharedApplication]; + if (![application isKindOfClass:UIApplication.class]) { + return nil; + } + + UIWindow *window = application.keyWindow; + if (window == nil || window.windowLevel != UIWindowLevelNormal) { + for (window in application.windows) { + if (window.windowLevel == UIWindowLevelNormal) { + break; + } + } + } + + if (@available(iOS 13.0, tvOS 13, *)) { + NSSet *scenes = [[TDAppState sharedApplication] valueForKey:@"connectedScenes"]; + for (id scene in scenes) { + if (window) { + break; + } + + id activationState = [scene valueForKeyPath:@"activationState"]; + BOOL isActive = activationState != nil && [activationState integerValue] == 0; + if (isActive) { + Class WindowScene = NSClassFromString(@"UIWindowScene"); + if ([scene isKindOfClass:WindowScene]) { + NSArray *windows = [scene valueForKeyPath:@"windows"]; + for (UIWindow *w in windows) { + if (w.isKeyWindow) { + window = w; + break; + } + } + } + } + } + } + + return window; +} + +//MARK: - App Life Cycle + +- (void)registerAppLifeCycleListener { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + + [notificationCenter addObserver:self selector:@selector(appStateWillChangeNotification:) name:kTDAppLifeCycleStateWillChangeNotification object:nil]; +} + +- (void)appStateWillChangeNotification:(NSNotification *)notification { + TDAppLifeCycleState newState = [[notification.userInfo objectForKey:kTDAppLifeCycleNewStateKey] integerValue]; + TDAppLifeCycleState oldState = [[notification.userInfo objectForKey:kTDAppLifeCycleOldStateKey] integerValue]; + + if (newState == TDAppLifeCycleStateStart) { + for (NSString *appid in self.autoTrackOptions.allKeys) { + TDAutoTrackEventType type = (TDAutoTrackEventType)[self.autoTrackOptions[appid] integerValue]; + + // Only open the start event of collecting hot start. Cold start event, reported when automatic collection is turned on + if ((type & ThinkingAnalyticsEventTypeAppStart) && oldState != TDAppLifeCycleStateInit) { + NSString *eventName = [TDAppState shareInstance].relaunchInBackground ? TD_APP_START_BACKGROUND_EVENT : TD_APP_START_EVENT; + TDAppStartEvent *event = [[TDAppStartEvent alloc] initWithName:eventName]; + event.resumeFromBackground = YES; + + if (![TDCorePresetDisableConfig disableStartReason]) { + NSString *reason = [TDRunTime getAppLaunchReason]; + if (reason && reason.length) { + event.startReason = reason; + } + } + [self.appHotStartTracker trackWithInstanceTag:appid event:event params:@{}]; + } + + if (type & ThinkingAnalyticsEventTypeAppEnd) { + + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appid]; + [instance innerTimeEvent:TD_APP_END_EVENT]; + } + } + } else if (newState == TDAppLifeCycleStateEnd) { + for (NSString *appid in self.autoTrackOptions) { + TDAutoTrackEventType type = (TDAutoTrackEventType)[self.autoTrackOptions[appid] integerValue]; + if (type & ThinkingAnalyticsEventTypeAppEnd) { + TDAppEndEvent *event = [[TDAppEndEvent alloc] initWithName:TD_APP_END_EVENT]; + td_dispatch_main_sync_safe(^{ + + NSString *screenName = NSStringFromClass([[TDAutoTrackManager topPresentedViewController] class]); + event.screenName = screenName; + [self.appEndTracker trackWithInstanceTag:appid event:event params:@{}]; + }); + } + + if (type & ThinkingAnalyticsEventTypeAppStart) { + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appid]; + [instance innerTimeEvent:TD_APP_START_EVENT]; + } + } + } +} + +//MARK: - Getter & Setter + +- (TDHotStartTracker *)appHotStartTracker { + if (!_appHotStartTracker) { + _appHotStartTracker = [[TDHotStartTracker alloc] init]; + } + return _appHotStartTracker; +} + +- (TDColdStartTracker *)appColdStartTracker { + if (!_appColdStartTracker) { + _appColdStartTracker = [[TDColdStartTracker alloc] init]; + } + return _appColdStartTracker; +} + +- (TDInstallTracker *)appInstallTracker { + if (!_appInstallTracker) { + _appInstallTracker = [[TDInstallTracker alloc] init]; + } + return _appInstallTracker; +} + +- (TDAppEndTracker *)appEndTracker { + if (!_appEndTracker) { + _appEndTracker = [[TDAppEndTracker alloc] init]; + } + return _appEndTracker; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.m.meta new file mode 100644 index 0000000..c0a1b5d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4df3c68e4c10242c4a93e8087f0cc5bd +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackProtocol.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackProtocol.h new file mode 100644 index 0000000..5ba79a5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackProtocol.h @@ -0,0 +1,80 @@ +// +// TDAutoTrackProtocol.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#ifndef TDAutoTrackProtocol_h +#define TDAutoTrackProtocol_h + +#import + +@protocol TDUIViewAutoTrackDelegate + +@optional + +/** + UITableView event properties + + @return event properties + */ +- (NSDictionary *)thinkingAnalytics_tableView:(UITableView *)tableView autoTrackPropertiesAtIndexPath:(NSIndexPath *)indexPath; + +/** + APPID UITableView event properties + + @return event properties + */ +- (NSDictionary *)thinkingAnalyticsWithAppid_tableView:(UITableView *)tableView autoTrackPropertiesAtIndexPath:(NSIndexPath *)indexPath; + +@optional + +/** + UICollectionView event properties + + @return event properties + */ +- (NSDictionary *)thinkingAnalytics_collectionView:(UICollectionView *)collectionView autoTrackPropertiesAtIndexPath:(NSIndexPath *)indexPath; + +/** + APPID UICollectionView event properties + + @return event properties + */ +- (NSDictionary *)thinkingAnalyticsWithAppid_collectionView:(UICollectionView *)collectionView autoTrackPropertiesAtIndexPath:(NSIndexPath *)indexPath; + +@end + + +@protocol TDAutoTracker + +@optional + +- (NSDictionary *)getTrackProperties; + + +- (NSDictionary *)getTrackPropertiesWithAppid; + +@end + +/** + Automatically track the page + */ +@protocol TDScreenAutoTracker + +@optional + +/** + Attributes for custom page view events + */ +- (NSString *)getScreenUrl; + +/** + Configure the properties of the APPID custom page view event + */ +- (NSDictionary *)getScreenUrlWithAppid; + +@end + +#endif /* TDAutoTrackProtocol_h */ diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackProtocol.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackProtocol.h.meta new file mode 100644 index 0000000..d43c453 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackProtocol.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2a15bdeebde374a98944129726bc5717 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackPublicHeader.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackPublicHeader.h new file mode 100644 index 0000000..f93e611 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackPublicHeader.h @@ -0,0 +1,29 @@ +// +// TDAutoTrackPublicHeader.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#ifndef TDAutoTrackPublicHeader_h +#define TDAutoTrackPublicHeader_h + +#if __has_include() +#import +#else +#import "TDAutoTrackProtocol.h" +#endif + +#if __has_include() +#import +#else +#import "UIView+ThinkingAnalytics.h" +#endif + +#if __has_include() +#import +#else +#import "TDAutoTrackConst.h" +#endif + +#endif /* TDAutoTrackPublicHeader_h */ diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackPublicHeader.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackPublicHeader.h.meta new file mode 100644 index 0000000..31f84b4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDAutoTrackPublicHeader.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4194a7b3dfc4941a1b12956a2fee33d4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.h new file mode 100644 index 0000000..ab653f6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.h @@ -0,0 +1,21 @@ +// +// TDRunTime.h +// ThinkingSDK +// +// Created by wwango on 2021/12/30. +// When used for plug-in, get the class name and parameters through reflection +// This class is not thread-safe, pay attention to multi-threading issues when using it + + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDRunTime : NSObject + +// start reason ++ (NSString *)getAppLaunchReason; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.h.meta new file mode 100644 index 0000000..48213bf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a6c0e615e93964aa4b486dc9627fcb49 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.m new file mode 100644 index 0000000..7adba66 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.m @@ -0,0 +1,53 @@ +// +// TDRunTime.m +// ThinkingSDK +// +// Created by wwango on 2021/12/30. +// + +#import "TDRunTime.h" + +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@implementation TDRunTime + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + ++ (NSString *)getAppLaunchReason { + // start reason + Class cls = NSClassFromString(@"TDAppLaunchReason"); + id appLaunch = [cls performSelector:@selector(sharedInstance)]; + + if (appLaunch && [appLaunch respondsToSelector:@selector(appLaunchParams)] && ![TDCorePresetDisableConfig disableStartReason]) { + NSDictionary *startReason = [appLaunch performSelector:@selector(appLaunchParams)]; + NSString *url = startReason[@"url"]; + NSDictionary *data = startReason[@"data"]; + if (url.length == 0 && data.allKeys.count == 0) { + return @""; + } else { + if (data.allKeys.count == 0) { + startReason = @{@"url":url, @"data":@""}; + } + NSString *startReasonString = [TDJSONUtil JSONStringForObject:startReason]; + if (startReasonString && startReasonString.length) { + return startReasonString; + } + } + } + return @""; +} + +#pragma clang diagnostic pop + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.m.meta new file mode 100644 index 0000000..dc33029 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/TDRunTime.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: da6f2608c3dcc4a92b3e15110e509538 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker.meta new file mode 100644 index 0000000..7b1ccad --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c350cba01555c41e4aceb6039c8408a8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.h new file mode 100644 index 0000000..b8787ad --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.h @@ -0,0 +1,16 @@ +// +// TDAppEndTracker.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/16. +// + +#import "TDAutoTracker.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAppEndTracker : TDAutoTracker + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.h.meta new file mode 100644 index 0000000..a415e45 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c086add947134424b809df8a51900ab1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.m new file mode 100644 index 0000000..7618737 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.m @@ -0,0 +1,12 @@ +// +// TDAppEndTracker.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/16. +// + +#import "TDAppEndTracker.h" + +@implementation TDAppEndTracker + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.m.meta new file mode 100644 index 0000000..55c1e5d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAppEndTracker.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4d35cb2477a7d4d7cb3de90ac7b73eca +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.h new file mode 100644 index 0000000..471beba --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.h @@ -0,0 +1,28 @@ +// +// TDAutoTracker.h +// ThinkingSDK +// +// Created by wwango on 2021/10/13. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import +#import "ThinkingAnalyticsSDK.h" +#import "TDAutoTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAutoTracker : NSObject + +@property (atomic, assign) BOOL isOneTime; + +@property (atomic, assign) BOOL autoFlush; + +@property (atomic, assign) BOOL additionalCondition; + +- (void)trackWithInstanceTag:(NSString *)instanceName event:(TDAutoTrackEvent *)event params:(nullable NSDictionary *)params; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.h.meta new file mode 100644 index 0000000..ce106e8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: eb845cd4c31074234baa5452aa01b957 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.m new file mode 100644 index 0000000..c68d03d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.m @@ -0,0 +1,77 @@ +// +// TDAutoTracker.m +// ThinkingSDK +// +// Created by wwango on 2021/10/13. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDAutoTracker.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +#if __has_include() +#import +#else +#import "ThinkingDataCore.h" +#endif + +@interface TDAutoTracker () + +@property (nonatomic, strong) NSMutableDictionary *trackCounts; + +@end + +@implementation TDAutoTracker + +- (instancetype)init +{ + self = [super init]; + if (self) { + _isOneTime = NO; + _autoFlush = YES; + _additionalCondition = YES; + + self.trackCounts = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)trackWithInstanceTag:(NSString *)instanceName event:(TDAutoTrackEvent *)event params:(NSDictionary *)params { + if ([self canTrackWithInstanceToken:instanceName]) { + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:instanceName]; +#ifdef DEBUG + if (!instance) { + @throw [NSException exceptionWithName:@"Thinkingdata Exception" reason:[NSString stringWithFormat:@"check this thinking instance, instanceTag: %@", instanceName] userInfo:nil]; + } +#endif + [instance autoTrackWithEvent:event properties:params]; + + if (self.autoFlush) [instance innerFlush]; + + if ([[self class] isEqual:NSClassFromString(@"TDInstallTracker")]) { + [TDNotificationManager postAnalyticsAppInstallEventWithAppId:instanceName]; + } + } +} + +- (BOOL)canTrackWithInstanceToken:(NSString *)token { + + if (!self.additionalCondition) { + return NO; + } + + NSInteger trackCount = [self.trackCounts[token] integerValue]; + + if (self.isOneTime && trackCount >= 1) { + return NO; + } + + if (self.isOneTime) { + trackCount++; + self.trackCounts[token] = @(trackCount); + } + + return YES; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.m.meta new file mode 100644 index 0000000..be5a54e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDAutoTracker.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 37c4139007b304431bc20e515eacb5bb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.h new file mode 100644 index 0000000..9b76e5c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.h @@ -0,0 +1,16 @@ +// +// TDColdStartTracker.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDAutoTracker.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDColdStartTracker : TDAutoTracker + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.h.meta new file mode 100644 index 0000000..430716a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1d55b13ee71a645fb9ac64cf57507008 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.m new file mode 100644 index 0000000..04fc57a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.m @@ -0,0 +1,19 @@ +// +// TDColdStartTracker.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDColdStartTracker.h" + +@implementation TDColdStartTracker + +- (instancetype)init { + if (self = [super init]) { + self.isOneTime = YES; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.m.meta new file mode 100644 index 0000000..9b8c06b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDColdStartTracker.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f877656a50550492bac50b5751b362a5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.h new file mode 100644 index 0000000..4323db2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.h @@ -0,0 +1,16 @@ +// +// TDHotStartTracker.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDAutoTracker.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDHotStartTracker : TDAutoTracker + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.h.meta new file mode 100644 index 0000000..e4279ea --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4fb20614614b44d0ca7cc5cca29271d1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.m new file mode 100644 index 0000000..53cecc0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.m @@ -0,0 +1,12 @@ +// +// TDHotStartTracker.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDHotStartTracker.h" + +@implementation TDHotStartTracker + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.m.meta new file mode 100644 index 0000000..8c53d0f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDHotStartTracker.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ddf70b375e3c245f9a3484f2def07096 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.h new file mode 100644 index 0000000..f9f6aeb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.h @@ -0,0 +1,17 @@ +// +// TDInstallTracker.h +// ThinkingSDK +// +// Created by wwango on 2021/10/13. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDAutoTracker.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDInstallTracker : TDAutoTracker + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.h.meta new file mode 100644 index 0000000..17f4ba7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b5418cddfc5c94976b671523079f3d99 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.m new file mode 100644 index 0000000..26d31cb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.m @@ -0,0 +1,22 @@ +// +// TDInstallTracker.m +// ThinkingSDK +// +// Created by wwango on 2021/10/13. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDInstallTracker.h" +#import "TDDeviceInfo.h" + +@implementation TDInstallTracker + +- (BOOL)isOneTime { + return YES; +} + +- (BOOL)additionalCondition { + return [TDDeviceInfo sharedManager].isFirstOpen; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.m.meta new file mode 100644 index 0000000..2b9d7c9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/Tracker/TDInstallTracker.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 60a777c3a36f044dca34b330d75949f1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit.meta new file mode 100644 index 0000000..84f1be0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 110fe4351dde84adaaceb4d3d1a724bc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.h new file mode 100644 index 0000000..6560494 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.h @@ -0,0 +1,14 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIApplication (AutoTrack) + +- (BOOL)td_sendAction:(SEL)action + to:(nullable id)to + from:(nullable id)from + forEvent:(nullable UIEvent *)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.h.meta new file mode 100644 index 0000000..0c684c3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4231e3dad819f4cbcba8a5f9f21ec1fb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.m new file mode 100644 index 0000000..1d3640f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.m @@ -0,0 +1,24 @@ +#import "UIApplication+AutoTrack.h" +#import "TDAutoTrackManager.h" + +@implementation UIApplication (AutoTrack) + +- (BOOL)td_sendAction:(SEL)action to:(id)to from:(id)from forEvent:(UIEvent *)event { + if ([from isKindOfClass:[UIControl class]]) { + if (([from isKindOfClass:[UISwitch class]] || + [from isKindOfClass:[UISegmentedControl class]] || + [from isKindOfClass:[UIStepper class]])) { + [[TDAutoTrackManager sharedManager] trackEventView:from]; + } + + else if ([event isKindOfClass:[UIEvent class]] && + event.type == UIEventTypeTouches && + [[[event allTouches] anyObject] phase] == UITouchPhaseEnded) { + [[TDAutoTrackManager sharedManager] trackEventView:from]; + } + } + + return [self td_sendAction:action to:to from:from forEvent:event]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.m.meta new file mode 100644 index 0000000..f548302 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIApplication+AutoTrack.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 894a13b5eda684890a9d7cac8ae3126e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.h new file mode 100644 index 0000000..30d41cc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.h @@ -0,0 +1,51 @@ +// +// UIView+ThinkingAnalytics.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIView (ThinkingAnalytics) + +/** + Set the control element ID + */ +@property (copy,nonatomic) NSString *thinkingAnalyticsViewID; + +/** + Configure the control element ID of APPID + */ +@property (strong,nonatomic) NSDictionary *thinkingAnalyticsViewIDWithAppid; + +/** + Ignore the click event of a control + */ +@property (nonatomic,assign) BOOL thinkingAnalyticsIgnoreView; + +/** + Configure APPID to ignore the click event of a control + */ +@property (strong,nonatomic) NSDictionary *thinkingAnalyticsIgnoreViewWithAppid; + +/** + Properties of custom control click event + */ +@property (strong,nonatomic) NSDictionary *thinkingAnalyticsViewProperties; + +/** + Configure the properties of the APPID custom control click event + */ +@property (strong,nonatomic) NSDictionary *thinkingAnalyticsViewPropertiesWithAppid; + +/** + thinkingAnalyticsDelegate + */ +@property (nonatomic, weak, nullable) id thinkingAnalyticsDelegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.h.meta new file mode 100644 index 0000000..981fd57 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a5a8c330e1377497dba3d444335c5d1d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.m new file mode 100644 index 0000000..6cb6509 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.m @@ -0,0 +1,77 @@ +// +// UIView+ThinkingAnalytics.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "UIView+ThinkingAnalytics.h" +#import + +static char TD_AUTOTRACK_VIEW_ID; +static char TD_AUTOTRACK_VIEW_ID_APPID; +static char TD_AUTOTRACK_VIEW_IGNORE; +static char TD_AUTOTRACK_VIEW_IGNORE_APPID; +static char TD_AUTOTRACK_VIEW_PROPERTIES; +static char TD_AUTOTRACK_VIEW_PROPERTIES_APPID; +static char TD_AUTOTRACK_VIEW_DELEGATE; + +@implementation UIView (ThinkingAnalytics) + +- (NSString *)thinkingAnalyticsViewID { + return objc_getAssociatedObject(self, &TD_AUTOTRACK_VIEW_ID); +} + +- (void)setThinkingAnalyticsViewID:(NSString *)thinkingAnalyticsViewID { + objc_setAssociatedObject(self, &TD_AUTOTRACK_VIEW_ID, thinkingAnalyticsViewID, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + +- (BOOL)thinkingAnalyticsIgnoreView { + return [objc_getAssociatedObject(self, &TD_AUTOTRACK_VIEW_IGNORE) boolValue]; +} + +- (void)setThinkingAnalyticsIgnoreView:(BOOL)thinkingAnalyticsIgnoreView { + objc_setAssociatedObject(self, &TD_AUTOTRACK_VIEW_IGNORE, [NSNumber numberWithBool:thinkingAnalyticsIgnoreView], OBJC_ASSOCIATION_ASSIGN); +} + +- (NSDictionary *)thinkingAnalyticsIgnoreViewWithAppid { + return objc_getAssociatedObject(self, &TD_AUTOTRACK_VIEW_IGNORE_APPID); +} + +- (void)setThinkingAnalyticsIgnoreViewWithAppid:(NSDictionary *)thinkingAnalyticsViewProperties { + objc_setAssociatedObject(self, &TD_AUTOTRACK_VIEW_IGNORE_APPID, thinkingAnalyticsViewProperties, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSDictionary *)thinkingAnalyticsViewIDWithAppid { + return objc_getAssociatedObject(self, &TD_AUTOTRACK_VIEW_ID_APPID); +} + +- (void)setThinkingAnalyticsViewIDWithAppid:(NSDictionary *)thinkingAnalyticsViewProperties { + objc_setAssociatedObject(self, &TD_AUTOTRACK_VIEW_ID_APPID, thinkingAnalyticsViewProperties, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSDictionary *)thinkingAnalyticsViewProperties { + return objc_getAssociatedObject(self, &TD_AUTOTRACK_VIEW_PROPERTIES); +} + +- (void)setThinkingAnalyticsViewProperties:(NSDictionary *)thinkingAnalyticsViewProperties { + objc_setAssociatedObject(self, &TD_AUTOTRACK_VIEW_PROPERTIES, thinkingAnalyticsViewProperties, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSDictionary *)thinkingAnalyticsViewPropertiesWithAppid { + return objc_getAssociatedObject(self, &TD_AUTOTRACK_VIEW_PROPERTIES_APPID); +} + +- (void)setThinkingAnalyticsViewPropertiesWithAppid:(NSDictionary *)thinkingAnalyticsViewProperties { + objc_setAssociatedObject(self, &TD_AUTOTRACK_VIEW_PROPERTIES_APPID, thinkingAnalyticsViewProperties, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (id)thinkingAnalyticsDelegate { + return objc_getAssociatedObject(self, &TD_AUTOTRACK_VIEW_DELEGATE); +} + +- (void)setThinkingAnalyticsDelegate:(id)thinkingAnalyticsDelegate { + objc_setAssociatedObject(self, &TD_AUTOTRACK_VIEW_DELEGATE, thinkingAnalyticsDelegate, OBJC_ASSOCIATION_ASSIGN); +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.m.meta new file mode 100644 index 0000000..1d00c2c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIView+ThinkingAnalytics.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 386fae234a3a846a98321d5e551238b5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.h b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.h new file mode 100644 index 0000000..4e2e17c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.h @@ -0,0 +1,7 @@ +#import + +@interface UIViewController (AutoTrack) + +- (void)td_autotrack_viewWillAppear:(BOOL)animated; + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.h.meta new file mode 100644 index 0000000..39215b8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 529ad0356001a49ae855e1c55175fba5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.m b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.m new file mode 100644 index 0000000..f563f69 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.m @@ -0,0 +1,16 @@ +#import "UIViewController+AutoTrack.h" +#import "TDAutoTrackManager.h" +#import "TDLogging.h" + +@implementation UIViewController (AutoTrack) + +- (void)td_autotrack_viewWillAppear:(BOOL)animated { + @try { + [[TDAutoTrackManager sharedManager] viewControlWillAppear:self]; + } @catch (NSException *exception) { + TDLogError(@"%@ error: %@", self, exception); + } + [self td_autotrack_viewWillAppear:animated]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.m.meta new file mode 100644 index 0000000..0db0e20 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/AutoTrack/UIKit/UIViewController+AutoTrack.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: efb2847493fa54184af815adecc38259 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Config.meta new file mode 100644 index 0000000..18325ff --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c12da08287e3048dabcda0f70108dd46 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.h new file mode 100644 index 0000000..d6588ae --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.h @@ -0,0 +1,127 @@ +#import + +#if __has_include() +#import +#else +#import "TDConstant.h" +#endif + +#if __has_include() +#import +#else +#import "TDSecurityPolicy.h" +#endif + +#if TARGET_OS_IOS +#if __has_include() +#import +#else +#import "TDSecretKey.h" +#endif +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDConfig:NSObject + +/// app id +@property (atomic, copy) NSString *appid; + +/// server url +@property (atomic, copy) NSString *serverUrl; + +/// SDK mode +@property (nonatomic, assign) TDMode mode; + +/// Set default time zone. +/// You can use this time zone to compare the offset of the current time zone and the default time zone +@property (nonatomic, strong) NSTimeZone *defaultTimeZone; + +/// SDK instance name +@property (nonatomic, copy) NSString *name; + +/// Set the network environment for reporting data +@property (nonatomic, assign) TDReportingNetworkType reportingNetworkType; + +/// Data upload interval +@property (nonatomic, strong) NSNumber *uploadInterval; + +/// When there is data to upload, when the number of data cache reaches the uploadsize, upload the data immediately +@property (nonatomic, strong) NSNumber *uploadSize; + +/// Event blacklist, event names that are not counted are added here +@property (strong, nonatomic) NSArray *disableEvents; + +/// instance Token +@property (atomic, copy) NSString *(^getInstanceName)(void); + +/// Initialize and configure background self-starting events +/// YES: Collect background self-starting events +/// NO: Do not collect background self-starting events +@property (nonatomic, assign) BOOL trackRelaunchedInBackgroundEvents; + +/// app launchOptions +@property (nonatomic, copy) NSDictionary *launchOptions; + +/// Initialize and configure the certificate verification policy +@property (nonatomic, strong) TDSecurityPolicy *securityPolicy; + +/// share data with App Extension +@property (nonatomic, copy) NSString *appGroupName; + +@property (nonatomic, assign) BOOL enableAutoPush; + +/// Enable the automatic time calibration function +@property (nonatomic, assign) BOOL enableAutoCalibrated; + +/// server url +@property (nonatomic, copy) NSString *configureURL DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with property: serverUrl"); + +#if TARGET_OS_IOS +/// enable encryption +@property (nonatomic, assign) BOOL enableEncrypt DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: -enableEncryptWithVersion:publicKey:"); +/// Get local key configuration +@property (nonatomic, strong) TDSecretKey *secretKey DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: -enableEncryptWithVersion:publicKey:"); +#endif +/** + Debug Mode +*/ +@property (nonatomic, assign) ThinkingAnalyticsDebugMode debugMode DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with property: mode"); +/** + Network environment for data transmission + */ +@property (assign, nonatomic) ThinkingNetworkType networkTypePolicy DEPRECATED_MSG_ATTRIBUTE("Deprecated. don't need this property"); +/** + Set automatic burying type + */ +@property (assign, nonatomic) ThinkingAnalyticsAutoTrackEventType autoTrackEventType DEPRECATED_MSG_ATTRIBUTE("Deprecated. don't need this property"); +/** + The maximum number of cached events, the default is 10000, the minimum is 5000 + */ +@property (class, nonatomic) NSInteger maxNumEvents DEPRECATED_MSG_ATTRIBUTE("Please config TAConfigInfo in main info.plist"); +/** + Data cache expiration time, the default is 10 days, the longest is 10 days + */ +@property (class, nonatomic) NSInteger expirationDays DEPRECATED_MSG_ATTRIBUTE("Please config TAConfigInfo in main info.plist"); + +- (void)setNetworkType:(ThinkingAnalyticsNetworkType)type DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: -setUploadNetworkType:"); +- (void)updateConfig:(void(^)(NSDictionary *dict))block DEPRECATED_MSG_ATTRIBUTE("Deprecated"); +- (NSString *)getMapInstanceToken DEPRECATED_MSG_ATTRIBUTE("Deprecated"); ++ (TDConfig *)defaultTDConfig DEPRECATED_MSG_ATTRIBUTE("Deprecated"); + +/// Initialize the SDK config file +/// @param appId project app Id +/// @param serverUrl Thinking Engine receiver url +- (instancetype)initWithAppId:(NSString *)appId serverUrl:(NSString *)serverUrl; + +/// enable encrypt +/// @param version version of the encryption configuration file +/// @param publicKey public key +- (void)enableEncryptWithVersion:(NSUInteger)version publicKey:(NSString *)publicKey; + +/// enable DNS parse. Must close ATS in info.plist. +/// @param services DNS service list +- (void)enableDNSServcie:(NSArray *)services; + +@end +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.h.meta new file mode 100644 index 0000000..620544f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 138e749d506714c15bc9b7134cc64ee2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.m new file mode 100644 index 0000000..9369b06 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.m @@ -0,0 +1,326 @@ +#import "TDConfig.h" + +#import "TDAnalyticsNetwork.h" +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDSecurityPolicy.h" +#import "TDFile.h" +#import "TDConfigPrivate.h" + +#if __has_include() +#import +#else +#import "TDCalibratedTime.h" +#endif +#if __has_include() +#import +#else +#import "NSString+TDCore.h" +#endif + +#define TDSDKSETTINGS_PLIST_SETTING_IMPL(TYPE, PLIST_KEY, GETTER, SETTER, DEFAULT_VALUE, ENABLE_CACHE) \ +static TYPE *g_##PLIST_KEY = nil; \ ++ (TYPE *)GETTER \ +{ \ + if (!g_##PLIST_KEY && ENABLE_CACHE) { \ + g_##PLIST_KEY = [[[NSUserDefaults standardUserDefaults] objectForKey:@#PLIST_KEY] copy]; \ + } \ + if (!g_##PLIST_KEY) { \ + g_##PLIST_KEY = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@#PLIST_KEY] copy] ?: DEFAULT_VALUE; \ + } \ + return g_##PLIST_KEY; \ +} \ ++ (void)SETTER:(TYPE *)value { \ + g_##PLIST_KEY = [value copy]; \ + if (ENABLE_CACHE) { \ + if (value) { \ + [[NSUserDefaults standardUserDefaults] setObject:value forKey:@#PLIST_KEY]; \ + } else { \ + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@#PLIST_KEY]; \ + } \ + } \ +} + + +#define kTAConfigInfo @"TAConfigInfo" + +static NSDictionary *configInfo; + +@interface TDConfig () +@property (nonatomic, assign) ThinkingNetworkType innerNetworkType; + +@end + +@implementation TDConfig + +TDSDKSETTINGS_PLIST_SETTING_IMPL(NSNumber, ThinkingSDKMaxCacheSize, _maxNumEventsNumber, _setMaxNumEventsNumber, @10000, NO); +TDSDKSETTINGS_PLIST_SETTING_IMPL(NSNumber, ThinkingSDKExpirationDays, _expirationDaysNumber, _setExpirationDaysNumber, @10, NO); + +- (instancetype)init { + self = [super init]; + if (self) { + self.reportingNetworkType = TDReportingNetworkTypeALL; + self.mode = TDModeNormal; + + _trackRelaunchedInBackgroundEvents = NO; + _autoTrackEventType = ThinkingAnalyticsEventTypeNone; + _networkTypePolicy = ThinkingNetworkTypeWIFI | ThinkingNetworkType3G | ThinkingNetworkType4G | ThinkingNetworkType2G | ThinkingNetworkType5G; + _securityPolicy = [TDSecurityPolicy defaultPolicy]; + _defaultTimeZone = [NSTimeZone localTimeZone]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if (!configInfo) { + configInfo = (NSDictionary *)[[[NSBundle mainBundle] infoDictionary] objectForKey: kTAConfigInfo]; + } + + if (configInfo && [configInfo.allKeys containsObject:@"maxNumEvents"]) { + [TDConfig setMaxNumEvents:[configInfo[@"maxNumEvents"] integerValue]]; + } + if (configInfo && [configInfo.allKeys containsObject:@"expirationDays"]) { + [TDConfig setExpirationDays:[configInfo[@"expirationDays"] integerValue]]; + } +#pragma clang diagnostic pop + + } + return self; +} + +- (instancetype)initWithAppId:(NSString *)appId serverUrl:(NSString *)serverUrl +{ + self = [self init]; + if (self) { + _appid = appId; + _serverUrl = serverUrl; + } + return self; +} + +- (void)enableEncryptWithVersion:(NSUInteger)version publicKey:(NSString *)publicKey { +#if TARGET_OS_IOS + if ([publicKey isKindOfClass:NSString.class] && publicKey.length > 0) { + self.innerEnableEncrypt = YES; + self.innerSecretKey = [[TDSecretKey alloc] initWithVersion:version publicKey:publicKey]; + } else { + self.innerEnableEncrypt = NO; + } +#endif +} + +- (void)enableDNSServcie:(NSArray *)services { + // check DNS service list + if (!services || services.count <= 0) { + TDLogDebug(@"Enable DNS service error: Service is empty"); + return; + } + NSArray *dNSServices = @[TDDNSServiceCloudFlare, TDDNSServiceCloudALi, TDDNSServiceCloudGoogle]; + + NSMutableArray *filterServices = [NSMutableArray array]; + for (TDDNSService obj in services) { + if ([obj isKindOfClass:NSString.class] && [dNSServices containsObject:obj]) { + [filterServices addObject:obj]; + } + } + if (filterServices.count > 0) { + TDLogDebug(@"Enable DNS service. Server url list is: %@", filterServices); + self.dnsServices = filterServices; + [TDAnalyticsNetwork enableDNSServcie:filterServices]; + } else { + TDLogDebug(@"Enable DNS service error: Service url authentication failed"); + } +} + +- (void)setName:(NSString *)name { + _name = name.td_trim; +} + +#pragma mark - NSCopying +- (id)copyWithZone:(NSZone *)zone { + TDConfig *config = [[[self class] allocWithZone:zone] init]; + config.trackRelaunchedInBackgroundEvents = self.trackRelaunchedInBackgroundEvents; + config.innerNetworkType = self.innerNetworkType; + config.launchOptions = [self.launchOptions copyWithZone:zone]; + config.mode = self.mode; + config.reportingNetworkType = self.reportingNetworkType; + config.securityPolicy = [self.securityPolicy copyWithZone:zone]; + config.defaultTimeZone = [self.defaultTimeZone copyWithZone:zone]; + config.name = [self.name copy]; + config.appGroupName = [self.appGroupName copy]; + config.serverUrl = [self.serverUrl copy]; + config.enableAutoPush = self.enableAutoPush; + config.dnsServices = self.dnsServices; +#if TARGET_OS_IOS + config.innerSecretKey = [self.innerSecretKey copyWithZone:zone]; + config.innerEnableEncrypt = self.innerEnableEncrypt; +#endif + + return config; +} + +#pragma mark - SETTINGS + +- (void)setReportingNetworkType:(TDReportingNetworkType)reportingNetworkType { + switch (reportingNetworkType) { + case TDReportingNetworkTypeWIFI: { + self.innerNetworkType = ThinkingNetworkTypeWIFI; + } break; + case TDReportingNetworkTypeALL: { + self.innerNetworkType = ThinkingNetworkTypeALL; + } break; + default: { + self.innerNetworkType = ThinkingNetworkTypeALL; + } break; + } +} + +//MARK: - private + +- (ThinkingNetworkType)getNetworkType { + return self.innerNetworkType; +} + +- (void)innerUpdateConfig:(void (^)(NSDictionary *))block { + NSString *serverUrlStr = [NSString stringWithFormat:@"%@/config",self.serverUrl]; + TDAnalyticsNetwork *network = [[TDAnalyticsNetwork alloc] init]; + network.serverURL = [NSURL URLWithString:serverUrlStr]; + network.securityPolicy = _securityPolicy; + + [network fetchRemoteConfig:self.appid handler:^(NSDictionary * _Nonnull result, NSError * _Nullable error) { + if (!error) { + NSInteger uploadInterval = [[result objectForKey:@"sync_interval"] integerValue]; + NSInteger uploadSize = [[result objectForKey:@"sync_batch_size"] integerValue]; + if (self.enableAutoCalibrated) { + NSNumber *serverTimestampNum = result[@"server_timestamp"]; + if ([serverTimestampNum isKindOfClass:NSNumber.class]) { + NSTimeInterval serverTimestamp = [serverTimestampNum doubleValue] * 0.001; + [[TDCalibratedTime sharedInstance] recalibrationWithTimeInterval:serverTimestamp]; + } + } + if (uploadInterval != [self->_uploadInterval integerValue] || uploadSize != [self->_uploadSize integerValue]) { + TDFile *file = [[TDFile alloc] initWithAppid:self.appid]; + if (uploadInterval > 0) { + self.uploadInterval = [NSNumber numberWithInteger:uploadInterval]; + [file archiveUploadInterval:self.uploadInterval]; + NSString *name = self.getInstanceName ? self.getInstanceName() : self.appid; + [[ThinkingAnalyticsSDK instanceWithAppid:name] startFlushTimer]; + } + if (uploadSize > 0) { + self.uploadSize = [NSNumber numberWithInteger:uploadSize]; + [file archiveUploadSize:self.uploadSize]; + } + } + self.disableEvents = [result objectForKey:@"disable_event_list"]; + + if (block) { + block([result objectForKey:@"secret_key"]); + } + } + }]; +} + +- (void)innerUpdateIPMap { + if (self.dnsServices.count <= 0) { + return; + } + NSString *serverUrlStr = [NSString stringWithFormat:@"%@/sync", self.serverUrl]; + TDAnalyticsNetwork *network = [[TDAnalyticsNetwork alloc] init]; + network.serverURL = [NSURL URLWithString:serverUrlStr]; + network.securityPolicy = self.securityPolicy; + [network fetchIPMap]; +} + +- (NSString *)innerGetMapInstanceToken { + if (self.name && [self.name isKindOfClass:[NSString class]] && self.name.length) { + return self.name; + } else { + return self.appid; + } +} + +//MARK: - Deprecated: public + ++ (TDConfig *)defaultTDConfig DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + static dispatch_once_t onceToken; + static TDConfig * _defaultTDConfig; + dispatch_once(&onceToken, ^{ + _defaultTDConfig = [TDConfig new]; + }); + return _defaultTDConfig; +} + +- (NSString *)getMapInstanceToken DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + return [self innerGetMapInstanceToken]; +} + +- (void)updateConfig:(void (^)(NSDictionary *))block DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + [self innerUpdateConfig:block]; +} + +- (void)setNetworkType:(ThinkingAnalyticsNetworkType)type DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + switch (type) { + case TDNetworkTypeOnlyWIFI: { + self.reportingNetworkType = TDReportingNetworkTypeWIFI; + } break; + case TDNetworkTypeALL: { + self.reportingNetworkType = TDReportingNetworkTypeALL; + } break; + default: { + self.innerNetworkType = ThinkingNetworkTypeALL; + } break; + } +} + +//MARK: - Deprecated: setter & geter + +- (void)setConfigureURL:(NSString *)configureURL { + self.serverUrl = configureURL; +} + +- (NSString *)configureURL { + return self.serverUrl; +} + +#if TARGET_OS_IOS +- (void)setSecretKey:(TDSecretKey *)secretKey { + _secretKey = secretKey; + + [self enableEncryptWithVersion:secretKey.version publicKey:secretKey.publicKey]; +} + +- (void)setEnableEncrypt:(BOOL)enableEncrypt { + _enableEncrypt = enableEncrypt; + self.innerEnableEncrypt = enableEncrypt; +} +#endif + +- (void)setNetworkTypePolicy:(ThinkingNetworkType)networkTypePolicy DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + _networkTypePolicy = networkTypePolicy; + self.innerNetworkType = networkTypePolicy; +} + +- (void)setDebugMode:(ThinkingAnalyticsDebugMode)debugMode DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + _debugMode = debugMode; + self.mode = (TDMode)debugMode; +} + ++ (NSInteger)maxNumEvents DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + NSInteger maxNumEvents = [self _maxNumEventsNumber].integerValue; + if (maxNumEvents < 5000) { + maxNumEvents = 5000; + } + return maxNumEvents; +} + ++ (void)setMaxNumEvents:(NSInteger)maxNumEventsNumber DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + [self _setMaxNumEventsNumber:@(maxNumEventsNumber)]; +} + ++ (NSInteger)expirationDays DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + NSInteger maxNumEvents = [self _expirationDaysNumber].integerValue; + return maxNumEvents >= 0 ? maxNumEvents : 10; +} + ++ (void)setExpirationDays:(NSInteger)expirationDays DEPRECATED_MSG_ATTRIBUTE("Deprecated"){ + [self _setExpirationDaysNumber:@(expirationDays)]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.m.meta new file mode 100644 index 0000000..01743a2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfig.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8af41e5499deb452491c8aa99ae7e698 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfigPrivate.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfigPrivate.h new file mode 100644 index 0000000..ee10971 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfigPrivate.h @@ -0,0 +1,33 @@ +// +// TDConfigPrivate.h +// Pods +// +// Created by 杨雄 on 2023/8/15. +// + +#if __has_include() +#import +#else +#import "TDConfig.h" +#endif + +#ifndef TDConfigPrivate_h +#define TDConfigPrivate_h + +@interface TDConfig () +@property (atomic, assign) BOOL innerEnableEncrypt; +/// DNS service url for fetching ips +@property (atomic, copy) NSArray *dnsServices; + +#if TARGET_OS_IOS +@property (nonatomic, strong) TDSecretKey *innerSecretKey; +#endif + +- (ThinkingNetworkType)getNetworkType; +- (void)innerUpdateConfig:(void(^)(NSDictionary *dict))block; +- (NSString *)innerGetMapInstanceToken; +- (void)innerUpdateIPMap; + +@end + +#endif /* TDConfigPrivate_h */ diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfigPrivate.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfigPrivate.h.meta new file mode 100644 index 0000000..91ae349 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDConfigPrivate.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 05e72c394e15442e2985410cef03f8ce +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.h new file mode 100644 index 0000000..37de6ab --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.h @@ -0,0 +1,22 @@ +// +// TDPublicConfig.h +// ThinkingSDK +// +// Created by LiHuanan on 2020/9/8. +// Copyright © 2020 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDPublicConfig : NSObject + +@property(copy,nonatomic) NSArray* controllers; +@property(copy,nonatomic) NSString* version; ++ (NSArray*)controllers; ++ (NSString*)version; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.h.meta new file mode 100644 index 0000000..067724a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d19be503ed4684ca2a2419354befb2f7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.m new file mode 100644 index 0000000..1807f85 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.m @@ -0,0 +1,62 @@ +// +// TDPublicConfig.m +// ThinkingSDK +// +// Created by LiHuanan on 2020/9/8. +// Copyright © 2020 thinkingdata. All rights reserved. +// + +#import "TDPublicConfig.h" +static TDPublicConfig* config; + +@implementation TDPublicConfig ++ (void)load +{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + config = [TDPublicConfig new]; + }); +} +- (instancetype)init +{ + self = [super init]; + if(self) + { + self.controllers = @[ + @"UICompatibilityInputViewController", + @"UIKeyboardCandidateGridCollectionViewController", + @"UIInputWindowController", + @"UIApplicationRotationFollowingController", + @"UIApplicationRotationFollowingControllerNoTouches", + @"UISystemKeyboardDockController", + @"UINavigationController", + @"SFBrowserRemoteViewController", + @"SFSafariViewController", + @"UIAlertController", + @"UIImagePickerController", + @"PUPhotoPickerHostViewController", + @"UIViewController", + @"UITableViewController", + @"UITabBarController", + @"_UIRemoteInputViewController", + @"UIEditingOverlayViewController", + @"_UIAlertControllerTextFieldViewController", + @"UIActivityGroupViewController", + @"_UISFAirDropInstructionsViewController", + @"_UIActivityGroupListViewController", + @"_UIShareExtensionRemoteViewController", + @"SLRemoteComposeViewController", + @"SLComposeViewController", + ]; + } + return self; +} ++ (NSArray*)controllers +{ + return config.controllers; +} ++ (NSString*)version +{ + return @"3.1.1"; +} +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.m.meta new file mode 100644 index 0000000..60d8b6b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Config/TDPublicConfig.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2ce9b91a7899b48d08e6a4657935e1a9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo.meta new file mode 100644 index 0000000..e1fa090 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 573f9b30d37104af0b1e33df00a0c526 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.h new file mode 100644 index 0000000..6625233 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.h @@ -0,0 +1,18 @@ +// +// TDAnalyticsPresetProperty.h +// ThinkingSDK +// +// Created by 杨雄 on 2024/5/27. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAnalyticsPresetProperty : NSObject + ++ (NSDictionary *)propertiesWithAppId:(NSString *)appId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.h.meta new file mode 100644 index 0000000..7dc341b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: cfdf928c8073849d0accf16a69e4ccd6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.m new file mode 100644 index 0000000..0032c1f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.m @@ -0,0 +1,58 @@ +// +// TDAnalyticsPresetProperty.m +// ThinkingSDK +// +// Created by 杨雄 on 2024/5/27. +// + +#import "TDAnalyticsPresetProperty.h" +#import "TDDeviceInfo.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +#if __has_include() +#import +#else +#import "NSDate+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "NSString+TDCore.h" +#endif + +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDAnalyticsPresetProperty + ++ (NSDictionary *)propertiesWithAppId:(NSString *)appId { + NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; + + if (![TDCorePresetDisableConfig disableLib]) { + NSString *value = [[TDDeviceInfo sharedManager] libName]; + if (value) { + mutableDict[@"#lib"] = value; + } + } + if (![TDCorePresetDisableConfig disableLibVersion]) { + NSString *value = [[TDDeviceInfo sharedManager] libVersion]; + if (value) { + mutableDict[@"#lib_version"] = value; + } + } + + if (![NSString td_isEmpty:appId]) { + ThinkingAnalyticsSDK *sdk = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + double offset = [[NSDate date] td_timeZoneOffset:sdk.config.defaultTimeZone ?: [NSTimeZone localTimeZone]]; + [mutableDict setObject:@(offset) forKey:@"#zone_offset"]; + } + + return mutableDict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.m.meta new file mode 100644 index 0000000..239f6e3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDAnalyticsPresetProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 067caa9474be64ef0a3c32d8703f8c7a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.h b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.h new file mode 100644 index 0000000..8218973 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.h @@ -0,0 +1,17 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +FOUNDATION_EXTERN NSString *const VERSION; + +@interface TDDeviceInfo : NSObject +@property (nonatomic, copy, readonly) NSString *uniqueId; +@property (nonatomic, assign, readonly) BOOL isFirstOpen; +@property (nonatomic, copy) NSString *libName; +@property (nonatomic, copy) NSString *libVersion; + ++ (TDDeviceInfo *)sharedManager; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.h.meta new file mode 100644 index 0000000..06b82ab --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7de6737a81af64127a0e9e26437c140f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.m b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.m new file mode 100644 index 0000000..df45b5f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.m @@ -0,0 +1,152 @@ +#import "TDDeviceInfo.h" +#import "TDPublicConfig.h" +#import "TDKeychainHelper.h" +#import "TDFile.h" +#import "TDKeychainHelper.h" + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + +#if __has_include() +#import +#else +#import "TDCoreKeychainHelper.h" +#endif + +#import "ThinkingAnalyticsSDKPrivate.h" + + +@interface TDDeviceInfo () +@property (nonatomic, copy, readwrite) NSString *uniqueId; +@property (nonatomic, assign, readwrite) BOOL isFirstOpen; + +@end + +@implementation TDDeviceInfo + ++ (TDDeviceInfo *)sharedManager { + static dispatch_once_t onceToken; + static TDDeviceInfo *manager; + dispatch_once(&onceToken, ^{ + manager = [[TDDeviceInfo alloc] init]; + }); + return manager; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.libName = @"iOS"; + self.libVersion = [TDPublicConfig version]; + } + return self; +} + ++ (NSString *)libVersion { + return [self sharedManager].libVersion; +} + +- (NSString *)uniqueId { + static dispatch_once_t onceToken; + static NSString *uniqueId = nil; + dispatch_once(&onceToken, ^{ + uniqueId = [self getDeviceUniqueId]; + }); + return uniqueId; +} + + +#if TARGET_OS_OSX + +- (nullable NSString *)getSystemSerialNumber { + io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); + if (platformExpert) { + CFTypeRef serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0); + IOObjectRelease(platformExpert); + if (serialNumberAsCFString) { + NSString *serialNumber = (__bridge_transfer NSString *)serialNumberAsCFString; + return serialNumber; + } + } + return nil; +} + +- (NSString *)getDeviceUniqueId { + NSString *keyExistFirstRecord = @"thinking_isfirst"; + BOOL isExistFirstRecord = [[[NSUserDefaults standardUserDefaults] objectForKey:keyExistFirstRecord] boolValue]; + if (!isExistFirstRecord) { + self.isFirstOpen = YES; + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:keyExistFirstRecord]; + } else { + self.isFirstOpen = NO; + } + + NSString *keyDefaultDistinctId = @"thinking_data_default_distinct_id"; + NSString *defaultDistinctId = [[NSUserDefaults standardUserDefaults] stringForKey:keyDefaultDistinctId]; + if (!defaultDistinctId) { + defaultDistinctId = [TDCoreDeviceInfo deviceId]; + [[NSUserDefaults standardUserDefaults] setObject:defaultDistinctId forKey:keyDefaultDistinctId]; + } + + return defaultDistinctId; +} + +#endif + +#if TARGET_OS_IOS + +- (NSString *)getDeviceUniqueId { + NSString *uniqueId = nil; + @synchronized (self) { + NSString *deviceId = [TDCoreDeviceInfo deviceId]; + NSString *installTimes = [TDKeychainHelper readInstallTimes]; + BOOL isExistFirstRecord = [[[NSUserDefaults standardUserDefaults] objectForKey:@"thinking_isfirst"] boolValue]; + if (!isExistFirstRecord) { + self.isFirstOpen = YES; + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"thinking_isfirst"]; + } else { + self.isFirstOpen = NO; + } + + TDFile *file = [[TDFile alloc] initWithAppid:[ThinkingAnalyticsSDK defaultInstance].config.appid]; + if (deviceId.length == 0) { + deviceId = [file unarchiveDeviceId]; + if (deviceId.length > 0) { + [TDCoreKeychainHelper saveDeviceId:deviceId]; + } + } + if (installTimes.length == 0) { + installTimes = [file unarchiveInstallTimes]; + if (installTimes.length > 0) { + [TDKeychainHelper saveInstallTimes:installTimes]; + } + } + if (installTimes.length == 0) { + installTimes = @"1"; + [file archiveInstallTimes:installTimes]; + [TDKeychainHelper saveInstallTimes:installTimes]; + } else { + if (!isExistFirstRecord) { + int setup_int = [installTimes intValue]; + setup_int++; + installTimes = [NSString stringWithFormat:@"%d", setup_int]; + [file archiveInstallTimes:installTimes]; + [TDKeychainHelper saveInstallTimes:installTimes]; + } + } + + if ([installTimes isEqualToString:@"1"]) { + uniqueId = deviceId; + } else { + uniqueId = [NSString stringWithFormat:@"%@_%@",deviceId, installTimes]; + } + } + return uniqueId; +} + +#endif + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.m.meta new file mode 100644 index 0000000..c5f3021 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/DeviceInfo/TDDeviceInfo.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 744d610cea1594481a55109a212558f7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt.meta new file mode 100644 index 0000000..515ddfb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: baf6ca963286f4fe49728f2419026900 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncrypt.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncrypt.h new file mode 100644 index 0000000..f356dd4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncrypt.h @@ -0,0 +1,11 @@ +// +// TDEncrypt.h +// ThinkingSDK +// +// Created by wwango on 2022/1/27. +// + +#import "TDEncryptAlgorithm.h" +#import "TDEncryptProtocol.h" +#import "TDEncryptManager.h" +#import "TDSecretKey.h" diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncrypt.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncrypt.h.meta new file mode 100644 index 0000000..604529a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncrypt.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 99ffee2b45dd4439c8b49b22c8899d70 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptAlgorithm.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptAlgorithm.h new file mode 100644 index 0000000..ceea259 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptAlgorithm.h @@ -0,0 +1,20 @@ +// +// TDEncryptAlgorithm.h +// ThinkingSDK +// +// Created by wwango on 2022/1/27. + + +NS_ASSUME_NONNULL_BEGIN + +@protocol TDEncryptAlgorithm + + +- (nullable NSString *)encryptData:(NSData *)data; + + +- (NSString *)algorithm; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptAlgorithm.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptAlgorithm.h.meta new file mode 100644 index 0000000..772f02b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptAlgorithm.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: be6654071274442269e91d5fd5a7fb7c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.h new file mode 100644 index 0000000..e3eaa9a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.h @@ -0,0 +1,29 @@ +// +// TDEncryptManager.h +// ThinkingSDK +// +// Created by wwango on 2022/1/21. + + +#import + +@class TDSecretKey; + +NS_ASSUME_NONNULL_BEGIN + +@interface TDEncryptManager : NSObject + + +@property(nonatomic, assign, getter=isValid) BOOL valid; + + +- (instancetype)initWithSecretKey:(TDSecretKey *)secretKey; + +- (void)handleEncryptWithConfig:(NSDictionary *)encryptConfig; + + +- (NSDictionary *)encryptJSONObject:(NSDictionary *)obj; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.h.meta new file mode 100644 index 0000000..095e796 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ecffce0fb694b4e81a9a0e64f8584b98 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.m new file mode 100644 index 0000000..1b91336 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.m @@ -0,0 +1,216 @@ +// +// TDEncryptManager.m +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import "TDEncryptManager.h" +#import "TDEncryptProtocol.h" +#import "TDSecretKey.h" +#import "TDRSAEncryptorPlugin.h" +#if __has_include() +#import +#else +#import "NSData+TDGzip.h" +#endif +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif +#import "TDLogging.h" + +@interface TDEncryptManager () +@property (nonatomic, strong) id encryptor; +@property (nonatomic, copy) NSArray> *encryptors; +@property (nonatomic, copy) NSString *encryptedSymmetricKey; +@property (nonatomic, strong) TDSecretKey *secretKey; +@property (nonatomic, strong) TDSecretKey *customSecretKey; + +@end + +@implementation TDEncryptManager + +- (instancetype)initWithSecretKey:(TDSecretKey *)secretKey { + self = [self init]; + if (self) { + self.customSecretKey = secretKey; + [self updateEncryptor:secretKey]; + } + return self; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + NSMutableArray *encryptors = [NSMutableArray array]; + [encryptors addObject:[TDRSAEncryptorPlugin new]]; + self.encryptors = encryptors; + } + return self; +} + +- (void)handleEncryptWithConfig:(NSDictionary *)encryptConfig { + + if (!encryptConfig || ![encryptConfig isKindOfClass:[NSDictionary class]]) { + return; + } + + if (![encryptConfig objectForKey:@"version"]) { + return; + } + + NSInteger version = [[encryptConfig objectForKey:@"version"] integerValue]; + TDSecretKey *secretKey = [[TDSecretKey alloc] initWithVersion:version + publicKey:encryptConfig[@"key"] + asymmetricEncryption:encryptConfig[@"asymmetric"] + symmetricEncryption:encryptConfig[@"symmetric"]]; + + + if (![secretKey isValid]) { + return; + } + + + if (![self encryptorWithSecretKey:secretKey]) { + return; + } + + + [self updateEncryptor:secretKey]; +} + +- (void)updateEncryptor:(TDSecretKey *)obj { + @try { + + TDSecretKey *secretKey = obj; + if (!secretKey.publicKey.length) { + return; + } + + if ([self needUpdateSecretKey:self.secretKey newSecretKey:secretKey]) { + return; + } + + id encryptor = [self filterEncrptor:secretKey]; + if (!encryptor) { + return; + } + + NSString *encryptedSymmetricKey = [encryptor encryptSymmetricKeyWithPublicKey:secretKey.publicKey]; + + if (encryptedSymmetricKey.length) { + + self.secretKey = secretKey; + + self.encryptor = encryptor; + + self.encryptedSymmetricKey = encryptedSymmetricKey; + + TDLogDebug(@"\n****************secretKey****************\n public key: %@ \n encrypted symmetric key: %@\n****************secretKey****************", secretKey.publicKey, encryptedSymmetricKey); + } + } @catch (NSException *exception) { + TDLogError(@"%@ error: %@", self, exception); + } +} + +- (BOOL)needUpdateSecretKey:(TDSecretKey *)oldSecretKey newSecretKey:(TDSecretKey *)newSecretKey { + if (oldSecretKey.version != newSecretKey.version) { + return NO; + } + if (![oldSecretKey.publicKey isEqualToString:newSecretKey.publicKey]) { + return NO; + } + if (![oldSecretKey.symmetricEncryption isEqualToString:newSecretKey.symmetricEncryption]) { + return NO; + } + if (![oldSecretKey.asymmetricEncryption isEqualToString:newSecretKey.asymmetricEncryption]) { + return NO; + } + return YES; +} + +- (id)filterEncrptor:(TDSecretKey *)secretKey { + id encryptor = [self encryptorWithSecretKey:secretKey]; + if (!encryptor) { + NSString *format = @"\n You have used the [%@] key, but the corresponding encryption plugin has not been registered. \n"; + NSString *type = [NSString stringWithFormat:@"%@+%@", secretKey.asymmetricEncryption, secretKey.symmetricEncryption]; + NSString *message = [NSString stringWithFormat:format, type]; + NSAssert(NO, message); + return nil; + } + return encryptor; +} + +- (id)encryptorWithSecretKey:(TDSecretKey *)secretKey { + if (!secretKey) { + return nil; + } + __block id encryptor; + [self.encryptors enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + BOOL isSameAsymmetricType = [[obj asymmetricEncryptType] isEqualToString:secretKey.asymmetricEncryption]; + BOOL isSameSymmetricType = [[obj symmetricEncryptType] isEqualToString:secretKey.symmetricEncryption]; + if (isSameAsymmetricType && isSameSymmetricType) { + encryptor = obj; + *stop = YES; + } + }]; + return encryptor; +} + +- (NSDictionary *)encryptJSONObject:(NSDictionary *)obj { + @try { + if (!obj) { + TDLogDebug(@"Enable encryption but the input obj is invalid!"); + return nil; + } + + if (!self.encryptor) { + TDLogDebug(@"Enable encryption but the secret key is invalid!"); + return nil; + } + + if (![self encryptSymmetricKey]) { + TDLogDebug(@"Enable encryption but encrypt symmetric key is failed!"); + return nil; + } + + + NSData *jsonData = [TDJSONUtil JSONSerializeForObject:obj]; + + + NSString *encryptedString = [self.encryptor encryptEvent:jsonData]; + if (!encryptedString) { + TDLogDebug(@"Enable encryption but encrypted input obj is invalid!"); + return nil; + } + + + NSMutableDictionary *secretObj = [NSMutableDictionary dictionary]; + secretObj[@"pkv"] = @(self.secretKey.version); + secretObj[@"ekey"] = self.encryptedSymmetricKey; + secretObj[@"payload"] = encryptedString; + return [NSDictionary dictionaryWithDictionary:secretObj]; + } @catch (NSException *exception) { + TDLogDebug(@"%@ error: %@", self, exception); + return nil; + } +} + + +- (BOOL)encryptSymmetricKey { + if (self.encryptedSymmetricKey) { + return YES; + } + NSString *publicKey = self.secretKey.publicKey; + self.encryptedSymmetricKey = [self.encryptor encryptSymmetricKeyWithPublicKey:publicKey]; + return self.encryptedSymmetricKey != nil; +} + +- (BOOL)isValid { + return _encryptor ? YES:NO; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.m.meta new file mode 100644 index 0000000..18d6f5d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1ad3a2338631944cd87df838012e7751 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptProtocol.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptProtocol.h new file mode 100644 index 0000000..fad0aa6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptProtocol.h @@ -0,0 +1,26 @@ +// +// TDEncryptProtocol.h +// ThinkingSDK +// +// Created by wwango on 2022/1/27. + + +NS_ASSUME_NONNULL_BEGIN + +@protocol TDEncryptProtocol + + +- (NSString *)symmetricEncryptType; + + +- (NSString *)asymmetricEncryptType; + + +- (NSString *)encryptEvent:(NSData *)event; + + +- (NSString *)encryptSymmetricKeyWithPublicKey:(NSString *)publicKey; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptProtocol.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptProtocol.h.meta new file mode 100644 index 0000000..91e05af --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDEncryptProtocol.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 0bb0d612c5fc140eeb484ac00d791b63 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.h new file mode 100644 index 0000000..f5fe539 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.h @@ -0,0 +1,37 @@ +// +// TDSecretKey.h +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDSecretKey : NSObject + +/// Initialize key information +- (instancetype)initWithVersion:(NSUInteger)version publicKey:(NSString *)publicKey; + +/// Initialize key information +/// @param version key version number +/// @param publicKey public key +/// @param asymmetricEncryption asymmetric encryption type +/// @param symmetricEncryption Symmetric encryption type +- (instancetype)initWithVersion:(NSUInteger)version + publicKey:(NSString *)publicKey + asymmetricEncryption:(NSString *)asymmetricEncryption + symmetricEncryption:(NSString *)symmetricEncryption; + +@property (nonatomic, assign, readonly) NSUInteger version; +@property (nonatomic, copy, readonly) NSString *publicKey; +@property (nonatomic, copy, readonly) NSString *symmetricEncryption; +@property (nonatomic, copy, readonly) NSString *asymmetricEncryption; + +/// Whether the key information is available +@property (nonatomic, assign, readonly) BOOL isValid; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.h.meta new file mode 100644 index 0000000..66ed025 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ec629b9835a264c5d91241e2774be8d8 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.m new file mode 100644 index 0000000..cf97361 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.m @@ -0,0 +1,80 @@ +// +// TDSecretKey.m +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import "TDSecretKey.h" + +@interface TDSecretKey () + +@property (nonatomic, assign) NSUInteger version; +@property (nonatomic, copy) NSString *publicKey; +@property (nonatomic, copy) NSString *symmetricEncryption; +@property (nonatomic, copy) NSString *asymmetricEncryption; + +@end + +@implementation TDSecretKey + + +- (instancetype)initWithVersion:(NSUInteger)version + publicKey:(NSString *)publicKey { + + return [[TDSecretKey alloc] initWithVersion:version + publicKey:publicKey + asymmetricEncryption:@"RSA" + symmetricEncryption:@"AES"]; +} + +- (instancetype)initWithVersion:(NSUInteger)version + publicKey:(NSString *)publicKey + asymmetricEncryption:(NSString *)asymmetricEncryption + symmetricEncryption:(NSString *)symmetricEncryption { + self = [super init]; + if (self) { + self.version = version; + self.publicKey = publicKey; + self.asymmetricEncryption = asymmetricEncryption; + self.symmetricEncryption = symmetricEncryption; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeInteger:self.version forKey:@"version"]; + [coder encodeObject:self.publicKey forKey:@"publicKey"]; + [coder encodeObject:self.symmetricEncryption forKey:@"symmetricEncrypt"]; + [coder encodeObject:self.asymmetricEncryption forKey:@"asymmetricEncrypt"]; +} + +- (instancetype)initWithCoder:(NSCoder *)coder { + self = [super init]; + if (self) { + self.version = [coder decodeIntegerForKey:@"version"]; + self.publicKey = [coder decodeObjectForKey:@"publicKey"]; + self.symmetricEncryption = [coder decodeObjectForKey:@"symmetricEncrypt"]; + self.asymmetricEncryption = [coder decodeObjectForKey:@"asymmetricEncrypt"]; + } + return self; +} + +- (BOOL)isValid { + if (self.publicKey.length && self.symmetricEncryption.length && self.asymmetricEncryption.length) { + return YES; + } + return NO; +} + +- (id)copyWithZone:(NSZone *)zone { + TDSecretKey *secretKey = [[[self class] allocWithZone:zone] init]; + secretKey.version = self.version; + secretKey.publicKey = [self.publicKey copy]; + secretKey.symmetricEncryption = [self.symmetricEncryption copy]; + secretKey.asymmetricEncryption = [self.asymmetricEncryption copy]; + return secretKey; +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.m.meta new file mode 100644 index 0000000..1e658b5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/TDSecretKey.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 03c8b384def5542ae8bd608d4b3968ed +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin.meta new file mode 100644 index 0000000..524faa6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a51f5c933df844bfaa6e322b24b3ed9e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.h new file mode 100644 index 0000000..df59789 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.h @@ -0,0 +1,19 @@ +// +// TDAESEncryptor.h +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import +#import "TDEncryptAlgorithm.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAESEncryptor : NSObject + +@property (nonatomic, copy, readonly) NSData *key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.h.meta new file mode 100644 index 0000000..d531101 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9d1974cff31e245d4a80d7890c19ca79 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.m new file mode 100644 index 0000000..634214a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.m @@ -0,0 +1,85 @@ +// +// TDAESEncryptor.m +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import "TDAESEncryptor.h" +#import +#import "TDLogging.h" + +@interface TDAESEncryptor () + +@property (nonatomic, copy, readwrite) NSData *key; + +@end + +@implementation TDAESEncryptor + + +- (NSData *)key { + if (!_key) { + NSUInteger length = 16; + NSString *letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + NSMutableString *randomString = [NSMutableString stringWithCapacity:length]; + for (NSUInteger i = 0; i < length; i++) { + [randomString appendFormat: @"%C", [letters characterAtIndex:arc4random_uniform((uint32_t)[letters length])]]; + } + _key = [randomString dataUsingEncoding:NSUTF8StringEncoding]; + } + return _key; +} + + +- (NSString *)algorithm { + return @"AES"; +} + + +- (nullable NSString *)encryptData:(NSData *)obj { + if (!obj) { + return nil; + } + + if (!self.key) { + return nil; + } + + NSData *data = obj; + NSUInteger dataLength = [data length]; + size_t bufferSize = dataLength + kCCBlockSizeAES128; + void *buffer = malloc(bufferSize); + + size_t numBytesEncrypted = 0; + CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, + kCCAlgorithmAES128, + kCCOptionPKCS7Padding | kCCOptionECBMode, + [self.key bytes], + kCCBlockSizeAES128, + nil, + [data bytes], + dataLength, + buffer, + bufferSize, + &numBytesEncrypted); + if (cryptStatus == kCCSuccess) { + + NSData *encryptData = [NSData dataWithBytes:buffer length:numBytesEncrypted]; + NSMutableData *ivEncryptData = [NSMutableData data]; + [ivEncryptData appendData:encryptData]; + + free(buffer); + + NSData *base64EncodeData = [ivEncryptData base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]; + NSString *encryptString = [[NSString alloc] initWithData:base64EncodeData encoding:NSUTF8StringEncoding]; + return encryptString; + } else { + free(buffer); + } + return nil; +} + + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.m.meta new file mode 100644 index 0000000..9057c28 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDAESEncryptor.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3356f39043a754358aac9d671c6355d0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.h new file mode 100644 index 0000000..ec1bfe8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.h @@ -0,0 +1,19 @@ +// +// TDRSAEncryptor.h +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import +#import "TDEncryptAlgorithm.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDRSAEncryptor : NSObject + +@property (nonatomic, copy) NSString *key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.h.meta new file mode 100644 index 0000000..c1b532d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 31a27833643c74455bef05a2933ee2eb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.m new file mode 100644 index 0000000..e00c6fe --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.m @@ -0,0 +1,180 @@ +// +// TDRSAEncryptor.m +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import "TDRSAEncryptor.h" + +@implementation TDRSAEncryptor + +- (void)setKey:(NSString *)key { + if (!key) { + return; + } + NSString *publicKeyCopy = [key copy]; + publicKeyCopy = [publicKeyCopy stringByReplacingOccurrencesOfString:@"\r" withString:@""]; + publicKeyCopy = [publicKeyCopy stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + publicKeyCopy = [publicKeyCopy stringByReplacingOccurrencesOfString:@"\t" withString:@""]; + publicKeyCopy = [publicKeyCopy stringByReplacingOccurrencesOfString:@" " withString:@""]; + _key = publicKeyCopy; +} + +- (NSString *)algorithm { + return @"RSA"; +} + +- (NSString *)encryptData:(NSData *)data { + if (!data) { + return nil; + } + + NSString *asymmetricPublicKey = self.key; + if (!asymmetricPublicKey) { + return nil; + } + + SecKeyRef keyRef = [self addPublicKey:asymmetricPublicKey]; + if (!keyRef) { + return nil; + } + + const uint8_t *srcbuf = (const uint8_t *)[data bytes]; + size_t srclen = (size_t)data.length; + + size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t); + void *outbuf = malloc(block_size); + size_t src_block_size = block_size - 11; + + NSMutableData *ret = [[NSMutableData alloc] init]; + for(int idx=0; idx src_block_size) { + data_len = src_block_size; + } + + size_t outlen = block_size; + OSStatus status = noErr; + + status = SecKeyEncrypt(keyRef, + kSecPaddingPKCS1, + srcbuf + idx, + data_len, + outbuf, + &outlen + ); + if (status != 0) { + ret = nil; + break; + }else{ + [ret appendBytes:outbuf length:outlen]; + } + } + free(outbuf); + CFRelease(keyRef); + + return [ret base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]; +} + +#pragma mark – Private Methods +- (SecKeyRef)addPublicKey:(NSString *)aymmetricPublicKey { + NSString *key = [aymmetricPublicKey copy]; + + NSData *data = [[NSData alloc] initWithBase64EncodedString:key options:NSDataBase64DecodingIgnoreUnknownCharacters]; + data = [self stripPublicKeyHeader:data]; + if (!data) { + return nil; + } + + //a tag to read/write keychain storage + NSString *tag = @"RSAUtil_PubKey_1"; + NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]]; + + // Delete any old lingering key with the same tag + NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init]; + [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass]; + [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; + [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag]; + [publicKey setObject:(__bridge id) kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id)kSecAttrAccessible]; + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)publicKey); + + // Add persistent version of the key to system keychain + [publicKey setObject:data forKey:(__bridge id)kSecValueData]; + [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass]; + [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id) + kSecReturnPersistentRef]; + + CFTypeRef persistKey = nil; + status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey); + if (persistKey != nil) { + CFRelease(persistKey); + } + if ((status != noErr) && (status != errSecDuplicateItem)) { + return nil; + } + + [publicKey removeObjectForKey:(__bridge id)kSecValueData]; + [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef]; + [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef]; + [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; + + // Now fetch the SecKeyRef version of the key + SecKeyRef keyRef = nil; + status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef); + if (status != noErr) { + return nil; + } + return keyRef; +} + +- (NSData *)stripPublicKeyHeader:(NSData *)d_key { + // Skip ASN.1 public key header + if (d_key == nil) { + return(nil); + } + + unsigned long len = [d_key length]; + if (!len) { + return(nil); + } + + unsigned char *c_key = (unsigned char *)[d_key bytes]; + unsigned int idx = 0; + + if (c_key[idx++] != 0x30) { + return(nil); + } + + if (c_key[idx] > 0x80) { + idx += c_key[idx] - 0x80 + 1; + } else { + idx++; + } + + // PKCS #1 rsaEncryption szOID_RSA_RSA + static unsigned char seqiod[] = + { 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00 }; + if (memcmp(&c_key[idx], seqiod, 15)) { + return(nil); + } + idx += 15; + + if (c_key[idx++] != 0x03) { + return(nil); + } + + if (c_key[idx] > 0x80) { + idx += c_key[idx] - 0x80 + 1; + } else { + idx++; + } + if (c_key[idx++] != '\0') { + return(nil); + } + // Now make a new NSData from this buffer + return([NSData dataWithBytes:&c_key[idx] length:len - idx]); +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.m.meta new file mode 100644 index 0000000..fec4d44 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptor.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9bee54e226cda4595abb93c0ebbe11df +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.h new file mode 100644 index 0000000..0d88a72 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.h @@ -0,0 +1,18 @@ +// +// TDRSAEncryptorPlugin.h +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import +#import "TDEncryptProtocol.h" +#import "TDRSAEncryptor.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDRSAEncryptorPlugin : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.h.meta new file mode 100644 index 0000000..657c24f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a6d6b82caa9fc42fa81c28fee8c4ad79 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.m new file mode 100644 index 0000000..97f650e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.m @@ -0,0 +1,53 @@ +// +// TDRSAEncryptorPlugin.m +// ThinkingSDK +// +// Created by wwango on 2022/1/21. +// + +#import "TDRSAEncryptorPlugin.h" +#import "TDAESEncryptor.h" +#import "TDRSAEncryptor.h" + +@interface TDRSAEncryptorPlugin () + +@property (nonatomic, strong) TDAESEncryptor *aesEncryptor; +@property (nonatomic, strong) TDRSAEncryptor *rsaEncryptor; + +@end + +@implementation TDRSAEncryptorPlugin + +- (instancetype)init { + self = [super init]; + if (self) { + _aesEncryptor = [[TDAESEncryptor alloc] init]; + _rsaEncryptor = [[TDRSAEncryptor alloc] init]; + } + return self; +} + + +- (NSString *)symmetricEncryptType { + return [_aesEncryptor algorithm]; +} + + +- (NSString *)asymmetricEncryptType { + return [_rsaEncryptor algorithm]; +} + + +- (NSString *)encryptEvent:(NSData *)event { + return [_aesEncryptor encryptData:event]; +} + + +- (NSString *)encryptSymmetricKeyWithPublicKey:(NSString *)publicKey { + if (![_rsaEncryptor.key isEqualToString:publicKey]) { + _rsaEncryptor.key = publicKey; + } + return [_rsaEncryptor encryptData:_aesEncryptor.key]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.m.meta new file mode 100644 index 0000000..0e7eebb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Encrypt/plugin/TDRSAEncryptorPlugin.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d4d26e5bdde0c4282bf6539cf6df7001 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker.meta new file mode 100644 index 0000000..379345f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d39d3850ca6b34272af89f0692e73180 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel.meta new file mode 100644 index 0000000..d4770b9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9560727ea3c7d4990b4106ce6735a5ff +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.h new file mode 100644 index 0000000..4216013 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.h @@ -0,0 +1,18 @@ +// +// TDBaseEvent+H5.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/19. +// + +#import "TDBaseEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDBaseEvent (H5) +@property (nonatomic, copy) NSString *h5TimeString; +@property (nonatomic, strong) NSNumber *h5ZoneOffSet; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.h.meta new file mode 100644 index 0000000..13f539c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ad6332a385abb409fac530fd09e031c1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.m new file mode 100644 index 0000000..2a742d1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.m @@ -0,0 +1,29 @@ +// +// TDBaseEvent+H5.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/19. +// + +#import "TDBaseEvent+H5.h" +#import + +@implementation TDBaseEvent (H5) + +- (NSString *)h5TimeString { + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setH5TimeString:(NSString *)h5TimeString { + objc_setAssociatedObject(self, @selector(h5TimeString), h5TimeString, OBJC_ASSOCIATION_COPY_NONATOMIC); +} + +- (NSNumber *)h5ZoneOffSet { + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setH5ZoneOffSet:(NSNumber *)h5ZoneOffSet { + objc_setAssociatedObject(self, @selector(h5ZoneOffSet), h5ZoneOffSet, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.m.meta new file mode 100644 index 0000000..1d4851a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent+H5.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f301ae1267df64970b42d12c61a9b8f8 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.h new file mode 100644 index 0000000..341d3a4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.h @@ -0,0 +1,85 @@ +// +// TDBaseEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import +#import "TDPropertyValidator.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString * kTDEventType; + +typedef NS_OPTIONS(NSUInteger, TDEventType) { + TDEventTypeNone = 0, + TDEventTypeTrack = 1 << 0, + TDEventTypeTrackFirst = 1 << 1, + TDEventTypeTrackUpdate = 1 << 2, + TDEventTypeTrackOverwrite = 1 << 3, + TDEventTypeUserSet = 1 << 4, + TDEventTypeUserUnset = 1 << 5, + TDEventTypeUserAdd = 1 << 6, + TDEventTypeUserDel = 1 << 7, + TDEventTypeUserSetOnce = 1 << 8, + TDEventTypeUserAppend = 1 << 9, + TDEventTypeUserUniqueAppend = 1 << 10, + TDEventTypeAll = 0xFFFFFFFF, +}; + +FOUNDATION_EXTERN NSString * const TD_BACKGROUND_DURATION; + +typedef NSString *kEDEventTypeName; + +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_TRACK; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_USER_DEL; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_USER_ADD; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_USER_SET; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_USER_SETONCE; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_USER_UNSET; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_USER_APPEND; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_USER_UNIQ_APPEND; + +typedef NS_OPTIONS(NSInteger, TDEventTimeValueType) { + TDEventTimeValueTypeNone = 0, + TDEventTimeValueTypeTimeOnly = 1 << 0, + TDEventTimeValueTypeTimeAndZone = 1 << 1, +}; + +@interface TDBaseEvent : NSObject +@property (nonatomic, assign) TDEventType eventType; +@property (nonatomic, copy) NSString *uuid; +@property (nonatomic, copy) NSString *accountId; +@property (nonatomic, copy) NSString *distinctId; +@property (nonatomic, strong) NSDate *time; +@property (nonatomic, strong) NSTimeZone *timeZone; +@property (nonatomic, strong, readonly) NSDateFormatter *timeFormatter; + +@property (nonatomic, assign) TDEventTimeValueType timeValueType; +@property (nonatomic, strong) NSMutableDictionary *properties; + +@property (nonatomic, assign) BOOL immediately; +@property (nonatomic, assign) BOOL isDebug; + +@property (atomic, assign, getter=isTrackPause) BOOL trackPause; + +@property (nonatomic, assign) BOOL isEnabled; + +@property (atomic, assign) BOOL isOptOut; + +- (instancetype)initWithType:(TDEventType)type; + +- (void)validateWithError:(NSError **)error; + +- (NSMutableDictionary *)jsonObject; + +- (NSMutableDictionary *)formatDateWithDict:(NSDictionary *)dict; + +- (NSString *)eventTypeString; + ++ (TDEventType)typeWithTypeString:(NSString *)typeString; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.h.meta new file mode 100644 index 0000000..8f9a423 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: afaae7e08bd134bc79ee77ede44b33ef +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.m new file mode 100644 index 0000000..5fc0596 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.m @@ -0,0 +1,209 @@ +// +// TDBaseEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDBaseEvent.h" + +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif + +#import "TDLogging.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +NSString * const TD_BACKGROUND_DURATION = @"#background_duration"; + +kEDEventTypeName const TD_EVENT_TYPE_TRACK = @"track"; +kEDEventTypeName const TD_EVENT_TYPE_TRACK_FIRST = @"track_first"; +kEDEventTypeName const TD_EVENT_TYPE_TRACK_UPDATE = @"track_update"; +kEDEventTypeName const TD_EVENT_TYPE_TRACK_OVERWRITE = @"track_overwrite"; +kEDEventTypeName const TD_EVENT_TYPE_USER_DEL = @"user_del"; +kEDEventTypeName const TD_EVENT_TYPE_USER_ADD = @"user_add"; +kEDEventTypeName const TD_EVENT_TYPE_USER_SET = @"user_set"; +kEDEventTypeName const TD_EVENT_TYPE_USER_SETONCE = @"user_setOnce"; +kEDEventTypeName const TD_EVENT_TYPE_USER_UNSET = @"user_unset"; +kEDEventTypeName const TD_EVENT_TYPE_USER_APPEND = @"user_append"; +kEDEventTypeName const TD_EVENT_TYPE_USER_UNIQ_APPEND= @"user_uniq_append"; + +@interface TDBaseEvent () +@property (nonatomic, strong) NSDateFormatter *timeFormatter; + +@end + +@implementation TDBaseEvent + +- (instancetype)init +{ + self = [super init]; + if (self) { + _time = [NSDate date]; + self.timeValueType = TDEventTimeValueTypeNone; + self.uuid = [NSUUID UUID].UUIDString; + } + return self; +} + +- (instancetype)initWithType:(TDEventType)type { + if (self = [self init]) { + self.eventType = type; + } + return self; +} + +- (void)validateWithError:(NSError *__autoreleasing _Nullable *)error { + +} + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + dict[@"#time"] = self.time; + dict[@"#uuid"] = self.uuid; + dict[@"#type"] = [self eventTypeString]; + if (self.accountId) { + dict[@"#account_id"] = self.accountId; + } + if (self.distinctId) { + dict[@"#distinct_id"] = self.distinctId; + } + dict[@"properties"] = self.properties; + return dict; +} + +- (NSMutableDictionary *)formatDateWithDict:(NSDictionary *)dict { + if (dict == nil || ![dict isKindOfClass:NSDictionary.class]) { + return nil; + } + return [TDJSONUtil formatDateWithFormatter:self.h5ZoneOffSet ? self.h5TimeFormatter : self.timeFormatter dict:dict]; +} + +- (NSString *)eventTypeString { + switch (self.eventType) { + case TDEventTypeTrack: { + return TD_EVENT_TYPE_TRACK; + } break; + case TDEventTypeTrackFirst: { + + return TD_EVENT_TYPE_TRACK; + } break; + case TDEventTypeTrackUpdate: { + return TD_EVENT_TYPE_TRACK_UPDATE; + } break; + case TDEventTypeTrackOverwrite: { + return TD_EVENT_TYPE_TRACK_OVERWRITE; + } break; + case TDEventTypeUserAdd: { + return TD_EVENT_TYPE_USER_ADD; + } break; + case TDEventTypeUserSet: { + return TD_EVENT_TYPE_USER_SET; + } break; + case TDEventTypeUserUnset: { + return TD_EVENT_TYPE_USER_UNSET; + } break; + case TDEventTypeUserAppend: { + return TD_EVENT_TYPE_USER_APPEND; + } break; + case TDEventTypeUserUniqueAppend: { + return TD_EVENT_TYPE_USER_UNIQ_APPEND; + } break; + case TDEventTypeUserDel: { + return TD_EVENT_TYPE_USER_DEL; + } break; + case TDEventTypeUserSetOnce: { + return TD_EVENT_TYPE_USER_SETONCE; + } break; + + default: + return nil; + break; + } +} + ++ (TDEventType)typeWithTypeString:(NSString *)typeString { + if ([typeString isEqualToString:TD_EVENT_TYPE_TRACK]) { + return TDEventTypeTrack; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_TRACK_FIRST]) { + return TDEventTypeTrack; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_TRACK_UPDATE]) { + return TDEventTypeTrackUpdate; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_TRACK_OVERWRITE]) { + return TDEventTypeTrackOverwrite; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_USER_ADD]) { + return TDEventTypeUserAdd; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_USER_DEL]) { + return TDEventTypeUserDel; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_USER_SET]) { + return TDEventTypeUserSet; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_USER_UNSET]) { + return TDEventTypeUserUnset; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_USER_APPEND]) { + return TDEventTypeUserAppend; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_USER_UNIQ_APPEND]) { + return TDEventTypeUserUniqueAppend; + } else if ([typeString isEqualToString:TD_EVENT_TYPE_USER_SETONCE]) { + return TDEventTypeUserSetOnce; + } + return TDEventTypeNone; +} + +//MARK: - Private + +//MARK: - Delegate + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError *__autoreleasing _Nullable *)error { + +} + +//MARK: - Setter & Getter + +- (NSMutableDictionary *)properties { + if (!_properties) { + _properties = [NSMutableDictionary dictionary]; + } + return _properties; +} + +- (void)setTimeZone:(NSTimeZone *)timeZone { + _timeZone = timeZone; + + self.timeFormatter.timeZone = timeZone ?: [NSTimeZone localTimeZone]; +} + +- (NSDateFormatter *)timeFormatter { + if (!_timeFormatter) { + _timeFormatter = [[NSDateFormatter alloc] init]; + _timeFormatter.dateFormat = kDefaultTimeFormat; + _timeFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + _timeFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; + + _timeFormatter.timeZone = [NSTimeZone localTimeZone]; + } + return _timeFormatter; +} + +- (NSDateFormatter *)h5TimeFormatter { + double timeZoneNumber = [self.h5ZoneOffSet doubleValue]; + NSString *prefix = timeZoneNumber >= 0 ? @"UTC+" : @"UTC-"; + int hours = (int)fabs(timeZoneNumber); + int minutes = (int)((fabs(timeZoneNumber) - hours) * 60); + NSString *minutesStr = minutes == 0 ? @":00" : [NSString stringWithFormat:@":%02d", minutes]; + NSString *result = [NSString stringWithFormat:@"%@%d%@", prefix, hours, minutesStr]; + self.timeFormatter.timeZone = [NSTimeZone timeZoneWithName: result]; + return self.timeFormatter; +} + +- (void)setTime:(NSDate *)time { + + if (time) { + [self willChangeValueForKey:@"time"]; + _time = time; + [self didChangeValueForKey:@"time"]; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.m.meta new file mode 100644 index 0000000..5f6893e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDBaseEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1b8d7f99e856c45c78b217ed83737cd2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEditableEventModel.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEditableEventModel.h new file mode 100644 index 0000000..98a2f4e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEditableEventModel.h @@ -0,0 +1,12 @@ + +#if __has_include() +#import +#else +#import "TDUpdateEventModel.h" +#endif + +#if __has_include() +#import +#else +#import "TDOverwriteEventModel.h" +#endif diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEditableEventModel.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEditableEventModel.h.meta new file mode 100644 index 0000000..752db9c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEditableEventModel.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: fba4ca753c9594b94b225ba0619faecc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.h new file mode 100644 index 0000000..473256e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.h @@ -0,0 +1,24 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NSString *kEDEventTypeName; + +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_TRACK_FIRST; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_TRACK_UPDATE; +FOUNDATION_EXTERN kEDEventTypeName const TD_EVENT_TYPE_TRACK_OVERWRITE; + +@interface TDEventModel : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@property (nonatomic, copy, readonly) NSString *eventName; +@property (nonatomic, copy, readonly) kEDEventTypeName eventType; +@property (nonatomic, strong) NSDictionary *properties; + +- (void)configTime:(NSDate *)time timeZone:(NSTimeZone *)timeZone; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.h.meta new file mode 100644 index 0000000..4cbaa8c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7d7f726d9fabe4abe85bfba590a4d099 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.m new file mode 100644 index 0000000..532e14b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.m @@ -0,0 +1,52 @@ + +#import "TDEventModel.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + +@interface TDEventModel () + +@property (nonatomic, copy) NSString *eventName; +@property (nonatomic, copy) kEDEventTypeName eventType; + +@end + +@implementation TDEventModel + +- (instancetype)initWithEventName:(NSString *)eventName eventType:(kEDEventTypeName)eventType { + if (self = [[[TDEventModel class] alloc] init]) { + self.eventName = eventName ?: @""; + self.eventType = eventType ?: @""; + if ([self.eventType isEqualToString:TD_EVENT_TYPE_TRACK_FIRST]) { + _extraID = [TDCoreDeviceInfo deviceId] ?: @""; + } + } + return self; +} + +#pragma mark - Public + +- (void)configTime:(NSDate *)time timeZone:(NSTimeZone *)timeZone { + self.time = time; + self.timeZone = timeZone; +} + +#pragma mark - Setter + +- (void)setExtraID:(NSString *)extraID { + if (extraID.length > 0) { + _extraID = extraID; + } else { + if ([self.eventType isEqualToString:TD_EVENT_TYPE_TRACK_FIRST]) { + TDLogError(@"Invalid firstCheckId. Use device Id"); + } else { + TDLogError(@"Invalid eventId"); + } + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.m.meta new file mode 100644 index 0000000..9b89236 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDEventModel.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3de42dea3b4f54381b502e54cf5584a5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.h new file mode 100644 index 0000000..a0d83a9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.h @@ -0,0 +1,19 @@ + +#if __has_include() +#import +#else +#import "TDEventModel.h" +#endif + + +NS_ASSUME_NONNULL_BEGIN + +@interface TDFirstEventModel : TDEventModel + +- (instancetype)initWithEventName:(NSString * _Nullable)eventName; + +- (instancetype)initWithEventName:(NSString * _Nullable)eventName firstCheckID:(NSString *)firstCheckID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.h.meta new file mode 100644 index 0000000..f864186 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 97a7f26110d42427091d0ecc77a0cef1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.m new file mode 100644 index 0000000..11db5a8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.m @@ -0,0 +1,17 @@ +#import "TDFirstEventModel.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDFirstEventModel + +- (instancetype)initWithEventName:(NSString *)eventName { + return [self initWithEventName:eventName eventType:TD_EVENT_TYPE_TRACK_FIRST]; +} + +- (instancetype)initWithEventName:(NSString *)eventName firstCheckID:(NSString *)firstCheckID { + if (self = [self initWithEventName:eventName eventType:TD_EVENT_TYPE_TRACK_FIRST]) { + self.extraID = firstCheckID; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.m.meta new file mode 100644 index 0000000..f95b4c1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDFirstEventModel.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ef9d0018898d449ac852a035e9776780 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.h new file mode 100644 index 0000000..46a2968 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.h @@ -0,0 +1,22 @@ +// +// TDOverwriteEventModel.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#if __has_include() +#import +#else +#import "TDEventModel.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDOverwriteEventModel : TDEventModel + +- (instancetype)initWithEventName:(NSString *)eventName eventID:(NSString *)eventID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.h.meta new file mode 100644 index 0000000..03be643 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5dc01cb9b7f4e42f9b63a0d9d768368f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.m new file mode 100644 index 0000000..7f9de48 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.m @@ -0,0 +1,20 @@ +// +// TDOverwriteEventModel.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDOverwriteEventModel.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDOverwriteEventModel + +- (instancetype)initWithEventName:(NSString *)eventName eventID:(NSString *)eventID { + if (self = [self initWithEventName:eventName eventType:TD_EVENT_TYPE_TRACK_OVERWRITE]) { + self.extraID = eventID; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.m.meta new file mode 100644 index 0000000..473857a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDOverwriteEventModel.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 30daf01e45573481881a7ae94d3b89a1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.h new file mode 100644 index 0000000..3ff2191 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.h @@ -0,0 +1,34 @@ +// +// TATrackEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDBaseEvent.h" + +NS_ASSUME_NONNULL_BEGIN + + +@interface TDTrackEvent : TDBaseEvent +/// eventName +@property (nonatomic, copy) NSString *eventName; +/// Cumulative front activity time +@property (nonatomic, assign) NSTimeInterval foregroundDuration; +/// Cumulative background time +@property (nonatomic, assign) NSTimeInterval backgroundDuration; + +/// Record the boot time node when the event occurred. Used to count the cumulative time of events +@property (nonatomic, assign) NSTimeInterval systemUpTime; + +/// Used to record dynamic public properties, dynamic public properties need to be obtained in the current thread where the event occurs +@property (nonatomic, strong) NSDictionary *dynamicSuperProperties; + +/// Used to document static public properties +@property (nonatomic, strong) NSDictionary *superProperties; + +- (instancetype)initWithName:(NSString *)eventName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.h.meta new file mode 100644 index 0000000..5dfbbdc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a4f0e76fae39a4d928ce3b4519ab1518 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.m new file mode 100644 index 0000000..4ce6194 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.m @@ -0,0 +1,86 @@ +// +// TATrackEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDTrackEvent.h" +#import "TDPresetProperties.h" + +#if __has_include() +#import +#else +#import "NSDate+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@implementation TDTrackEvent + +- (instancetype)initWithName:(NSString *)eventName { + if (self = [self init]) { + self.eventName = eventName; + } + return self; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.eventType = TDEventTypeTrack; + self.systemUpTime = [TDCoreDeviceInfo bootTime]; + } + return self; +} + +- (void)validateWithError:(NSError *__autoreleasing _Nullable *)error { + + [TDPropertyValidator validateEventOrPropertyName:self.eventName withError:error]; +} + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + dict[@"#event_name"] = self.eventName; + + if (![TDCorePresetDisableConfig disableDuration]) { + if (self.foregroundDuration > 0) { + self.properties[@"#duration"] = @([NSString stringWithFormat:@"%.3f", self.foregroundDuration].floatValue); + } + } + + if (![TDCorePresetDisableConfig disableBackgroundDuration]) { + if (self.backgroundDuration > 0) { + self.properties[TD_BACKGROUND_DURATION] = @([NSString stringWithFormat:@"%.3f", self.backgroundDuration].floatValue); + } + } + + self.properties[@"#zone_offset"] = @([self timeZoneOffset]); + + return dict; +} + +- (double)timeZoneOffset { + NSTimeZone *tz = self.timeZone ?: [NSTimeZone localTimeZone]; + return [[NSDate date] td_timeZoneOffset:tz]; +} + +//MARK: - Delegate + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError *__autoreleasing _Nullable *)error { + [TDPropertyValidator validateNormalTrackEventPropertyKey:key value:value error:error]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.m.meta new file mode 100644 index 0000000..df24782 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2612df3a7727940ceb0ccaf54e7c39e6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.h new file mode 100644 index 0000000..b179c63 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.h @@ -0,0 +1,18 @@ +// +// TATrackFirstEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDTrackFirstEvent : TDTrackEvent + +@property (nonatomic, copy) NSString *firstCheckId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.h.meta new file mode 100644 index 0000000..89fd8a3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 082ed5175f8a940cba9a16ec7c0ecc86 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.m new file mode 100644 index 0000000..d3c9561 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.m @@ -0,0 +1,48 @@ +// +// TATrackFirstEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDTrackFirstEvent.h" + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + + +@implementation TDTrackFirstEvent + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.eventType = TDEventTypeTrackFirst; + } + return self; +} + +- (void)validateWithError:(NSError *__autoreleasing _Nullable *)error { + [super validateWithError:error]; + if (*error) { + return; + } + if (self.firstCheckId.length <= 0) { + NSString *errorMsg = @"property 'firstCheckId' cannot be empty which in FirstEvent"; + *error = TAPropertyError(100010, errorMsg); + return; + } +} + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + dict[@"#first_check_id"] = self.firstCheckId ?: [TDCoreDeviceInfo deviceId]; + + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.m.meta new file mode 100644 index 0000000..4e44d90 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackFirstEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c1b41633104d5440b9e4ccdf9142868b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.h new file mode 100644 index 0000000..895fc61 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.h @@ -0,0 +1,18 @@ +// +// TATrackOverwriteEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDTrackOverwriteEvent : TDTrackEvent + +@property (nonatomic, copy) NSString *eventId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.h.meta new file mode 100644 index 0000000..96d82d0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b990dd3d951fe45a39e4ef860d751f0e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.m new file mode 100644 index 0000000..6205ae0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.m @@ -0,0 +1,40 @@ +// +// TATrackOverwriteEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDTrackOverwriteEvent.h" + +@implementation TDTrackOverwriteEvent + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.eventType = TDEventTypeTrackOverwrite; + } + return self; +} + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + dict[@"#event_id"] = self.eventId; + + return dict; +} + + +- (void)validateWithError:(NSError *__autoreleasing _Nullable *)error { + [super validateWithError:error]; + if (*error) { + return; + } + if (self.eventId.length <= 0) { + TDLogError(@"property 'eventId' cannot be empty which in OverwriteEvent"); + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.m.meta new file mode 100644 index 0000000..e0a233c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackOverwriteEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4414e47d72d0747ad85645f8f9904cdb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.h new file mode 100644 index 0000000..a40cc64 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.h @@ -0,0 +1,18 @@ +// +// TATrackUpdateEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDTrackEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDTrackUpdateEvent : TDTrackEvent + +@property (nonatomic, copy) NSString *eventId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.h.meta new file mode 100644 index 0000000..e51742f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2a4e6a92783804592a341df6acf7d256 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.m new file mode 100644 index 0000000..67bd78f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.m @@ -0,0 +1,40 @@ +// +// TATrackUpdateEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDTrackUpdateEvent.h" + +@implementation TDTrackUpdateEvent + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.eventType = TDEventTypeTrackUpdate; + } + return self; +} + +- (NSMutableDictionary *)jsonObject { + NSMutableDictionary *dict = [super jsonObject]; + + dict[@"#event_id"] = self.eventId; + + return dict; +} + + +- (void)validateWithError:(NSError *__autoreleasing _Nullable *)error { + [super validateWithError:error]; + if (*error) { + return; + } + if (self.eventId.length <= 0) { + TDLogError(@"property 'eventId' cannot be empty which in UpdateEvent"); + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.m.meta new file mode 100644 index 0000000..bb28d90 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDTrackUpdateEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 44092bc189b3646a89357b879cfc9918 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.h new file mode 100644 index 0000000..b356a60 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.h @@ -0,0 +1,22 @@ +// +// TDUpdateEventModel.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#if __has_include() +#import +#else +#import "TDEventModel.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUpdateEventModel : TDEventModel + +- (instancetype)initWithEventName:(NSString *)eventName eventID:(NSString *)eventID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.h.meta new file mode 100644 index 0000000..dbfff14 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bab971596eecc447e9515c9c200beeea +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.m new file mode 100644 index 0000000..16aeca7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.m @@ -0,0 +1,20 @@ +// +// TDUpdateEventModel.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUpdateEventModel.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDUpdateEventModel + +- (instancetype)initWithEventName:(NSString *)eventName eventID:(NSString *)eventID { + if (self = [self initWithEventName:eventName eventType:TD_EVENT_TYPE_TRACK_UPDATE]) { + self.extraID = eventID; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.m.meta new file mode 100644 index 0000000..b4c198c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/TDUpdateEventModel.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5a53fbef3fbd443c6b986f13fb2a9b76 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty.meta new file mode 100644 index 0000000..587ba89 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3cfc2ce7ca8134bceae9d8f4c9a620ab +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.h new file mode 100644 index 0000000..d893cdf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.h @@ -0,0 +1,16 @@ +// +// TAUserEvent.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDBaseEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEvent : TDBaseEvent + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.h.meta new file mode 100644 index 0000000..ded37e9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 33351f8746690438b9f1ee615980ad7e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.m new file mode 100644 index 0000000..0935ed4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.m @@ -0,0 +1,29 @@ +// +// TAUserEvent.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDUserEvent.h" + +@implementation TDUserEvent + +- (instancetype)init +{ + self = [super init]; + if (self) { + + } + return self; +} + +//MARK: - Delegate + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError *__autoreleasing _Nullable *)error { + [TDPropertyValidator validateBaseEventPropertyKey:key value:value error:error]; +} + +//MARK: - Setter & Getter + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.m.meta new file mode 100644 index 0000000..0118d4b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEvent.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 410475b18466c4e7e9c9fdc92a00b00e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.h new file mode 100644 index 0000000..e9d2962 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.h @@ -0,0 +1,16 @@ +// +// TAUserEventAdd.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEventAdd : TDUserEvent + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.h.meta new file mode 100644 index 0000000..ea81d80 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7415330e4e5124333ad47418f85722ac +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.m new file mode 100644 index 0000000..cd96ebc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.m @@ -0,0 +1,36 @@ +// +// TAUserEventAdd.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventAdd.h" + +@implementation TDUserEventAdd + +- (instancetype)init { + if (self = [super init]) { + self.eventType = TDEventTypeUserAdd; + } + return self; +} + +- (void)validateWithError:(NSError *__autoreleasing _Nullable *)error { + +} + +//MARK: - Delegate + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError *__autoreleasing _Nullable *)error { + [super ta_validateKey:key value:value error:error]; + if (*error) { + return; + } + if (![value isKindOfClass:NSNumber.class]) { + NSString *errMsg = [NSString stringWithFormat:@"Property value must be type NSNumber. got: %@ %@. ", [value class], value]; + *error = TAPropertyError(10008, errMsg); + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.m.meta new file mode 100644 index 0000000..76e68b3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAdd.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 680c661f9405d4b67bc86129e17a98a0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.h new file mode 100644 index 0000000..515887f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.h @@ -0,0 +1,16 @@ +// +// TAUserEventAppend.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEventAppend : TDUserEvent + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.h.meta new file mode 100644 index 0000000..3c08605 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7c0bdc64c7f214279a569e642cd28961 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.m new file mode 100644 index 0000000..f981d46 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.m @@ -0,0 +1,32 @@ +// +// TAUserEventAppend.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventAppend.h" + +@implementation TDUserEventAppend + +- (instancetype)init { + if (self = [super init]) { + self.eventType = TDEventTypeUserAppend; + } + return self; +} + +//MARK: - Delegate + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError *__autoreleasing _Nullable *)error { + [super ta_validateKey:key value:value error:error]; + if (*error) { + return; + } + if (![value isKindOfClass:NSArray.class]) { + NSString *errMsg = [NSString stringWithFormat:@"Property value must be type NSArray. got: %@ %@. ", [value class], value]; + *error = TAPropertyError(10009, errMsg); + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.m.meta new file mode 100644 index 0000000..dc100b7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventAppend.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4967adff1152f42f88274d5f55668bcf +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.h new file mode 100644 index 0000000..c9a5c9c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.h @@ -0,0 +1,16 @@ +// +// TAUserEventDelete.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEventDelete : TDUserEvent + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.h.meta new file mode 100644 index 0000000..3a5768c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 79a3dcbc3c69c45b7a0c67e92d5ae79c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.m new file mode 100644 index 0000000..10904b2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.m @@ -0,0 +1,19 @@ +// +// TAUserEventDelete.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventDelete.h" + +@implementation TDUserEventDelete + +- (instancetype)init { + if (self = [super init]) { + self.eventType = TDEventTypeUserDel; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.m.meta new file mode 100644 index 0000000..3ca8948 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventDelete.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 78e83efee5e48498697a633d44da9654 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.h new file mode 100644 index 0000000..1ed434d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.h @@ -0,0 +1,16 @@ +// +// TAUserEventSet.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEventSet : TDUserEvent + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.h.meta new file mode 100644 index 0000000..68c809f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: fe02e78f8ce8844c6a44e3f72f0a4fa5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.m new file mode 100644 index 0000000..eae172f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.m @@ -0,0 +1,19 @@ +// +// TAUserEventSet.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventSet.h" + +@implementation TDUserEventSet + +- (instancetype)init { + if (self = [super init]) { + self.eventType = TDEventTypeUserSet; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.m.meta new file mode 100644 index 0000000..a9c0002 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSet.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: fa8ff0a24d8a44baf8c83b4ac53779d6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.h new file mode 100644 index 0000000..709ec48 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.h @@ -0,0 +1,16 @@ +// +// TAUserEventSetOnce.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEventSetOnce : TDUserEvent + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.h.meta new file mode 100644 index 0000000..720f429 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 63e0e92cc8e83408cbf96e4c6f089dc0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.m new file mode 100644 index 0000000..f658c8f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.m @@ -0,0 +1,19 @@ +// +// TAUserEventSetOnce.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventSetOnce.h" + +@implementation TDUserEventSetOnce + +- (instancetype)init { + if (self = [super init]) { + self.eventType = TDEventTypeUserSetOnce; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.m.meta new file mode 100644 index 0000000..4cf6c21 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventSetOnce.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6130b943421394d6080baafd1dc59153 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.h new file mode 100644 index 0000000..98c0e72 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.h @@ -0,0 +1,16 @@ +// +// TAUserEventUniqueAppend.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventAppend.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEventUniqueAppend : TDUserEventAppend + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.h.meta new file mode 100644 index 0000000..93f6308 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: e57d6baf2b811472c8a5de647a77931a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.m new file mode 100644 index 0000000..caf2279 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.m @@ -0,0 +1,19 @@ +// +// TAUserEventUniqueAppend.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventUniqueAppend.h" + +@implementation TDUserEventUniqueAppend + +- (instancetype)init { + if (self = [super init]) { + self.eventType = TDEventTypeUserUniqueAppend; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.m.meta new file mode 100644 index 0000000..b3b91b1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUniqueAppend.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8c28f21e1f18848bb8088d92bafb44a4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.h new file mode 100644 index 0000000..75275c5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.h @@ -0,0 +1,16 @@ +// +// TAUserEventUnset.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDUserEventUnset : TDUserEvent + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.h.meta new file mode 100644 index 0000000..9de4162 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 174fff6c702c842a5ab7f44d3c179df1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.m new file mode 100644 index 0000000..8412240 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.m @@ -0,0 +1,19 @@ +// +// TAUserEventUnset.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDUserEventUnset.h" + +@implementation TDUserEventUnset + +- (instancetype)init { + if (self = [super init]) { + self.eventType = TDEventTypeUserUnset; + } + return self; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.m.meta new file mode 100644 index 0000000..e0871e1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserEventUnset.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 0fed9f759e1254d489963423aafc9425 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserPropertyHeader.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserPropertyHeader.h new file mode 100644 index 0000000..e3d213f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserPropertyHeader.h @@ -0,0 +1,19 @@ +// +// TDUserPropertyHeader.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#ifndef TDUserPropertyHeader_h +#define TDUserPropertyHeader_h + +#import "TDUserEventSet.h" +#import "TDUserEventSetOnce.h" +#import "TDUserEventUnset.h" +#import "TDUserEventAdd.h" +#import "TDUserEventDelete.h" +#import "TDUserEventAppend.h" +#import "TDUserEventUniqueAppend.h" + +#endif /* TDUserPropertyHeader_h */ diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserPropertyHeader.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserPropertyHeader.h.meta new file mode 100644 index 0000000..36ff600 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/EventModel/UserProperty/TDUserPropertyHeader.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: db85fc9b1ef384039b473d91fc3db066 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property.meta new file mode 100644 index 0000000..28ccda0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cf30d3548fdac432aaf17971e80d083b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins.meta new file mode 100644 index 0000000..0ea69e6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4410ea0e2817247de9eadf648fa01ac7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.h new file mode 100644 index 0000000..88cb3f1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.h @@ -0,0 +1,21 @@ +// +// TAPresetPropertyPlugin.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#if TARGET_OS_IOS +#import +#endif +#import "TDPropertyPluginManager.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDPresetPropertyPlugin : NSObject + +@property(nonatomic, copy)NSString *instanceToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.h.meta new file mode 100644 index 0000000..e927f81 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 051f3bf3a1e8f4130b2c68e397b6df06 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.m new file mode 100644 index 0000000..d366a3e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.m @@ -0,0 +1,60 @@ +// +// TAPresetPropertyPlugin.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDPresetPropertyPlugin.h" +#import "TDAnalyticsPresetProperty.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +#if __has_include() +#import +#else +#import "TDCorePresetProperty.h" +#endif + +@interface TDPresetPropertyPlugin () +@property (nonatomic, strong) NSMutableDictionary *properties; + +@end + +@implementation TDPresetPropertyPlugin + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.properties = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)start { + NSDictionary *staticProperties = [TDCorePresetProperty staticProperties]; + [self.properties addEntriesFromDictionary:staticProperties]; +} + +/// The properties here are dynamically updated +/// +- (void)asyncGetPropertyCompletion:(TDPropertyPluginCompletion)completion { + NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; + + NSDictionary *dynamicProperties = [TDCorePresetProperty dynamicProperties]; + [mutableDict addEntriesFromDictionary:dynamicProperties]; + + NSDictionary *analyticsProperties = [TDAnalyticsPresetProperty propertiesWithAppId:self.instanceToken]; + [mutableDict addEntriesFromDictionary:analyticsProperties]; + + if (completion) { + completion(mutableDict); + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.m.meta new file mode 100644 index 0000000..e7355fb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPresetPropertyPlugin.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 41a6f60eeb74149a4b1c17f9b8ff6412 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.h new file mode 100644 index 0000000..62110b5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.h @@ -0,0 +1,42 @@ +// +// TDPropertyPluginManager.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import +#import "TDBaseEvent.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void(^TDPropertyPluginCompletion)(NSDictionary *properties); + +@protocol TDPropertyPluginProtocol + +@property(nonatomic, copy)NSString *instanceToken; + +- (NSDictionary *)properties; + +@optional + +- (void)start; + +- (TDEventType)eventTypeFilter; + +- (void)asyncGetPropertyCompletion:(TDPropertyPluginCompletion)completion; + +@end + + +@interface TDPropertyPluginManager : NSObject + +- (void)registerPropertyPlugin:(id)plugin; + +- (NSMutableDictionary *)currentPropertiesForPluginClasses:(NSArray *)classes; + +- (NSMutableDictionary *)propertiesWithEventType:(TDEventType)type; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.h.meta new file mode 100644 index 0000000..f0374e3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1d497d7d900b340bc8afb11550ae0602 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.m new file mode 100644 index 0000000..8aa4da6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.m @@ -0,0 +1,125 @@ +// +// TDPropertyPluginManager.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/12. +// + +#import "TDPropertyPluginManager.h" + +@interface TDPropertyPluginManager () +@property (nonatomic, strong) NSMutableArray> *plugins; + +@end + + +@implementation TDPropertyPluginManager + +//MARK: - Public Methods + +- (instancetype)init { + self = [super init]; + if (self) { + self.plugins = [NSMutableArray array]; + } + return self; +} + +- (void)registerPropertyPlugin:(id)plugin { + BOOL isResponds = [plugin respondsToSelector:@selector(properties)]; + NSAssert(isResponds, @"properties plugin must implement `- properties` method!"); + if (!isResponds) { + return; + } + + // delete old plugin + for (id object in self.plugins) { + if (object.class == plugin.class) { + [self.plugins removeObject:object]; + break; + } + } + [self.plugins addObject:plugin]; + + + if ([plugin respondsToSelector:@selector(start)]) { + [plugin start]; + } +} + +- (NSMutableDictionary *)currentPropertiesForPluginClasses:(NSArray *)classes { + NSArray *plugins = [self.plugins copy]; + NSMutableArray> *matchResult = [NSMutableArray array]; + + for (id obj in plugins) { + + for (Class cla in classes) { + if ([obj isKindOfClass:cla]) { + [matchResult addObject:obj]; + break; + } + } + } + + NSMutableDictionary *pluginProperties = [self propertiesWithPlugins:matchResult]; + + return pluginProperties; +} + +- (NSMutableDictionary *)propertiesWithEventType:(TDEventType)type { + + NSArray *plugins = [self.plugins copy]; + NSMutableArray> *matchResult = [NSMutableArray array]; + for (id obj in plugins) { + if ([self isMatchedWithPlugin:obj eventType:type]) { + [matchResult addObject:obj]; + } + } + return [self propertiesWithPlugins:matchResult]; +} + +//MARK: - Private Methods + +- (NSMutableDictionary *)propertiesWithPlugins:(NSArray> *)plugins { + NSMutableDictionary *properties = [NSMutableDictionary dictionary]; + for (id plugin in plugins) { + if ([plugin respondsToSelector:@selector(start)]) { + [plugin start]; + } + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + if ([plugin respondsToSelector:@selector(asyncGetPropertyCompletion:)]) { + [plugin asyncGetPropertyCompletion:^(NSDictionary * _Nonnull dict) { + [properties addEntriesFromDictionary:dict]; + dispatch_semaphore_signal(semaphore); + }]; + } + + NSDictionary *pluginProperties = [plugin respondsToSelector:@selector(properties)] ? plugin.properties : nil; + if (pluginProperties) { + [properties addEntriesFromDictionary:pluginProperties]; + } + if (semaphore) { + dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC))); + } + + } + return properties; +} + +- (BOOL)isMatchedWithPlugin:(id)plugin eventType:(TDEventType)type { + TDEventType eventTypeFilter; + + if (![plugin respondsToSelector:@selector(eventTypeFilter)]) { + // If the plug-in does not implement the type filtering method, it will only be added for track type data by default, including the first event, updateable event, and rewritable event. In addition to user attribute events + eventTypeFilter = TDEventTypeTrack | TDEventTypeTrackFirst | TDEventTypeTrackUpdate | TDEventTypeTrackOverwrite; + } else { + eventTypeFilter = plugin.eventTypeFilter; + } + + if ((eventTypeFilter & type) == type) { + return YES; + } + return NO; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.m.meta new file mode 100644 index 0000000..c1fbbc6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDPropertyPluginManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ca009646dd0fd4c21ba1c71d04cbd54d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.h new file mode 100644 index 0000000..b34b95c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.h @@ -0,0 +1,19 @@ +// +// TASessionIdManager.h +// ThinkingSDK +// +// Created by Charles on 6.12.22. +// + +#import + + +NS_ASSUME_NONNULL_BEGIN + +@interface TDSessionIdManager : NSObject + ++ (instancetype)shareInstance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.h.meta new file mode 100644 index 0000000..a5f02a3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ee185d71a647c463486848a4e1365ffc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.m new file mode 100644 index 0000000..bbb6509 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.m @@ -0,0 +1,75 @@ +// +// TASessionIdManager.m +// ThinkingSDK +// +// Created by Charles on 6.12.22. +// + +#if TARGET_OS_IOS +#import +#endif +#import "TDSessionIdManager.h" +#import "TDAppLifeCycle.h" +#import "TDAppState.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDSessionIdManager + ++ (instancetype)shareInstance { + static dispatch_once_t onceToken; + static id instance = nil; + dispatch_once(&onceToken, ^{ + instance = [[[self class] alloc] init]; + }); + return instance; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + [self registerAppLifeCycleListener]; + } + return self; +} + +- (void)registerAppLifeCycleListener { + if ([TDAppState runningInAppExtension]) { + return; + } + + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; +#if TARGET_OS_IOS + + [notificationCenter addObserver:self selector:@selector(appStateWillChangeNotification:) name:kTDAppLifeCycleStateWillChangeNotification object:nil]; + +#endif +} + + +- (void)appStateWillChangeNotification:(NSNotification *)notification { + TDAppLifeCycleState newState = [[notification.userInfo objectForKey:kTDAppLifeCycleNewStateKey] integerValue]; + TDAppLifeCycleState oldState = [[notification.userInfo objectForKey:kTDAppLifeCycleOldStateKey] integerValue]; + + if (oldState == TDAppLifeCycleStateInit) { + return; + } + + if (newState == TDAppLifeCycleStateStart) { + @synchronized ([self class]) { + [self updateSessionId]; + } + } +} + +- (void)updateSessionId { +// NSMutableDictionary *dic = [ThinkingAnalyticsSDK _getAllInstances]; +// for (NSString *instanceToken in dic.allKeys) { +// ThinkingAnalyticsSDK *instance = dic[instanceToken]; +// if ([instance isKindOfClass:[ThinkingAnalyticsSDK class]]) { +// [instance.sessionidPlugin updateSessionId]; +// } +// } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.m.meta new file mode 100644 index 0000000..f91aace --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdManager.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 056160bd921ba4a6da9c1472922e0368 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.h new file mode 100644 index 0000000..7cbeb8d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.h @@ -0,0 +1,23 @@ +// +// TASessionIdPropertyPlugin.h +// ThinkingSDK +// +// Created by Charles on 28.11.22. +// + +#if TARGET_OS_IOS +#import +#endif +#import "TDPropertyPluginManager.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDSessionIdPropertyPlugin : NSObject + +@property(nonatomic, copy)NSString *instanceToken; + +- (void)updateSessionId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.h.meta new file mode 100644 index 0000000..5a5b3be --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 0d3906cb9621143178e639f99a0bb87a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.m new file mode 100644 index 0000000..c849420 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.m @@ -0,0 +1,75 @@ +// +// TASessionIdPropertyPlugin.m +// ThinkingSDK +// +// Created by Charles on 28.11.22. +// + +#import "TDSessionIdPropertyPlugin.h" +#import "TDPresetProperties.h" +#import "TDAppLifeCycle.h" +#import "TDFile.h" +#import "TDAppState.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +@interface TDSessionIdPropertyPlugin () +@property (nonatomic, strong) NSMutableDictionary *properties; +@property (nonatomic, strong) TDFile *file; +@property (atomic, assign) long long sessionid; +@property (atomic, copy) NSString *sessionidString; +@end + + +@implementation TDSessionIdPropertyPlugin + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.properties = [NSMutableDictionary dictionary]; + + } + return self; +} + +- (void)updateSessionId { +#if TARGET_OS_IOS + if (![TDCorePresetDisableConfig disableSessionID]) { + @synchronized ([self class]) { + self.sessionid ++; + self.sessionidString = [NSString stringWithFormat:@"%@_%lld", [NSUUID UUID].UUIDString, self.sessionid]; + [self.file archiveSessionID:self.sessionid]; + self.properties[@"#session_id"] = self.sessionidString; + } + } +#endif +} + +- (void)start { + if (![TDCorePresetDisableConfig disableSessionID]) { + @synchronized ([self class]) { + if (!self.file) { + self.file = [[TDFile alloc] initWithAppid:self.instanceToken]; + } + self.sessionid = [self.file unarchiveSessionID]; + [self updateSessionId]; + } + + } +} + +- (void)asyncGetPropertyCompletion:(TDPropertyPluginCompletion)completion { + NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary]; + + if (completion) { + completion(mutableDict); + } +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.m.meta new file mode 100644 index 0000000..9adebab --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/PropertyPlugins/TDSessionIdPropertyPlugin.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 075a93a31c872428194005ca4deaa887 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.h new file mode 100644 index 0000000..6492058 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.h @@ -0,0 +1,34 @@ +// +// TDAutoTrackSuperProperty.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/19. +// + +#import +#import "TDAutoTrackConst.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAutoTrackSuperProperty : NSObject + +- (void)registerSuperProperties:(NSDictionary *)properties withType:(TDAutoTrackEventType)type; + +- (NSDictionary *)currentSuperPropertiesWithEventName:(NSString *)eventName; + +- (void)registerDynamicSuperProperties:(NSDictionary *(^)(TDAutoTrackEventType, NSDictionary *))dynamicSuperProperties; + +- (NSDictionary *)obtainDynamicSuperPropertiesWithType:(TDAutoTrackEventType)type currentProperties:(NSDictionary *)properties; + +/// Only used for auto track in Unity3D environment +/// - Parameter dynamicSuperProperties: dynamic properties +- (void)registerAutoTrackDynamicProperties:(NSDictionary *(^ _Nullable)(void))dynamicSuperProperties; + +/// Only used for auto track in Unity3D environment +- (NSDictionary *)obtainAutoTrackDynamicSuperProperties; + +- (void)clearSuperProperties; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.h.meta new file mode 100644 index 0000000..8be67ad --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: e4239d98391f44715b2bd436774a1fc5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.m new file mode 100644 index 0000000..5141574 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.m @@ -0,0 +1,121 @@ +// +// TDAutoTrackSuperProperty.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/19. +// + +#import "TDAutoTrackSuperProperty.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@interface TDAutoTrackSuperProperty () +@property (atomic, strong) NSMutableDictionary *eventProperties; +@property (nonatomic, copy) NSDictionary *(^dynamicSuperProperties)(TDAutoTrackEventType type, NSDictionary *properties); +/// Only used for auto track in Unity3D environment +@property (nonatomic, copy) NSDictionary *(^autoTrackDynamicSuperProperties)(void); + +@end + +@implementation TDAutoTrackSuperProperty + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.eventProperties = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)registerSuperProperties:(NSDictionary *)properties withType:(TDAutoTrackEventType)type { + NSDictionary *autoTypes = @{ + @(ThinkingAnalyticsEventTypeAppStart) : TD_APP_START_EVENT, + @(ThinkingAnalyticsEventTypeAppEnd) : TD_APP_END_EVENT, + @(ThinkingAnalyticsEventTypeAppClick) : TD_APP_CLICK_EVENT, + @(ThinkingAnalyticsEventTypeAppInstall) : TD_APP_INSTALL_EVENT, + @(ThinkingAnalyticsEventTypeAppViewCrash) : TD_APP_CRASH_EVENT, + @(ThinkingAnalyticsEventTypeAppViewScreen) : TD_APP_VIEW_EVENT + }; + + NSArray *typeKeys = autoTypes.allKeys; + for (NSInteger i = 0; i < typeKeys.count; i++) { + NSNumber *key = typeKeys[i]; + TDAutoTrackEventType eventType = key.integerValue; + if ((type & eventType) == eventType) { + NSString *eventName = autoTypes[key]; + if (properties) { + + NSDictionary *oldProperties = self.eventProperties[eventName]; + if (oldProperties && [oldProperties isKindOfClass:[NSDictionary class]]) { + NSMutableDictionary *mutiOldProperties = [oldProperties mutableCopy]; + [mutiOldProperties addEntriesFromDictionary:properties]; + self.eventProperties[eventName] = mutiOldProperties; + } else { + self.eventProperties[eventName] = properties; + } + + + if (eventType == ThinkingAnalyticsEventTypeAppStart) { + NSDictionary *startParam = self.eventProperties[TD_APP_START_EVENT]; + if (startParam && [startParam isKindOfClass:[NSDictionary class]]) { + self.eventProperties[TD_APP_START_BACKGROUND_EVENT] = startParam; + } + } + } + } + } +} + + +- (NSDictionary *)currentSuperPropertiesWithEventName:(NSString *)eventName { + NSDictionary *autoEventProperty = [self.eventProperties objectForKey:eventName]; + + NSDictionary *validProperties = [TDPropertyValidator validateProperties:[autoEventProperty copy]]; + return validProperties; +} + +- (void)registerDynamicSuperProperties:(NSDictionary *(^)(TDAutoTrackEventType, NSDictionary *))dynamicSuperProperties { + @synchronized (self) { + self.dynamicSuperProperties = dynamicSuperProperties; + } +} + +- (NSDictionary *)obtainDynamicSuperPropertiesWithType:(TDAutoTrackEventType)type currentProperties:(NSDictionary *)properties { + @synchronized (self) { + if (self.dynamicSuperProperties) { + NSDictionary *result = self.dynamicSuperProperties(type, properties); + + NSDictionary *validProperties = [TDPropertyValidator validateProperties:[result copy]]; + return validProperties; + } + return nil; + } +} + +- (void)registerAutoTrackDynamicProperties:(NSDictionary * _Nonnull (^)(void))dynamicSuperProperties { + @synchronized (self) { + self.autoTrackDynamicSuperProperties = dynamicSuperProperties; + } +} + +- (NSDictionary *)obtainAutoTrackDynamicSuperProperties { + @synchronized (self) { + if (self.autoTrackDynamicSuperProperties) { + NSDictionary *properties = self.autoTrackDynamicSuperProperties(); + + NSDictionary *validProperties = [TDPropertyValidator validateProperties:[properties copy]]; + return validProperties; + } + return nil; + } +} + +- (void)clearSuperProperties { + self.eventProperties = [@{} mutableCopy]; +} + +//MARK: - Private Methods + + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.m.meta new file mode 100644 index 0000000..95ff29a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDAutoTrackSuperProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 7e7e1b3a7158c454c996df4567bbdb5f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.h new file mode 100644 index 0000000..24c2737 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.h @@ -0,0 +1,35 @@ +// +// TASuperProperty.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/10. +// +// Methods related to static public properties of this class are not thread-safe; methods related to dynamic public properties are thread-safe. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDSuperProperty : NSObject + +#pragma mark - UNAVAILABLE +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +- (instancetype)initWithToken:(NSString *)token isLight:(BOOL)isLight; + +- (void)registerSuperProperties:(NSDictionary *)properties; + +- (void)unregisterSuperProperty:(NSString *)property; + +- (void)clearSuperProperties; + +- (NSDictionary *)currentSuperProperties; + +- (void)registerDynamicSuperProperties:(NSDictionary *(^ _Nullable)(void))dynamicSuperProperties; + +- (NSDictionary *)obtainDynamicSuperProperties; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.h.meta new file mode 100644 index 0000000..9c75dfd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ffe5d63cbb6e04df89f9fd115255ab29 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.m new file mode 100644 index 0000000..d0246be --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.m @@ -0,0 +1,107 @@ +// +// TASuperProperty.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/10. +// + +#import "TDSuperProperty.h" +#import "TDPropertyValidator.h" +#import "TDLogging.h" +#import "TDFile.h" + +@interface TDSuperProperty () +///multi-instance identifier +@property (nonatomic, copy) NSString *token; +/// static public property +@property (atomic, strong) NSDictionary *superProperties; +/// dynamic public properties +@property (nonatomic, copy) NSDictionary *(^dynamicSuperProperties)(void); +@property (nonatomic, strong) TDFile *file; +@property (nonatomic, assign) BOOL isLight; + +@end + +@implementation TDSuperProperty + +- (instancetype)initWithToken:(NSString *)token isLight:(BOOL)isLight { + if (self = [super init]) { + NSAssert(token.length > 0, @"token cant empty"); + self.token = token; + self.isLight = isLight; + if (!isLight) { + + self.file = [[TDFile alloc] initWithAppid:token]; + self.superProperties = [self.file unarchiveSuperProperties]; + } + } + return self; +} + +- (void)registerSuperProperties:(NSDictionary *)properties { + properties = [properties copy]; + properties = [TDPropertyValidator validateProperties:properties]; + if (properties.count <= 0) { + TDLogError(@"%@ propertieDict error.", properties); + return; + } + + + NSMutableDictionary *tmp = [NSMutableDictionary dictionaryWithDictionary:self.superProperties]; + + [tmp addEntriesFromDictionary:properties]; + self.superProperties = [NSDictionary dictionaryWithDictionary:tmp]; + + + [self.file archiveSuperProperties:self.superProperties]; + TDLogInfo(@"set super properties success"); +} + +- (void)unregisterSuperProperty:(NSString *)property { + NSError *error = nil; + [TDPropertyValidator validateEventOrPropertyName:property withError:&error]; + if (error) { + return; + } + + NSMutableDictionary *tmp = [NSMutableDictionary dictionaryWithDictionary:self.superProperties]; + tmp[property] = nil; + self.superProperties = [NSDictionary dictionaryWithDictionary:tmp]; + + [self.file archiveSuperProperties:self.superProperties]; + TDLogInfo(@"unset super properties success"); +} + +- (void)clearSuperProperties { + self.superProperties = @{}; + [self.file archiveSuperProperties:self.superProperties]; + TDLogInfo(@"clear super properties success"); +} + +- (NSDictionary *)currentSuperProperties { + if (self.superProperties) { + return [TDPropertyValidator validateProperties:[self.superProperties copy]]; + } else { + return @{}; + } +} + +- (void)registerDynamicSuperProperties:(NSDictionary *(^ _Nullable)(void))dynamicSuperProperties { + @synchronized (self) { + self.dynamicSuperProperties = dynamicSuperProperties; + } +} + + +- (NSDictionary *)obtainDynamicSuperProperties { + @synchronized (self) { + if (self.dynamicSuperProperties) { + NSDictionary *properties = self.dynamicSuperProperties(); + NSDictionary *validProperties = [TDPropertyValidator validateProperties:[properties copy]]; + return validProperties; + } + return nil; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.m.meta new file mode 100644 index 0000000..d17a90a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/TDSuperProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5ac704519bb1544229fbdd110009769f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate.meta new file mode 100644 index 0000000..5441881 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 860147d4f77334254a37e4e9d5bbec1a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.h new file mode 100644 index 0000000..970281f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.h @@ -0,0 +1,17 @@ +// +// NSArray+TDProperty.h +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import +#import "TDValidatorProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NSArray (TDProperty) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.h.meta new file mode 100644 index 0000000..c0652d4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4ccca081373f94af7ab1fc37b3da9a3a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.m new file mode 100644 index 0000000..8fe0347 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.m @@ -0,0 +1,16 @@ +// +// NSArray+TDProperty.m +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import "NSArray+TDProperty.h" + +@implementation NSArray (TDProperty) + +- (void)ta_validatePropertyValueWithError:(NSError *__autoreleasing _Nullable *)error { + +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.m.meta new file mode 100644 index 0000000..f4730f9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSArray+TDProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f0ccf793fb9d34fb8a044b00769459d0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.h new file mode 100644 index 0000000..65a5923 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.h @@ -0,0 +1,17 @@ +// +// NSDate+TDProperty.h +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import +#import "TDValidatorProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDate (TDProperty) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.h.meta new file mode 100644 index 0000000..9ba94b6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 5bd640f0705e244d3b800f158b37a005 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.m new file mode 100644 index 0000000..6e5ab03 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.m @@ -0,0 +1,16 @@ +// +// NSDate+TDProperty.m +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import "NSDate+TDProperty.h" + +@implementation NSDate (TDProperty) + +- (void)ta_validatePropertyValueWithError:(NSError *__autoreleasing _Nullable *)error { + +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.m.meta new file mode 100644 index 0000000..7f1d4db --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDate+TDProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b252ae6780e87490893021d8be60499e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.h new file mode 100644 index 0000000..eca6181 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.h @@ -0,0 +1,17 @@ +// +// NSDictionary+TDProperty.h +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import +#import "TDValidatorProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDictionary (TAProperty) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.h.meta new file mode 100644 index 0000000..33c832b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d48c6bdcb25844d83b15e74bf7e84cad +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.m new file mode 100644 index 0000000..f76d4ba --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.m @@ -0,0 +1,16 @@ +// +// NSDictionary+TDProperty.m +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import "NSDictionary+TDProperty.h" + +@implementation NSDictionary (TAProperty) + +- (void)ta_validatePropertyValueWithError:(NSError *__autoreleasing _Nullable *)error { + +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.m.meta new file mode 100644 index 0000000..038db38 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSDictionary+TDProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: fe25956be5b1e4417b6d095ddf2925bb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.h new file mode 100644 index 0000000..30dc510 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.h @@ -0,0 +1,17 @@ +// +// NSNumber+TDProperty.h +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import +#import "TDValidatorProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NSNumber (TAProperty) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.h.meta new file mode 100644 index 0000000..c0b9099 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f59c5ace498ac4c0cb5bdc9f50e136f9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.m new file mode 100644 index 0000000..79e3726 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.m @@ -0,0 +1,20 @@ +// +// NSNumber+TDProperty.m +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import "NSNumber+TDProperty.h" + +@implementation NSNumber (TAProperty) + +- (void)ta_validatePropertyValueWithError:(NSError *__autoreleasing _Nullable *)error { + if ([self doubleValue] > 9999999999999.999 || [self doubleValue] < -9999999999999.999) { + NSString *errorMsg = [NSString stringWithFormat:@"The number value [%@] is invalid.", self]; + TDLogError(errorMsg); + *error = TAPropertyError(10009, errorMsg); + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.m.meta new file mode 100644 index 0000000..06e1125 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSNumber+TDProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b0e872d03f68c486bbb916834c990882 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.h new file mode 100644 index 0000000..543eecf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.h @@ -0,0 +1,17 @@ +// +// NSString+TDProperty.h +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import +#import "TDValidatorProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NSString (TAProperty) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.h.meta new file mode 100644 index 0000000..117fadd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bdd7b1a2929964449b750124cc364774 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.m new file mode 100644 index 0000000..9ecb9bd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.m @@ -0,0 +1,36 @@ +// +// NSString+TDProperty.m +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import "NSString+TDProperty.h" + + +static NSInteger kTAPropertyNameMaxLength = 50; + +@implementation NSString (TAProperty) + +- (void)ta_validatePropertyKeyWithError:(NSError *__autoreleasing _Nullable *)error { + if (self.length == 0) { + NSString *errorMsg = @"Property key or Event name is empty"; + TDLogError(errorMsg); + *error = TAPropertyError(10003, errorMsg); + return; + } + + if (self.length > kTAPropertyNameMaxLength) { + NSString *errorMsg = [NSString stringWithFormat:@"Property key or Event name %@'s length is longer than %ld", self, kTAPropertyNameMaxLength]; + TDLogError(errorMsg); + *error = TAPropertyError(10006, errorMsg); + return; + } + *error = nil; +} + +- (void)ta_validatePropertyValueWithError:(NSError *__autoreleasing _Nullable *)error { + +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.m.meta new file mode 100644 index 0000000..91f8d41 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/NSString+TDProperty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a4c9df72edb2643dc90762dd6f76c593 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.h new file mode 100644 index 0000000..2a10f70 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.h @@ -0,0 +1,17 @@ +// +// TAPropertyDefaultValidator.h +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import +#import "TDValidatorProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDPropertyDefaultValidator : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.h.meta new file mode 100644 index 0000000..95bae47 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 55f53cfe19fee4cdcb3fc6c4c5490642 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.m new file mode 100644 index 0000000..f2f45ed --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.m @@ -0,0 +1,17 @@ +// +// TAPropertyDefaultValidator.m +// Adjust +// +// Created by Yangxiongon 2022/7/1. +// + +#import "TDPropertyDefaultValidator.h" +#import "TDPropertyValidator.h" + +@implementation TDPropertyDefaultValidator + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError *__autoreleasing _Nullable *)error { + [TDPropertyValidator validateBaseEventPropertyKey:key value:value error:error]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.m.meta new file mode 100644 index 0000000..dcac914 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyDefaultValidator.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: eebd3afcb4ccc446eb78003734d6a083 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.h new file mode 100644 index 0000000..331adcb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.h @@ -0,0 +1,30 @@ +// +// TDPropertyValidator.h +// Adjust +// +// Created by Yangxiongon 2022/6/10. +// + +#import +#import "TDValidatorProtocol.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TDPropertyValidator : NSObject + ++ (void)validateEventOrPropertyName:(NSString *)name withError:(NSError **)error; + ++ (void)validateBaseEventPropertyKey:(NSString *)key value:(NSString *)value error:(NSError **)error; + ++ (void)validateNormalTrackEventPropertyKey:(NSString *)key value:(NSString *)value error:(NSError **)error; + ++ (void)validateAutoTrackEventPropertyKey:(NSString *)key value:(NSString *)value error:(NSError **)error; + + ++ (NSMutableDictionary *)validateProperties:(NSDictionary *)properties; + ++ (NSMutableDictionary *)validateProperties:(NSDictionary *)properties validator:(id)validator; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.h.meta new file mode 100644 index 0000000..ce093f1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f045b31c3d4434ff3b597c9a05328f0a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.m new file mode 100644 index 0000000..6246e5b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.m @@ -0,0 +1,133 @@ +// +// TDPropertyValidator.m +// Adjust +// +// Created by Yangxiongon 2022/6/10. +// + +#import "TDPropertyValidator.h" +#import "NSString+TDProperty.h" +#import "TDPropertyDefaultValidator.h" + +@implementation TDPropertyValidator + +/// Custom attribute name format validation +static NSString *const kTANormalTrackProperNameValidateRegularExpression = @"^([a-zA-Z][a-zA-Z\\d_]*|\\#(ops_push_status|ops_push_id|ops_task_id|client_user_id|ops_trigger_time|ops_exp_group_id|ops_actual_push_time|ops_receipt_properties|ops_risk_type|rcc_pull_result))$"; +/// Custom attribute name regularization +static NSRegularExpression *_regexForNormalTrackValidateKey; + +/// Automatic collection, custom attribute name format validation. All automatic collection of custom attributes needs to meet the following rules +static NSString *const kTAAutoTrackProperNameValidateRegularExpression = @"^([a-zA-Z][a-zA-Z\\d_]{0,49}|\\#(resume_from_background|app_crashed_reason|screen_name|referrer|title|url|element_id|element_type|element_content|element_position|background_duration|start_reason))$"; + +static NSRegularExpression *_regexForAutoTrackValidateKey; + ++ (void)validateEventOrPropertyName:(NSString *)name withError:(NSError *__autoreleasing _Nullable *)error { + if (!name) { + NSString *errorMsg = @"Property key or Event name is empty"; + TDLogError(errorMsg); + *error = TAPropertyError(10003, errorMsg); + return; + } + if (![name isKindOfClass:NSString.class]) { + NSString *errorMsg = [NSString stringWithFormat:@"Property key or Event name is not NSString: [%@]", name]; + TDLogError(errorMsg); + *error = TAPropertyError(10007, errorMsg); + return; + } + + [name ta_validatePropertyKeyWithError:error]; +} + ++ (void)validateBaseEventPropertyKey:(NSString *)key value:(NSString *)value error:(NSError **)error { + + if (![key conformsToProtocol:@protocol(TAPropertyKeyValidating)]) { + NSString *errMsg = [NSString stringWithFormat:@"The property KEY must be NSString. got: %@ %@", [key class], key]; + TDLogError(errMsg); + *error = TAPropertyError(10001, errMsg); + return; + } + [(id )key ta_validatePropertyKeyWithError:error]; + if (*error) { + return; + } + + + if (![value conformsToProtocol:@protocol(TDPropertyValueValidating)]) { + NSString *errMsg = [NSString stringWithFormat:@"Property value must be type NSString, NSNumber, NSDate, NSDictionary or NSArray. got: %@ %@. ", [value class], value]; + TDLogError(errMsg); + *error = TAPropertyError(10002, errMsg); + return; + } + [(id )value ta_validatePropertyValueWithError:error]; +} + ++ (void)validateNormalTrackEventPropertyKey:(NSString *)key value:(NSString *)value error:(NSError **)error { + [self validateBaseEventPropertyKey:key value:value error:error]; + if (*error) { + return; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _regexForNormalTrackValidateKey = [NSRegularExpression regularExpressionWithPattern:kTANormalTrackProperNameValidateRegularExpression options:NSRegularExpressionCaseInsensitive error:nil]; + }); + if (!_regexForNormalTrackValidateKey) { + NSString *errorMsg = @"Property Key validate regular expression init failed"; + TDLogError(errorMsg); + *error = TAPropertyError(10004, errorMsg); + return; + } + NSRange range = NSMakeRange(0, key.length); + if ([_regexForNormalTrackValidateKey numberOfMatchesInString:key options:0 range:range] < 1) { + NSString *errorMsg = [NSString stringWithFormat:@"Property Key or Event name: [%@] is invalid.", key]; + TDLogError(errorMsg); + *error = TAPropertyError(10005, errorMsg); + return; + } +} + ++ (void)validateAutoTrackEventPropertyKey:(NSString *)key value:(NSString *)value error:(NSError **)error { + [self validateBaseEventPropertyKey:key value:value error:error]; + if (*error) { + return; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _regexForAutoTrackValidateKey = [NSRegularExpression regularExpressionWithPattern:kTAAutoTrackProperNameValidateRegularExpression options:NSRegularExpressionCaseInsensitive error:nil]; + }); + if (!_regexForAutoTrackValidateKey) { + NSString *errorMsg = @"Property Key validate regular expression init failed"; + TDLogError(errorMsg); + *error = TAPropertyError(10004, errorMsg); + return; + } + NSRange range = NSMakeRange(0, key.length); + if ([_regexForAutoTrackValidateKey numberOfMatchesInString:key options:0 range:range] < 1) { + NSString *errorMsg = [NSString stringWithFormat:@"Property Key or Event name: [%@] is invalid.", key]; + TDLogError(errorMsg); + *error = TAPropertyError(10005, errorMsg); + return; + } +} + ++ (NSMutableDictionary *)validateProperties:(NSDictionary *)properties { + return [self validateProperties:properties validator:[[TDPropertyDefaultValidator alloc] init]]; +} + ++ (NSMutableDictionary *)validateProperties:(NSDictionary *)properties validator:(id)validator { + if (![properties isKindOfClass:[NSDictionary class]] || ![validator conformsToProtocol:@protocol(TDEventPropertyValidating)]) { + return nil; + } + + for (id key in properties) { + NSError *error = nil; + id value = properties[key]; + + + [validator ta_validateKey:key value:value error:&error]; + } + return [properties copy]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.m.meta new file mode 100644 index 0000000..f4c43f2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDPropertyValidator.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3bf426d0830804292bfa44163cde39d5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDValidatorProtocol.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDValidatorProtocol.h new file mode 100644 index 0000000..b3eca49 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDValidatorProtocol.h @@ -0,0 +1,45 @@ +// +// TDValidatorProtocol.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/7/1. +// + +#ifndef TDValidatorProtocol_h +#define TDValidatorProtocol_h + +#import + +#if __has_include() +#import +#else +#import "TDLogging.h" +#endif + +#define TAPropertyError(errorCode, errorMsg) \ + [NSError errorWithDomain:@"ThinkingAnalyticsErrorDomain" \ + code:errorCode \ + userInfo:@{NSLocalizedDescriptionKey:errorMsg}] \ + + +@protocol TAPropertyKeyValidating + +- (void)ta_validatePropertyKeyWithError:(NSError **)error; + +@end + +/// The validator protocol of the attribute value, used to verify the attribute value +@protocol TDPropertyValueValidating + +- (void)ta_validatePropertyValueWithError:(NSError **)error; + +@end + +/// The validator protocol of event properties, used to verify the key-value of a certain property +@protocol TDEventPropertyValidating + +- (void)ta_validateKey:(NSString *)key value:(id)value error:(NSError **)error; + +@end + +#endif /* TDValidatorProtocol_h */ diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDValidatorProtocol.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDValidatorProtocol.h.meta new file mode 100644 index 0000000..e5b2513 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/Property/Validate/TDValidatorProtocol.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bc9e5606226e945cbbec051ce90d733e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.h new file mode 100644 index 0000000..e1e5dbc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.h @@ -0,0 +1,47 @@ +// +// TAEventTracker.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/19. +// + +#import + +#if __has_include() +#import +#else +#import "TDConstant.h" +#endif + +#import "TDSecurityPolicy.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +NS_ASSUME_NONNULL_BEGIN + +@class TDEventTracker; + +@interface TDEventTracker : NSObject + ++ (dispatch_queue_t)td_networkQueue; + +- (instancetype)initWithQueue:(dispatch_queue_t)queue instanceToken:(NSString *)instanceToken; + +- (void)flush; + +- (void)track:(NSDictionary *)event immediately:(BOOL)immediately saveOnly:(BOOL)isSaveOnly; + +- (void)trackDebugEvent:(NSDictionary *)event; + +- (NSInteger)saveEventsData:(NSDictionary *)data; + +- (void)_asyncWithCompletion:(void(^)(void))completion; + +- (void)syncSendAllData; + +#pragma mark - UNAVAILABLE +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.h.meta new file mode 100644 index 0000000..fa2dccc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 96e49283fc793452c9d7d6c1c2882bf3 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.m new file mode 100644 index 0000000..a40fa42 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.m @@ -0,0 +1,352 @@ +// +// TAEventTracker.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/19. +// + +#import "TDEventTracker.h" +#import "TDAnalyticsNetwork.h" +#import "TDEventRecord.h" +#import "TDConfigPrivate.h" + +#if TARGET_OS_IOS + +#if __has_include() +#import +#else +#import "TDNetworkReachability.h" +#endif + +#endif + +static dispatch_queue_t td_networkQueue; +static NSUInteger const kBatchSize = 50; +static NSURLSessionTask *g_currentTask = nil; + +@interface TDEventTracker () +@property (atomic, strong) TDAnalyticsNetwork *network; +@property (atomic, strong) TDConfig *config; +@property (atomic, strong) dispatch_queue_t queue; +@property (nonatomic, strong) TDSqliteDataQueue *dataQueue; +@property (atomic, assign) BOOL networkProcessing; + +@end + +@implementation TDEventTracker + ++ (void)initialize { + static dispatch_once_t ThinkingOnceToken; + dispatch_once(&ThinkingOnceToken, ^{ + NSString *queuelabel = [NSString stringWithFormat:@"cn.thinkingdata.%p", (void *)self]; + NSString *networkLabel = [queuelabel stringByAppendingString:@".network"]; + td_networkQueue = dispatch_queue_create([networkLabel UTF8String], DISPATCH_QUEUE_SERIAL); + }); +} + ++ (dispatch_queue_t)td_networkQueue { + return td_networkQueue; +} + +- (instancetype)initWithQueue:(dispatch_queue_t)queue instanceToken:(nonnull NSString *)instanceToken { + if (self = [self init]) { + self.queue = queue; + self.config = [ThinkingAnalyticsSDK instanceWithAppid:instanceToken].config; + self.network = [self generateNetworkWithConfig:self.config]; + self.dataQueue = [TDSqliteDataQueue sharedInstanceWithAppid:[self.config innerGetMapInstanceToken]]; + } + return self; +} + +- (TDAnalyticsNetwork *)generateNetworkWithConfig:(TDConfig *)config { + TDAnalyticsNetwork *network = [[TDAnalyticsNetwork alloc] init]; + network.appid = config.appid; + network.sessionDidReceiveAuthenticationChallenge = config.securityPolicy.sessionDidReceiveAuthenticationChallenge; + network.serverURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/sync", config.serverUrl]]; + network.serverDebugURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@/data_debug", config.serverUrl]]; + network.securityPolicy = config.securityPolicy; + return network; +} + +//MARK: - Public + +- (void)track:(NSDictionary *)event immediately:(BOOL)immediately saveOnly:(BOOL)isSaveOnly { + TDMode mode = self.config.mode; + NSInteger count = 0; + if (mode == TDModeDebugOnly || mode == TDModeDebug) { + + if (isSaveOnly) { + return; + } + TDLogInfo(@"Enqueue data: %@", event); + dispatch_async(self.queue, ^{ + dispatch_async(td_networkQueue, ^{ + [self flushDebugEvent:event]; + }); + }); + // TDModeDebug Mode After the data is sent, it will still be stored locally, so it is necessary to query the database data to determine whether the number of records is sufficient for uploading + @synchronized (TDSqliteDataQueue.class) { + count = [self.dataQueue sqliteCountForAppid:[self.config innerGetMapInstanceToken]]; + } + } else { + if (immediately) { + + if (isSaveOnly) { + return; + } + TDLogInfo(@"Enqueue data: %@", event); + dispatch_async(self.queue, ^{ + dispatch_async(td_networkQueue, ^{ + [self flushImmediately:event]; + }); + }); + } else { + TDLogInfo(@"Enqueue data: %@", event); + count = [self saveEventsData:event]; + } + } + if (count >= [self.config.uploadSize integerValue]) { + + if (isSaveOnly) { + return; + } + TDLogInfo(@"SDK flush success. The cache is full. count: %ld, uploadSize: %d", count, [self.config.uploadSize integerValue]); + [self flush]; + } +} + +- (void)trackDebugEvent:(NSDictionary *)event { + dispatch_async(self.queue, ^{ + dispatch_async(td_networkQueue, ^{ + [self.network flushDebugEvents:event appid:self.config.appid isDebugOnly:YES]; + }); + }); +} + +- (void)flushImmediately:(NSDictionary *)event { + TDLogInfo(@"SDK flush success. Immediately."); + [self.network flushEvents:@[event]]; +} + +- (NSInteger)saveEventsData:(NSDictionary *)data { + NSMutableDictionary *event = [[NSMutableDictionary alloc] initWithDictionary:data]; + NSInteger count = 0; + @synchronized (TDSqliteDataQueue.class) { + + if (self.config.innerEnableEncrypt) { +#if TARGET_OS_IOS + NSDictionary *encryptData = [[ThinkingAnalyticsSDK instanceWithAppid:[self.config innerGetMapInstanceToken]].encryptManager encryptJSONObject:event]; + if (encryptData == nil) { + encryptData = event; + } + count = [self.dataQueue addObject:encryptData withAppid:[self.config innerGetMapInstanceToken]]; +#elif TARGET_OS_OSX + count = [self.dataQueue addObject:event withAppid:[self.config innerGetMapInstanceToken]]; +#endif + } else { + count = [self.dataQueue addObject:event withAppid:[self.config innerGetMapInstanceToken]]; + } + } + return count; +} + +- (void)flushDebugEvent:(NSDictionary *)event { + if (self.config.mode == TDModeDebug || self.config.mode == TDModeDebugOnly) { + BOOL isDebugOnly = self.config.mode == TDModeDebugOnly; + int debugResult = [self.network flushDebugEvents:event appid:self.config.appid isDebugOnly:isDebugOnly]; + if (debugResult == -1) { + // Downgrade + if (self.config.mode == TDModeDebug) { + dispatch_async(self.queue, ^{ + [self saveEventsData:event]; + }); + } else if (self.config.mode == TDModeDebugOnly) { + TDLogDebug(@"The data will be discarded due to this device is not allowed to debug:%@", event); + } + self.config.mode = TDModeNormal; + } + else if (debugResult == -2) { + TDLogDebug(@"Exception occurred when sending message to Server:%@", event); + if (self.config.mode == TDModeDebug) { + + dispatch_async(self.queue, ^{ + [self saveEventsData:event]; + }); + } + } + } else { + + NSInteger count = [self saveEventsData:event]; + if (count >= [self.config.uploadSize integerValue]) { + [self flush]; + } + } +} + +- (void)flush { + [self _asyncWithCompletion:^{}]; +} + +/// Synchronize data asynchronously (synchronize data in the local database to TA) +/// Need to add this event to the serialQueue queue +/// In some scenarios, event warehousing and sending network requests happen at the same time. Event storage is performed in serialQueue, and data reporting is performed in networkQueue. To ensure that events are stored first, you need to add the reported data operation to serialQueue +- (void)_asyncWithCompletion:(void(^)(void))completion { + if (self.networkProcessing) { + return; + } + + void(^block)(void) = ^{ + dispatch_async(td_networkQueue, ^{ + [self _syncWithSize:kBatchSize completion:completion]; + }); + }; + if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(self.queue)) { + block(); + } else { + dispatch_async(self.queue, block); + } +} + +/// Synchronize data (synchronize the data in the local database to TA) +/// @param size The maximum number of items obtained from the database each time, the default is 50 +/// @param completion synchronous callback +/// This method needs to be performed in networkQueue, and will continue to send network requests until the data in the database is sent +- (void)_syncWithSize:(NSUInteger)size completion:(void(^)(void))completion { +#if TARGET_OS_IOS + NSString *networkType = [[TDNetworkReachability shareInstance] networkState]; + if (!([self convertNetworkType:networkType] & [self.config getNetworkType])) { + if (completion) { + completion(); + } + return; + } +#endif + + NSArray *recordArray; + NSArray *recodIds; + NSArray *uuids; + @synchronized (TDSqliteDataQueue.class) { + + NSArray *records = [self.dataQueue getFirstRecords:kBatchSize withAppid:[self.config innerGetMapInstanceToken]]; + NSArray *encryptRecords = [self encryptEventRecords:records]; + NSMutableArray *indexs = [[NSMutableArray alloc] initWithCapacity:encryptRecords.count]; + NSMutableArray *recordContents = [[NSMutableArray alloc] initWithCapacity:encryptRecords.count]; + for (TDEventRecord *record in encryptRecords) { + [indexs addObject:record.index]; + [recordContents addObject:record.event]; + } + recodIds = indexs; + recordArray = recordContents; + + + uuids = [self.dataQueue upadteRecordIds:recodIds]; + } + + + if (recordArray.count == 0 || uuids.count == 0) { + if (completion) { + completion(); + } + return; + } + + self.networkProcessing = YES; + + BOOL flushSucc = YES; + int _maxStackCount = 0; + while (recordArray.count > 0 && uuids.count > 0 && flushSucc && _maxStackCount <= 100) { + @autoreleasepool { + flushSucc = [self.network flushEvents:recordArray]; + if (flushSucc) { + @synchronized (TDSqliteDataQueue.class) { + _maxStackCount ++; + BOOL ret = [self.dataQueue removeDataWithuids:uuids]; + if (!ret) { + break; + } + + NSArray *records = [self.dataQueue getFirstRecords:kBatchSize withAppid:[self.config innerGetMapInstanceToken]]; + NSArray *encryptRecords = [self encryptEventRecords:records]; + NSMutableArray *indexs = [[NSMutableArray alloc] initWithCapacity:encryptRecords.count]; + NSMutableArray *recordContents = [[NSMutableArray alloc] initWithCapacity:encryptRecords.count]; + for (TDEventRecord *record in encryptRecords) { + [indexs addObject:record.index]; + [recordContents addObject:record.event]; + } + recodIds = indexs; + recordArray = recordContents; + + + uuids = [self.dataQueue upadteRecordIds:recodIds]; + } + } else { + _maxStackCount = 0; + break; + } + } + } + if (completion) { + completion(); + } + + self.networkProcessing = NO; +} + +- (NSArray *)encryptEventRecords:(NSArray *)records { +#if TARGET_OS_IOS + NSMutableArray *encryptRecords = [NSMutableArray arrayWithCapacity:records.count]; + + TDEncryptManager *encryptManager = [ThinkingAnalyticsSDK instanceWithAppid:[self.config innerGetMapInstanceToken]].encryptManager; + + if (self.config.innerEnableEncrypt && encryptManager.isValid) { + for (TDEventRecord *record in records) { + + if (record.encrypted) { + + [encryptRecords addObject:record]; + } else { + + NSDictionary *obj = [encryptManager encryptJSONObject:record.event]; + if (obj) { + [record setSecretObject:obj]; + [encryptRecords addObject:record]; + } else { + [encryptRecords addObject:record]; + } + } + } + return encryptRecords.count == 0 ? records : encryptRecords; + } else { + return records; + } +#elif TARGET_OS_OSX + return records; +#endif +} + +- (void)syncSendAllData { + dispatch_sync(td_networkQueue, ^{}); +} + +- (ThinkingNetworkType)convertNetworkType:(NSString *)networkType { + if ([@"NULL" isEqualToString:networkType]) { + return ThinkingNetworkTypeALL; + } else if ([@"WIFI" isEqualToString:networkType]) { + return ThinkingNetworkTypeWIFI; + } else if ([@"2G" isEqualToString:networkType]) { + return ThinkingNetworkType2G; + } else if ([@"3G" isEqualToString:networkType]) { + return ThinkingNetworkType3G; + } else if ([@"4G" isEqualToString:networkType]) { + return ThinkingNetworkType4G; + }else if([@"5G"isEqualToString:networkType]) + { + return ThinkingNetworkType5G; + } + return ThinkingNetworkTypeNONE; +} + +//MARK: - Setter & Getter + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.m.meta new file mode 100644 index 0000000..c737eca --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TDEventTracker.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: de132dccb9e414af19f5261fa4b9b5fa +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration.meta new file mode 100644 index 0000000..81b4af7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 42a60c1e385b74b2da608fb4a875b5f2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.h new file mode 100644 index 0000000..5d42800 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.h @@ -0,0 +1,33 @@ +// +// TATrackTimer.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/1. +// Copyright © 2022 thinking. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDTrackTimer : NSObject + +- (void)trackEvent:(NSString *)eventName withSystemUptime:(NSTimeInterval)systemUptime; + +- (void)enterForegroundWithSystemUptime:(NSTimeInterval)systemUptime; + +- (void)enterBackgroundWithSystemUptime:(NSTimeInterval)systemUptime; + +- (NSTimeInterval)foregroundDurationOfEvent:(NSString * _Nonnull)eventName isActive:(BOOL)isActive systemUptime:(NSTimeInterval)systemUptime; + +- (NSTimeInterval)backgroundDurationOfEvent:(NSString * _Nonnull)eventName isActive:(BOOL)isActive systemUptime:(NSTimeInterval)systemUptime; + +- (void)removeEvent:(NSString * _Nonnull)eventName; + +- (BOOL)isExistEvent:(NSString * _Nonnull)eventName; + +- (void)clear; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.h.meta new file mode 100644 index 0000000..54daacd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4341e200d79f546c689421e723d7cc4a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.m new file mode 100644 index 0000000..935afc2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.m @@ -0,0 +1,150 @@ +// +// TATrackTimer.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/1. +// Copyright © 2022 thinking. All rights reserved. +// + +#import "TDTrackTimer.h" +#import "TDTrackTimerItem.h" +#import "TDLogging.h" + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + +@interface TDTrackTimer () +@property (nonatomic, strong) NSMutableDictionary *events; + +@end + +@implementation TDTrackTimer + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.events = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)trackEvent:(NSString *)eventName withSystemUptime:(NSTimeInterval)systemUptime { + if (!eventName.length) { + return; + } + TDTrackTimerItem *item = [[TDTrackTimerItem alloc] init]; + item.beginTime = systemUptime ?: [TDCoreDeviceInfo bootTime]; + @synchronized (self) { + self.events[eventName] = item; + } + TDLogInfo(@"time event success"); +} + +- (void)enterForegroundWithSystemUptime:(NSTimeInterval)systemUptime { + @synchronized (self) { + NSArray *keys = [self.events allKeys]; + for (NSString *key in keys) { + TDTrackTimerItem *item = self.events[key]; + item.beginTime = systemUptime; + if (item.enterBackgroundTime == 0) { + item.backgroundDuration = 0; + } else { + item.backgroundDuration = systemUptime - item.enterBackgroundTime + item.backgroundDuration; + } + } + } +} + +- (void)enterBackgroundWithSystemUptime:(NSTimeInterval)systemUptime { + @synchronized (self) { + NSArray *keys = [self.events allKeys]; + for (NSString *key in keys) { + TDTrackTimerItem *item = self.events[key]; + item.enterBackgroundTime = systemUptime; + item.foregroundDuration = systemUptime - item.beginTime + item.foregroundDuration; + } + } +} + +- (NSTimeInterval)foregroundDurationOfEvent:(NSString *)eventName isActive:(BOOL)isActive systemUptime:(NSTimeInterval)systemUptime { + if (!eventName.length) { + return 0; + } + TDTrackTimerItem *item = nil; + @synchronized (self) { + item = self.events[eventName]; + } + if (!item) { + return 0; + } + + if (isActive) { + NSTimeInterval duration = systemUptime - item.beginTime + item.foregroundDuration; + return [self validateDuration:duration eventName:eventName]; + } else { + return [self validateDuration:item.foregroundDuration eventName:eventName]; + } + +} + +- (NSTimeInterval)backgroundDurationOfEvent:(NSString *)eventName isActive:(BOOL)isActive systemUptime:(NSTimeInterval)systemUptime { + if (!eventName.length) { + return 0; + } + TDTrackTimerItem *item = nil; + @synchronized (self) { + item = self.events[eventName]; + } + if (!item) { + return 0; + } + if (isActive) { + return [self validateDuration:item.backgroundDuration eventName:eventName]; + } else { + NSTimeInterval duration = 0; + if (item.enterBackgroundTime == 0) { + duration = 0; + } else { + duration = systemUptime - item.enterBackgroundTime + item.backgroundDuration; + } + return [self validateDuration:duration eventName:eventName]; + } +} + +- (void)removeEvent:(NSString *)eventName { + @synchronized (self) { + [self.events removeObjectForKey:eventName]; + } +} + +- (BOOL)isExistEvent:(NSString *)eventName { + BOOL result = NO; + @synchronized (self) { + result = self.events[eventName] != nil; + } + return result; +} + +- (void)clear { + @synchronized (self) { + [self.events removeAllObjects]; + } +} + +//MARK: - Private Methods + +- (NSTimeInterval)validateDuration:(NSTimeInterval)duration eventName:(NSString *)eventName { + NSInteger max = 3600 * 24; + if (duration >= max) { + return max; + } + return duration; +} + +@end + + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.m.meta new file mode 100644 index 0000000..b0fb54c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimer.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 22581b89ad23541399cb273d79c4cd59 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.h b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.h new file mode 100644 index 0000000..2acbdec --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.h @@ -0,0 +1,25 @@ +// +// TATrackTimerItem.h +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/1. +// Copyright © 2022 thinking. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDTrackTimerItem : NSObject +/// The moment when the event starts to be recorded (the total time the device has been running) +@property (nonatomic, assign) NSTimeInterval beginTime; +/// Accumulated time in the foreground +@property (nonatomic, assign) NSTimeInterval foregroundDuration; +/// The time the event entered the background (total time the device has been running) +@property (nonatomic, assign) NSTimeInterval enterBackgroundTime; +/// accumulated time in the background +@property (nonatomic, assign) NSTimeInterval backgroundDuration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.h.meta new file mode 100644 index 0000000..d8588bf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4e9cbb821670a4b9bbed0f25a7b3822d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.m b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.m new file mode 100644 index 0000000..9f97ab0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.m @@ -0,0 +1,17 @@ +// +// TATrackTimerItem.m +// ThinkingSDK +// +// Created by Yangxiongon 2022/6/1. +// Copyright © 2022 thinking. All rights reserved. +// + +#import "TDTrackTimerItem.h" + +@implementation TDTrackTimerItem + +-(NSString *)description { + return [NSString stringWithFormat:@"beginTime: %lf, foregroundDuration: %lf, enterBackgroundTime: %lf, backgroundDuration: %lf", _beginTime, _foregroundDuration, _enterBackgroundTime, _backgroundDuration];; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.m.meta new file mode 100644 index 0000000..a53ceb3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/EventTracker/TrackDuration/TDTrackTimerItem.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 48de2073ef1674bc191b3fc5c5262d00 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Exception.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception.meta new file mode 100644 index 0000000..de99cb0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 424ad4c901eb74799ac16ee8ebcf5c5a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.h new file mode 100644 index 0000000..5c5933e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.h @@ -0,0 +1,15 @@ +#import + +#import "ThinkingAnalyticsSDKPrivate.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ThinkingExceptionHandler : NSObject + ++ (void)start; + ++ (void)trackCrashWithMessage:(NSString *)message; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.h.meta new file mode 100644 index 0000000..e3d8c77 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 324500141046444d2b21f6b4a110accc +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.m new file mode 100644 index 0000000..ae941d0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.m @@ -0,0 +1,223 @@ +#import "ThinkingExceptionHandler.h" +#include +#include +#import "TDLogging.h" +#import "TDAutoTrackManager.h" + +#if __has_include() +#import +#else +#import "TDCorePresetDisableConfig.h" +#endif + +static NSString * const TD_CRASH_REASON = @"#app_crashed_reason"; +static NSUInteger const TD_PROPERTY_CRASH_LENGTH_LIMIT = 8191*2; + +static NSString * const TDUncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName"; +static NSString * const TDUncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey"; +static int TDSignals[] = {SIGILL, SIGABRT, SIGBUS, SIGSEGV, SIGFPE, SIGPIPE, SIGTRAP}; +static volatile atomic_int_fast32_t TDExceptionCount = 0; +static const atomic_int_fast32_t TDExceptionMaximum = 9; + +@interface ThinkingExceptionHandler () +@property (nonatomic) NSUncaughtExceptionHandler *td_lastExceptionHandler; +@property (nonatomic, unsafe_unretained) struct sigaction *td_signalHandlers; + +@end + +@implementation ThinkingExceptionHandler + ++ (void)start { + [self sharedHandler]; +} + ++ (instancetype)sharedHandler { + static ThinkingExceptionHandler *gSharedHandler = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + gSharedHandler = [[ThinkingExceptionHandler alloc] init]; + }); + return gSharedHandler; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _td_signalHandlers = calloc(NSIG, sizeof(struct sigaction)); + [self setupHandlers]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + // start APMStuck + Class cls = NSClassFromString(@"TAAPMStuckMonitor"); + if (cls && [cls respondsToSelector:@selector(shareInstance)]) { + id ins = [cls performSelector:@selector(shareInstance)]; + if (ins && [ins respondsToSelector:@selector(beginMonitor)]) { + [ins performSelector:@selector(beginMonitor)]; + } + } +#pragma clang diagnostic push + } + return self; +} + +- (void)setupHandlers { + _td_lastExceptionHandler = NSGetUncaughtExceptionHandler(); + NSSetUncaughtExceptionHandler(&TDHandleException); + + struct sigaction action; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = &TDSignalHandler; + for (int i = 0; i < sizeof(TDSignals) / sizeof(int); i++) { + struct sigaction prev_action; + int err = sigaction(TDSignals[i], &action, &prev_action); + if (err == 0) { + memcpy(_td_signalHandlers + TDSignals[i], &prev_action, sizeof(prev_action)); + } else { + TDLogError(@"Error Signal: %d", TDSignals[i]); + } + } +} + +static void TDHandleException(NSException *exception) { + ThinkingExceptionHandler *handler = [ThinkingExceptionHandler sharedHandler]; + + atomic_int_fast32_t exceptionCount = atomic_fetch_add_explicit(&TDExceptionCount, 1, memory_order_relaxed); + if (exceptionCount <= TDExceptionMaximum) { + [handler td_handleUncaughtException:exception]; + } + if (handler.td_lastExceptionHandler) { + handler.td_lastExceptionHandler(exception); + } +} + +static void TDSignalHandler(int signalNumber, struct __siginfo *info, void *context) { + ThinkingExceptionHandler *handler = [ThinkingExceptionHandler sharedHandler]; + NSMutableDictionary *crashInfo; + NSString *reason; + NSException *exception; + + atomic_int_fast32_t exceptionCount = atomic_fetch_add_explicit(&TDExceptionCount, 1, memory_order_relaxed); + if (exceptionCount <= TDExceptionMaximum) { + [crashInfo setObject:[NSNumber numberWithInt:signalNumber] forKey:TDUncaughtExceptionHandlerSignalKey]; + reason = [NSString stringWithFormat:@"Signal %d was raised.", signalNumber]; + exception = [NSException exceptionWithName:TDUncaughtExceptionHandlerSignalExceptionName reason:reason userInfo:crashInfo]; + [handler td_handleUncaughtException:exception]; + } + + struct sigaction prev_action = handler.td_signalHandlers[signalNumber]; + if (prev_action.sa_handler == SIG_DFL) { + signal(signalNumber, SIG_DFL); + raise(signalNumber); + return; + } + if (prev_action.sa_flags & SA_SIGINFO) { + if (prev_action.sa_sigaction) { + prev_action.sa_sigaction(signalNumber, info, context); + } + } else if (prev_action.sa_handler) { + prev_action.sa_handler(signalNumber); + } +} + +- (void)td_handleUncaughtException:(NSException *)exception { + NSDictionary *crashInfo = [ThinkingExceptionHandler crashInfoWithException:exception]; + TDAutoTrackEvent *crashEvent = [[TDAutoTrackEvent alloc] initWithName:TD_APP_CRASH_EVENT]; + [[TDAutoTrackManager sharedManager] trackWithEvent:crashEvent withProperties:crashInfo]; + + TDAutoTrackEvent *appEndEvent = [[TDAutoTrackEvent alloc] initWithName:TD_APP_END_EVENT]; + [[TDAutoTrackManager sharedManager] trackWithEvent:appEndEvent withProperties:nil]; + + dispatch_sync([ThinkingAnalyticsSDK sharedTrackQueue], ^{}); + dispatch_sync([ThinkingAnalyticsSDK sharedNetworkQueue], ^{}); + + NSSetUncaughtExceptionHandler(NULL); + for (int i = 0; i < sizeof(TDSignals) / sizeof(int); i++) { + signal(TDSignals[i], SIG_DFL); + } +} + ++ (void)trackCrashWithMessage:(NSString *)message { + NSDictionary *crashInfo = [ThinkingExceptionHandler crashInfoWithMessage:message]; + TDAutoTrackEvent *crashEvent = [[TDAutoTrackEvent alloc] initWithName:TD_APP_CRASH_EVENT]; + [[TDAutoTrackManager sharedManager] trackWithEvent:crashEvent withProperties:crashInfo]; +} + ++ (NSMutableDictionary *)crashInfoWithMessage:(NSString *)message { + NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; + + if ([TDCorePresetDisableConfig disableAppCrashedReason]) { + return properties; + } + + NSString *crashStr = message; + @try { + crashStr = [crashStr stringByReplacingOccurrencesOfString:@"\n" withString:@"
"]; + + NSUInteger strLength = [((NSString *)crashStr) lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + NSUInteger strMaxLength = TD_PROPERTY_CRASH_LENGTH_LIMIT; + if (strLength > strMaxLength) { + crashStr = [NSMutableString stringWithString:[ThinkingExceptionHandler limitString:crashStr withLength:strMaxLength - 1]]; + } + + [properties setValue:crashStr forKey:TD_CRASH_REASON]; + } @catch(NSException *exception) { + TDLogError(@"%@ error: %@", self, exception); + } + return properties; +} + ++ (NSMutableDictionary *)crashInfoWithException:(NSException *)exception { + NSMutableDictionary *properties = [[NSMutableDictionary alloc] init]; + + + if ([TDCorePresetDisableConfig disableAppCrashedReason]) { + return properties; + } + + NSString *crashStr; + @try { + if ([exception callStackSymbols]) { + crashStr = [NSString stringWithFormat:@"Exception Reason:%@\nException Stack:%@", [exception reason], [exception callStackSymbols]]; + } else { + NSString *exceptionStack = [[NSThread callStackSymbols] componentsJoinedByString:@"\n"]; + crashStr = [NSString stringWithFormat:@"%@ %@", [exception reason], exceptionStack]; + } + crashStr = [crashStr stringByReplacingOccurrencesOfString:@"\n" withString:@"
"]; + + NSUInteger strLength = [((NSString *)crashStr) lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + NSUInteger strMaxLength = TD_PROPERTY_CRASH_LENGTH_LIMIT; + if (strLength > strMaxLength) { + crashStr = [NSMutableString stringWithString:[ThinkingExceptionHandler limitString:crashStr withLength:strMaxLength - 1]]; + } + + [properties setValue:crashStr forKey:TD_CRASH_REASON]; + } @catch(NSException *exception) { + TDLogError(@"%@ error: %@", self, exception); + } + return properties; +} + ++ (NSString *)limitString:(NSString *)originalString withLength:(NSInteger)length { + NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF8); + NSData *originalData = [originalString dataUsingEncoding:encoding]; + NSData *subData = [originalData subdataWithRange:NSMakeRange(0, length)]; + NSString *limitString = [[NSString alloc] initWithData:subData encoding:encoding]; + + NSInteger index = 1; + while (index <= 3 && !limitString) { + if (length > index) { + subData = [originalData subdataWithRange:NSMakeRange(0, length - index)]; + limitString = [[NSString alloc] initWithData:subData encoding:encoding]; + } + index ++; + } + + if (!limitString) { + return originalString; + } + return limitString; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.m.meta new file mode 100644 index 0000000..a8812a3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Exception/ThinkingExceptionHandler.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 117c7c030e0b54e6e8f897168f54a42a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook.meta new file mode 100644 index 0000000..a6f6ae8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1fad8194c321b459a87a1d406935f376 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.h new file mode 100644 index 0000000..55a67f3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.h @@ -0,0 +1,18 @@ + +#import +#import "TDDelegateProxyObject.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (TDDelegateProxy) + +@property (nonatomic, copy, nullable) NSSet *thinkingdata_optionalSelectors; +@property (nonatomic, strong, nullable) TDDelegateProxyObject *thinkingdata_delegateObject; + +/// hook respondsToSelector to resolve optional selectors +/// @param aSelector selector +- (BOOL)thinkingdata_respondsToSelector:(SEL)aSelector; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.h.meta new file mode 100644 index 0000000..8590660 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bf6b9bccbe81e45df980f2d62857723f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.m new file mode 100644 index 0000000..3b90390 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.m @@ -0,0 +1,43 @@ + +#import "NSObject+TDDelegateProxy.h" +#import + +#if TARGET_OS_IOS +#import +#endif + +@implementation NSObject (TDDelegateProxy) + +- (NSSet *)thinkingdata_optionalSelectors { + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setThinkingdata_optionalSelectors:(NSSet *)thinkingdata_optionalSelectors { + objc_setAssociatedObject(self, @selector(thinkingdata_optionalSelectors), thinkingdata_optionalSelectors, OBJC_ASSOCIATION_COPY); +} + +- (TDDelegateProxyObject *)thinkingdata_delegateObject { + return objc_getAssociatedObject(self, _cmd); +} + +- (void)setThinkingdata_delegateObject:(TDDelegateProxyObject *)thinkingdata_delegateObject { + objc_setAssociatedObject(self, @selector(thinkingdata_delegateObject), thinkingdata_delegateObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (BOOL)thinkingdata_respondsToSelector:(SEL)aSelector { + if ([self thinkingdata_respondsToSelector:aSelector]) { + return YES; + } + if (@available(iOS 18.0, *)) { + char startOfHeader = (char)sel_getName(aSelector); + if (startOfHeader == '\x01') { + return NO; + } + } + if ([self.thinkingdata_optionalSelectors containsObject:NSStringFromSelector(aSelector)]) { + return YES; + } + return NO; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.m.meta new file mode 100644 index 0000000..f4adb9d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/NSObject+TDDelegateProxy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1443a480bd360400fbb0620d42807fd8 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.h new file mode 100644 index 0000000..5a14c76 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.h @@ -0,0 +1,25 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol TDHookDelegateProtocol +@optional ++ (NSSet *)optionalSelectors; + +@end + +@interface TDDelegateProxy : NSObject + ++ (void)proxyDelegate:(id)delegate selectors:(NSSet*)selectors; + ++ (void)invokeWithTarget:(NSObject *)target selector:(SEL)selector, ...; + ++ (BOOL)invokeReturnBOOLWithTarget:(NSObject *)target selector:(SEL)selector arg1:(id)arg1 arg2:(id)arg2; ++ (BOOL)invokeReturnBOOLWithTarget:(NSObject *)target selector:(SEL)selector arg1:(id)arg1 arg2:(id)arg2 arg3:(id)arg3; + ++ (void)resolveOptionalSelectorsForDelegate:(id)delegate; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.h.meta new file mode 100644 index 0000000..8b17caf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: abc2d6f428f894d56a694a776f137fc6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.m new file mode 100644 index 0000000..ee58d2d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.m @@ -0,0 +1,210 @@ + +#import "TDDelegateProxy.h" +#import "TDLogging.h" + +#if __has_include() +#import +#else +#import "TDClassHelper.h" +#endif +#if __has_include() +#import +#else +#import "TDMethodHelper.h" +#endif +#import "NSObject+TDDelegateProxy.h" +#import + +static NSString * const kTDNSObjectRemoveObserverSelector = @"removeObserver:forKeyPath:"; +static NSString * const kTDNSObjectAddObserverSelector = @"addObserver:forKeyPath:options:context:"; +static NSString * const kTDNSObjectClassSelector = @"class"; + +@implementation TDDelegateProxy + ++ (void)proxyDelegate:(id)delegate selectors:(NSSet *)selectors { + if (object_isClass(delegate) || selectors.count == 0) { + return; + } + + Class proxyClass = [self class]; + NSMutableSet *delegateSelectors = [NSMutableSet setWithSet:selectors]; + + TDDelegateProxyObject *object = [delegate thinkingdata_delegateObject]; + if (!object) { + object = [[TDDelegateProxyObject alloc] initWithDelegate:delegate proxy:proxyClass]; + [delegate setThinkingdata_delegateObject:object]; + } + + [delegateSelectors minusSet:object.selectors]; + if (delegateSelectors.count == 0) { + return; + } + + if (object.thinkingClass) { + [self addInstanceMethodWithSelectors:delegateSelectors fromClass:proxyClass toClass:object.thinkingClass]; + [object.selectors unionSet:delegateSelectors]; + + if (![object_getClass(delegate) isSubclassOfClass:object.thinkingClass]) { + [TDClassHelper setObject:delegate toClass:object.thinkingClass]; + } + return; + } + + if (object.kvoClass) { + if ([delegate isKindOfClass:NSObject.class] && ![object.selectors containsObject:kTDNSObjectRemoveObserverSelector]) { + [delegateSelectors addObject:kTDNSObjectRemoveObserverSelector]; + } + [self addInstanceMethodWithSelectors:delegateSelectors fromClass:proxyClass toClass:object.kvoClass]; + [object.selectors unionSet:delegateSelectors]; + return; + } + + Class thinkingClass = [TDClassHelper allocateClassWithObject:delegate className:object.thinkingClassName]; + [TDClassHelper registerClass:thinkingClass]; + + if ([delegate isKindOfClass:NSObject.class] && ![object.selectors containsObject:kTDNSObjectAddObserverSelector]) { + [delegateSelectors addObject:kTDNSObjectAddObserverSelector]; + } + + if (![object.selectors containsObject:kTDNSObjectClassSelector]) { + [delegateSelectors addObject:kTDNSObjectClassSelector]; + } + + [self addInstanceMethodWithSelectors:delegateSelectors fromClass:proxyClass toClass:thinkingClass]; + [object.selectors unionSet:delegateSelectors]; + + [TDClassHelper setObject:delegate toClass:thinkingClass]; +} + ++ (void)addInstanceMethodWithSelectors:(NSSet *)selectors fromClass:(Class)fromClass toClass:(Class)toClass { + for (NSString *selector in selectors) { + SEL sel = NSSelectorFromString(selector); + [TDMethodHelper addInstanceMethodWithSelector:sel fromClass:fromClass toClass:toClass]; + } +} + ++ (BOOL)invokeReturnBOOLWithTarget:(NSObject *)target selector:(SEL)selector arg1:(id)arg1 arg2:(id)arg2 arg3:(id)arg3 { + Class originalClass = target.thinkingdata_delegateObject.delegateISA; + + struct objc_super targetSuper = { + .receiver = target, + .super_class = originalClass + }; + + BOOL returnValue = NO; + @try { + returnValue = ((BOOL (*)(struct objc_super *, SEL, id, id, id))objc_msgSendSuper)(&targetSuper, selector, arg1, arg2, arg3); + } @catch (NSException *exception) { + TDLogInfo(@"msgSendSuper with exception: %@", exception); + } @finally { + + } + return returnValue; +} + ++ (BOOL)invokeReturnBOOLWithTarget:(NSObject *)target selector:(SEL)selector arg1:(id)arg1 arg2:(id)arg2 { + Class originalClass = target.thinkingdata_delegateObject.delegateISA; + + struct objc_super targetSuper = { + .receiver = target, + .super_class = originalClass + }; + + BOOL returnValue = NO; + @try { + returnValue = ((BOOL (*)(struct objc_super *, SEL, id, id))objc_msgSendSuper)(&targetSuper, selector, arg1, arg2); + } @catch (NSException *exception) { + TDLogInfo(@"msgSendSuper with exception: %@", exception); + } @finally { + + } + return returnValue; +} + ++ (void)invokeWithTarget:(NSObject *)target selector:(SEL)selector, ... { + Class originalClass = target.thinkingdata_delegateObject.delegateISA; + + va_list args; + va_start(args, selector); + id arg1 = nil, arg2 = nil, arg3 = nil, arg4 = nil; + NSInteger count = [NSStringFromSelector(selector) componentsSeparatedByString:@":"].count - 1; + for (NSInteger i = 0; i < count; i++) { + i == 0 ? (arg1 = va_arg(args, id)) : nil; + i == 1 ? (arg2 = va_arg(args, id)) : nil; + i == 2 ? (arg3 = va_arg(args, id)) : nil; + i == 3 ? (arg4 = va_arg(args, id)) : nil; + } + struct objc_super targetSuper = { + .receiver = target, + .super_class = originalClass + }; + + @try { + void (*func)(struct objc_super *, SEL, id, id, id, id) = (void *)&objc_msgSendSuper; + func(&targetSuper, selector, arg1, arg2, arg3, arg4); + } @catch (NSException *exception) { + TDLogInfo(@"msgSendSuper with exception: %@", exception); + } @finally { + va_end(args); + } +} + + ++ (void)resolveOptionalSelectorsForDelegate:(id)delegate { + if (object_isClass(delegate)) { + return; + } + + NSSet *currentOptionalSelectors = ((NSObject *)delegate).thinkingdata_optionalSelectors; + NSMutableSet *optionalSelectors = [[NSMutableSet alloc] init]; + if (currentOptionalSelectors) { + [optionalSelectors unionSet:currentOptionalSelectors]; + } + + if ([self respondsToSelector:@selector(optionalSelectors)] &&[self optionalSelectors]) { + [optionalSelectors unionSet:[self optionalSelectors]]; + } + ((NSObject *)delegate).thinkingdata_optionalSelectors = [optionalSelectors copy]; +} + +@end + +#pragma mark - Class +@implementation TDDelegateProxy (Class) + +- (Class)class { + if (self.thinkingdata_delegateObject.delegateClass) { + return self.thinkingdata_delegateObject.delegateClass; + } + return [super class]; +} + +@end + +#pragma mark - KVO +@implementation TDDelegateProxy (KVO) + +- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context { + [super addObserver:observer forKeyPath:keyPath options:options context:context]; + if (self.thinkingdata_delegateObject) { + [TDMethodHelper replaceInstanceMethodWithDestinationSelector:@selector(class) sourceSelector:@selector(class) fromClass:TDDelegateProxy.class toClass:object_getClass(self)]; + } +} + +- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath { + BOOL oldClassIsKVO = [TDDelegateProxyObject isKVOClass:object_getClass(self)]; + [super removeObserver:observer forKeyPath:keyPath]; + BOOL newClassIsKVO = [TDDelegateProxyObject isKVOClass:object_getClass(self)]; + + if (oldClassIsKVO && !newClassIsKVO) { + Class delegateProxy = self.thinkingdata_delegateObject.delegateProxy; + NSSet *selectors = [self.thinkingdata_delegateObject.selectors copy]; + + [self.thinkingdata_delegateObject removeKVO]; + if ([delegateProxy respondsToSelector:@selector(proxyDelegate:selectors:)]) { + [delegateProxy proxyDelegate:self selectors:selectors]; + } + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.m.meta new file mode 100644 index 0000000..8f43adb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: df179f624e9fc47ec8d5df299227eba7 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.h new file mode 100644 index 0000000..76d5b16 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.h @@ -0,0 +1,34 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDDelegateProxyObject : NSObject + +@property (nonatomic, strong) Class delegateISA; + +@property (nonatomic, strong, nullable) Class kvoClass; + +@property (nonatomic, copy, nullable) NSString *thinkingClassName; + +@property (nonatomic, strong, readonly, nullable) Class thinkingClass; + +@property (nonatomic, strong) id delegateClass; + +@property (nonatomic, strong) Class delegateProxy; + +@property (nonatomic, strong) NSMutableSet *selectors; + +- (instancetype)initWithDelegate:(id)delegate proxy:(id)proxy; + +- (void)removeKVO; + +@end + +@interface TDDelegateProxyObject (Utils) + ++ (BOOL)isKVOClass:(Class _Nullable)cls; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.h.meta new file mode 100644 index 0000000..603fba1 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9f695fe5c0b134075a398b6de1a0b0e0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.m new file mode 100644 index 0000000..63164d3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.m @@ -0,0 +1,56 @@ + +#import "TDDelegateProxyObject.h" +#import + +NSString * const kTDDelegateClassThinkingSuffix = @"_TD.THINKINGDATA"; +NSString * const kTDDelegateClassKVOPrefix = @"KVONotifying_"; + +@implementation TDDelegateProxyObject + +- (instancetype)initWithDelegate:(id)delegate proxy:(id)proxy { + self = [super init]; + if (self) { + _delegateProxy = proxy; + + _selectors = [NSMutableSet set]; + _delegateClass = [delegate class]; + + Class cla = object_getClass(delegate); + NSString *name = NSStringFromClass(cla); + + if ([name containsString:kTDDelegateClassKVOPrefix]) { + _delegateISA = class_getSuperclass(cla); + _kvoClass = cla; + } else if ([name containsString:kTDDelegateClassThinkingSuffix]) { + _delegateISA = class_getSuperclass(cla); + _thinkingClassName = name; + } else { + _delegateISA = cla; + _thinkingClassName = [NSString stringWithFormat:@"%@%@", name, kTDDelegateClassThinkingSuffix]; + } + } + return self; +} + +- (Class)thinkingClass { + return NSClassFromString(self.thinkingClassName); +} + +- (void)removeKVO { + self.kvoClass = nil; + self.thinkingClassName = [NSString stringWithFormat:@"%@%@", self.delegateISA, kTDDelegateClassThinkingSuffix]; + [self.selectors removeAllObjects]; +} + +@end + +#pragma mark - Utils + +@implementation TDDelegateProxyObject (Utils) + ++ (BOOL)isKVOClass:(Class _Nullable)cls { + return [NSStringFromClass(cls) containsString:kTDDelegateClassKVOPrefix]; +} + +@end + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.m.meta new file mode 100644 index 0000000..c680fac --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Hook/TDDelegateProxyObject.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 98c147b3fa40d45539700d4a545ad01e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Logger.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger.meta new file mode 100644 index 0000000..7eb10d2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0120f127190314e89affebd1c9a54166 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.h new file mode 100644 index 0000000..033ede5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.h @@ -0,0 +1,27 @@ +#import +#import "TDConstant.h" + +NS_ASSUME_NONNULL_BEGIN + +#define TDLogDebug(message, ...) TDLogWithType(TDLoggingLevelDebug, message, ##__VA_ARGS__) +#define TDLogInfo(message, ...) TDLogWithType(TDLoggingLevelInfo, message, ##__VA_ARGS__) +#define TDLogError(message, ...) TDLogWithType(TDLoggingLevelError, message, ##__VA_ARGS__) + +#define TDLogWithType(type, message, ...) \ +{ \ +if ([TDLogging sharedInstance].loggingLevel != TDLoggingLevelNone && type <= [TDLogging sharedInstance].loggingLevel) \ +{ \ +[[TDLogging sharedInstance] logCallingFunction:type format:(message), ##__VA_ARGS__]; \ +} \ +} + +@interface TDLogging : NSObject +@property (assign, nonatomic) TDLoggingLevel loggingLevel; + ++ (instancetype)sharedInstance; + +- (void)logCallingFunction:(TDLoggingLevel)type format:(id)messageFormat, ...; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.h.meta new file mode 100644 index 0000000..c9c161a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: d0672cd3af5d9412f878f36eacab6134 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.m new file mode 100644 index 0000000..48c3c9e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.m @@ -0,0 +1,54 @@ +#import "TDLogging.h" + +#if __has_include() +#import +#else +#import "TDOSLog.h" +#endif + +@implementation TDLogging + ++ (instancetype)sharedInstance { + static dispatch_once_t once; + static id sharedInstance; + dispatch_once(&once, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; +} + +- (void)logCallingFunction:(TDLoggingLevel)type format:(id)messageFormat, ... { + if (messageFormat) { + va_list formatList; + va_start(formatList, messageFormat); + NSString *formattedMessage = [[NSString alloc] initWithFormat:messageFormat arguments:formatList]; + va_end(formatList); + + TDLogType logType = TDLogTypeOff; + switch (type) { + case TDLoggingLevelNone: + logType = TDLogTypeOff; + break; + case TDLoggingLevelError: + logType = TDLogTypeError; + break; + case TDLoggingLevelWarning: + logType = TDLogTypeWarning; + break; + case TDLoggingLevelInfo: + logType = TDLogTypeInfo; + break; + case TDLoggingLevelDebug: + logType = TDLogTypeDebug; + break; + default: + logType = TDLogTypeOff; + break; + } + NSString *prefix = @"ThinkingData"; + [TDOSLog logMessage:formattedMessage prefix:prefix type:logType asynchronous:YES]; + } +} + +@end + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.m.meta new file mode 100644 index 0000000..88e9273 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Logger/TDLogging.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c05e62825e23a4c159c5d4b8608a9e89 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Network.meta new file mode 100644 index 0000000..c36ad05 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a0ac6f354c3474862987da42fe4db1aa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.h new file mode 100644 index 0000000..3a6623a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.h @@ -0,0 +1,29 @@ +#import + +#import "ThinkingAnalyticsSDKPrivate.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^TDFlushConfigBlock)(NSDictionary *result, NSError * _Nullable error); + +@interface TDAnalyticsNetwork : NSObject + +@property (nonatomic, copy) NSString *appid; +@property (nonatomic, strong) NSURL *serverURL; + +@property (nonatomic, strong) NSURL *serverDebugURL; +@property (nonatomic, strong) TDSecurityPolicy *securityPolicy; +@property (nonatomic, copy) TDURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge; + +- (BOOL)flushEvents:(NSArray *)events; + +- (void)fetchRemoteConfig:(NSString *)appid handler:(TDFlushConfigBlock)handler; +- (int)flushDebugEvents:(NSDictionary *)record appid:(NSString *)appid isDebugOnly:(BOOL)isDebugOnly; +- (void)fetchIPMap; + ++ (void)enableDNSServcie:(NSArray *)services; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.h.meta new file mode 100644 index 0000000..2c85b13 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a542eb235a6bc440f9aebb7d13d953b5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.m new file mode 100644 index 0000000..99a8893 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.m @@ -0,0 +1,496 @@ +#import "TDAnalyticsNetwork.h" + +#if __has_include() +#import +#else +#import "NSData+TDGzip.h" +#endif +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif +#import "TDLogging.h" +#import "TDSecurityPolicy.h" +#import "TDAppState.h" + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + +#if TARGET_OS_IOS +#import "TDToastView.h" +#endif + +static NSString *kTAIntegrationType = @"TA-Integration-Type"; +static NSString *kTAIntegrationVersion = @"TA-Integration-Version"; +static NSString *kTAIntegrationCount = @"TA-Integration-Count"; +static NSString *kTAIntegrationExtra = @"TA-Integration-Extra"; +static NSString *kTADatasType = @"TA-Datas-Type"; + +static NSTimeInterval g_lastQueryDNSTime = 0; +static dispatch_queue_t g_queryDNSQueue = nil; +static NSArray *g_dnsServices = nil; +static NSMutableDictionary *g_dnsIpMap = nil; + +@interface TDAnalyticsNetwork () + +@property (atomic, assign) BOOL dnsServiceDegrade; + +@end + +@implementation TDAnalyticsNetwork + +- (NSURLSession *)sharedURLSession { + static dispatch_once_t onceToken; + static NSURLSession *sharedSession = nil; + dispatch_once(&onceToken, ^{ + NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; + sharedSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; + }); + return sharedSession; +} + +- (NSString *)URLEncode:(NSString *)string { + NSString *encodedString = [string stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@"?!@#$^&%*+,:;='\"`<>()[]{}/\\| "] invertedSet]]; + return encodedString; +} + +- (int)flushDebugEvents:(NSDictionary *)record appid:(NSString *)appid isDebugOnly:(BOOL)isDebugOnly { + __block int debugResult = -1; + NSString *jsonString = [TDJSONUtil JSONStringForObject:record]; + NSMutableURLRequest *request = [self buildDebugRequestWithJSONString:jsonString appid:appid deviceId:[TDCoreDeviceInfo deviceId] isDebugOnly:isDebugOnly]; + dispatch_semaphore_t flushSem = dispatch_semaphore_create(0); + + void (^block)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) { + + if (error || ![response isKindOfClass:[NSHTTPURLResponse class]]) { + debugResult = -2; + TDLogError(@"Debug Networking error:%@", error); + [self callbackNetworkErrorWithRequest:jsonString error:error.debugDescription]; + dispatch_semaphore_signal(flushSem); + return; + } + NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *)response; + if ([urlResponse statusCode] == 200) { + NSError *err; + + if (!data) { + dispatch_semaphore_signal(flushSem); + return; + } + + NSDictionary *retDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&err]; + TDLogDebug(@"Send event, Response = %@", retDic); + + if (err) { + TDLogError(@"Debug data json error:%@", err); + debugResult = -2; + } else if ([[retDic objectForKey:@"errorLevel"] isEqualToNumber:[NSNumber numberWithInt:1]]) { + debugResult = 1; + NSArray* errorProperties = [retDic objectForKey:@"errorProperties"]; + NSMutableString *errorStr = [NSMutableString string]; + for (id obj in errorProperties) { + NSString *errorReasons = [obj objectForKey:@"errorReason"]; + NSString *propertyName = [obj objectForKey:@"propertyName"]; + [errorStr appendFormat:@" propertyName:%@ errorReasons:%@\n", propertyName, errorReasons]; + } + TDLogError(@"Debug data error:%@", errorStr); + } else if ([[retDic objectForKey:@"errorLevel"] isEqualToNumber:[NSNumber numberWithInt:2]]) { + debugResult = 2; + NSString *errorReasons = [[retDic objectForKey:@"errorReasons"] componentsJoinedByString:@" "]; + TDLogError(@"Debug data error:%@", errorReasons); + } else if ([[retDic objectForKey:@"errorLevel"] isEqualToNumber:[NSNumber numberWithInt:0]]) { + debugResult = 0; + TDLogDebug(@"Verify data success."); + } else if ([[retDic objectForKey:@"errorLevel"] isEqualToNumber:[NSNumber numberWithInt:-1]]) { + debugResult = -1; + NSString *errorReasons = [[retDic objectForKey:@"errorReasons"] componentsJoinedByString:@" "]; + TDLogError(@"Debug mode error:%@", errorReasons); + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + if (debugResult == 0 || debugResult == 1 || debugResult == 2) { +#if TARGET_OS_IOS + dispatch_async(dispatch_get_main_queue(), ^{ + UIApplication *application = [TDAppState sharedApplication]; + if (![application isKindOfClass:UIApplication.class]) { + return; + } + UIWindow *window = application.keyWindow; + [TDToastView showInWindow:window text:[NSString stringWithFormat:@"The current mode is:%@", isDebugOnly ? @"DebugOnly(Data is not persisted) \n The test joint debugging stage is allowed to open \n Please turn off the Debug function before the official launch" : @"Debug"] duration:2.0]; + }); +#endif + } + }); + + @try { + if ([retDic isKindOfClass:[NSDictionary class]]) { + if ([[(NSDictionary *)retDic objectForKey:@"errorLevel"] integerValue] != 0) { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:retDic options:NSJSONWritingPrettyPrinted error:NULL]; + NSString *string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + [self callbackNetworkErrorWithRequest:jsonString error:string]; + } + } + } @catch (NSException *exception) { + + } + } else { + if ([TDAnalyticsNetwork isEnableDNS]) { + self.dnsServiceDegrade = YES; + } + debugResult = -2; + NSString *urlResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + TDLogError(@"%@", [NSString stringWithFormat:@"Debug %@ network failed with response '%@'.", self, urlResponse]); + [self callbackNetworkErrorWithRequest:jsonString error:urlResponse]; + } + dispatch_semaphore_signal(flushSem); + }; + + NSURLSessionDataTask *task = [[self sharedURLSession] dataTaskWithRequest:request completionHandler:block]; + TDLogDebug(@"Send event. %@\nRequest = %@", request.URL.absoluteString, record); + [task resume]; + + dispatch_semaphore_wait(flushSem, DISPATCH_TIME_FOREVER); + return debugResult; +} + +- (BOOL)flushEvents:(NSArray *)recordArray { + __block BOOL flushSucc = YES; + UInt64 time = [[NSDate date] timeIntervalSince1970] * 1000; + NSDictionary *flushDic = @{ + @"data": recordArray, + @"#app_id": self.appid, + @"#flush_time": @(time), + }; + + __block BOOL isEncrypt; + [recordArray enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if ([obj.allKeys containsObject:@"ekey"]) { + isEncrypt = YES; + *stop = YES; + } + }]; + + NSString *jsonString = [TDJSONUtil JSONStringForObject:flushDic]; + NSMutableURLRequest *request = [self buildRequestWithJSONString:jsonString]; + [request addValue:[TDDeviceInfo sharedManager].libName forHTTPHeaderField:kTAIntegrationType]; + [request addValue:[TDDeviceInfo sharedManager].libVersion forHTTPHeaderField:kTAIntegrationVersion]; + [request addValue:@(recordArray.count).stringValue forHTTPHeaderField:kTAIntegrationCount]; + [request addValue:@"iOS" forHTTPHeaderField:kTAIntegrationExtra]; + if (isEncrypt) { + [request addValue:@"1" forHTTPHeaderField:kTADatasType]; + } +// [request addValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"]; +// [request addValue:@"timeout=15,max=100" forHTTPHeaderField:@"Keep-Alive"]; + + dispatch_semaphore_t flushSem = dispatch_semaphore_create(0); + + void (^block)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) { + if (error || ![response isKindOfClass:[NSHTTPURLResponse class]]) { + flushSucc = NO; + TDLogError(@"Networking error:%@", error); + [self callbackNetworkErrorWithRequest:jsonString error:error.debugDescription]; + dispatch_semaphore_signal(flushSem); + return; + } + + NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *)response; + if ([urlResponse statusCode] == 200) { + flushSucc = YES; + if (!data) { + dispatch_semaphore_signal(flushSem); + return; + } + id result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; + TDLogDebug(@"Send event, Response = %@", result); + + @try { + if ([result isKindOfClass:[NSDictionary class]]) { + if ([[(NSDictionary *)result objectForKey:@"code"] integerValue] != 0) { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:result options:NSJSONWritingPrettyPrinted error:NULL]; + NSString *string = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + [self callbackNetworkErrorWithRequest:jsonString error:string]; + } + } + } @catch (NSException *exception) { + + } + + } else { + flushSucc = NO; + if ([TDAnalyticsNetwork isEnableDNS]) { + self.dnsServiceDegrade = YES; + } + NSString *urlResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + TDLogError(@"%@", [NSString stringWithFormat:@"%@ network failed with response '%@'.", self, urlResponse]); + [self callbackNetworkErrorWithRequest:jsonString error:urlResponse]; + } + + dispatch_semaphore_signal(flushSem); + }; + + NSURLSessionDataTask *task = [[self sharedURLSession] dataTaskWithRequest:request completionHandler:block]; + TDLogDebug(@"Send event. %@\nRequest = %@", request.URL.absoluteString, flushDic); + [task resume]; + dispatch_semaphore_wait(flushSem, DISPATCH_TIME_FOREVER); + return flushSucc; +} + ++ (void)enableDNSServcie:(NSArray *)services { + @synchronized (TDAnalyticsNetwork.class) { + g_dnsServices = [services copy]; + } + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + g_queryDNSQueue = dispatch_queue_create("cn.thinkingdata.analytics.queryDNS", DISPATCH_QUEUE_SERIAL); + }); +} + ++ (BOOL)isEnableDNS { + BOOL result = NO; + @synchronized (TDAnalyticsNetwork.class) { + if (g_dnsServices.count > 0) { + result = YES; + } + } + return result; +} + +- (void)fetchIPMap { + [self getDNSIps]; +} + +- (void)callbackNetworkErrorWithRequest:(NSString *)request error:(NSString *)error { + if (request == nil && error == nil) return; + + ThinkingAnalyticsSDK *tdSDK = [ThinkingAnalyticsSDK instanceWithAppid:self.appid]; + if (tdSDK.errorCallback) { + NSInteger code = 10001; + NSString *errorMsg = error; + NSString *ext = request; + tdSDK.errorCallback(code, errorMsg, ext); + } +} + +- (NSMutableURLRequest *)buildRequestWithJSONString:(NSString *)jsonString { + NSData *zippedData = [NSData td_gzipData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]]; + NSString *postBody = [zippedData base64EncodedStringWithOptions:0]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[self formatURLWithOriginalUrl:self.serverURL]]; + [request setHTTPMethod:@"POST"]; + [request setHTTPBody:[postBody dataUsingEncoding:NSUTF8StringEncoding]]; + NSString *contentType = [NSString stringWithFormat:@"text/plain"]; + [request addValue:contentType forHTTPHeaderField:@"Content-Type"]; + [request setTimeoutInterval:60.0]; + return request; +} + +- (NSURL *)formatURLWithOriginalUrl:(NSURL *)url { + if (!url) { + return nil; + } + @synchronized (TDAnalyticsNetwork.class) { + if (!g_dnsServices || g_dnsServices.count <= 0) { + return url; + } + } + if (self.dnsServiceDegrade) { + return url; + } + NSString *ipStr = nil; + @synchronized (TDAnalyticsNetwork.class) { + ipStr = [g_dnsIpMap objectForKey:url.host]; + } + if ([ipStr isKindOfClass:NSString.class] && ipStr.length > 0) { + NSString *ipUrlString = [NSString stringWithFormat:@"%@://%@%@", url.scheme, ipStr, url.path]; + NSURL *serverUrl = [NSURL URLWithString:ipUrlString] ?: url; + return serverUrl; + } else { + [self getDNSIps]; + return url; + } +} + +- (NSMutableURLRequest *)buildDebugRequestWithJSONString:(NSString *)jsonString appid:(NSString *)appid deviceId:(NSString *)deviceId isDebugOnly:(BOOL)isDebugOnly { + // dryRun=0, if the verification is passed, it will be put into storage. dryRun=1, no storage + int dryRun = isDebugOnly ? 1 : 0; + NSString *appendParams = [NSString stringWithFormat:@"appid=%@&source=client&dryRun=%d&deviceId=%@", appid, dryRun, deviceId]; + TDLogDebug(@"RequestAppendParams: %@", appendParams); + NSString *postData = [NSString stringWithFormat:@"%@&data=%@", appendParams, [self URLEncode:jsonString]]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[self formatURLWithOriginalUrl:self.serverDebugURL]]; + [request setHTTPMethod:@"POST"]; + request.HTTPBody = [postData dataUsingEncoding:NSUTF8StringEncoding]; + return request; +} + +- (void)fetchRemoteConfig:(NSString *)appid handler:(TDFlushConfigBlock)handler { + void (^block)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) { + if (error || ![response isKindOfClass:[NSHTTPURLResponse class]]) { + TDLogError(@"Get remote config failed:%@", error); + return; + } + NSError *err; + if (!data) { + return; + } + NSDictionary *ret = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&err]; + if (err) { + TDLogError(@"Get remote config error:%@", err); + } else if ([ret isKindOfClass:[NSDictionary class]] && [ret[@"code"] isEqualToNumber:[NSNumber numberWithInt:0]]) { + TDLogInfo(@"Get remote config for %@ : %@", appid, [ret objectForKey:@"data"]); + handler([ret objectForKey:@"data"], error); + } else { + TDLogError(@"Get remote config failed"); + } + }; + NSString *urlStr = [NSString stringWithFormat:@"%@?appid=%@", self.serverURL, appid]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr]]; + [request setHTTPMethod:@"Get"]; + NSURLSessionDataTask *task = [[self sharedURLSession] dataTaskWithRequest:request completionHandler:block]; + [task resume]; +} + +#pragma mark - NSURLSessionDelegate +- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { + NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling; + NSURLCredential *credential = nil; + + NSString *domain = challenge.protectionSpace.host; + + if ([TDAnalyticsNetwork isEnableDNS]) { + // is IP or not + if (![self.serverURL.host isEqualToString:domain] && ![self isDomainInDNSService:domain]) { + domain = [self getOriginHostWithIp:domain]; + if (domain == nil) { + domain = self.serverURL.host; + } + } + } + + if (self.sessionDidReceiveAuthenticationChallenge) { + disposition = self.sessionDidReceiveAuthenticationChallenge(session, challenge, &credential); + } else { + if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { + if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:domain]) { + credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; + if (credential) { + disposition = NSURLSessionAuthChallengeUseCredential; + } else { + disposition = NSURLSessionAuthChallengePerformDefaultHandling; + } + } else { + disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge; + } + } else { + disposition = NSURLSessionAuthChallengePerformDefaultHandling; + } + } + + if (completionHandler) { + completionHandler(disposition, credential); + } +} + +- (void)getDNSIps { + NSArray *dnsServices = nil; + @synchronized (TDAnalyticsNetwork.class) { + if (!g_dnsServices || g_dnsServices.count <= 0) { + return; + } + dnsServices = [g_dnsServices copy]; + // Throttle DNS network query. Period is 30s + NSTimeInterval nowTimeInterval = [[NSDate date] timeIntervalSince1970]; + if (nowTimeInterval - g_lastQueryDNSTime <= 30) { + return; + } else { + g_lastQueryDNSTime = nowTimeInterval; + } + } + NSString *serverHost = [self.serverURL host]; + dispatch_async(g_queryDNSQueue, ^{ + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + TDLogDebug(@"Parse DNS request is begining ..."); + for (TDDNSService dnsServiceUrl in dnsServices) { + NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", dnsServiceUrl, serverHost]]; + NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; + [request setHTTPMethod:@"GET"]; + [request addValue:@"application/dns-json" forHTTPHeaderField:@"accept"]; + [request setTimeoutInterval:6]; + __block BOOL result = NO; + NSURLSessionDataTask *task = [[self sharedURLSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { + if (error == nil && data != nil && data.length > 0) { + NSError *jsonError = nil; + NSDictionary *dnsResult = nil; + @try { + dnsResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError]; + } @catch (NSException *exception) { + + } + if (jsonError == nil && [dnsResult isKindOfClass:NSDictionary.class]) { + NSString *ipStr = nil; + NSArray *answer = [dnsResult objectForKey:@"Answer"]; + if (answer && [answer isKindOfClass:[NSArray class]]) { + NSDictionary *dnsObj = [answer lastObject]; + if (dnsObj && [dnsObj isKindOfClass:[NSDictionary class]]) { + ipStr = [dnsObj objectForKey:@"data"]; + } + } + if (ipStr && [ipStr isKindOfClass:[NSString class]]) { + result = YES; + @synchronized (TDAnalyticsNetwork.class) { + if (g_dnsIpMap == nil) { + g_dnsIpMap = [NSMutableDictionary dictionary]; + } + [g_dnsIpMap setObject:ipStr forKey:serverHost]; + } + } + } + } else { + TDLogError(@"Parse DNS error: %@", error.localizedDescription); + } + dispatch_semaphore_signal(semaphore); + }]; + TDLogDebug(@"Parse DNS request: %@", request.URL.absoluteString); + [task resume]; + dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC))); + TDLogDebug(@"Parse DNS response: %@. Service url: %@", result ? @"success" : @"failed", request.URL.absoluteString); + if (result) { + @synchronized (TDAnalyticsNetwork.class) { + TDLogDebug(@"Parse DNS is end. %@", g_dnsIpMap); + } + break; + } + } + }); +} + +- (BOOL)isDomainInDNSService:(NSString *)domain { + NSArray *dNSServices = @[TDDNSServiceCloudFlare, TDDNSServiceCloudALi, TDDNSServiceCloudGoogle]; + for (TDDNSService dnsServiceUrl in dNSServices) { + if ([dnsServiceUrl containsString:domain]) { + return YES; + } + } + return NO; +} + +- (NSString *)getOriginHostWithIp:(NSString *)ip { + if ([ip isKindOfClass:NSString.class] && ip.length <= 0) { + return nil; + } + __block NSString *originHost = nil; + @synchronized (TDAnalyticsNetwork.class) { + [g_dnsIpMap enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { + if ([obj isKindOfClass:[NSString class]] && [obj containsString:ip]) { + originHost = key; + *stop = YES; + } + }]; + } + return originHost; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.m.meta new file mode 100644 index 0000000..d41d92e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDAnalyticsNetwork.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 15979de9edb0f4a7da257667abe7a19f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.h new file mode 100644 index 0000000..f15a3c6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.h @@ -0,0 +1,50 @@ + +/** + Thinks AFNetworking: https://github.com/AFNetworking/AFNetworking + */ +#import + +#if __has_include() +#import +#else +#import "TDConstant.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + + +@interface TDSecurityPolicy: NSObject + +@property (nonatomic, assign) BOOL allowInvalidCertificates; +@property (nonatomic, assign) BOOL validatesDomainName; +@property (nonatomic, copy) TDURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge; ++ (instancetype)policyWithPinningMode:(TDSSLPinningMode)pinningMode; ++ (instancetype)defaultPolicy; +- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain; + +@end + +#ifndef __Require_Quiet + #define __Require_Quiet(assertion, exceptionLabel) \ + do \ + { \ + if ( __builtin_expect(!(assertion), 0) ) \ + { \ + goto exceptionLabel; \ + } \ + } while ( 0 ) +#endif + +#ifndef __Require_noErr_Quiet + #define __Require_noErr_Quiet(errorCode, exceptionLabel) \ + do \ + { \ + if ( __builtin_expect(0 != (errorCode), 0) ) \ + { \ + goto exceptionLabel; \ + } \ + } while ( 0 ) +#endif + + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.h.meta new file mode 100644 index 0000000..58808da --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 9781dc44aea76461dbad775986c949f1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.m new file mode 100644 index 0000000..c0f61af --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.m @@ -0,0 +1,248 @@ +#import "TDSecurityPolicy.h" + +#import "TDLogging.h" + +static id TDPublicKeyForCertificate(NSData *certificate) { + id allowedPublicKey = nil; + SecCertificateRef allowedCertificate; + SecPolicyRef policy = nil; + SecTrustRef allowedTrust = nil; + SecTrustResultType result; + + allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); + __Require_Quiet(allowedCertificate != NULL, _out); + + policy = SecPolicyCreateBasicX509(); + __Require_noErr_Quiet(SecTrustCreateWithCertificates(allowedCertificate, policy, &allowedTrust), _out); + __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out); + + allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust); + +_out: + if (allowedTrust) { + CFRelease(allowedTrust); + } + + if (policy) { + CFRelease(policy); + } + + if (allowedCertificate) { + CFRelease(allowedCertificate); + } + + return allowedPublicKey; +} + +static BOOL TDServerTrustIsValid(SecTrustRef serverTrust) { + BOOL isValid = NO; + SecTrustResultType result; + __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); + + isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); + +_out: + return isValid; +} + +static NSArray * TDCertificateTrustChainForServerTrust(SecTrustRef serverTrust) { + CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); + NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; + + for (CFIndex i = 0; i < certificateCount; i++) { + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); + [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]; + } + + return [NSArray arrayWithArray:trustChain]; +} + +static NSArray * TDPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { + SecPolicyRef policy = SecPolicyCreateBasicX509(); + CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); + NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; + for (CFIndex i = 0; i < certificateCount; i++) { + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); + + SecCertificateRef someCertificates[] = {certificate}; + CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL); + + SecTrustRef trust; + __Require_noErr_Quiet(SecTrustCreateWithCertificates(certificates, policy, &trust), _out); + + SecTrustResultType result; + __Require_noErr_Quiet(SecTrustEvaluate(trust, &result), _out); + + [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)]; + + _out: + if (trust) { + CFRelease(trust); + } + + if (certificates) { + CFRelease(certificates); + } + + continue; + } + CFRelease(policy); + + return [NSArray arrayWithArray:trustChain]; +} + +static BOOL TDSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) { + return [(__bridge id)key1 isEqual:(__bridge id)key2]; +} + +@interface TDSecurityPolicy () + +@property (nonatomic, assign) TDSSLPinningMode SSLPinningMode; +@property (nonatomic, strong, nullable) NSSet *pinnedCertificates; +@property (readwrite, nonatomic, strong) NSSet *pinnedPublicKeys; + +@end + +@implementation TDSecurityPolicy + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + self.validatesDomainName = YES; + + return self; +} + ++ (NSSet *)certificatesInBundle:(NSBundle *)bundle { + NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."]; + + NSMutableSet *certificates = [NSMutableSet setWithCapacity:[paths count]]; + for (NSString *path in paths) { + NSData *certificateData = [NSData dataWithContentsOfFile:path]; + [certificates addObject:certificateData]; + } + + return [NSSet setWithSet:certificates]; +} + ++ (NSSet *)defaultPinnedCertificates { + static NSSet *_defaultPinnedCertificates = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + _defaultPinnedCertificates = [self certificatesInBundle:bundle]; + }); + + return _defaultPinnedCertificates; +} + ++ (instancetype)defaultPolicy { + TDSecurityPolicy *securityPolicy = [[self alloc] init]; + securityPolicy.SSLPinningMode = TDSSLPinningModeNone; + return securityPolicy; +} + ++ (instancetype)policyWithPinningMode:(TDSSLPinningMode)pinningMode { + return [self policyWithPinningMode:pinningMode withPinnedCertificates:[self defaultPinnedCertificates]]; +} + ++ (instancetype)policyWithPinningMode:(TDSSLPinningMode)pinningMode withPinnedCertificates:(NSSet *)pinnedCertificates { + TDSecurityPolicy *securityPolicy = [[self alloc] init]; + securityPolicy.SSLPinningMode = pinningMode; + [securityPolicy setPinnedCertificates:pinnedCertificates]; + return securityPolicy; +} + +- (void)setPinnedCertificates:(NSSet *)pinnedCertificates { + _pinnedCertificates = pinnedCertificates; + + if (self.pinnedCertificates) { + NSMutableSet *mutablePinnedPublicKeys = [NSMutableSet setWithCapacity:[self.pinnedCertificates count]]; + for (NSData *certificate in self.pinnedCertificates) { + id publicKey = TDPublicKeyForCertificate(certificate); + if (publicKey) { + [mutablePinnedPublicKeys addObject:publicKey]; + } + } + self.pinnedPublicKeys = [NSSet setWithSet:mutablePinnedPublicKeys]; + } else { + self.pinnedPublicKeys = nil; + } +} + +- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain { + if (domain && self.allowInvalidCertificates && self.validatesDomainName && (self.SSLPinningMode == TDSSLPinningModeNone || [self.pinnedCertificates count] == 0)) { + TDLogDebug(@"In order to validate a domain name for self signed certificates, you MUST use pinning."); + return NO; + } + + NSMutableArray *policies = [NSMutableArray array]; + if (self.validatesDomainName) { + [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; + } else { + [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()]; + } + + SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); + + if (self.SSLPinningMode == TDSSLPinningModeNone) { + return self.allowInvalidCertificates || TDServerTrustIsValid(serverTrust); + } else if (!TDServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { + return NO; + } + + switch (self.SSLPinningMode) { + case TDSSLPinningModeCertificate: { + NSMutableArray *pinnedCertificates = [NSMutableArray array]; + for (NSData *certificateData in self.pinnedCertificates) { + [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)]; + } + SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates); + + if (!TDServerTrustIsValid(serverTrust)) { + return NO; + } + + NSArray *serverCertificates = TDCertificateTrustChainForServerTrust(serverTrust); + for (NSData *trustChainCertificate in [serverCertificates reverseObjectEnumerator]) { + if ([self.pinnedCertificates containsObject:trustChainCertificate]) { + return YES; + } + } + return NO; + } + case TDSSLPinningModePublicKey: { + NSUInteger trustedPublicKeyCount = 0; + NSArray *publicKeys = TDPublicKeyTrustChainForServerTrust(serverTrust); + + for (id trustChainPublicKey in publicKeys) { + for (id pinnedPublicKey in self.pinnedPublicKeys) { + if (TDSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) { + trustedPublicKeyCount += 1; + } + } + } + return trustedPublicKeyCount > 0; + } + + default: + return NO; + } + + return NO; +} + +#pragma mark - NSCopying +- (instancetype)copyWithZone:(NSZone *)zone { + TDSecurityPolicy *securityPolicy = [[[self class] allocWithZone:zone] init]; + securityPolicy.SSLPinningMode = self.SSLPinningMode; + securityPolicy.allowInvalidCertificates = self.allowInvalidCertificates; + securityPolicy.validatesDomainName = self.validatesDomainName; + securityPolicy.pinnedCertificates = [self.pinnedCertificates copyWithZone:zone]; + return securityPolicy; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.m.meta new file mode 100644 index 0000000..1e726c6 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Network/TDSecurityPolicy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 11369661a3b6e47e9a9b7c0607c9db2c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty.meta new file mode 100644 index 0000000..0991d1d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ca77b616b13e34ddbbc5ae27a6a510ed +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.h b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.h new file mode 100644 index 0000000..5a87b9f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.h @@ -0,0 +1,79 @@ +// +// TDPresetProperties.h +// ThinkingSDK +// +// Created by huangdiao on 2021/5/25. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDPresetProperties : NSObject + +/// app bundle id +@property (nonatomic, copy, readonly) NSString *bundle_id; + +/// Mobile phone SIM card operator information. The value is null after ios 16 +@property (nonatomic, copy, readonly) NSString *carrier; + +/// Device id +@property (nonatomic, copy, readonly) NSString *device_id; + +/// Device model +@property (nonatomic, copy, readonly) NSString *device_model; + +/// Device manufacture +@property (nonatomic, copy, readonly) NSString *manufacturer; + +/// Network type +@property (nonatomic, copy, readonly) NSString *network_type; + +/// Operating system name +@property (nonatomic, copy, readonly) NSString *os; + +/// Operating system version +@property (nonatomic, copy, readonly) NSString *os_version; + +/// screen height +@property (nonatomic, strong, readonly) NSNumber *screen_height; + +/// screen width +@property (nonatomic, strong, readonly) NSNumber *screen_width; + +/// Mobile phone system language +@property (nonatomic, copy, readonly) NSString *system_language; + +/// Time zone offset +@property (nonatomic, copy, readonly) NSNumber *zone_offset; + +/// App version +@property (nonatomic, copy, readonly) NSString *appVersion; + +/// App install time +@property (nonatomic, copy, readonly) NSString *install_time; + +/// Is it a simulator +@property (nonatomic, strong, readonly) NSNumber *isSimulator; + +/// Available memory and total memory +@property (nonatomic, copy, readonly) NSString *ram; + +/// Available disk and total disk +@property (nonatomic, copy, readonly) NSString *disk; + +/// Frame rate +@property (nonatomic, strong, readonly) NSNumber *fps; + +/// Device type +@property (nonatomic, copy, readonly) NSString *deviceType; + +/** + * The key of the returned event preset property starts with "#", and it is not recommended to use it directly as the property of the event + */ +- (NSDictionary *)toEventPresetProperties; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.h.meta new file mode 100644 index 0000000..eea1668 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8765a67cf93f8484583bbd6257fffde5 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.m b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.m new file mode 100644 index 0000000..1edf24e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.m @@ -0,0 +1,146 @@ +// +// TDPresetProperties.m +// ThinkingSDK +// +// Created by huangdiao on 2021/5/25. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDPresetProperties.h" + +static const NSString *kTDPresetBundleId = @"#bundle_id"; +static const NSString *kTDPresetCarrier = @"#carrier"; +static const NSString *kTDPresetDeviceId = @"#device_id"; +static const NSString *kTDPresetDeviceModel = @"#device_model"; +static const NSString *kTDPresetManufacturer = @"#manufacturer"; +static const NSString *kTDPresetNetworkType = @"#network_type"; +static const NSString *kTDPresetOSName = @"#os"; +static const NSString *kTDPresetOSVersion = @"#os_version"; +static const NSString *kTDPresetScreenHeight = @"#screen_height"; +static const NSString *kTDPresetScreenWidth = @"#screen_width"; +static const NSString *kTDPresetSystemLanguage = @"#system_language"; +static const NSString *kTDPresetZoneOffset = @"#zone_offset"; +static const NSString *kTDPresetAppVersion = @"#app_version"; +static const NSString *kTDPresetInstallTime = @"#install_time"; +static const NSString *kTDPresetIsSimulator = @"#simulator"; +static const NSString *kTDPresetRam = @"#ram"; +static const NSString *kTDPresetDisk = @"#disk"; +static const NSString *kTDPresetFps = @"#fps"; +static const NSString *kTDPresetDeviceType = @"#device_type"; + +@interface TDPresetProperties () + +@property (nonatomic, copy, readwrite) NSString *bundle_id; +@property (nonatomic, copy, readwrite) NSString *carrier; +@property (nonatomic, copy, readwrite) NSString *device_id; +@property (nonatomic, copy, readwrite) NSString *device_model; +@property (nonatomic, copy, readwrite) NSString *manufacturer; +@property (nonatomic, copy, readwrite) NSString *network_type; +@property (nonatomic, copy, readwrite) NSString *os; +@property (nonatomic, copy, readwrite) NSString *os_version; +@property (nonatomic, strong, readwrite) NSNumber *screen_height; +@property (nonatomic, strong, readwrite) NSNumber *screen_width; +@property (nonatomic, copy, readwrite) NSString *system_language; +@property (nonatomic, copy, readwrite) NSNumber *zone_offset; +@property (nonatomic, copy, readwrite) NSString *appVersion; +@property (nonatomic, copy, readwrite) NSString *install_time; +@property (nonatomic, strong, readwrite) NSNumber *isSimulator; +@property (nonatomic, copy, readwrite) NSString *ram; +@property (nonatomic, copy, readwrite) NSString *disk; +@property (nonatomic, strong, readwrite) NSNumber *fps; +@property (nonatomic, copy, readwrite) NSString *deviceType; + +@end + +@implementation TDPresetProperties + +- (instancetype)initWithDictionary:(NSDictionary *)dict { + self = [super init]; + if (self) { + self.bundle_id = dict[kTDPresetBundleId]; + self.carrier = dict[kTDPresetCarrier]; + self.device_id = dict[kTDPresetDeviceId]; + self.device_model = dict[kTDPresetDeviceModel]; + self.manufacturer = dict[kTDPresetManufacturer]; + self.network_type = dict[kTDPresetNetworkType]; + self.os = dict[kTDPresetOSName]; + self.os_version = dict[kTDPresetOSVersion]; + self.screen_height = dict[kTDPresetScreenHeight]; + self.screen_width = dict[kTDPresetScreenWidth]; + self.system_language = dict[kTDPresetSystemLanguage]; + self.zone_offset = dict[kTDPresetZoneOffset]; + self.appVersion = dict[kTDPresetAppVersion]; + self.install_time = dict[kTDPresetInstallTime]; + self.isSimulator = dict[kTDPresetIsSimulator]; + self.ram = dict[kTDPresetRam]; + self.disk = dict[kTDPresetDisk]; + self.fps = dict[kTDPresetFps]; + self.deviceType = dict[kTDPresetDeviceType]; + } + return self; +} + +- (NSDictionary *)toEventPresetProperties { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + if (self.bundle_id) { + dict[kTDPresetBundleId] = self.bundle_id; + } + if (self.carrier) { + dict[kTDPresetCarrier] = self.carrier; + } + if (self.device_id) { + dict[kTDPresetDeviceId] = self.device_id; + } + if (self.device_model) { + dict[kTDPresetDeviceModel] = self.device_model; + } + if (self.manufacturer) { + dict[kTDPresetManufacturer] = self.manufacturer; + } + if (self.network_type) { + dict[kTDPresetNetworkType] = self.network_type; + } + if (self.os) { + dict[kTDPresetOSName] = self.os; + } + if (self.os_version) { + dict[kTDPresetOSVersion] = self.os_version; + } + if (self.screen_height) { + dict[kTDPresetScreenHeight] = self.screen_height; + } + if (self.screen_width) { + dict[kTDPresetScreenWidth] = self.screen_width; + } + if (self.system_language) { + dict[kTDPresetSystemLanguage] = self.system_language; + } + if (self.zone_offset) { + dict[kTDPresetZoneOffset] = self.zone_offset; + } + if (self.appVersion) { + dict[kTDPresetAppVersion] = self.appVersion; + } + if (self.install_time) { + dict[kTDPresetInstallTime] = self.install_time; + } + if (self.isSimulator) { + dict[kTDPresetIsSimulator] = self.isSimulator; + } + if (self.ram) { + dict[kTDPresetRam] = self.ram; + } + if (self.disk) { + dict[kTDPresetDisk] = self.disk; + } + if (self.fps) { + dict[kTDPresetFps] = self.fps; + } + if (self.deviceType) { + dict[kTDPresetDeviceType] = self.deviceType; + } + + return dict; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.m.meta new file mode 100644 index 0000000..1983aff --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/PresetProperty/TDPresetProperties.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c0b4133a7594d4fa1bcfc4e24177ea4e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store.meta new file mode 100644 index 0000000..9d8ca71 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: de79325140491402e88158d3e68becea +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.h new file mode 100644 index 0000000..9cfb65a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.h @@ -0,0 +1,33 @@ +// +// TDEventRecord.h +// ThinkingSDK +// +// Created by wwango on 2022/1/24. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDEventRecord : NSObject + +// Due to historical reasons, there is no event identifier stored in the database +// Record index when fetching data, update uuid before reporting data, remove data according to uuid after successful reporting +@property (nonatomic, copy) NSString *uuid; +@property (nonatomic, strong) NSNumber *index; + +@property (nonatomic, copy, readonly) NSString *content; +@property (nonatomic, copy, readonly) NSDictionary *event; +@property (nonatomic, assign) BOOL encrypted; +@property (nonatomic, copy, readonly) NSString *ekey; + + +- (instancetype)initWithIndex:(NSNumber *)index content:(NSDictionary *)content; +- (instancetype)initWithContent:(NSDictionary *)content; + +- (void)setSecretObject:(NSDictionary *)obj; + +- (NSString *)flushContent:(NSString *)appid; +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.h.meta new file mode 100644 index 0000000..8403da8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: f0fa3872576744e84bf96137f346eefd +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.m new file mode 100644 index 0000000..20137e2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.m @@ -0,0 +1,101 @@ +// +// TDEventRecord.m +// ThinkingSDK +// +// Created by wwango on 2022/1/24. +// + +#import "TDEventRecord.h" + +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif + +static NSString * const TDEncryptRecordKeyEKey = @"ekey"; +static NSString * const TDEncryptRecordKeyPayload = @"payload"; + +@implementation TDEventRecord { + NSMutableDictionary *_event; +} + + +- (instancetype)initWithEvent:(NSDictionary *)event type:(NSString *)type { + if (self = [super init]) { + + _event = [event mutableCopy]; + _encrypted = _event[TDEncryptRecordKeyEKey] != nil; + } + return self; +} + +- (instancetype)initWithUUID:(NSString *)uuid content:(NSDictionary *)content { + if (self = [super init]) { + _uuid = uuid; + + if (content && [content isKindOfClass:[NSDictionary class]]) { + _event = [NSMutableDictionary dictionaryWithDictionary:content]; + _encrypted = _event[TDEncryptRecordKeyEKey] != nil; + } + } + return self; +} + +- (instancetype)initWithIndex:(NSNumber *)index content:(NSDictionary *)content { + if (self = [super init]) { + _index = index; + + if (content && [content isKindOfClass:[NSDictionary class]]) { + _event = [NSMutableDictionary dictionaryWithDictionary:content]; + _encrypted = _event[TDEncryptRecordKeyEKey] != nil; + } + } + return self; +} + +- (instancetype)initWithContent:(NSDictionary *)content { + if (self = [super init]) { + if (content && [content isKindOfClass:[NSDictionary class]]) { + _event = [NSMutableDictionary dictionaryWithDictionary:content]; + _encrypted = _event[TDEncryptRecordKeyEKey] != nil; + } + } + return self; +} + +- (NSString *)ekey { + return _event[TDEncryptRecordKeyEKey]; +} + +- (void)setSecretObject:(NSDictionary *)obj { + if (!obj || ![obj isKindOfClass:[NSDictionary class]]) { + return; + } + [_event removeAllObjects]; + [_event addEntriesFromDictionary:obj]; + + _encrypted = YES; +} + +- (BOOL)isValid { + return self.event.count > 0; +} + +- (NSString *)content { + return [TDJSONUtil JSONStringForObject:self.event]; +} + +- (NSString *)flushContent:(NSString *)appid { + if (![self isValid]) { + return nil; + } + + UInt64 time = [[NSDate date] timeIntervalSince1970] * 1000; + _event[@"#flush_time"] = @(time); + _event[@"#app_id"] =appid; + + return self.content; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.m.meta new file mode 100644 index 0000000..2977112 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDEventRecord.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 656854da589404714ba6e708de4aacce +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.h new file mode 100644 index 0000000..2f756da --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.h @@ -0,0 +1,63 @@ +// +// TDFile.h +// ThinkingSDK +// +// Created by LiHuanan on 2020/9/8. +// Copyright © 2020 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDFile : NSObject + +@property(strong,nonatomic) NSString* appid; + +- (instancetype)initWithAppid:(NSString*)appid; + +- (void)archiveSessionID:(long long)sessionid; +- (long long)unarchiveSessionID ; + +- (void)archiveIdentifyId:(nullable NSString *)identifyId; +- (NSString*)unarchiveIdentifyID ; + +- (void)archiveAccountID:(nullable NSString *)accountID; +- (NSString*)unarchiveAccountID ; + +- (void)archiveUploadSize:(NSNumber *)uploadSize; +- (NSNumber*)unarchiveUploadSize; + +- (void)archiveUploadInterval:(NSNumber *)uploadInterval; +- (NSNumber*)unarchiveUploadInterval; + + +- (void)archiveSuperProperties:(nullable NSDictionary *)superProperties; +- (NSDictionary*)unarchiveSuperProperties; + +- (void)archiveTrackPause:(BOOL)trackPause; +- (BOOL)unarchiveTrackPause; + +- (void)archiveOptOut:(BOOL)optOut; +- (BOOL)unarchiveOptOut; + +- (void)archiveIsEnabled:(BOOL)isEnabled; +- (BOOL)unarchiveEnabled; + +- (void)archiveDeviceId:(NSString *)deviceId; +- (NSString *)unarchiveDeviceId; + +- (void)archiveInstallTimes:(NSString *)installTimes; +- (NSString *)unarchiveInstallTimes; + +- (BOOL)archiveObject:(id)object withFilePath:(NSString *)filePath; + +- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *)filePathString; +// Compatible with old versions +- (NSString*)unarchiveOldLoginId; +// Compatible with old versions +- (void)deleteOldLoginId; + +@end; + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.h.meta new file mode 100644 index 0000000..73e984b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: edc5e228d7fc2439a826a347e3f63e4f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.m new file mode 100644 index 0000000..e7355da --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.m @@ -0,0 +1,287 @@ +// +// TDFile.m +// ThinkingSDK +// +// Created by LiHuanan on 2020/9/8. +// Copyright © 2020 thinkingdata. All rights reserved. +// + +#import "TDFile.h" +#import "TDLogging.h" +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif + +@implementation TDFile + +- (instancetype)initWithAppid:(NSString*)appid +{ + self = [super init]; + if(self) + { + self.appid = appid; + } + return self; +} + +- (void)archiveSessionID:(long long)sessionid { + NSString *filePath = [self sessionIdFilePath]; + if (![self archiveObject:@(sessionid) withFilePath:filePath]) { + TDLogError(@"%@ unable to archive identifyId", self); + } +} +- (long long)unarchiveSessionID { + return [[self unarchiveFromFile:[self sessionIdFilePath] asClass:[NSNumber class]] longLongValue]; +} + + +- (void)archiveIdentifyId:(NSString *)identifyId { + + NSString *filePath = [self identifyIdFilePath]; + if (![self archiveObject:[identifyId copy] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive identifyId", self); + } +} + +- (NSString*)unarchiveIdentifyID { + return [self unarchiveFromFile:[self identifyIdFilePath] asClass:[NSString class]]; +} + +- (NSString*)unarchiveAccountID { + return [self unarchiveFromFile:[self accountIDFilePath] asClass:[NSString class]]; +} + +- (void)archiveUploadSize:(NSNumber *)uploadSize { + NSString *filePath = [self uploadSizeFilePath]; + if (![self archiveObject:uploadSize withFilePath:filePath]) { + TDLogError(@"%@ unable to archive uploadSize", self); + } +} +- (NSNumber*)unarchiveUploadSize { + NSNumber* uploadSize = [self unarchiveFromFile:[self uploadSizeFilePath] asClass:[NSNumber class]]; + if (!uploadSize) { + uploadSize = [NSNumber numberWithInteger:30]; + } + return uploadSize; +} + +- (void)archiveUploadInterval:(NSNumber *)uploadInterval { + NSString *filePath = [self uploadIntervalFilePath]; + if (![self archiveObject:uploadInterval withFilePath:filePath]) { + TDLogError(@"%@ unable to archive uploadInterval", self); + } +} + +- (NSNumber*)unarchiveUploadInterval { + NSNumber* uploadInterval = [self unarchiveFromFile:[self uploadIntervalFilePath] asClass:[NSNumber class]]; + if (!uploadInterval) { + uploadInterval = [NSNumber numberWithInteger:30]; + } + return uploadInterval; +} + +- (void)archiveAccountID:(NSString *)accountID { + NSString *filePath = [self accountIDFilePath]; + if (![self archiveObject:[accountID copy] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive accountID", self); + } +} + +- (void)archiveSuperProperties:(NSDictionary *)superProperties { + NSString *filePath = [self superPropertiesFilePath]; + if (![self archiveObject:[superProperties copy] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive superProperties", self); + } +} + +- (NSDictionary*)unarchiveSuperProperties { + return [self unarchiveFromFile:[self superPropertiesFilePath] asClass:[NSDictionary class]]; +} + +- (void)archiveTrackPause:(BOOL)trackPause { + NSString *filePath = [self trackPauseFilePath]; + if (![self archiveObject:[NSNumber numberWithBool:trackPause] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive trackPause", self); + } +} + +- (BOOL)unarchiveTrackPause { + NSNumber *trackPause = (NSNumber *)[self unarchiveFromFile:[self trackPauseFilePath] asClass:[NSNumber class]]; + return [trackPause boolValue]; +} + +- (void)archiveOptOut:(BOOL)optOut { + NSString *filePath = [self optOutFilePath]; + if (![self archiveObject:[NSNumber numberWithBool:optOut] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive isOptOut", self); + } +} + +- (BOOL)unarchiveOptOut { + NSNumber *optOut = (NSNumber *)[self unarchiveFromFile:[self optOutFilePath] asClass:[NSNumber class]]; + return [optOut boolValue]; +} + +- (void)archiveIsEnabled:(BOOL)isEnabled { + NSString *filePath = [self enabledFilePath]; + if (![self archiveObject:[NSNumber numberWithBool:isEnabled] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive isEnabled", self); + } +} + +- (BOOL)unarchiveEnabled { + NSNumber *enabled = (NSNumber *)[self unarchiveFromFile:[self enabledFilePath] asClass:[NSNumber class]]; + if (enabled == nil) { + return YES; + } else { + return [enabled boolValue]; + } +} + +- (void)archiveDeviceId:(NSString *)deviceId { + NSString *filePath = [self deviceIdFilePath]; + if (![self archiveObject:[deviceId copy] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive deviceId", self); + } +} + +- (NSString *)unarchiveDeviceId { + return [self unarchiveFromFile:[self deviceIdFilePath] asClass:[NSString class]]; +} + +- (void)archiveInstallTimes:(NSString *)installTimes { + NSString *filePath = [self installTimesFilePath]; + if (![self archiveObject:[installTimes copy] withFilePath:filePath]) { + TDLogError(@"%@ unable to archive installTimes", self); + } +} + +- (NSString *)unarchiveInstallTimes { + return [self unarchiveFromFile:[self installTimesFilePath] asClass:[NSString class]]; +} + +- (BOOL)archiveObject:(id)object withFilePath:(NSString *)filePath { + @try { + if (![NSKeyedArchiver archiveRootObject:object toFile:filePath]) { + return NO; + } + } @catch (NSException *exception) { + TDLogError(@"Got exception: %@, reason: %@. You can only send to Thinking values that inherit from NSObject and implement NSCoding.", exception.name, exception.reason); + return NO; + } + + [self addSkipBackupAttributeToItemAtPath:filePath]; + return YES; +} + +- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *)filePathString { + NSURL *URL = [NSURL fileURLWithPath:filePathString]; + assert([[NSFileManager defaultManager] fileExistsAtPath:[URL path]]); + + NSError *error = nil; + BOOL success = [URL setResourceValue:[NSNumber numberWithBool:YES] + forKey:NSURLIsExcludedFromBackupKey error:&error]; + if (!success) { + TDLogError(@"Error excluding %@ from backup %@", [URL lastPathComponent], error); + } + return success; +} + +- (id)unarchiveFromFile:(NSString *)filePath asClass:(Class)class { + id unarchivedData = nil; + @try { + unarchivedData = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + if (![unarchivedData isKindOfClass:class]) { + unarchivedData = nil; + } + } + @catch (NSException *exception) { + TDLogError(@"Error unarchive in %@", filePath); + unarchivedData = nil; + NSError *error = NULL; + BOOL removed = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; + if (!removed) { + TDLogDebug(@"Error remove file in %@, error: %@", filePath, error); + } + } + return unarchivedData; +} + +- (NSString *)superPropertiesFilePath { + return [self persistenceFilePath:@"superProperties"]; +} + +- (NSString *)accountIDFilePath { + return [self persistenceFilePath:@"accountID"]; +} + +- (NSString *)uploadSizeFilePath { + return [self persistenceFilePath:@"uploadSize"]; +} + +- (NSString *)uploadIntervalFilePath { + return [self persistenceFilePath:@"uploadInterval"]; +} + +- (NSString *)identifyIdFilePath { + return [self persistenceFilePath:@"identifyId"]; +} + +- (NSString *)sessionIdFilePath { + return [self persistenceFilePath:@"sessionId"]; +} + +- (NSString *)enabledFilePath { + return [self persistenceFilePath:@"isEnabled"]; +} + +- (NSString *)trackPauseFilePath { + return [self persistenceFilePath:@"trackPause"]; +} + +- (NSString *)optOutFilePath { + return [self persistenceFilePath:@"optOut"]; +} + +- (NSString *)deviceIdFilePath { + return [self persistenceFilePath:@"deviceId"]; +} + +- (NSString *)installTimesFilePath { + return [self persistenceFilePath:@"installTimes"]; +} + +- (NSString *)persistenceFilePath:(NSString *)data{ + NSString *filename = [NSString stringWithFormat:@"thinking-%@-%@.plist", self.appid, data]; + return [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject] + stringByAppendingPathComponent:filename]; +} + +- (NSString*)unarchiveOldLoginId { + return [[NSUserDefaults standardUserDefaults] objectForKey:@"thinkingdata_accountId"]; +} + +- (void)deleteOldLoginId { + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"thinkingdata_accountId"]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +- (NSString *)description { + NSMutableDictionary *dic = [NSMutableDictionary dictionary]; + [dic setObject:self.appid forKey:@"appid"]; + [dic setObject:[self unarchiveIdentifyID]?:@"" forKey:@"distincid"]; + [dic setObject:[self unarchiveAccountID]?:@"" forKey:@"accountID"]; + [dic setObject:[self unarchiveUploadSize] forKey:@"uploadSize"]; + [dic setObject:[self unarchiveUploadInterval] forKey:@"uploadInterval"]; + [dic setObject:[self unarchiveSuperProperties]?:@{} forKey:@"superProperties"]; + [dic setObject:[NSNumber numberWithBool:[self unarchiveOptOut] ]forKey:@"optOut"]; + [dic setObject:[NSNumber numberWithBool:[self unarchiveEnabled]] forKey:@"isEnabled"]; + [dic setObject:[NSNumber numberWithBool:[self unarchiveTrackPause]] forKey:@"isTrackPause"]; + [dic setObject:[self unarchiveDeviceId]?:@"" forKey:@"deviceId"]; + [dic setObject:[self unarchiveInstallTimes]?:@"" forKey:@"installTimes"]; + return [TDJSONUtil JSONStringForObject:dic]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.m.meta new file mode 100644 index 0000000..e2d777d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDFile.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4b3d46619dada4e3fbbf81943c05f348 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.h new file mode 100644 index 0000000..e87814d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.h @@ -0,0 +1,8 @@ +#import + +@interface TDKeychainHelper : NSObject + ++ (void)saveInstallTimes:(NSString *)string; ++ (NSString *)readInstallTimes; + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.h.meta new file mode 100644 index 0000000..3ab157f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 73497cc4e0a42458da46d1a0ad6013f1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.m new file mode 100644 index 0000000..590f329 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.m @@ -0,0 +1,36 @@ +#import "TDKeychainHelper.h" + +#if __has_include() +#import +#else +#import "TDKeychainManager.h" +#endif + +static NSString * const TDInstallTimesOld = @"com.thinkingddata.analytics.installtimes"; +static NSString * const TDInstallTimesNew = @"com.thinkingddata.analytics.installtimes_1"; + +@interface TDKeychainHelper () + +@end + +@implementation TDKeychainHelper + ++ (void)saveInstallTimes:(NSString *)string { + [TDKeychainManager saveItem:string forKey:TDInstallTimesNew]; + + // Compatibility handles the case of jumping back and forth between old and new SDK versions + [TDKeychainManager oldSaveItem:string forKey:TDInstallTimesOld]; +} + ++ (NSString *)readInstallTimes { + NSString *data = [TDKeychainManager itemForKey:TDInstallTimesNew]; + if (data == nil) { + data = [TDKeychainManager oldItemForKey:TDInstallTimesOld]; + if (data) { + [TDKeychainManager saveItem:data forKey:TDInstallTimesNew]; + } + } + return data; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.m.meta new file mode 100644 index 0000000..82ad8f4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDKeychainHelper.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b93c3eb20b626476baf8b47dbec8bf2e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.h new file mode 100644 index 0000000..7b86803 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.h @@ -0,0 +1,19 @@ +#import + +@class TDEventRecord; + +@interface TDSqliteDataQueue : NSObject + ++ (TDSqliteDataQueue *)sharedInstanceWithAppid:(NSString *)appid; +- (NSInteger)addObject:(id)obj withAppid:(NSString *)appid; +- (NSArray *)getFirstRecords:(NSUInteger)recordSize withAppid:(NSString *)appid; +- (BOOL)removeFirstRecords:(NSUInteger)recordSize withAppid:(NSString *)appid; +- (void)deleteAll:(NSString *)appid; +- (NSInteger)sqliteCountForAppid:(NSString *)appid; +- (void)addColumnText:(NSString *)columnText; + +- (NSArray *)upadteRecordIds:(NSArray *)recordIds; +- (BOOL)removeDataWithuids:(NSArray *)recordIDs; + +@end + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.h.meta new file mode 100644 index 0000000..9a1788a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: e7000d0d7ca0c4b6185f8ea0d2719dc2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.m new file mode 100644 index 0000000..3c0fbd5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.m @@ -0,0 +1,363 @@ +#import "TDSqliteDataQueue.h" +#import + +#import "TDLogging.h" +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif +#import "TDConfig.h" +#import "TDEventRecord.h" + +@implementation TDSqliteDataQueue { + sqlite3 *_database; + NSInteger _allmessageCount; +} + +- (void) closeDatabase { + sqlite3_close(_database); + sqlite3_shutdown(); +} + +- (void) dealloc { + [self closeDatabase]; +} + ++ (TDSqliteDataQueue *)sharedInstanceWithAppid:(NSString *)appid { + static TDSqliteDataQueue *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString *filepath = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"TDData-data.plist"]; + sharedInstance = [[self alloc] initWithPath:filepath withAppid:appid]; + }); + return sharedInstance; +} + +- (id)initWithPath:(NSString *)filePath withAppid:(NSString *)appid { + self = [super init]; + if (sqlite3_initialize() != SQLITE_OK) { + return nil; + } + if (sqlite3_open_v2([filePath UTF8String], &_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) == SQLITE_OK ) { + NSString *_sql = @"create table if not exists TDData (id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, appid TEXT, creatAt INTEGER)"; + char *errorMsg; + if (sqlite3_exec(_database, [_sql UTF8String], NULL, NULL, &errorMsg)==SQLITE_OK) { + } else { + return nil; + } + + _allmessageCount = [self sqliteCount]; + + if (![self isExistColumnInTable:@"appid"] || ![self isExistColumnInTable:@"creatAt"]) { + [self addColumn:appid]; + } else if (_allmessageCount > 0) { + [self delExpiredData]; + } + + if (![self isExistColumnInTable:@"uuid"]) { + [self addColumnText:@"uuid"]; + } + + } else { + return nil; + } + return self; +} + +- (void)addColumn:(NSString *)appid { + int epochInterval = [[NSDate date] timeIntervalSince1970]; + NSString *query; + if (appid.length > 0 && [appid isKindOfClass: [NSString class]]) + query = [NSString stringWithFormat:@"alter table TDData add 'appid' TEXT default \"%@\"", appid]; + else + query = [NSString stringWithFormat:@"alter table TDData add 'appid' TEXT"]; + NSString *query2 = [NSString stringWithFormat:@"alter table TDData add 'creatAt' INTEGER default %d ", epochInterval]; + char *errMsg; + @try { + sqlite3_exec(_database, [query UTF8String], NULL, NULL, &errMsg); + sqlite3_exec(_database, [query2 UTF8String], NULL, NULL, &errMsg); + } @catch (NSException *exception) { + TDLogError(@"addColumn: %@", exception); + } +} + +- (void)addColumnText:(NSString *)columnText { + NSString *query = [NSString stringWithFormat:@"alter table TDData add '%@' TEXT", columnText];; + char *errMsg; + @try { + sqlite3_exec(_database, [query UTF8String], NULL, NULL, &errMsg); + } @catch (NSException *exception) { + TDLogError(@"addColumn: %@", exception); + } +} + +- (BOOL)isExistColumnInTable:(NSString *)column { + sqlite3_stmt *statement = nil; + NSString *sql = [NSString stringWithFormat:@"PRAGMA table_info(TDData)"]; + if (sqlite3_prepare_v2(_database, [sql UTF8String], -1, &statement, NULL) != SQLITE_OK ) { + sqlite3_finalize(statement); + return NO; + } + while (sqlite3_step(statement) == SQLITE_ROW) { + NSString *columntem = [[NSString alloc] initWithCString:(char *)sqlite3_column_text(statement, 1) encoding:NSUTF8StringEncoding]; + + if ([column isEqualToString:columntem]) { + sqlite3_finalize(statement); + return YES; + } + } + sqlite3_finalize(statement); + return NO; +} + +- (void)delExpiredData { + NSTimeInterval oneDay = 24*60*60*1; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow: -oneDay * [TDConfig expirationDays]]; +#pragma clang diagnostic pop + + int expirationDate = [date timeIntervalSince1970]; + [self removeOldRecords:expirationDate]; +} + +- (NSInteger)addObject:(id)obj withAppid:(NSString *)appid { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + NSUInteger maxCacheSize = [TDConfig maxNumEvents]; +#pragma clang diagnostic pop + + if (_allmessageCount >= maxCacheSize) { + [self removeFirstRecords:100 withAppid:nil]; + } + + NSString *jsonStr = [TDJSONUtil JSONStringForObject:obj]; + if (!jsonStr) { + return [self sqliteCountForAppid:appid]; + } + NSTimeInterval epochInterval = [[NSDate date] timeIntervalSince1970]; + NSString *query = @"INSERT INTO TDData(content, appid, creatAt) values(?, ?, ?)"; + sqlite3_stmt *insertStatement; + int rc; + rc = sqlite3_prepare_v2(_database, [query UTF8String],-1, &insertStatement, nil); + if (rc == SQLITE_OK) { + sqlite3_bind_text(insertStatement, 1, [jsonStr UTF8String], -1, SQLITE_TRANSIENT); + sqlite3_bind_text(insertStatement, 2, [appid UTF8String], -1, SQLITE_TRANSIENT); + sqlite3_bind_int(insertStatement, 3, epochInterval); + + rc = sqlite3_step(insertStatement); + if (rc == SQLITE_DONE) { + _allmessageCount ++; + } + } + + sqlite3_finalize(insertStatement); + return [self sqliteCountForAppid:appid]; +} + +- (NSArray *)getFirstRecords:(NSUInteger)recordSize withAppid:(NSString *)appid { + if (_allmessageCount == 0) { + return @[]; + } + + NSMutableArray *records = [[NSMutableArray alloc] init]; + NSString *query = @"SELECT id,content FROM TDData where appid=? ORDER BY id ASC LIMIT ?"; + sqlite3_stmt *stmt = NULL; + int rc = sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL); + if (rc == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, [appid UTF8String], -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, 2, (int)recordSize); + while (sqlite3_step(stmt) == SQLITE_ROW) { + sqlite3_int64 index = sqlite3_column_int64(stmt, 0); + char *jsonChar = (char *)sqlite3_column_text(stmt, 1); + if (!jsonChar) { + continue; + } + + @try { + NSData *jsonData = [[NSString stringWithUTF8String:jsonChar] dataUsingEncoding:NSUTF8StringEncoding]; + NSError *err; + if (jsonData) { + NSDictionary *eventDict = [NSJSONSerialization JSONObjectWithData:jsonData + options:NSJSONReadingMutableContainers + error:&err]; + if (!err && [eventDict isKindOfClass:[NSDictionary class]]) { + [records addObject:[[TDEventRecord alloc] initWithIndex:[NSNumber numberWithLongLong:index] content:eventDict]]; + } + } + } @catch (NSException *exception) { + + } + } + } + sqlite3_finalize(stmt); + return records; +} + +- (BOOL)removeDataWithuids:(NSArray *)uids { + + if (uids.count == 0) { + return NO; + } + + NSString *query = [NSString stringWithFormat:@"DELETE FROM TDData WHERE uuid IN (%@);", [uids componentsJoinedByString:@","]]; + sqlite3_stmt *stmt; + + if (sqlite3_prepare_v2(_database, query.UTF8String, -1, &stmt, NULL) != SQLITE_OK) { + TDLogError(@"Delete records Error: %s", sqlite3_errmsg(_database)); + return NO; + } + BOOL success = YES; + if (sqlite3_step(stmt) != SQLITE_DONE) { + TDLogError(@"Delete records Error: %s", sqlite3_errmsg(_database)); + success = NO; + } + sqlite3_finalize(stmt); + _allmessageCount = [self sqliteCount]; + return YES; +} + +- (BOOL)removeFirstRecords:(NSUInteger)recordSize withAppid:(NSString *)appid { + NSString *query; + + if (appid.length == 0) { + query = @"DELETE FROM TDData WHERE id IN (SELECT id FROM TDData ORDER BY id ASC LIMIT ?)"; + } else { + query = @"DELETE FROM TDData WHERE id IN (SELECT id FROM TDData where appid=? ORDER BY id ASC LIMIT ?)"; + } + + sqlite3_stmt *stmt = NULL; + int rc = sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL); + + if (rc == SQLITE_OK) { + if (appid.length == 0) { + sqlite3_bind_int(stmt, 1, (int)recordSize); + } else { + sqlite3_bind_text(stmt, 1, [appid UTF8String], -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, 2, (int)recordSize); + } + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE && rc != SQLITE_OK) { + sqlite3_finalize(stmt); + return NO; + } + } else { + sqlite3_finalize(stmt); + return NO; + } + sqlite3_finalize(stmt); + _allmessageCount = [self sqliteCount]; + return YES; +} + +- (NSArray *)upadteRecordIds:(NSArray *)recordIds { + if (recordIds.count == 0) { + return @[]; + } + NSMutableArray *uids = [NSMutableArray arrayWithCapacity:recordIds.count]; + [recordIds enumerateObjectsUsingBlock:^(NSNumber *recordId, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *uuid = [self rand13NumString]; + NSString *query = [NSString stringWithFormat:@"UPDATE TDData SET uuid = '%@' WHERE id = %lld;", uuid, [recordId longLongValue]]; + if ([self execUpdateSQL:query]) { + [uids addObject:uuid]; + } + }]; + return uids; +} + + + +-(NSString *)rand13NumString +{ + int NUMBER_OF_CHARS = 13; + + char data[NUMBER_OF_CHARS]; + + for (int x = 0; x < NUMBER_OF_CHARS; data[x++] = (char)('1' + (arc4random_uniform(9)))); + + NSString *numString = [[NSString alloc] initWithBytes:data length:NUMBER_OF_CHARS encoding:NSUTF8StringEncoding]; + + return numString; +} + + +- (BOOL)execUpdateSQL:(NSString *)sql { + + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(_database, sql.UTF8String, -1, &stmt, NULL) != SQLITE_OK) { + TDLogError(@"Update Records Error: %s", sqlite3_errmsg(_database)); + sqlite3_finalize(stmt); + return NO; + } + if (sqlite3_step(stmt) != SQLITE_DONE) { + TDLogError(@"Update Records Error: %s", sqlite3_errmsg(_database)); + sqlite3_finalize(stmt); + return NO; + } + sqlite3_finalize(stmt); + return YES; +} + +- (BOOL)removeOldRecords:(int)timestamp { + NSString *query = @"DELETE FROM TDData WHERE creatAt 0) { + sqlite3_bind_text(stmt, 1, [appid UTF8String], -1, SQLITE_TRANSIENT); + } + if (sqlite3_step(stmt) == SQLITE_ROW) { + count = sqlite3_column_int(stmt, 0); + } + } + + sqlite3_finalize(stmt); + return count; +} + +- (void)deleteAll:(NSString *)appid { + if ([appid isKindOfClass:[NSString class]] && appid.length > 0) { + NSString *query = @"DELETE FROM TDData where appid=? "; + + sqlite3_stmt *stmt = NULL; + int rc = sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, NULL); + if (rc == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, [appid UTF8String], -1, SQLITE_TRANSIENT); + sqlite3_step(stmt); + } + sqlite3_finalize(stmt); + + _allmessageCount = [self sqliteCount]; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.m.meta new file mode 100644 index 0000000..849a461 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Store/TDSqliteDataQueue.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: fcb464e18d497453b9d760cdc73d5a7a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Toast.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast.meta new file mode 100644 index 0000000..7ce02d3 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9c37151661ecf42d3be5b0e33e5405c0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.h new file mode 100644 index 0000000..d42b0c5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.h @@ -0,0 +1,11 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDToastView : UIView + ++ (instancetype)showInWindow:(UIWindow *)window text:(NSString *)text duration:(NSTimeInterval)duration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.h.meta new file mode 100644 index 0000000..ce4263a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: c9cf0253f00c8488ea65bf03a71f3d28 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.m new file mode 100644 index 0000000..f92a475 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.m @@ -0,0 +1,97 @@ +#import "TDToastView.h" + +@implementation TDToastView +{ + UITextView *_textView; +} + +#define TOAST_HORIZONTAL_PADDING 20.0 +#define TOAST_VERTICAL_PADDING 15.0 + +- (instancetype)initWithFrame:(CGRect)frame { + if ((self = [super initWithFrame:frame])) { + _textView = [[UITextView alloc] initWithFrame:CGRectZero]; + _textView.opaque = NO; + _textView.editable = NO; + _textView.selectable = NO; + _textView.textColor = [UIColor whiteColor]; + _textView.backgroundColor = [UIColor clearColor]; + _textView.userInteractionEnabled = YES; + [self addSubview:_textView]; + self.alpha = 0.9; + self.backgroundColor = [UIColor darkGrayColor]; + self.layer.cornerRadius = 20.0; + self.opaque = NO; + self.userInteractionEnabled = YES; + [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_tapHandler:)]]; + } + return self; +} + ++ (instancetype)showInWindow:(UIWindow *)window text:(NSString *)text duration:(NSTimeInterval)duration { + TDToastView *toast = [[self alloc] initWithFrame:CGRectZero]; + toast.text = text; + [toast showInWindow:window duration:duration]; + return toast; +} + + +- (void)showInWindow:(UIWindow *)window duration:(NSTimeInterval)duration { + if (window == nil) { + return; + } + CGRect windowBounds = CGRectInset(window.bounds, 20.0, 20.0); + CGRect toastBounds = CGRectZero; + toastBounds.size = [self sizeThatFits:windowBounds.size]; + self.bounds = toastBounds; + self.center = CGPointMake(CGRectGetMidX(windowBounds), CGRectGetMidY(windowBounds)); + CGFloat alpha = self.alpha; + self.alpha = 0.0; + [window addSubview:self]; + [UIView animateWithDuration:0.3 animations:^{ + self.alpha = alpha; + } completion:^(BOOL finishedShowing) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self dismiss]; + }); + }]; +} + +- (NSString *)text { + return _textView.text; +} + +- (void)setText:(NSString *)text { + _textView.text = text; +} + +- (void)dismiss { + if (!self.superview) { + return; + } + [UIView animateWithDuration:0.3 animations:^{ + self.alpha = 0.0; + } completion:^(BOOL finishedHiding) { + [self removeFromSuperview]; + }]; +} + +- (void)_tapHandler:(UITapGestureRecognizer *)tapGestureRecognizer { + [self dismiss]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + _textView.frame = CGRectInset(self.bounds, TOAST_HORIZONTAL_PADDING, TOAST_VERTICAL_PADDING); +} + +- (CGSize)sizeThatFits:(CGSize)size { + CGSize textConstrainedSize = CGSizeMake(size.width - 2 * TOAST_HORIZONTAL_PADDING, + size.height - 2 * TOAST_VERTICAL_PADDING); + CGSize textSize = [_textView sizeThatFits:textConstrainedSize]; + CGFloat width = MIN(size.width, textSize.width + 2 * TOAST_HORIZONTAL_PADDING); + CGFloat height = MIN(size.height, textSize.height + 2 * TOAST_VERTICAL_PADDING); + return CGSizeMake(width, height); +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.m.meta new file mode 100644 index 0000000..9bd55bb --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Toast/TDToastView.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 43699f8778c624c46bc5afbb602485d0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util.meta new file mode 100644 index 0000000..7d75670 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 25157fdc2a1044168862c6c03f435462 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category.meta new file mode 100644 index 0000000..9aa4aac --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b37051d2565fd43dfba2108cdecdd66f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.h new file mode 100644 index 0000000..56f9f68 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.h @@ -0,0 +1,17 @@ +// +// NSDictionary+TDJsonOutput.h +// ThinkingSDK +// +// Created by huangdiao on 2021/3/18. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSDictionary (TDJsonOutput) + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.h.meta new file mode 100644 index 0000000..3ce5724 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6dcaf30c4b0eb430b8244e993dc551a4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.m new file mode 100644 index 0000000..759620d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.m @@ -0,0 +1,30 @@ +// +// NSDictionary+TDJsonOutput.m +// ThinkingSDK +// +// Created by huangdiao on 2021/3/18. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "NSDictionary+TDJsonOutput.h" + +@implementation NSDictionary (TDJsonOutput) + +- (NSString *)descriptionWithLocale:(nullable id)locale { + if ([NSJSONSerialization isValidJSONObject:self]) { + NSString *output = nil; + @try { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:nil]; + output = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + output = [output stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"]; + } + @catch (NSException *exception) { + output = self.description; + } + return output; + } else { + return self.description; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.m.meta new file mode 100644 index 0000000..2796bb7 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSDictionary+TDJsonOutput.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 53a00c2672fe24a528f94803871d160f +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.h new file mode 100644 index 0000000..b60ab65 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.h @@ -0,0 +1,19 @@ +// +// NSObject+TDUtil.h +// ThinkingSDK +// +// Created by wwango on 2021/10/18. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject (TDUtil) + ++ (id)performSelector:(SEL)selector onTarget:(id)target withArguments:(NSArray *)arguments; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.h.meta new file mode 100644 index 0000000..43eb311 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1ab5993d5baaf4457b1b7f166e9bbbe1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.m new file mode 100644 index 0000000..584c5e4 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.m @@ -0,0 +1,187 @@ +// +// NSObject+TDUtil.m +// ThinkingSDK +// +// Created by wwango on 2021/10/18. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "NSObject+TDUtil.h" +#import + +#if TARGET_OS_IOS +#import +#elif TARGET_OS_OSX +#import +#endif + +@implementation NSObject (TDUtil) + ++ (NSValue *)valueForPrimitivePointer:(void *)pointer objCType:(const char *)type +{ + // CASE marcro inspired by https://www.mikeash.com/pyblog/friday-qa-2013-02-08-lets-build-key-value-coding.html +#define CASE(ctype, selectorpart) \ +if(strcmp(type, @encode(ctype)) == 0) { \ +return [NSNumber numberWith ## selectorpart: *(ctype *)pointer]; \ +} + + CASE(BOOL, Bool); + CASE(unsigned char, UnsignedChar); + CASE(short, Short); + CASE(unsigned short, UnsignedShort); + CASE(int, Int); + CASE(unsigned int, UnsignedInt); + CASE(long, Long); + CASE(unsigned long, UnsignedLong); + CASE(long long, LongLong); + CASE(unsigned long long, UnsignedLongLong); + CASE(float, Float); + CASE(double, Double); + +#undef CASE + + NSValue *value = nil; + @try { + value = [NSValue valueWithBytes:pointer objCType:type]; + } @catch (NSException *exception) { + // Certain type encodings are not supported by valueWithBytes:objCType:. Just fail silently if an exception is thrown. + } + + return value; +} + + ++ (BOOL)isTollFreeBridgedValue:(id)value forCFType:(const char *)typeEncoding +{ + // See https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/Toll-FreeBridgin/Toll-FreeBridgin.html +#define CASE(cftype, foundationClass) \ +if(strcmp(typeEncoding, @encode(cftype)) == 0) { \ +return [value isKindOfClass:[foundationClass class]]; \ +} + + CASE(CFArrayRef, NSArray); + CASE(CFAttributedStringRef, NSAttributedString); + CASE(CFCalendarRef, NSCalendar); + CASE(CFCharacterSetRef, NSCharacterSet); + CASE(CFDataRef, NSData); + CASE(CFDateRef, NSDate); + CASE(CFDictionaryRef, NSDictionary); + CASE(CFErrorRef, NSError); + CASE(CFLocaleRef, NSLocale); + CASE(CFMutableArrayRef, NSMutableArray); + CASE(CFMutableAttributedStringRef, NSMutableAttributedString); + CASE(CFMutableCharacterSetRef, NSMutableCharacterSet); + CASE(CFMutableDataRef, NSMutableData); + CASE(CFMutableDictionaryRef, NSMutableDictionary); + CASE(CFMutableSetRef, NSMutableSet); + CASE(CFMutableStringRef, NSMutableString); + CASE(CFNumberRef, NSNumber); + CASE(CFReadStreamRef, NSInputStream); + CASE(CFRunLoopTimerRef, NSTimer); + CASE(CFSetRef, NSSet); + CASE(CFStringRef, NSString); + CASE(CFTimeZoneRef, NSTimeZone); + CASE(CFURLRef, NSURL); + CASE(CFWriteStreamRef, NSOutputStream); + +#undef CASE + + return NO; +} + + ++ (id)performSelector:(SEL)selector onTarget:(id)target withArguments:(NSArray *)arguments{ + + if ([target respondsToSelector:selector]) { + + NSMethodSignature *signature = [target methodSignatureForSelector:selector]; + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; + [invocation setTarget:target]; + [invocation setSelector:selector]; + [invocation retainArguments]; + + // Always self and _cmd + NSUInteger numberOfArguments = [signature numberOfArguments]; + for (NSUInteger argumentIndex = 2; argumentIndex < numberOfArguments; argumentIndex++) { + NSUInteger argumentsArrayIndex = argumentIndex - 2; + + id argumentObject = [arguments count] > argumentsArrayIndex ? [arguments objectAtIndex:argumentsArrayIndex] : nil; + + // NSNull in the arguments array can be passed as a placeholder to indicate nil. We only need to set the argument if it will be non-nil. + if (argumentObject && ![argumentObject isKindOfClass:[NSNull class]]) { + const char *typeEncodingCString = [signature getArgumentTypeAtIndex:argumentIndex]; + if (typeEncodingCString[0] == @encode(id)[0] || typeEncodingCString[0] == @encode(Class)[0] || [self isTollFreeBridgedValue:argumentObject forCFType:typeEncodingCString]) { + // Object + [invocation setArgument:&argumentObject atIndex:argumentIndex]; + } else if (strcmp(typeEncodingCString, @encode(CGColorRef)) == 0 +#if TARGET_OS_IOS + && [argumentObject isKindOfClass:[UIColor class]] +#elif TARGET_OS_OSX + && [argumentObject isKindOfClass:[NSColor class]] +#endif + ) { + // Bridging UIColor to CGColorRef + CGColorRef colorRef = [argumentObject CGColor]; + [invocation setArgument:&colorRef atIndex:argumentIndex]; + } else if ([argumentObject isKindOfClass:[NSValue class]]) { + // Primitive boxed in NSValue + NSValue *argumentValue = (NSValue *)argumentObject; + + // Ensure that the type encoding on the NSValue matches the type encoding of the argument in the method signature + if (strcmp([argumentValue objCType], typeEncodingCString) != 0) { + return nil; + } + + NSUInteger bufferSize = 0; + @try { + // NSGetSizeAndAlignment barfs on type encoding for bitfields. + NSGetSizeAndAlignment(typeEncodingCString, &bufferSize, NULL); + } @catch (NSException *exception) { } + + if (bufferSize > 0) { + void *buffer = calloc(bufferSize, 1); + [argumentValue getValue:buffer]; + [invocation setArgument:buffer atIndex:argumentIndex]; + free(buffer); + } + } + } + } + + // Try to invoke the invocation but guard against an exception being thrown. + BOOL successfullyInvoked = NO; + @try { + // Some methods are not fit to be called... + // Looking at you -[UIResponder(UITextInputAdditions) _caretRect] + [invocation invoke]; + successfullyInvoked = YES; + } @catch (NSException *exception) { + // Bummer... + } + + // Retreive the return value and box if necessary. + id returnObject = nil; + if (successfullyInvoked) { + const char *returnType = [signature methodReturnType]; + if (returnType[0] == @encode(id)[0] || returnType[0] == @encode(Class)[0]) { + __unsafe_unretained id objectReturnedFromMethod = nil; + [invocation getReturnValue:&objectReturnedFromMethod]; + returnObject = objectReturnedFromMethod; + } else if (returnType[0] != @encode(void)[0]) { + void *returnValue = malloc([signature methodReturnLength]); + if (returnValue) { + [invocation getReturnValue:returnValue]; + returnObject = [self valueForPrimitivePointer:returnValue objCType:returnType]; + free(returnValue); + } + } + } + + return returnObject; + } + + return nil; +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.m.meta new file mode 100644 index 0000000..223a86a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Category/NSObject+TDUtil.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4bc8c4ead3507483e85343120a67c2cf +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.h new file mode 100644 index 0000000..59eca16 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.h @@ -0,0 +1,36 @@ +// +// TDCheck.h +// ThinkingSDK +// +// Created by wwango on 2021/9/10. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +#define TD_CHECK_NIL(_object) (_object == nil || [_object isKindOfClass:[NSNull class]]) + +#define TD_CHECK_CLASS(_object, _class) (!TD_CHECK_NIL(_object) && [_object isKindOfClass:[_class class]]) + +#define TD_CHECK_CLASS_NSString(_object) TD_CHECK_CLASS(_object, [NSString class]) +#define TD_CHECK_CLASS_NSNumber(_object) TD_CHECK_CLASS(_object, [NSNumber class]) +#define TD_CHECK_CLASS_NSArray(_object) TD_CHECK_CLASS(_object, [NSArray class]) +#define TD_CHECK_CLASS_NSData(_object) TD_CHECK_CLASS(_object, [NSData class]) +#define TD_CHECK_CLASS_NSDate(_object) TD_CHECK_CLASS(_object, [NSDate class]) +#define TD_CHECK_CLASS_NSDictionary(_object) TD_CHECK_CLASS(_object, [NSDictionary class]) + +#define TD_Valid_NSString(_object) (TD_CHECK_CLASS_NSString(_object) && (_object.length > 0)) +#define TD_Valid_NSArray(_object) (TD_CHECK_CLASS_NSArray(_object) && (_object.count > 0)) +#define TD_Valid_NSData(_object) (TD_CHECK_CLASS_NSData(_object) && (_object.length > 0)) +#define TD_Valid_NSDictionary(_object) (TD_CHECK_CLASS_NSDictionary(_object) && (_object.allKeys.count > 0)) + +@interface TDCheck : NSObject + ++ (NSDictionary *)td_checkToJSONObjectRecursive:(NSDictionary *)properties timeFormatter:(NSDateFormatter *)timeFormatter; + +@end + + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.h.meta new file mode 100644 index 0000000..e1aa12b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3174e763d579e48f885f7bbf52454067 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.m new file mode 100644 index 0000000..2bb5f8d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.m @@ -0,0 +1,68 @@ +// +// TDCheck.m +// ThinkingSDK +// +// Created by wwango on 2021/9/10. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDCheck.h" +#import "TDLogging.h" + +@implementation TDCheck + ++ (NSDictionary *)td_checkToJSONObjectRecursive:(NSDictionary *)properties timeFormatter:(NSDateFormatter *)timeFormatter { + return (NSDictionary *)[self td_checkToObjectRecursive:properties timeFormatter:timeFormatter]; +} + +// Five basic types: list, time, Boolean, value, text, list only supports basic data types +// Advanced data types: object, object group ++ (NSObject *)td_checkToObjectRecursive:(NSObject *)properties timeFormatter:(NSDateFormatter *)timeFormatter { + if (TD_CHECK_NIL(properties)) { + return properties; + } else if (TD_CHECK_CLASS_NSDictionary(properties)) { + NSDictionary *propertyDic = [(NSDictionary *)properties copy]; + NSMutableDictionary *propertiesDic = [NSMutableDictionary dictionaryWithDictionary:propertyDic]; + for (NSString *key in [propertyDic keyEnumerator]) { + NSObject *newValue = [self td_checkToJSONObjectRecursive:propertyDic[key] timeFormatter:timeFormatter]; + propertiesDic[key] = newValue; + } + return propertiesDic; + } else if (TD_CHECK_CLASS_NSArray(properties)) { + NSMutableArray *arrayItem = [(NSArray *)properties mutableCopy]; + for (int i = 0; i < arrayItem.count ; i++) { + id item = [self td_checkToJSONObjectRecursive:arrayItem[i] timeFormatter:timeFormatter]; + if (item) arrayItem[i] = item; + } + return arrayItem; + } else if (TD_CHECK_CLASS_NSDate(properties)) { + NSString *dateStr = [timeFormatter stringFromDate:(NSDate *)properties]; + return dateStr; + } else { + return properties; + } +} + +// old method +//inline static NSDictionary *_td_old_checkToJSONObject(NSDictionary *properties, NSDateFormatter *timeFormatter) { +// NSMutableDictionary *propertiesDic = [NSMutableDictionary dictionaryWithDictionary:properties]; +// for (NSString *key in [properties keyEnumerator]) { +// if ([properties[key] isKindOfClass:[NSDate class]]) { +// NSString *dateStr = [timeFormatter stringFromDate:(NSDate *)properties[key]]; +// propertiesDic[key] = dateStr; +// } else if ([properties[key] isKindOfClass:[NSArray class]]) { +// NSMutableArray *arrayItem = [properties[key] mutableCopy]; +// for (int i = 0; i < arrayItem.count ; i++) { +// if ([arrayItem[i] isKindOfClass:[NSDate class]]) { +// NSString *dateStr = [timeFormatter stringFromDate:(NSDate *)arrayItem[i]]; +// arrayItem[i] = dateStr; +// } +// } +// propertiesDic[key] = arrayItem; +// } +// } +// return propertiesDic; +//} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.m.meta new file mode 100644 index 0000000..456e875 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCheck.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 956605faf624745158ad0a460ca710b9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.h new file mode 100644 index 0000000..214daa8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.h @@ -0,0 +1,21 @@ +// +// TDCommonUtil.h +// ThinkingSDK +// +// Created by wwango on 2022/1/11. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDCommonUtil : NSObject + ++ (NSString *)string:(NSString *)string; + ++ (NSDictionary *)dictionary:(NSDictionary *)dic; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.h.meta new file mode 100644 index 0000000..60bcc16 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: cdbf44bbd4cb144ff979af417b5774cf +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.m new file mode 100644 index 0000000..5116c68 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.m @@ -0,0 +1,28 @@ +// +// TDCommonUtil.m +// ThinkingSDK +// +// Created by wwango on 2022/1/11. +// + +#import "TDCommonUtil.h" + +@implementation TDCommonUtil + ++ (NSString *)string:(NSString *)string { + if ([string isKindOfClass:[NSString class]] && string.length) { + return string; + } else { + return @""; + } +} + ++ (NSDictionary *)dictionary:(NSDictionary *)dic { + if (dic && [dic isKindOfClass:[NSDictionary class]] && dic.allKeys.count) { + return dic; + } else { + return @{}; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.m.meta new file mode 100644 index 0000000..d50e166 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDCommonUtil.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 646b3aad38f76494ba9bbbb79ce88007 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.h new file mode 100644 index 0000000..5e9a897 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.h @@ -0,0 +1,17 @@ +// +// TDUtil.h +// ThinkingSDK +// +// Created by LiHuanan on 2020/9/8. +// Copyright © 2020 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDSDKUtil : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.h.meta new file mode 100644 index 0000000..b949e41 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4b3d4c8f9a5e94ad2a1cbc415bf27aef +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.m new file mode 100644 index 0000000..db9c0f5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.m @@ -0,0 +1,13 @@ +// +// TDUtil.m +// ThinkingSDK +// +// Created by LiHuanan on 2020/9/8. +// Copyright © 2020 thinkingdata. All rights reserved. +// + +#import "TDSDKUtil.h" + +@implementation TDSDKUtil + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.m.meta new file mode 100644 index 0000000..ff4bb97 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDSDKUtil.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a56c0e17f9b4643af98c0a4f64548a75 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.h new file mode 100644 index 0000000..2abb6c5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.h @@ -0,0 +1,24 @@ +// +// TDWeakProxy.h +// ThinkingSDK +// +// Created by wwango on 2021/9/15. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface TDWeakProxy : NSProxy + +@property (nullable, nonatomic, weak, readonly) id target; + +- (instancetype)initWithTarget:(id)target; + ++ (instancetype)proxyWithTarget:(id)target; + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.h.meta new file mode 100644 index 0000000..25581bf --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 26287937f0ac74abeaed5f1da5b092ed +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.m new file mode 100644 index 0000000..81384d2 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.m @@ -0,0 +1,81 @@ +// +// TDWeakProxy.m +// ThinkingSDK +// +// Created by wwango on 2021/9/15. +// Copyright © 2021 thinkingdata. All rights reserved. +// + +#import "TDWeakProxy.h" + +@implementation TDWeakProxy + + +- (instancetype)initWithTarget:(id)target { + _target = target; + return self; +} + ++ (instancetype)proxyWithTarget:(id)target { + return [[TDWeakProxy alloc] initWithTarget:target]; +} + +- (id)forwardingTargetForSelector:(SEL)selector { + return _target; +} + +- (void)forwardInvocation:(NSInvocation *)invocation { + void *null = NULL; + [invocation setReturnValue:&null]; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + return [NSObject instanceMethodSignatureForSelector:@selector(init)]; +} + +- (BOOL)respondsToSelector:(SEL)aSelector { + return [_target respondsToSelector:aSelector]; +} + +- (BOOL)isEqual:(id)object { + return [_target isEqual:object]; +} + +- (NSUInteger)hash { + return [_target hash]; +} + +- (Class)superclass { + return [_target superclass]; +} + +- (Class)class { + return [_target class]; +} + +- (BOOL)isKindOfClass:(Class)aClass { + return [_target isKindOfClass:aClass]; +} + +- (BOOL)isMemberOfClass:(Class)aClass { + return [_target isMemberOfClass:aClass]; +} + +- (BOOL)conformsToProtocol:(Protocol *)aProtocol { + return [_target conformsToProtocol:aProtocol]; +} + +- (BOOL)isProxy { + return YES; +} + +- (NSString *)description { + return [_target description]; +} + +- (NSString *)debugDescription { + return [_target debugDescription]; +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.m.meta new file mode 100644 index 0000000..6628f78 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/TDWeakProxy.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: a6edacb4206a84710b119b660398b43d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.h b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.h new file mode 100644 index 0000000..8bf6d3a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.h @@ -0,0 +1,36 @@ +// +// Target_Analytics.h +// ThinkingSDK +// +// Created by 杨雄 on 2024/3/18. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface Target_Analytics : NSObject + +- (void)Action_nativeInitWithParams:(nullable NSDictionary *)params; + +- (nullable NSString *)Action_nativeGetAccountIdWithParams:(nullable NSDictionary *)params; + +- (nullable NSString *)Action_nativeGetDistinctIdWithParams:(nullable NSDictionary *)params; + +- (void)Action_nativeTrackEventWithParams:(nullable NSDictionary *)params; + +- (void)Action_nativeUserSetWithParams:(nullable NSDictionary *)params; + +- (nullable NSDictionary *)Action_nativeGetPresetPropertiesWithParams:(nullable NSDictionary *)params; + +- (void)Action_nativeTrackDebugEventWithParams:(nullable NSDictionary *)params; + +- (BOOL)Action_nativeGetEnableAutoPushWithParams:(nullable NSDictionary *)params; + +- (nullable NSArray *)Action_nativeGetAllAppIdsWithParams:(nullable NSDictionary *)params; + +- (nullable NSString *)Action_nativeGetSDKVersionWithParams:(nullable NSDictionary *)params; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.h.meta new file mode 100644 index 0000000..4dff872 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: ae6cef6c0d4a9421d97059c75673c5f2 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.m b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.m new file mode 100644 index 0000000..063ff96 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.m @@ -0,0 +1,121 @@ +// +// Target_Analytics.m +// ThinkingSDK +// +// Created by 杨雄 on 2024/3/18. +// + +#import "Target_Analytics.h" +#import "TDAnalytics+Public.h" +#import "TDAnalytics+Multiple.h" +#import "TDAnalytics+Private.h" +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDAnalyticsPresetProperty.h" + +#if __has_include() +#import +#else +#import "ThinkingDataCore.h" +#endif + +@implementation Target_Analytics + +- (void)Action_nativeInitWithParams:(NSDictionary *)params { + TDSettings *settings = params[@"settings"]; + if (![settings isKindOfClass:TDSettings.class]) { + return; + } + [TDAnalytics enableLog:settings.enableLog]; + + TDConfig *config = [[TDConfig alloc] init]; + config.appid = settings.appId; + config.serverUrl = settings.serverUrl; + + TDMode mode = TDModeNormal; + switch (settings.mode) { + case TDSDKModeNomal:{ + mode = TDModeNormal; + } break; + case TDSDKModeDebug:{ + mode = TDModeDebug; + } break; + case TDSDKModeDebugOnly:{ + mode = TDModeDebugOnly; + } break; + default: + break; + } + config.mode = mode; + config.appid = settings.appId; + config.defaultTimeZone = settings.defaultTimeZone; + + if (![NSString td_isEmpty:settings.encryptKey]) { + [config enableEncryptWithVersion:settings.encryptVersion publicKey:settings.encryptKey]; + } + + config.enableAutoPush = settings.enableAutoPush; + config.enableAutoCalibrated = settings.enableAutoCalibrated; + [TDAnalytics startAnalyticsWithConfig:config]; +} + +- (nullable NSString *)Action_nativeGetAccountIdWithParams:(nullable NSDictionary *)params { + NSString *appId = params[@"appId"]; + NSString *accountId = [[ThinkingAnalyticsSDK instanceWithAppid:appId] innerAccountId]; + return accountId; +} + +- (nullable NSString *)Action_nativeGetDistinctIdWithParams:(nullable NSDictionary *)params { + NSString *appId = params[@"appId"]; + NSString *distinctId = [TDAnalytics getDistinctIdWithAppId:appId]; + return distinctId; +} + +- (void)Action_nativeTrackEventWithParams:(nullable NSDictionary *)params { + NSString *appId = params[@"appId"]; + NSString *eventName = params[@"eventName"]; + NSDictionary *properties = params[@"properties"]; + if ([eventName isKindOfClass:NSString.class] && eventName.length > 0) { + [TDAnalytics track:eventName properties:properties withAppId:appId]; + [TDAnalytics flushWithAppId:appId]; + } +} + +- (void)Action_nativeUserSetWithParams:(nullable NSDictionary *)params { + NSString *appId = params[@"appId"]; + NSDictionary *properties = params[@"properties"]; + if ([properties isKindOfClass:NSDictionary.class] && properties.count > 0) { + [TDAnalytics userSet:properties withAppId:appId]; + [TDAnalytics flushWithAppId:appId]; + } +} + +- (nullable NSDictionary *)Action_nativeGetPresetPropertiesWithParams:(nullable NSDictionary *)params { + NSString *appId = params[@"appId"]; + NSDictionary *dict = [TDAnalyticsPresetProperty propertiesWithAppId:appId]; + return dict; +} + +- (void)Action_nativeTrackDebugEventWithParams:(NSDictionary *)params { + NSString *appId = params[@"appId"]; + NSString *eventName = params[@"eventName"]; + NSDictionary *properties = params[@"properties"]; + if ([eventName isKindOfClass:NSString.class] && eventName.length > 0) { + [TDAnalytics trackDebug:eventName properties:properties appId:appId]; + } +} + +- (BOOL)Action_nativeGetEnableAutoPushWithParams:(NSDictionary *)params { + NSString *appId = params[@"appId"]; + return [[[ThinkingAnalyticsSDK instanceWithAppid:appId] config] enableAutoPush]; +} + +- (NSArray *)Action_nativeGetAllAppIdsWithParams:(NSDictionary *)params { + NSDictionary *instances = [ThinkingAnalyticsSDK _getAllInstances]; + return instances.allKeys; +} + +- (NSString *)Action_nativeGetSDKVersionWithParams:(NSDictionary *)params { + return [TDAnalytics getSDKVersion]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.m.meta new file mode 100644 index 0000000..ff1a9ab --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/Util/Target_Analytics.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bd615af26aad4450a9939e7c52b8e60d +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main.meta new file mode 100644 index 0000000..c644734 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e6e61b2e4e2f1466785d1454a550de40 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/LightThinkingAnalyticsSDK.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/LightThinkingAnalyticsSDK.m new file mode 100644 index 0000000..bed17b9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/LightThinkingAnalyticsSDK.m @@ -0,0 +1,90 @@ +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDLogging.h" + +@implementation LightThinkingAnalyticsSDK + +- (instancetype)initWithAPPID:(NSString *)appID withServerURL:(NSString *)serverURL withConfig:(TDConfig *)config { + if (self = [self initLight:appID withServerURL:serverURL withConfig:config]) { + } + return self; +} + +- (void)innerLogin:(NSString *)accountId { + if ([self hasDisabled]) { + return; + } + if (![accountId isKindOfClass:[NSString class]] || accountId.length == 0) { + TDLogError(@"accountId invald", accountId); + return; + } + TDLogInfo(@"light SDK login, SDK Name = %@, AccountId = %@", self.config.name, accountId); + self.accountId = accountId; +} + +- (void)innerLogout { + if ([self hasDisabled]) { + return; + } + TDLogInfo(@"light SDK logout."); + self.accountId = nil; +} + +- (void)innerSetIdentify:(NSString *)distinctId { + if ([self hasDisabled]) { + return; + } + if (![distinctId isKindOfClass:[NSString class]] || distinctId.length == 0) { + TDLogError(@"identify cannot null"); + return; + } + + TDLogInfo(@"light SDK set distinct ID, Distinct Id = %@", distinctId); + + self.identifyId = distinctId; +} + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType withAppId:(NSString *)appId { + return; +} + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType callback:(NSDictionary * _Nonnull (^)(TDAutoTrackEventType, NSDictionary * _Nonnull))callback withAppId:(NSString *)appId { + return; +} ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType properties:(NSDictionary *)properties withAppId:(NSString *)appId { + return; +} + +- (void)innerFlush { + return; +} + +#pragma mark - EnableTracking + +- (void)innerSetTrackStatus: (TDTrackStatus)status { + switch (status) { + case TDTrackStatusPause: { + TDLogInfo(@"light instance [%@] change status to Pause", self.config.name) + self.isEnabled = NO; + break; + } + case TDTrackStatusStop: { + TDLogInfo(@"light instance [%@] change status to Stop", self.config.name) + self.isEnabled = NO; + break; + } + case TDTrackStatusSaveOnly: { + TDLogInfo(@"light instance [%@] change status to SaveOnly", self.config.name) + self.isEnabled = YES; + break; + } + case TDTrackStatusNormal: { + TDLogInfo(@"light instance [%@] change status to Normal", self.config.name) + self.isEnabled = YES; + break; + } + default: + break; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/LightThinkingAnalyticsSDK.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/LightThinkingAnalyticsSDK.m.meta new file mode 100644 index 0000000..a20c310 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/LightThinkingAnalyticsSDK.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6ea8076903d3c4e979c5765a2dfc7c59 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.h new file mode 100644 index 0000000..62de478 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.h @@ -0,0 +1,284 @@ +// +// TDAnalytics+Multiple.h +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#if __has_include() +#import +#else +#import "TDAnalytics.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAnalytics (Multiple) + +//MARK: track + +/** + Empty the cache queue. When this api is called, the data in the current cache queue will attempt to be reported. + If the report succeeds, local cache data will be deleted. + @param appId appId + */ ++ (void)flushWithAppId:(NSString * _Nullable)appId; + +/** + Switch reporting status + @param status TDTrackStatus reporting status + @param appId appId + */ ++ (void)setTrackStatus:(TDTrackStatus)status withAppId:(NSString * _Nullable)appId; + +/** + Track Events + @param eventName event name + @param appId appId + */ ++ (void)track:(NSString *)eventName withAppId:(NSString * _Nullable)appId; +/** + Track Events + @param eventName event name + @param properties event properties + @param appId appId + */ ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties withAppId:(NSString * _Nullable)appId; +/** + Track Events + @param eventName event name + @param properties event properties + @param time event trigger time + @param timeZone event trigger time time zone + @param appId appId + */ ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties time:(NSDate *)time timeZone:(NSTimeZone *)timeZone withAppId:(NSString * _Nullable)appId; +/** + Track Events + @param eventModel event Model + @param appId appId + */ ++ (void)trackWithEventModel:(TDEventModel *)eventModel withAppId:(NSString * _Nullable)appId; +/** + Timing Events + Record the event duration, call this method to start the timing, stop the timing when the target event is uploaded, and add the attribute #duration to the event properties, in seconds. + @param appId appId + */ ++ (void)timeEvent:(NSString *)eventName withAppId:(NSString * _Nullable)appId; + + +//MARK: user property + +/** + Sets the user property, replacing the original value with the new value if the property already exists. + @param properties user properties + @param appId appId + */ ++ (void)userSet:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId; +/** + Sets a single user attribute, ignoring the new attribute value if the attribute already exists. + @param properties user properties + @param appId appId + */ ++ (void)userSetOnce:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId; +/** + Reset single user attribute. + @param propertyName user properties + @param appId appId + */ ++ (void)userUnset:(NSString *)propertyName withAppId:(NSString * _Nullable)appId; +/** + Reset user properties. + @param propertyNames user properties +*/ ++ (void)userUnsets:(NSArray *)propertyNames withAppId:(NSString * _Nullable)appId; +/** + Adds the numeric type user attributes. + @param properties user properties + @param appId appId + */ ++ (void)userAdd:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId; +/** + Adds the numeric type user attribute. + @param propertyName propertyName + @param propertyValue propertyValue + @param appId appId + */ ++ (void)userAddWithName:(NSString *)propertyName andValue:(NSNumber *)propertyValue withAppId:(NSString * _Nullable)appId; +/** + Appends an element to a property of an array type. + @param properties user properties + @param appId appId + */ ++ (void)userAppend:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId; +/** + Appends an element to a property of an array type. It filters out elements that already exist. + @param properties user properties +*/ ++ (void)userUniqAppend:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId; +/** + Delete the user attributes. This operation is not reversible and should be performed with caution. + @param appId appId + */ ++ (void)userDeleteWithAppId:(NSString * _Nullable)appId; + + +//MARK: super property & preset property + +/** + Set the public event attribute, which will be included in every event uploaded after that. The public event properties are saved without setting them each time. + @param properties super properties + @param appId appId + */ ++ (void)setSuperProperties:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId; +/** + Clears a public event attribute. + @param property property name + @param appId appId + */ ++ (void)unsetSuperProperty:(NSString *)property withAppId:(NSString * _Nullable)appId; +/** + Clear all public event attributes. + @param appId appId + */ ++ (void)clearSuperPropertiesWithAppId:(NSString * _Nullable)appId; +/** + Get the public event properties that have been set. + + @return super properties that have been set. + @param appId appId + */ ++ (NSDictionary *)getSuperPropertiesWithAppId:(NSString * _Nullable)appId; +/** + Set dynamic public properties. Each event uploaded after that will contain a public event attribute. + @param propertiesHandler propertiesHandler. + @param appId appId + */ ++ (void)setDynamicSuperProperties:(NSDictionary *(^)(void))propertiesHandler withAppId:(NSString * _Nullable)appId; +/** + Get the SDK's preset properties. + + @return preset property object + @param appId appId + */ ++ (TDPresetProperties *)getPresetPropertiesWithAppId:(NSString * _Nullable)appId; + +//MARK: error callback + +/** + Register TD error callback + + @param errorCallback code = 10001, ext = "string or json string", errorMsg = "error" + @param appId appId + */ ++ (void)registerErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback withAppId:(NSString * _Nullable)appId; + + +//MARK: custom property + +/** + Set the distinct ID to replace the default UUID distinct ID. + @param distinctId distinctId + @param appId appId + */ ++ (void)setDistinctId:(NSString *)distinctId withAppId:(NSString * _Nullable)appId; + +/** + Get distinct ID: The #distinct_id value in the reported data. + + @param appId appId + @return distinctId + */ ++ (NSString *)getDistinctIdWithAppId:(NSString * _Nullable)appId; + +/** + Set the account ID. Each setting overrides the previous value. Login events will not be uploaded. + @param accountId accountId + @param appId appId + */ ++ (void)login:(NSString *)accountId withAppId:(NSString * _Nullable)appId; + +/** + Get account ID: The #account_id value in the reported data. + + @param appId appId + @return accountId + */ ++ (NSString *)getAccountIdWithAppId:(NSString * _Nullable)appId; + +/** + Clearing the account ID will not upload user logout events. + @param appId appId + */ ++ (void)logoutWithAppId:(NSString * _Nullable)appId; + +/** + Set the network conditions for uploading. By default, the SDK will set the network conditions as 3G, 4G and Wifi to upload data + @param type network type + @param appId appId + */ ++ (void)setUploadingNetworkType:(TDReportingNetworkType)type withAppId:(NSString * _Nullable)appId; + +/// Format the time output in the format of SDK +/// @param date date +/// @param appId appId +/// @return date string ++ (NSString *)timeStringWithDate:(NSDate *)date withAppId:(NSString * _Nullable)appId; + +#if TARGET_OS_IOS + +/** + Enable Auto-Tracking + @param eventType Auto-Tracking type + @param appId appId + */ ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos); +/** + Enable auto tracking with super properties. + @param eventType Auto-Tracking type + @param properties super properties + @param appId appId + */ ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos); + +/** + Enable the auto tracking function. + @param eventType Auto-Tracking type + @param callback In the callback, eventType indicates the type of automatic collection, properties indicates the event properties before storage, and this block can return a dictionary for adding new properties + @param appId appId + */ ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType callback:(NSDictionary *(^_Nullable)(TDAutoTrackEventType eventType, NSDictionary *properties))callback withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos); + +/** + Set and Update the value of a custom property for Auto-Tracking + @param eventType A list of TDAutoTrackEventType, indicating the types of automatic collection events that need to be enabled + @param properties properties + @param appId appId + */ ++ (void)setAutoTrackProperties:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos); + +/** + Ignore the Auto-Tracking of a UIViewController + @param controllers Ignore the name of the UIViewController + @param appId appId + */ ++ (void)ignoreAutoTrackViewControllers:(NSArray *)controllers withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos); + +/** + Ignore the Auto-Tracking of click UIView + @param aClass ignored UIView Class + @param appId appId + */ ++ (void)ignoreViewType:(Class)aClass withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos); + +/** + Dynamic super properties in auto track environment + Set dynamic public properties for auto track event + */ ++ (void)setAutoTrackDynamicProperties:(NSDictionary *(^)(void))dynamicSuperProperties withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos); + +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.h.meta new file mode 100644 index 0000000..4e14f88 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 039da0391bbe64e758f3be4538394c80 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.m new file mode 100644 index 0000000..897ac3b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.m @@ -0,0 +1,256 @@ +// +// TDAnalytics+Multiple.m +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#import "TDAnalytics+Multiple.h" +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDConfigPrivate.h" +#if TARGET_OS_IOS +#import "TDAutoTrackManager.h" +#endif + +@implementation TDAnalytics (Multiple) + ++ (void)flushWithAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerFlush]; +} + ++ (void)setTrackStatus:(TDTrackStatus)status withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerSetTrackStatus:status]; +} + ++ (void)track:(NSString *)eventName withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerTrack:eventName]; +} + ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerTrack:eventName properties:properties]; +} + ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties time:(NSDate *)time timeZone:(NSTimeZone *)timeZone withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerTrack:eventName properties:properties time:time timeZone:timeZone]; +} + ++ (void)trackWithEventModel:(TDEventModel *)eventModel withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerTrackWithEventModel:eventModel]; +} + ++ (void)timeEvent:(NSString *)eventName withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerTimeEvent:eventName]; +} + +//MARK: user property + ++ (void)userSet:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserSet:properties]; +} + ++ (void)userSetOnce:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserSetOnce:properties]; +} + ++ (void)userUnset:(NSString *)propertyName withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserUnset:propertyName]; +} + ++ (void)userUnsets:(NSArray *)propertyNames withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserUnsets:propertyNames]; +} + ++ (void)userAdd:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserAdd:properties]; +} + ++ (void)userAddWithName:(NSString *)propertyName andValue:(NSNumber *)propertyValue withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserAdd:propertyName andPropertyValue:propertyValue]; +} + ++ (void)userAppend:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserAppend:properties]; +} + ++ (void)userUniqAppend:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserUniqAppend:properties]; +} + ++ (void)userDeleteWithAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUserDelete]; +} + +//MARK: super property & preset property + ++ (void)setSuperProperties:(NSDictionary *)properties withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerSetSuperProperties:properties]; +} + ++ (void)unsetSuperProperty:(NSString *)property withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerUnsetSuperProperty:property]; +} + ++ (void)clearSuperPropertiesWithAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerClearSuperProperties]; +} + ++ (NSDictionary *)getSuperPropertiesWithAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + return [teSDK innerCurrentSuperProperties]; +} + ++ (void)setDynamicSuperProperties:(NSDictionary *(^)(void))propertiesHandler withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerRegisterDynamicSuperProperties:propertiesHandler]; +} + ++ (TDPresetProperties *)getPresetPropertiesWithAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + return [teSDK innerGetPresetProperties]; +} + +//MARK: error callback + ++ (void)registerErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerRegisterErrorCallback:errorCallback]; +} + +//MARK: custom property + ++ (void)setDistinctId:(NSString *)distinctId withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerSetIdentify:distinctId]; +} + ++ (NSString *)getDistinctIdWithAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + return [teSDK innerDistinctId]; +} + ++ (void)login:(NSString *)accountId withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerLogin:accountId]; +} + ++ (void)logoutWithAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerLogout]; +} + ++ (NSString *)getAccountIdWithAppId:(NSString *)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + return [teSDK innerAccountId]; +} + ++ (void)setUploadingNetworkType:(TDReportingNetworkType)type withAppId:(NSString * _Nullable)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerSetNetworkType:type]; +} + ++ (NSString *)timeStringWithDate:(NSDate *)date withAppId:(NSString *)appId { + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + return [teSDK innetGetTimeString:date]; +} + +//MARK: - auto track + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType callback:(NSDictionary *(^ _Nullable)(TDAutoTrackEventType, NSDictionary *))callback withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos){ + [self innerEnableAutoTrack:eventType properties:nil callback:callback withAppId:appId]; +} + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos){ + [self innerEnableAutoTrack:eventType properties:properties callback:nil withAppId:appId]; +} + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos){ + [self innerEnableAutoTrack:eventType properties:nil callback:nil withAppId:appId]; +} + ++ (void)ignoreAutoTrackViewControllers:(nonnull NSArray *)controllers withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos){ + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + if ([teSDK hasDisabled]) { + return; + } + if (controllers == nil || controllers.count == 0) { + return; + } + @synchronized (teSDK.ignoredViewControllers) { + [teSDK.ignoredViewControllers addObjectsFromArray:controllers]; + } +} + ++ (void)ignoreViewType:(nonnull Class)aClass withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos){ + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + if ([teSDK hasDisabled]) { + return; + } + @synchronized (teSDK.ignoredViewTypeList) { + [teSDK.ignoredViewTypeList addObject:aClass]; + } +} + ++ (void)setAutoTrackProperties:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos){ +#if TARGET_OS_IOS + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + if ([teSDK hasDisabled]) { + return; + } + if (properties == nil) { + return; + } + @synchronized (teSDK.autoTrackSuperProperty) { + [teSDK.autoTrackSuperProperty registerSuperProperties:[properties copy] withType:eventType]; + } +#endif +} + ++ (void)innerEnableAutoTrack:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties callback:(NSDictionary *(^ _Nullable)(TDAutoTrackEventType eventType, NSDictionary *properties))callback withAppId:(NSString * _Nullable)appId API_UNAVAILABLE(macos){ +#if TARGET_OS_IOS + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + + if (teSDK.autoTrackSuperProperty == nil) { + teSDK.autoTrackSuperProperty = [[TDAutoTrackSuperProperty alloc] init]; + } + [teSDK.autoTrackSuperProperty registerSuperProperties:properties withType:eventType]; + [teSDK.autoTrackSuperProperty registerDynamicSuperProperties:callback]; + + NSString *instanceToken = [teSDK.config innerGetMapInstanceToken]; + [[TDAutoTrackManager sharedManager] trackWithAppid:instanceToken withOption:eventType]; +#endif +} + ++ (void)setAutoTrackDynamicProperties:(NSDictionary * _Nonnull (^)(void))dynamicSuperProperties withAppId:(NSString *)appId { +#if TARGET_OS_IOS + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + if ([teSDK hasDisabled]) { + return; + } + @synchronized (teSDK.autoTrackSuperProperty) { + [teSDK.autoTrackSuperProperty registerAutoTrackDynamicProperties:dynamicSuperProperties]; + } +#endif +} + +//MARK: - + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.m.meta new file mode 100644 index 0000000..6722b50 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Multiple.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 54e52b932bbbe4791bfe599a3278d6b1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.h new file mode 100644 index 0000000..af3f1fe --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.h @@ -0,0 +1,22 @@ +// +// TDAnalytics+Private.h +// ThinkingSDK +// +// Created by 杨雄 on 2024/5/31. +// + +#if __has_include() +#import +#else +#import "TDAnalytics.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAnalytics (Private) + ++ (void)trackDebug:(NSString *)eventName properties:(nullable NSDictionary *)properties appId:(NSString * _Nullable)appId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.h.meta new file mode 100644 index 0000000..523d92e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 442a67bdcbbfd43e88aac2710506d772 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.m new file mode 100644 index 0000000..6118fcc --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.m @@ -0,0 +1,21 @@ +// +// TDAnalytics+Private.m +// ThinkingSDK +// +// Created by 杨雄 on 2024/5/31. +// + +#import "TDAnalytics+Private.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDAnalytics (Private) + ++ (void)trackDebug:(NSString *)eventName properties:(NSDictionary *)properties appId:(NSString * _Nullable)appId { + if (appId == nil) { + appId = [ThinkingAnalyticsSDK defaultAppId]; + } + ThinkingAnalyticsSDK *teSDK = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + [teSDK innerTrackDebug:eventName properties:properties]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.m.meta new file mode 100644 index 0000000..cc38bb5 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Private.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 14e555d29c8374add9223007e4a0e950 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.h new file mode 100644 index 0000000..10a83dd --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.h @@ -0,0 +1,294 @@ +// +// TDAnalytics+Public.h +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#if __has_include() +#import +#else +#import "TDAnalytics.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAnalytics (Public) + +//MARK: SDK info ++ (void)enableLog:(BOOL)enable; ++ (void)calibrateTimeWithNtp:(NSString *)ntpServer; ++ (void)calibrateTime:(NSTimeInterval)timestamp; ++ (nullable NSString *)getLocalRegion; ++ (void)setCustomerLibInfoWithLibName:(NSString *)libName libVersion:(NSString *)libVersion; +/** + Get sdk version + + @return version string + */ ++ (NSString *)getSDKVersion; +/** + Get DeviceId + + @return deviceId + */ ++ (NSString *)getDeviceId; +/** + Format the time output in the format of SDK + @param date date + @return date string + */ ++ (NSString *)timeStringWithDate:(NSDate *)date; + +//MARK: - init + +/** + Initialization method + After the SDK initialization is complete, the saved instance can be obtained through this api + + @param appId appId + @param url server url + */ ++ (void)startAnalyticsWithAppId:(NSString *)appId serverUrl:(NSString *)url; + +/** + Initialization method + After the SDK initialization is complete, the saved instance can be obtained through this api + + @param config initialization configuration + */ ++ (void)startAnalyticsWithConfig:(nullable TDConfig *)config; + +/// Create light instance based on original instance +/// @param appId appId +/// @return light instance appId ++ (NSString * _Nullable)lightInstanceIdWithAppId:(NSString * _Nonnull)appId; + +//MARK: track + +/** + Empty the cache queue. When this api is called, the data in the current cache queue will attempt to be reported. + If the report succeeds, local cache data will be deleted. + */ ++ (void)flush; + +/** + Switch reporting status + @param status TDTrackStatus reporting status + */ ++ (void)setTrackStatus:(TDTrackStatus)status; + +/** + Track Events + @param eventName event name + */ ++ (void)track:(NSString *)eventName; +/** + Track Events + @param eventName event name + @param properties event properties + */ ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties; +/** + Track Events + @param eventName event name + @param properties event properties + @param time event trigger time + @param timeZone event trigger time time zone + */ ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties time:(NSDate *)time timeZone:(NSTimeZone *)timeZone; +/** + Track Events + @param eventModel event Model + */ ++ (void)trackWithEventModel:(TDEventModel *)eventModel; +/** + Timing Events + Record the event duration, call this method to start the timing, stop the timing when the target event is uploaded, and add the attribute #duration to the event properties, in seconds. + */ ++ (void)timeEvent:(NSString *)eventName; + + +//MARK: user property + +/** + Sets the user property, replacing the original value with the new value if the property already exists. + @param properties user properties + */ ++ (void)userSet:(NSDictionary *)properties; +/** + Sets a single user attribute, ignoring the new attribute value if the attribute already exists. + @param properties user properties + */ ++ (void)userSetOnce:(NSDictionary *)properties; +/** + Reset single user attribute. + @param propertyName user properties + */ ++ (void)userUnset:(NSString *)propertyName; +/** + Reset user properties. + @param propertyNames user properties +*/ ++ (void)userUnsets:(NSArray *)propertyNames; +/** + Adds the numeric type user attributes. + @param properties user properties + */ ++ (void)userAdd:(NSDictionary *)properties; +/** + Adds the numeric type user attribute. + @param propertyName propertyName + @param propertyValue propertyValue + */ ++ (void)userAddWithName:(NSString *)propertyName andValue:(NSNumber *)propertyValue; +/** + Appends an element to a property of an array type. + @param properties user properties + */ ++ (void)userAppend:(NSDictionary *)properties; +/** + Appends an element to a property of an array type. It filters out elements that already exist. + @param properties user properties +*/ ++ (void)userUniqAppend:(NSDictionary *)properties; +/** + Delete the user attributes. This operation is not reversible and should be performed with caution. + */ ++ (void)userDelete; + + +//MARK: super property & preset property + +/** + Set the public event attribute, which will be included in every event uploaded after that. The public event properties are saved without setting them each time. + @param properties super properties + */ ++ (void)setSuperProperties:(NSDictionary *)properties; +/** + Clears a public event attribute. + @param property property name + */ ++ (void)unsetSuperProperty:(NSString *)property; +/** + Clear all public event attributes. + */ ++ (void)clearSuperProperties; +/** + Get the public event properties that have been set. + + @return super properties that have been set. + */ ++ (NSDictionary *)getSuperProperties; +/** + Set dynamic public properties. Each event uploaded after that will contain a public event attribute. + @param propertiesHandler propertiesHandler. + */ ++ (void)setDynamicSuperProperties:(NSDictionary *(^)(void))propertiesHandler; +/** + Get the SDK's preset properties. + + @return preset property object + */ ++ (TDPresetProperties *)getPresetProperties; + +//MARK: error callback + +/** + Register TD error callback + + @param errorCallback code = 10001, ext = "string or json string", errorMsg = "error" + */ ++ (void)registerErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback; + + +//MARK: custom property + +/** + Set the distinct ID to replace the default UUID distinct ID. + @param distinctId distinctId + */ ++ (void)setDistinctId:(NSString *)distinctId; + +/** + Get distinct ID: The #distinct_id value in the reported data. + + @return distinctId + */ ++ (NSString *)getDistinctId; + +/** + Set the account ID. Each setting overrides the previous value. Login events will not be uploaded. + @param accountId accountId + */ ++ (void)login:(NSString *)accountId; + +/** + Get account ID: The #account_id value in the reported data. + + @return accountId + */ ++ (NSString *)getAccountId; + +/** + Clearing the account ID will not upload user logout events. + */ ++ (void)logout; + +/** + Set the network conditions for uploading. By default, the SDK will set the network conditions as 3G, 4G and Wifi to upload data + @param type network type + */ ++ (void)setUploadingNetworkType:(TDReportingNetworkType)type; + +#if TARGET_OS_IOS + +/** + Enable Auto-Tracking + @param eventType Auto-Tracking type + */ ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType API_UNAVAILABLE(macos); +/** + Enable auto tracking with super properties. + @param eventType Auto-Tracking type + @param properties super properties + */ ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties API_UNAVAILABLE(macos); + +/** + Enable the auto tracking function. + @param eventType Auto-Tracking type + @param callback In the callback, eventType indicates the type of automatic collection, properties indicates the event properties before storage, and this block can return a dictionary for adding new properties + */ ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType callback:(NSDictionary *(^_Nullable)(TDAutoTrackEventType eventType, NSDictionary *properties))callback API_UNAVAILABLE(macos); + +/** + Set and Update the value of a custom property for Auto-Tracking + @param eventType A list of TDAutoTrackEventType, indicating the types of automatic collection events that need to be enabled + @param properties properties + */ ++ (void)setAutoTrackProperties:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties API_UNAVAILABLE(macos); + +/** + Ignore the Auto-Tracking of a UIViewController + @param controllers Ignore the name of the UIViewController + */ ++ (void)ignoreAutoTrackViewControllers:(NSArray *)controllers API_UNAVAILABLE(macos); + +/** + Ignore the Auto-Tracking of click UIView + @param aClass ignored UIView Class + */ ++ (void)ignoreViewType:(Class)aClass API_UNAVAILABLE(macos); + +/** + Dynamic super properties in auto track environment + Set dynamic public properties for auto track event + */ ++ (void)setAutoTrackDynamicProperties:(NSDictionary *(^)(void))dynamicSuperProperties API_UNAVAILABLE(macos); + +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.h.meta new file mode 100644 index 0000000..809f3ad --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 519475da6f5f54abd854ba2fff09b3d1 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.m new file mode 100644 index 0000000..835fb54 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.m @@ -0,0 +1,328 @@ +// +// TDAnalytics+Public.m +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#import "TDAnalytics+Public.h" +#import "TDAnalytics+Multiple.h" +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDLogging.h" +#import "TDPublicConfig.h" +#import "TDConfigPrivate.h" + +#if __has_include() +#import +#else +#import "TDCalibratedTime.h" +#endif + +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif + +#if __has_include() +#import +#else +#import "NSString+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "NSURL+TDCore.h" +#endif + +@implementation TDAnalytics (Public) + +#pragma mark - Logging + ++ (void)enableLog:(BOOL)enable { + [TDLogging sharedInstance].loggingLevel = enable ? TDLoggingLevelDebug : TDLoggingLevelNone; +} + +#pragma mark - Calibrate time + ++ (void)calibrateTime:(NSTimeInterval)timestamp { + [[TDCalibratedTime sharedInstance] recalibrationWithTimeInterval:timestamp/1000.0]; +} + ++ (void)calibrateTimeWithNtp:(NSString *)ntpServer { + if ([ntpServer isKindOfClass:[NSString class]] && ntpServer.length > 0) { + [[TDCalibratedTime sharedInstance] recalibrationWithNtps:@[ntpServer]]; + } +} + +// MARK: info + ++ (nullable NSString *)getLocalRegion { + NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode]; + return countryCode; +} + ++ (void)setCustomerLibInfoWithLibName:(NSString *)libName libVersion:(NSString *)libVersion { + if (libName.length > 0) { + [TDDeviceInfo sharedManager].libName = libName; + } + if (libVersion.length > 0) { + [TDDeviceInfo sharedManager].libVersion = libVersion; + } +} + ++ (NSString *)getSDKVersion { + return TDPublicConfig.version; +} + ++ (NSString *)getDeviceId { + return [TDCoreDeviceInfo deviceId]; +} + ++ (NSString *)timeStringWithDate:(NSDate *)date { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + return [TDAnalytics timeStringWithDate:date withAppId:appId]; +} + +//MARK: - init + ++ (void)startAnalyticsWithAppId:(NSString *)appId serverUrl:(NSString *)url { + TDConfig *config = [[TDConfig alloc] init]; + config.appid = appId; + config.serverUrl = url; + [self startAnalyticsWithConfig:config]; +} + ++ (void)startAnalyticsWithConfig:(TDConfig *)config { + if (!config) { + return; + } + config.appid = [config.appid td_trim]; + + NSString *appId = config.appid; + if (appId.length == 0) { + return; + } + + NSMutableDictionary *instances = [ThinkingAnalyticsSDK _getAllInstances]; + if ([instances objectForKey:[config innerGetMapInstanceToken]]) { + return; + } + + config.serverUrl = [NSURL td_baseUrlStringWithString:config.serverUrl]; + NSString *url = config.serverUrl; + if (url.length == 0) { + return; + } + + ThinkingAnalyticsSDK *sdk = [[ThinkingAnalyticsSDK alloc] initWithConfig:config]; + TDLogInfo(@"instance token: %@", [sdk.config innerGetMapInstanceToken]); +} + ++ (NSString *)lightInstanceIdWithAppId:(NSString *)appId { + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + if (instance) { + ThinkingAnalyticsSDK *lightInstance = [instance innerCreateLightInstance]; + return [lightInstance.config innerGetMapInstanceToken]; + } + return nil; +} + +//MARK: track + ++ (void)flush { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics flushWithAppId:appId]; +} + ++ (void)setTrackStatus:(TDTrackStatus)status { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics setTrackStatus:status withAppId:appId]; +} + ++ (void)track:(NSString *)eventName { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics track:eventName withAppId:appId]; +} + ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics track:eventName properties:properties withAppId:appId]; +} + ++ (void)track:(NSString *)eventName properties:(nullable NSDictionary *)properties time:(NSDate *)time timeZone:(NSTimeZone *)timeZone { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics track:eventName properties:properties time:time timeZone:timeZone withAppId:appId]; +} + ++ (void)trackWithEventModel:(TDEventModel *)eventModel { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics trackWithEventModel:eventModel withAppId:appId]; +} + ++ (void)timeEvent:(NSString *)eventName { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics timeEvent:eventName withAppId:appId]; +} + +//MARK: user property + ++ (void)userSet:(NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userSet:properties withAppId:appId]; +} + ++ (void)userSetOnce:(NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userSetOnce:properties withAppId:appId]; +} + ++ (void)userUnset:(NSString *)propertyName { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userUnset:propertyName withAppId:appId]; +} + ++ (void)userUnsets:(NSArray *)propertyNames { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userUnsets:propertyNames withAppId:appId]; +} + ++ (void)userAdd:(NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userAdd:properties withAppId:appId]; +} + ++ (void)userAddWithName:(NSString *)propertyName andValue:(NSNumber *)propertyValue { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userAddWithName:propertyName andValue:propertyValue withAppId:appId]; +} + ++ (void)userAppend:(NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userAppend:properties withAppId:appId]; +} + ++ (void)userUniqAppend:(NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userUniqAppend:properties withAppId:appId]; +} + ++ (void)userDelete { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics userDeleteWithAppId:appId]; +} + +//MARK: super property & preset property + ++ (void)setSuperProperties:(NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics setSuperProperties:properties withAppId:appId]; +} + ++ (void)unsetSuperProperty:(NSString *)property { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics unsetSuperProperty:property withAppId:appId]; +} + ++ (void)clearSuperProperties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics clearSuperPropertiesWithAppId:appId]; +} + ++ (NSDictionary *)getSuperProperties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + return [TDAnalytics getSuperPropertiesWithAppId:appId]; +} + ++ (void)setDynamicSuperProperties:(NSDictionary *(^)(void))propertiesHandler { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics setDynamicSuperProperties:propertiesHandler withAppId:appId]; +} + ++ (TDPresetProperties *)getPresetProperties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + return [TDAnalytics getPresetPropertiesWithAppId:appId]; +} + +//MARK: error callback + ++ (void)registerErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics registerErrorCallback:errorCallback withAppId:appId]; +} + +//MARK: custom property + ++ (void)setDistinctId:(NSString *)distinctId { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics setDistinctId:distinctId withAppId:appId]; +} + ++ (NSString *)getDistinctId { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + return [TDAnalytics getDistinctIdWithAppId:appId]; +} + ++ (void)login:(NSString *)accountId { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics login:accountId withAppId:appId]; +} + ++ (NSString *)getAccountId { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + return [TDAnalytics getAccountIdWithAppId:appId]; +} + ++ (void)logout { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics logoutWithAppId:appId]; +} + ++ (void)setUploadingNetworkType:(TDReportingNetworkType)type { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics setUploadingNetworkType:type withAppId:appId]; +} + +// MARK: auto track + +#if TARGET_OS_IOS + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType API_UNAVAILABLE(macos){ + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics enableAutoTrack:eventType withAppId:appId]; +} + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties API_UNAVAILABLE(macos){ + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics enableAutoTrack:eventType properties:properties withAppId:appId]; +} + ++ (void)enableAutoTrack:(TDAutoTrackEventType)eventType callback:(NSDictionary *(^ _Nullable)(TDAutoTrackEventType, NSDictionary *))callback API_UNAVAILABLE(macos){ + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics enableAutoTrack:eventType callback:callback withAppId:appId]; +} + ++ (void)ignoreAutoTrackViewControllers:(nonnull NSArray *)controllers API_UNAVAILABLE(macos){ + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics ignoreAutoTrackViewControllers:controllers withAppId:appId]; +} + ++ (void)ignoreViewType:(nonnull Class)aClass API_UNAVAILABLE(macos){ + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics ignoreViewType:aClass withAppId:appId]; +} + ++ (void)setAutoTrackProperties:(TDAutoTrackEventType)eventType properties:(NSDictionary * _Nullable)properties API_UNAVAILABLE(macos){ + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics setAutoTrackProperties:eventType properties:properties withAppId:appId]; +} + ++ (void)setAutoTrackDynamicProperties:(NSDictionary * _Nonnull (^)(void))dynamicSuperProperties API_UNAVAILABLE(macos){ + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [TDAnalytics setAutoTrackDynamicProperties:dynamicSuperProperties withAppId:appId]; +} + +#endif + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.m.meta new file mode 100644 index 0000000..0d5b696 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+Public.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1acfcd5ae045b409fad76724fe46c1fd +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.h new file mode 100644 index 0000000..30a8fbe --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.h @@ -0,0 +1,30 @@ +// +// TDAnalytics+ThirdParty.h +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#if __has_include() +#import +#else +#import "TDAnalytics.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAnalytics (ThirdParty) + +#if TARGET_OS_IOS + ++ (void)enableThirdPartySharing:(TDThirdPartyType)type API_UNAVAILABLE(macos); ++ (void)enableThirdPartySharing:(TDThirdPartyType)type properties:(NSDictionary *)properties API_UNAVAILABLE(macos); + ++ (void)enableThirdPartySharing:(TDThirdPartyType)type withAppId:(NSString *)appId API_UNAVAILABLE(macos); ++ (void)enableThirdPartySharing:(TDThirdPartyType)type properties:(NSDictionary *)properties withAppId:(NSString *)appId API_UNAVAILABLE(macos); + +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.h.meta new file mode 100644 index 0000000..36cb599 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6dc4712154e264aeb8dff858b6f9cadb +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.m new file mode 100644 index 0000000..cc7aaea --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.m @@ -0,0 +1,73 @@ +// +// TDAnalytics+ThirdParty.m +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#import "TDAnalytics+ThirdParty.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +@implementation TDAnalytics (ThirdParty) + +#if TARGET_OS_IOS + ++ (void)enableThirdPartySharing:(TDThirdPartyType)type { + [self enableThirdPartySharing:type properties:@{}]; +} + ++ (void)enableThirdPartySharing:(TDThirdPartyType)type properties:(NSDictionary *)properties { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + [self enableThirdPartySharing:type properties:properties withAppId:appId]; +} + ++ (void)enableThirdPartySharing:(TDThirdPartyType)type withAppId:(NSString *)appId { + [self enableThirdPartySharing:type properties:@{} withAppId:appId]; +} + ++ (void)enableThirdPartySharing:(TDThirdPartyType)type properties:(NSDictionary *)properties withAppId:(NSString *)appId { + ThinkingAnalyticsSDK *instance = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + + if (instance != nil) { + Class TAThirdPartyManager = NSClassFromString(@"TAThirdPartyManager"); + if (TAThirdPartyManager == nil) { + return; + } + NSObject *manager = [[TAThirdPartyManager alloc] init]; + if (manager == nil) { + return; + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + SEL action = @selector(enableThirdPartySharing:instance:property:); +#pragma clang diagnostic pop + + NSMethodSignature *methodSig = [manager methodSignatureForSelector:action]; + if (methodSig == nil) { + return; + } + + @try { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig]; + + NSNumber *thirdPartyTypeNumber = [NSNumber numberWithInteger:type]; + [invocation setArgument:&thirdPartyTypeNumber atIndex:2]; + + [invocation setArgument:&instance atIndex:3]; + + NSDictionary *thirdPartyProperties = properties; + [invocation setArgument:&thirdPartyProperties atIndex:4]; + + [invocation setSelector:action]; + [invocation setTarget:manager]; + [invocation invoke]; + } @catch (NSException *exception) { + TDLogError(@"ThirdParty invocate failed!") + } + } +} + +#endif + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.m.meta new file mode 100644 index 0000000..cafab61 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+ThirdParty.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1f2f67a3159fe48038d44fb0fc53df6c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.h new file mode 100644 index 0000000..eef38df --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.h @@ -0,0 +1,36 @@ +// +// TDAnalytics+WebView.h +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#if __has_include() +#import +#else +#import "TDAnalytics.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAnalytics (WebView) + +/// H5 is connected with the native APP SDK and used in conjunction with the addWebViewUserAgent interface +/// @param webView webView +/// @param request NSURLRequest request +/// @return YES:Process this request NO: This request has not been processed ++ (BOOL)showUpWebView:(id)webView withRequest:(NSURLRequest *)request; + +/// When connecting data with H5, you need to call this interface to configure UserAgent ++ (void)addWebViewUserAgent; + +/// H5 is connected with the native APP SDK and used in conjunction with the addWebViewUserAgent interface +/// @param webView webView +/// @param request NSURLRequest request +/// @param appId appId +/// @return YES:Process this request NO: This request has not been processed ++ (BOOL)showUpWebView:(id)webView withRequest:(NSURLRequest *)request withAppId:(NSString * _Nullable)appId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.h.meta new file mode 100644 index 0000000..773efd0 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 85ee0bdc2089f4f74ba52d6aac59f187 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.m new file mode 100644 index 0000000..6370ef8 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.m @@ -0,0 +1,169 @@ +// +// TDAnalytics+WebView.m +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#import "TDAnalytics+WebView.h" +#import "ThinkingAnalyticsSDKPrivate.h" + +static NSString * const TA_JS_TRACK_SCHEME = @"thinkinganalytics://trackEvent"; + +@implementation TDAnalytics (WebView) + ++ (BOOL)showUpWebView:(nonnull id)webView withRequest:(nonnull NSURLRequest *)request { + NSString *appId = [ThinkingAnalyticsSDK defaultAppId]; + return [self showUpWebView:webView withRequest:request withAppId:appId]; +} + ++ (BOOL)showUpWebView:(id)webView withRequest:(NSURLRequest *)request withAppId:(NSString *)appId { + if (webView == nil || request == nil || ![request isKindOfClass:NSURLRequest.class]) { + return NO; + } + + NSString *urlStr = request.URL.absoluteString; + if (!urlStr) { + return NO; + } + + if ([urlStr rangeOfString:TA_JS_TRACK_SCHEME].length == 0) { + return NO; + } + + NSString *query = [[request URL] query]; + NSArray *queryItem = [query componentsSeparatedByString:@"="]; + + if (queryItem.count != 2) + return YES; + + NSString *queryValue = [queryItem lastObject]; + if ([urlStr rangeOfString:TA_JS_TRACK_SCHEME].length > 0) { + NSString *eventData = [queryValue stringByRemovingPercentEncoding]; + if (eventData.length > 0) { + [TDAnalytics clickFromH5:eventData withAppId:appId]; + } + } + return YES; +} + ++ (void)addWebViewUserAgent { + void (^setUserAgent)(NSString *userAgent) = ^void (NSString *userAgent) { + if ([userAgent rangeOfString:@"td-sdk-ios"].location == NSNotFound) { + userAgent = [userAgent stringByAppendingString:@" /td-sdk-ios"]; + NSDictionary *userAgentDic = [[NSDictionary alloc] initWithObjectsAndKeys:userAgent, @"UserAgent", nil]; + [[NSUserDefaults standardUserDefaults] registerDefaults:userAgentDic]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } + }; + dispatch_block_t getUABlock = ^() { + [TDAnalytics wkWebViewGetUserAgent:^(NSString *userAgent) { + setUserAgent(userAgent); + }]; + }; + td_dispatch_main_sync_safe(getUABlock); +} + +// MARK: private + +static WKWebView *_blankWebView = nil; ++ (void)wkWebViewGetUserAgent:(void(^)(NSString *))completion { + if (!_blankWebView) { + _blankWebView = [[WKWebView alloc] initWithFrame:CGRectZero]; + } + [_blankWebView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id __nullable userAgent, NSError * __nullable error) { + completion(userAgent); + }]; +} + ++ (void)clickFromH5:(NSString *)data withAppId:(NSString *)appId { + NSData *jsonData = [data dataUsingEncoding:NSUTF8StringEncoding]; + if (!jsonData) { + return; + } + + NSError *err; + NSDictionary *eventDict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err]; + if (err) { + return; + } + + ThinkingAnalyticsSDK *instance = nil; + NSString *jsAppid = eventDict[@"#app_id"]; + if ([jsAppid isKindOfClass:[NSString class]]) { + instance = [ThinkingAnalyticsSDK instanceWithAppid:jsAppid]; + } + if (!instance) { + instance = [ThinkingAnalyticsSDK instanceWithAppid:appId]; + } + if (!instance) { + return; + } + + NSArray *dataArr = eventDict[@"data"]; + if (![dataArr isKindOfClass:[NSArray class]]) { + return; + } + + NSDictionary *dataInfo = dataArr.firstObject; + if (dataInfo != nil) { + NSString *type = [dataInfo objectForKey:@"#type"]; + NSString *event_name = [dataInfo objectForKey:@"#event_name"]; + NSString *time = [dataInfo objectForKey:@"#time"]; + NSDictionary *properties = [dataInfo objectForKey:@"properties"]; + + NSString *extraID; + + if ([type isEqualToString:TD_EVENT_TYPE_TRACK]) { + extraID = [dataInfo objectForKey:@"#first_check_id"]; + if (extraID) { + type = TD_EVENT_TYPE_TRACK_FIRST; + } + } else { + extraID = [dataInfo objectForKey:@"#event_id"]; + } + + NSMutableDictionary *dic = [properties mutableCopy]; + [dic removeObjectForKey:@"#account_id"]; + [dic removeObjectForKey:@"#distinct_id"]; + [dic removeObjectForKey:@"#device_id"]; + [dic removeObjectForKey:@"#lib"]; + [dic removeObjectForKey:@"#lib_version"]; + [dic removeObjectForKey:@"#screen_height"]; + [dic removeObjectForKey:@"#screen_width"]; + + [self h5trackWithInstance:instance eventName:event_name extraID:extraID properties:dic type:type time:time]; + } +} + ++ (void)h5trackWithInstance:(ThinkingAnalyticsSDK *)instance eventName:(NSString *)eventName extraID:(NSString *)extraID properties:(NSDictionary *)propertieDict type:(NSString *)type time:(NSString *)time { + if ([ThinkingAnalyticsSDK isTrackEvent:type]) { + TDTrackEvent *event = nil; + if ([type isEqualToString:TD_EVENT_TYPE_TRACK]) { + TDTrackEvent *trackEvent = [[TDTrackEvent alloc] initWithName:eventName]; + event = trackEvent; + } else if ([type isEqualToString:TD_EVENT_TYPE_TRACK_FIRST]) { + TDTrackFirstEvent *firstEvent = [[TDTrackFirstEvent alloc] initWithName:eventName]; + firstEvent.firstCheckId = extraID; + event = firstEvent; + } else if ([type isEqualToString:TD_EVENT_TYPE_TRACK_UPDATE]) { + TDTrackUpdateEvent *updateEvent = [[TDTrackUpdateEvent alloc] initWithName:eventName]; + updateEvent.eventId = extraID; + event = updateEvent; + } else if ([type isEqualToString:TD_EVENT_TYPE_TRACK_OVERWRITE]) { + TDTrackOverwriteEvent *overwriteEvent = [[TDTrackOverwriteEvent alloc] initWithName:eventName]; + overwriteEvent.eventId = extraID; + event = overwriteEvent; + } + event.h5TimeString = time; + if ([propertieDict objectForKey:@"#zone_offset"]) { + event.h5ZoneOffSet = [propertieDict objectForKey:@"#zone_offset"]; + } + [instance asyncTrackEventObject:event properties:propertieDict isH5:YES]; + } else { + TDUserEvent *event = [[TDUserEvent alloc] initWithType:[TDBaseEvent typeWithTypeString:type]]; + [instance asyncUserEventObject:event properties:propertieDict isH5:YES]; + } +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.m.meta new file mode 100644 index 0000000..fedb85c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics+WebView.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 3295eb25caa35446e933c34935a737f4 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.h new file mode 100644 index 0000000..8da24a9 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.h @@ -0,0 +1,55 @@ +// +// TDAnalytics.h +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#import + +#if TARGET_OS_IOS +#import + +#if __has_include() +#import +#else +#import "TDAutoTrackPublicHeader.h" +#endif + +#elif TARGET_OS_OSX +#import + +#endif + +#if __has_include() +#import +#else +#import "TDFirstEventModel.h" +#endif + +#if __has_include() +#import +#else +#import "TDEditableEventModel.h" +#endif + + +#if __has_include() +#import +#else +#import "TDConfig.h" +#endif + +#if __has_include() +#import +#else +#import "TDPresetProperties.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface TDAnalytics : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.h.meta new file mode 100644 index 0000000..07b5983 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: fe6a3a72a21bf4e71bf22410f1d779e0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.m new file mode 100644 index 0000000..fcc6709 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.m @@ -0,0 +1,12 @@ +// +// TDAnalytics.m +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/17. +// + +#import "TDAnalytics.h" + +@implementation TDAnalytics + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.m.meta new file mode 100644 index 0000000..a616e8f --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDAnalytics.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 6b511d6b0320645ec89166b365912c4a +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDConstant.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDConstant.h new file mode 100644 index 0000000..77eeb5b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDConstant.h @@ -0,0 +1,282 @@ +// +// TDConstant.h +// ThinkingSDK +// +// Created by LiHuanan on 2020/9/8. +// Copyright © 2020 thinkingdata. All rights reserved. +// + +#import + +/** + Log Level + + - TDLoggingLevelNone : Not enabled by default + */ +typedef NS_OPTIONS(NSInteger, TDLoggingLevel) { + /** + Not enabled by default + */ + TDLoggingLevelNone = 0, + + /** + Error Log + */ + TDLoggingLevelError = 1 << 0, + + + /** + Warning Log + */ + TDLoggingLevelWarning = 1 << 1, + + /** + Info Log + */ + TDLoggingLevelInfo = 1 << 2, + + /** + Debug Log + */ + TDLoggingLevelDebug = 1 << 3, +}; + +/** +Debug Mode + +- ThinkingAnalyticsDebugOff : Not enabled by default +*/ +__attribute__((deprecated("This class is deprecated. Use the newClass instead: TDMode"))) +typedef NS_OPTIONS(NSInteger, ThinkingAnalyticsDebugMode) { + /** + Not enabled by default + */ + ThinkingAnalyticsDebugOff = 0, + + /** + Enable DebugOnly Mode, Data is not persisted + */ + ThinkingAnalyticsDebugOnly = 1 << 0, + + /** + Enable Debug Mode,Data will persist + */ + ThinkingAnalyticsDebug = 1 << 1, + + /** + Enable Debug Mode,Data will persist,Equivalent to ThinkingAnalyticsDebug + */ + ThinkingAnalyticsDebugOn = ThinkingAnalyticsDebug, +}; + +/** +Debug Mode + +- ThinkingAnalyticsDebugOff : Not enabled by default +*/ +typedef NS_OPTIONS(NSInteger, TDMode) { + /** + Not enabled by default + */ + TDModeNormal = 0, + + /** + Enable DebugOnly Mode, Data is not persisted + */ + TDModeDebugOnly = 1 << 0, + + /** + Enable Debug Mode,Data will persist + */ + TDModeDebug = 1 << 1, +}; + + +/** + Https Certificate Verification Mode +*/ +typedef NS_OPTIONS(NSInteger, TDSSLPinningMode) { + /** + The default authentication method will only verify the certificate returned by the server in the system's trusted certificate list + */ + TDSSLPinningModeNone = 0, + + /** + The public key of the verification certificate + */ + TDSSLPinningModePublicKey = 1 << 0, + + /** + Verify all contents of the certificate + */ + TDSSLPinningModeCertificate = 1 << 1 +}; + +/** + Custom HTTPS Authentication +*/ +typedef NSURLSessionAuthChallengeDisposition (^TDURLSessionDidReceiveAuthenticationChallengeBlock)(NSURLSession *_Nullable session, NSURLAuthenticationChallenge *_Nullable challenge, NSURLCredential *_Nullable __autoreleasing *_Nullable credential); + + + +/** + Network Type Enum + + - TDNetworkTypeDefault : 3G、4G、WIFI + */ +__attribute__((deprecated("This class is deprecated. Use the newClass instead: TDReportingNetworkType"))) +typedef NS_OPTIONS(NSInteger, ThinkingAnalyticsNetworkType) { + + /** + only WIFI + */ + TDNetworkTypeOnlyWIFI = 1 << 0, + + /** + 2G、3G、4G、WIFI + */ + TDNetworkTypeALL = 1 << 1, + + /** + 3G、4G、WIFI + */ + TDNetworkTypeDefault = TDNetworkTypeALL, +}; + +typedef NS_OPTIONS(NSInteger, TDReportingNetworkType) { + TDReportingNetworkTypeWIFI = 1 << 0, + TDReportingNetworkTypeALL = 1 << 1, +}; + +/** + Auto-Tracking Enum + + - ThinkingAnalyticsEventTypeNone : auto-tracking is not enabled by default + */ +__attribute__((deprecated("This class is deprecated. Use the newClass instead: TDAutoTrackEventType"))) +typedef NS_OPTIONS(NSInteger, ThinkingAnalyticsAutoTrackEventType) { + + /** + auto-tracking is not enabled by default + */ + ThinkingAnalyticsEventTypeNone = 0, + + /* + Active Events + */ + ThinkingAnalyticsEventTypeAppStart = 1 << 0, + + /** + Inactive Events + */ + ThinkingAnalyticsEventTypeAppEnd = 1 << 1, + + /** + Clicked events + */ + ThinkingAnalyticsEventTypeAppClick = 1 << 2, + + /** + View Page Events + */ + ThinkingAnalyticsEventTypeAppViewScreen = 1 << 3, + + /** + Crash Events + */ + ThinkingAnalyticsEventTypeAppViewCrash = 1 << 4, + + /** + Installation Events + */ + ThinkingAnalyticsEventTypeAppInstall = 1 << 5, + /** + All Events + */ + ThinkingAnalyticsEventTypeAll = ThinkingAnalyticsEventTypeAppStart | ThinkingAnalyticsEventTypeAppEnd | ThinkingAnalyticsEventTypeAppClick | ThinkingAnalyticsEventTypeAppInstall | ThinkingAnalyticsEventTypeAppViewCrash | ThinkingAnalyticsEventTypeAppViewScreen + +}; + +typedef NS_OPTIONS(NSInteger, ThinkingNetworkType) { + ThinkingNetworkTypeNONE = 0, + ThinkingNetworkType2G = 1 << 0, + ThinkingNetworkType3G = 1 << 1, + ThinkingNetworkType4G = 1 << 2, + ThinkingNetworkTypeWIFI = 1 << 3, + ThinkingNetworkType5G = 1 << 4, + ThinkingNetworkTypeALL = 0xFF, +}; + + +typedef NS_OPTIONS(NSInteger, TDThirdPartyType) { + TDThirdPartyTypeNone = 0, + TDThirdPartyTypeAppsFlyer = 1 << 0, + TDThirdPartyTypeIronSource = 1 << 1, + TDThirdPartyTypeAdjust = 1 << 2, + TDThirdPartyTypeBranch = 1 << 3, + TDThirdPartyTypeTopOn = 1 << 4, + TDThirdPartyTypeTracking = 1 << 5, + TDThirdPartyTypeTradPlus = 1 << 6, + TDThirdPartyTypeAppLovin = 1 << 7, + TDThirdPartyTypeKochava = 1 << 8, + TDThirdPartyTypeTalkingData = 1 << 9, + TDThirdPartyTypeFirebase = 1 << 10, +}; + +__attribute__((deprecated("This class is deprecated. Use the newClass instead: TDThirdPartyType"))) +typedef NS_OPTIONS(NSUInteger, TAThirdPartyShareType) { + TAThirdPartyShareTypeNONE = TDThirdPartyTypeNone, + TAThirdPartyShareTypeAPPSFLYER = TDThirdPartyTypeAppsFlyer, + TAThirdPartyShareTypeIRONSOURCE = TDThirdPartyTypeIronSource, + TAThirdPartyShareTypeADJUST = TDThirdPartyTypeAdjust, + TAThirdPartyShareTypeBRANCH = TDThirdPartyTypeBranch, + TAThirdPartyShareTypeTOPON = TDThirdPartyTypeTopOn, + TAThirdPartyShareTypeTRACKING = TDThirdPartyTypeTracking, + TAThirdPartyShareTypeTRADPLUS = TDThirdPartyTypeTradPlus, + TAThirdPartyShareTypeAPPLOVIN = TDThirdPartyTypeAppLovin, + TAThirdPartyShareTypeKOCHAVA = TDThirdPartyTypeKochava, + TAThirdPartyShareTypeTALKINGDATA = TDThirdPartyTypeTalkingData, + TAThirdPartyShareTypeFIREBASE = TDThirdPartyTypeFirebase, + + TDThirdPartyShareTypeNONE = TAThirdPartyShareTypeNONE, + TDThirdPartyShareTypeAPPSFLYER = TAThirdPartyShareTypeAPPSFLYER, + TDThirdPartyShareTypeIRONSOURCE = TAThirdPartyShareTypeIRONSOURCE, + TDThirdPartyShareTypeADJUST = TAThirdPartyShareTypeADJUST, + TDThirdPartyShareTypeBRANCH = TAThirdPartyShareTypeBRANCH, + TDThirdPartyShareTypeTOPON = TAThirdPartyShareTypeTOPON, + TDThirdPartyShareTypeTRACKING = TAThirdPartyShareTypeTRACKING, + TDThirdPartyShareTypeTRADPLUS = TAThirdPartyShareTypeTRADPLUS, +}; + +//MARK: - Data reporting status +typedef NS_ENUM(NSInteger, TDTrackStatus) { + /// Suspend reporting + TDTrackStatusPause, + /// Stop reporting and clear cache + TDTrackStatusStop, + /// Suspend reporting and continue to persist data + TDTrackStatusSaveOnly, + /// reset normal + TDTrackStatusNormal +}; + + +//MARK: - Data reporting status +__attribute__((deprecated("This class is deprecated. Use the newClass instead: TDTrackStatus"))) +typedef NS_ENUM(NSInteger, TATrackStatus) { + /// Suspend reporting + TATrackStatusPause, + /// Stop reporting and clear cache + TATrackStatusStop, + /// Suspend reporting and continue to persist data + TATrackStatusSaveOnly, + /// reset normal + TATrackStatusNormal +}; + +//MARK: - DNS service +typedef NSString *TDDNSService NS_TYPED_EXTENSIBLE_ENUM; +static TDDNSService const _Nonnull TDDNSServiceCloudFlare = @"https://cloudflare-dns.com/dns-query?name="; +static TDDNSService const _Nonnull TDDNSServiceCloudALi = @"https://223.5.5.5/resolve?name="; +static TDDNSService const _Nonnull TDDNSServiceCloudGoogle = @"https://8.8.8.8/resolve?name="; + diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDConstant.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDConstant.h.meta new file mode 100644 index 0000000..0611b38 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/TDConstant.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 4ca0c85929cda4d0e804eb407175415e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.h new file mode 100644 index 0000000..012192a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.h @@ -0,0 +1,463 @@ +// +// ThinkingAnalyticsSDK+OldPublic.h +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/10. +// + +#if __has_include() +#import +#else +#import "ThinkingAnalyticsSDK.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +@interface ThinkingAnalyticsSDK (OldPublic) + +//MARK: SDK info + ++ (void)calibrateTimeWithNtp:(NSString *)ntpServer DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics calibrateTimeWithNtp:]"); ++ (void)calibrateTime:(NSTimeInterval)timestamp DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics calibrateTime:]"); ++ (nullable NSString *)getLocalRegion DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics getLocalRegion]"); +/** + Set Log level + @param level log level + */ ++ (void)setLogLevel:(TDLoggingLevel)level DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics enableLog:]"); ++ (void)setCustomerLibInfoWithLibName:(NSString *)libName libVersion:(NSString *)libVersion DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setCustomerLibInfoWithLibName:libVersion:]"); +/** + Get sdk version + + @return version string + */ ++ (NSString *)getSDKVersion DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics getSDKVersion]"); +/** + Get DeviceId + + @return deviceId + */ ++ (NSString *)getDeviceId DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics getDeviceId]"); +/** + Format the time output in the format of SDK + @param date date + @return date string + */ ++ (NSString *)timeStringWithDate:(NSDate *)date DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics timeStringWithDate:]"); + +#pragma mark - Tracking + +/** + Initialization method + After the SDK initialization is complete, the saved instance can be obtained through this api + + @param appId appId + @param url server url + @return sdk instance + */ ++ (ThinkingAnalyticsSDK *)startWithAppId:(NSString *)appId withUrl:(NSString *)url DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics startAnalyticsWithAppId:(NSString *)appId serverUrl:(NSString *)url]"); + +/** + Initialization method + After the SDK initialization is complete, the saved instance can be obtained through this api + + @param config initialization configuration + @return sdk instance + */ ++ (ThinkingAnalyticsSDK *)startWithConfig:(nullable TDConfig *)config DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics startAnalyticsWithConfig:(nullable TDConfig *)config]"); + +/** + Initialization method + After the SDK initialization is complete, the saved instance can be obtained through this api + + @param appId appId + @param url server url + @param config initialization configuration object + @return one instance + */ ++ (ThinkingAnalyticsSDK *)startWithAppId:(NSString *)appId withUrl:(NSString *)url withConfig:(nullable TDConfig *)config DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics startAnalyticsWithConfig:(nullable TDConfig *)config]"); + +/** + Get default instance + + @return SDK instance + */ ++ (nullable ThinkingAnalyticsSDK *)sharedInstance DEPRECATED_MSG_ATTRIBUTE("Deprecated. please use class method [TDAnalytics ...]"); + +/** + Get one instance according to appid or instanceName + + @param appid APP ID or instanceName + @return SDK instance + */ ++ (nullable ThinkingAnalyticsSDK *)sharedInstanceWithAppid:(NSString *)appid DEPRECATED_MSG_ATTRIBUTE("Deprecated. please use class method [TDAnalytics ...withAppId:(NSString *)appId]"); + +#pragma mark - Action Track + +/** + Track Events + + @param event event name + */ +- (void)track:(NSString *)event DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics track:]"); + +/** + Track Events + + @param event event name + @param propertieDict event properties + */ +- (void)track:(NSString *)event properties:(nullable NSDictionary *)propertieDict DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics track:properties:]"); + +/** + Track Events + + @param event event name + @param propertieDict event properties + @param time event trigger time + */ +- (void)track:(NSString *)event properties:(nullable NSDictionary *)propertieDict time:(NSDate *)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics track:properties:time:timeZone:]"); + +/** + Track Events + + @param event event name + @param propertieDict event properties + @param time event trigger time + @param timeZone event trigger time time zone + */ +- (void)track:(NSString *)event properties:(nullable NSDictionary *)propertieDict time:(NSDate *)time timeZone:(NSTimeZone *)timeZone DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics track:properties:time:timeZone:]"); + +/** + Track Events + + @param eventModel event Model + */ +- (void)trackWithEventModel:(TDEventModel *)eventModel DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics trackWithEventModel]"); + +/** + Get the events collected in the App Extension and report them + + @param appGroupId The app group id required for data sharing + */ +- (void)trackFromAppExtensionWithAppGroupId:(NSString *)appGroupId DEPRECATED_MSG_ATTRIBUTE("Deprecated"); + +#pragma mark - + +/** + Timing Events + Record the event duration, call this method to start the timing, stop the timing when the target event is uploaded, and add the attribute #duration to the event properties, in seconds. + */ +- (void)timeEvent:(NSString *)event DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics timeEvent:]"); + +/** + Identify + Set the distinct ID to replace the default UUID distinct ID. + */ +- (void)identify:(NSString *)distinctId DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setDistinctId:]"); + +/** + Get Distinctid + Get a visitor ID: The #distinct_id value in the reported data. + */ +- (NSString *)getDistinctId DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics getDistinctId]"); + +/** + Login + Set the account ID. Each setting overrides the previous value. Login events will not be uploaded. + + @param accountId account ID + */ +- (void)login:(NSString *)accountId DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics login:]"); + +/** + Logout + Clearing the account ID will not upload user logout events. + */ +- (void)logout DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics logout]"); + +/** + User_Set + Sets the user property, replacing the original value with the new value if the property already exists. + + @param properties user properties + */ +- (void)user_set:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userSet:]"); + +/** + User_Set + + @param properties user properties + @param time event trigger time +*/ +- (void)user_set:(NSDictionary *)properties withTime:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userSet:]"); + +/** + User_Unset + + @param propertyName user properties + */ +- (void)user_unset:(NSString *)propertyName DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userUnset:]"); + +/** + User_Unset + Reset user properties. + + @param propertyName user properties + @param time event trigger time +*/ +- (void)user_unset:(NSString *)propertyName withTime:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userUnset:]"); + +/** + User_SetOnce + Sets a single user attribute, ignoring the new attribute value if the attribute already exists. + + @param properties user properties + */ +- (void)user_setOnce:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userSetOnce:]"); + +/** + User_SetOnce + + @param properties user properties + @param time event trigger time +*/ +- (void)user_setOnce:(NSDictionary *)properties withTime:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userSetOnce:]"); + +/** + User_Add + Adds the numeric type user attributes. + + @param properties user properties + */ +- (void)user_add:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userAdd:]"); + +/** + User_Add + + @param properties user properties + @param time event trigger time +*/ +- (void)user_add:(NSDictionary *)properties withTime:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userAdd:]"); + +/** + User_Add + + @param propertyName propertyName + @param propertyValue propertyValue + */ +- (void)user_add:(NSString *)propertyName andPropertyValue:(NSNumber *)propertyValue DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userAddWithName:andValue:]"); + +/** + User_Add + + @param propertyName propertyName + @param propertyValue propertyValue + @param time event trigger time +*/ +- (void)user_add:(NSString *)propertyName andPropertyValue:(NSNumber *)propertyValue withTime:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userAddWithName:andValue:]"); + +/** + User_Delete + Delete the user attributes,This operation is not reversible and should be performed with caution. + */ +- (void)user_delete DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userDelete]"); + +/** + User_Delete + + @param time event trigger time + */ +- (void)user_delete:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userDelete]"); + +/** + User_Append + Append a user attribute of the List type. + + @param properties user properties +*/ +- (void)user_append:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userAppend:]"); + +/** + User_Append + The element appended to the library needs to be done to remove the processing,and then import. + + @param properties user properties + @param time event trigger time +*/ +- (void)user_append:(NSDictionary *)properties withTime:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userAppend:]"); + +/** + User_UniqAppend + + @param properties user properties +*/ +- (void)user_uniqAppend:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userUniqAppend:]"); + +/** + User_UniqAppend + + @param properties user properties + @param time event trigger time +*/ +- (void)user_uniqAppend:(NSDictionary *)properties withTime:(NSDate * _Nullable)time DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics userUniqAppend:]"); + + +/** + Static Super Properties + Set the public event attribute, which will be included in every event uploaded after that. The public event properties are saved without setting them each time. + * + */ +- (void)setSuperProperties:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setSuperProperties:]"); + +/** + Unset Super Property + Clears a public event attribute. + */ +- (void)unsetSuperProperty:(NSString *)property DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics unsetSuperProperty:]"); + +/** + Clear Super Properties + Clear all public event attributes. + */ +- (void)clearSuperProperties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics clearSuperProperties]"); + +/** + Get Static Super Properties + Gets the public event properties that have been set. + */ +- (NSDictionary *)currentSuperProperties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics getSuperProperties]"); + +/** + Dynamic super properties + Set dynamic public properties. Each event uploaded after that will contain a public event attribute. + */ +- (void)registerDynamicSuperProperties:(NSDictionary *(^)(void))dynamicSuperProperties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setDynamicSuperProperties:]"); + +/** + Register TD error callback + + @param errorCallback + code = 10001, + ext = "string or json string", + errorMsg = "error" + */ +- (void)registerErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics registerErrorCallback:]"); + +/** + Gets prefabricated properties for all events. + */ +- (TDPresetProperties *)getPresetProperties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics getSuperProperties]"); + +/** + Set the network conditions for uploading. By default, the SDK will set the network conditions as 3G, 4G and Wifi to upload data + */ +- (void)setNetworkType:(ThinkingAnalyticsNetworkType)type DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setUploadingNetworkType:]"); + +#if TARGET_OS_IOS + +/** + Enable Auto-Tracking + + @param eventType Auto-Tracking type + + detailed documentation http://doc.thinkingdata.cn/tgamanual/installation/ios_sdk_installation/ios_sdk_autotrack.html + */ +- (void)enableAutoTrack:(ThinkingAnalyticsAutoTrackEventType)eventType DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics enableAutoTrack:]"); + +/** + Enable the auto tracking function. + + @param eventType Auto-Tracking type + @param properties properties + */ +- (void)enableAutoTrack:(ThinkingAnalyticsAutoTrackEventType)eventType properties:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics enableAutoTrack:properties:]"); + +/** + Enable the auto tracking function. + + @param eventType Auto-Tracking type + @param callback callback + In the callback, eventType indicates the type of automatic collection, properties indicates the event properties before storage, and this block can return a dictionary for adding new properties + */ +- (void)enableAutoTrack:(ThinkingAnalyticsAutoTrackEventType)eventType callback:(NSDictionary *(^)(ThinkingAnalyticsAutoTrackEventType eventType, NSDictionary *properties))callback DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics enableAutoTrack:callback:]"); + +/** + Set and Update the value of a custom property for Auto-Tracking + + @param eventType A list of ThinkingAnalyticsAutoTrackEventType, indicating the types of automatic collection events that need to be enabled + @param properties properties + */ +- (void)setAutoTrackProperties:(ThinkingAnalyticsAutoTrackEventType)eventType properties:(NSDictionary *)properties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setAutoTrackProperties:]"); + +/** + Ignore the Auto-Tracking of a page + + @param controllers Ignore the name of the UIViewController + */ +- (void)ignoreAutoTrackViewControllers:(NSArray *)controllers DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics ignoreAutoTrackViewControllers:]"); + +/** + Ignore the Auto-Tracking of click event + + @param aClass ignored controls Class + */ +- (void)ignoreViewType:(Class)aClass DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics ignoreViewType:]"); + +/** + Dynamic super properties in auto track environment. + Set dynamic public properties for auto track event + */ +- (void)setAutoTrackDynamicProperties:(NSDictionary *(^)(void))dynamicSuperProperties DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setAutoTrackDynamicProperties:]"); + +#endif + +//MARK: - + +/** + Get DeviceId + */ +- (NSString *)getDeviceId DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics getDeviceId]"); + +/** + Empty the cache queue. When this api is called, the data in the current cache queue will attempt to be reported. + If the report succeeds, local cache data will be deleted. + */ +- (void)flush DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics flush]"); + +/** + Switch reporting status + + @param status TDTrackStatus reporting status + */ +- (void)setTrackStatus:(TATrackStatus)status DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setTrackStatus:]"); + +- (void)enableTracking:(BOOL)enabled DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setTrackStatus:]"); +- (void)optOutTracking DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setTrackStatus:]"); +- (void)optOutTrackingAndDeleteUser DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setTrackStatus:]"); +- (void)optInTracking DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics setTrackStatus:]"); + +/** + Create a light instance + */ +- (ThinkingAnalyticsSDK *)createLightInstance DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics lightInstanceIdWithAppId] and [TDAnalytics ...withAppId:(NSString *)appId]"); + +- (NSString *)getTimeString:(NSDate *)date DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics timeStringWithDate:]"); + +#if TARGET_OS_IOS +- (void)enableThirdPartySharing:(TAThirdPartyShareType)type DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics enableThirdPartySharing:]"); +- (void)enableThirdPartySharing:(TAThirdPartyShareType)type customMap:(NSDictionary *)customMap DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics enableThirdPartySharing:properties:]"); +#endif + +/// Deprecated. replace with: +showUpWebView:withRequest: +/// @param webView webView +/// @param request NSURLRequest +/// @return YES:Process this request NO: This request has not been processed +- (BOOL)showUpWebView:(id)webView WithRequest:(NSURLRequest *)request DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics showUpWebView:withRequest:]"); + +/// Deprecated. replace with: +addWebViewUserAgent +- (void)addWebViewUserAgent DEPRECATED_MSG_ATTRIBUTE("Deprecated. replace with: [TDAnalytics addWebViewUserAgent]"); + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.h.meta new file mode 100644 index 0000000..d973a7a --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 407b7f91e5ee74e38998c9e3176bf949 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.m new file mode 100644 index 0000000..e7a4c0b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.m @@ -0,0 +1,315 @@ +// +// ThinkingAnalyticsSDK+OldPublic.m +// ThinkingSDK +// +// Created by 杨雄 on 2023/8/10. +// + +#import "ThinkingAnalyticsSDK+OldPublic.h" +#import "ThinkingAnalyticsSDKPrivate.h" +#import "TDAnalytics+Public.h" +#import "TDAnalytics+Multiple.h" +#import "TDConfigPrivate.h" +#import "TDAnalytics+ThirdParty.h" +#import "TDAnalytics+WebView.h" + +@implementation ThinkingAnalyticsSDK (OldPublic) + +#pragma mark - Logging + ++ (void)setLogLevel:(TDLoggingLevel)level { + [TDLogging sharedInstance].loggingLevel = level; +} + +#pragma mark - Calibrate time + ++ (void)calibrateTime:(NSTimeInterval)timestamp { + [TDAnalytics calibrateTime:timestamp]; +} + ++ (void)calibrateTimeWithNtp:(NSString *)ntpServer { + [TDAnalytics calibrateTimeWithNtp:ntpServer]; +} + +// MARK: info + ++ (nullable NSString *)getLocalRegion { + return [TDAnalytics getLocalRegion]; +} + ++ (void)setCustomerLibInfoWithLibName:(NSString *)libName libVersion:(NSString *)libVersion { + [TDAnalytics setCustomerLibInfoWithLibName:libName libVersion:libVersion]; +} + ++ (NSString *)getSDKVersion { + return [TDAnalytics getSDKVersion]; +} + ++ (NSString *)getDeviceId { + return [TDAnalytics getDeviceId]; +} + ++ (NSString *)timeStringWithDate:(NSDate *)date { + return [TDAnalytics timeStringWithDate:date]; +} + +// MARK: init + ++ (ThinkingAnalyticsSDK *)startWithAppId:(NSString *)appId withUrl:(NSString *)url { + return [self startWithAppId:appId withUrl:url withConfig:nil]; +} + ++ (ThinkingAnalyticsSDK *)startWithAppId:(NSString *)appId withUrl:(NSString *)url withConfig:(nullable TDConfig *)config { + if (!config) { + config = [[TDConfig alloc] init]; + } + config.appid = appId; + config.serverUrl = url; + return [ThinkingAnalyticsSDK startWithConfig:config]; +} + ++ (ThinkingAnalyticsSDK *)startWithConfig:(TDConfig *)config { + [TDAnalytics startAnalyticsWithConfig:config]; + return [ThinkingAnalyticsSDK instanceWithAppid:[config innerGetMapInstanceToken]]; +} + ++ (nullable ThinkingAnalyticsSDK *)sharedInstance { + return [ThinkingAnalyticsSDK defaultInstance]; +} ++ (nullable ThinkingAnalyticsSDK *)sharedInstanceWithAppid:(NSString *)appid { + return [ThinkingAnalyticsSDK instanceWithAppid:appid]; +} +- (ThinkingAnalyticsSDK *)createLightInstance { + return [self innerCreateLightInstance]; +} +- (void)track:(NSString *)event { + [TDAnalytics track:event withAppId:[self instanceAliasNameOrAppId]]; +} +// TAThirdParty model used. +- (void)track:(NSString *)event properties:(nullable NSDictionary *)propertieDict { + [TDAnalytics track:event properties:propertieDict withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)track:(NSString *)event properties:(nullable NSDictionary *)propertieDict time:(NSDate *)time { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + [self track:event properties:propertieDict time:time timeZone:nil]; +#pragma clang diagnostic pop +} +- (void)track:(NSString *)event properties:(nullable NSDictionary *)propertieDict time:(NSDate *)time timeZone:(NSTimeZone *)timeZone { + [TDAnalytics track:event properties:propertieDict time:time timeZone:timeZone withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)trackWithEventModel:(TDEventModel *)eventModel { + [TDAnalytics trackWithEventModel:eventModel withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)trackFromAppExtensionWithAppGroupId:(NSString *)appGroupId { + // deprecated +} +- (void)timeEvent:(NSString *)event { + [TDAnalytics timeEvent:event withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)identify:(NSString *)distinctId { + [TDAnalytics setDistinctId:distinctId withAppId:[self instanceAliasNameOrAppId]]; +} + +// TAThirdParty model used. +- (NSString *)getDistinctId { + return [TDAnalytics getDistinctIdWithAppId:[self instanceAliasNameOrAppId]]; +} + +- (void)login:(NSString *)accountId { + [TDAnalytics login:accountId withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)logout { + [TDAnalytics logoutWithAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_set:(NSDictionary *)properties { + [TDAnalytics userSet:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_set:(NSDictionary *)properties withTime:(NSDate * _Nullable)time { + TDUserEventSet *event = [[TDUserEventSet alloc] init]; + if (time) { + event.time = time; + event.timeValueType = TDEventTimeValueTypeTimeOnly; + } + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)user_unset:(NSString *)propertyName { + [TDAnalytics userUnset:propertyName withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_unset:(NSString *)propertyName withTime:(NSDate * _Nullable)time { + if ([propertyName isKindOfClass:[NSString class]] && propertyName.length > 0) { + NSDictionary *properties = @{propertyName: @0}; + TDUserEventUnset *event = [[TDUserEventUnset alloc] init]; + if (time) { + event.time = time; + event.timeValueType = TDEventTimeValueTypeTimeOnly; + } + [self asyncUserEventObject:event properties:properties isH5:NO]; + } +} +- (void)user_setOnce:(NSDictionary *)properties { + [TDAnalytics userSetOnce:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_setOnce:(NSDictionary *)properties withTime:(NSDate * _Nullable)time { + TDUserEventSetOnce *event = [[TDUserEventSetOnce alloc] init]; + if (time) { + event.time = time; + event.timeValueType = TDEventTimeValueTypeTimeOnly; + } + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)user_add:(NSDictionary *)properties { + [TDAnalytics userAdd:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_add:(NSDictionary *)properties withTime:(NSDate * _Nullable)time { + TDUserEventAdd *event = [[TDUserEventAdd alloc] init]; + if (time) { + event.time = time; + event.timeValueType = TDEventTimeValueTypeTimeOnly; + } + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)user_add:(NSString *)propertyName andPropertyValue:(NSNumber *)propertyValue { + [TDAnalytics userAddWithName:propertyName andValue:propertyValue withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_add:(NSString *)propertyName andPropertyValue:(NSNumber *)propertyValue withTime:(NSDate * _Nullable)time { + if (propertyName && propertyValue) { + [self user_add:@{propertyName: propertyValue} withTime:time]; + } +} +- (void)user_delete { + [TDAnalytics userDeleteWithAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_delete:(NSDate * _Nullable)time { + TDUserEventDelete *event = [[TDUserEventDelete alloc] init]; + if (time) { + event.time = time; + event.timeValueType = TDEventTimeValueTypeTimeOnly; + } + [self asyncUserEventObject:event properties:nil isH5:NO]; +} +- (void)user_append:(NSDictionary *)properties { + [TDAnalytics userAppend:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_append:(NSDictionary *)properties withTime:(NSDate * _Nullable)time { + TDUserEventAppend *event = [[TDUserEventAppend alloc] init]; + if (time) { + event.time = time; + event.timeValueType = TDEventTimeValueTypeTimeOnly; + } + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)user_uniqAppend:(NSDictionary *)properties { + [TDAnalytics userUniqAppend:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)user_uniqAppend:(NSDictionary *)properties withTime:(NSDate * _Nullable)time { + TDUserEventUniqueAppend *event = [[TDUserEventUniqueAppend alloc] init]; + if (time) { + event.time = time; + event.timeValueType = TDEventTimeValueTypeTimeOnly; + } + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)setSuperProperties:(NSDictionary *)properties { + [TDAnalytics setSuperProperties:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)unsetSuperProperty:(NSString *)property { + [TDAnalytics unsetSuperProperty:property withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)clearSuperProperties { + [TDAnalytics clearSuperPropertiesWithAppId:[self instanceAliasNameOrAppId]]; +} +- (NSDictionary *)currentSuperProperties { + return [TDAnalytics getSuperPropertiesWithAppId:[self instanceAliasNameOrAppId]]; +} +- (void)registerDynamicSuperProperties:(NSDictionary *(^)(void))dynamicSuperProperties { + [TDAnalytics setDynamicSuperProperties:dynamicSuperProperties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)registerErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback { + [TDAnalytics registerErrorCallback:errorCallback withAppId:[self instanceAliasNameOrAppId]]; +} +- (TDPresetProperties *)getPresetProperties { + return [TDAnalytics getPresetPropertiesWithAppId:[self instanceAliasNameOrAppId]]; +} +- (void)setNetworkType:(ThinkingAnalyticsNetworkType)type { + [TDAnalytics setUploadingNetworkType:(TDReportingNetworkType)type withAppId:[self instanceAliasNameOrAppId]]; +} +#if TARGET_OS_IOS +- (void)enableAutoTrack:(ThinkingAnalyticsAutoTrackEventType)eventType { + [TDAnalytics enableAutoTrack:(TDAutoTrackEventType)eventType withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)enableAutoTrack:(ThinkingAnalyticsAutoTrackEventType)eventType properties:(NSDictionary *)properties { + [TDAnalytics enableAutoTrack:(TDAutoTrackEventType)eventType properties:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)enableAutoTrack:(ThinkingAnalyticsAutoTrackEventType)eventType callback:(NSDictionary *(^)(ThinkingAnalyticsAutoTrackEventType eventType, NSDictionary *properties))callback { + [TDAnalytics enableAutoTrack:(TDAutoTrackEventType)eventType callback:^NSDictionary *(TDAutoTrackEventType type, NSDictionary *dict){ + return callback((ThinkingAnalyticsAutoTrackEventType)type, dict); + } withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)setAutoTrackProperties:(ThinkingAnalyticsAutoTrackEventType)eventType properties:(NSDictionary *)properties { + [TDAnalytics setAutoTrackProperties:(TDAutoTrackEventType)eventType properties:properties withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)ignoreAutoTrackViewControllers:(NSArray *)controllers { + [TDAnalytics ignoreAutoTrackViewControllers:controllers withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)ignoreViewType:(Class)aClass { + [TDAnalytics ignoreViewType:aClass withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)setAutoTrackDynamicProperties:(NSDictionary * _Nonnull (^)(void))dynamicSuperProperties { + [TDAnalytics setAutoTrackDynamicProperties:dynamicSuperProperties withAppId:[self instanceAliasNameOrAppId]]; +} +#endif + +- (NSString *)getDeviceId { + return [TDAnalytics getDeviceId]; +} +- (void)flush { + [TDAnalytics flushWithAppId:[self instanceAliasNameOrAppId]]; +} +- (void)setTrackStatus: (TATrackStatus)status { + [TDAnalytics setTrackStatus:(TDTrackStatus)status withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)enableTracking:(BOOL)enabled { + [TDAnalytics setTrackStatus:enabled ? TDTrackStatusNormal : TDTrackStatusPause withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)optOutTracking { + [TDAnalytics setTrackStatus:TDTrackStatusStop withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)optOutTrackingAndDeleteUser { + TDUserEventDelete *deleteEvent = [[TDUserEventDelete alloc] init]; + deleteEvent.immediately = YES; + [self asyncUserEventObject:deleteEvent properties:nil isH5:NO]; + + [TDAnalytics setTrackStatus:TDTrackStatusStop withAppId:[self instanceAliasNameOrAppId]]; +} +- (void)optInTracking { + [TDAnalytics setTrackStatus:TDTrackStatusNormal withAppId:[self instanceAliasNameOrAppId]]; +} +- (NSString *)getTimeString:(NSDate *)date { + return [TDAnalytics timeStringWithDate:date withAppId:[self instanceAliasNameOrAppId]]; +} + +//MARK: - ThirdParty + +#if TARGET_OS_IOS +- (void)enableThirdPartySharing:(TAThirdPartyShareType)type { + [TDAnalytics enableThirdPartySharing:(TDThirdPartyType)type properties:@{} withAppId:[self instanceAliasNameOrAppId]]; +} + +- (void)enableThirdPartySharing:(TAThirdPartyShareType)type customMap:(NSDictionary *)customMap { + [TDAnalytics enableThirdPartySharing:(TDThirdPartyType)type properties:customMap withAppId:[self instanceAliasNameOrAppId]]; +} +#endif + +//MARK: - WebView + +- (void)addWebViewUserAgent { + [TDAnalytics addWebViewUserAgent]; +} + +- (BOOL)showUpWebView:(id)webView WithRequest:(NSURLRequest *)request { + return [TDAnalytics showUpWebView:webView withRequest:request withAppId:[self instanceAliasNameOrAppId]]; +} + + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.m.meta new file mode 100644 index 0000000..ea15a3c --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK+OldPublic.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 2c4b48d28bbd743b69c0db48d6a4ab66 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.h new file mode 100644 index 0000000..25a5e7d --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.h @@ -0,0 +1,50 @@ +#import + +#if TARGET_OS_IOS +#import + +#if __has_include() +#import +#else +#import "TDAutoTrackPublicHeader.h" +#endif + +#elif TARGET_OS_OSX +#import + +#endif + +#if __has_include() +#import +#else +#import "TDFirstEventModel.h" +#endif + +#if __has_include() +#import +#else +#import "TDEditableEventModel.h" +#endif + + +#if __has_include() +#import +#else +#import "TDConfig.h" +#endif + +#if __has_include() +#import +#else +#import "TDPresetProperties.h" +#endif + + +NS_ASSUME_NONNULL_BEGIN + +@interface ThinkingAnalyticsSDK : NSObject + + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.h.meta new file mode 100644 index 0000000..9033870 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 148eb28cb0e494f208a263fa8b46ec91 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.m b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.m new file mode 100644 index 0000000..30cdd2e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.m @@ -0,0 +1,1032 @@ +#import "ThinkingAnalyticsSDKPrivate.h" + +#if TARGET_OS_IOS + +#import "TDAutoTrackManager.h" +#import "TDAppLaunchReason.h" +#import "TDPushClickEvent.h" + +#endif + +#if __has_include() +#import +#else +#import "TDJSONUtil.h" +#endif +#if __has_include() +#import +#else +#import "TDNotificationManager+Analytics.h" +#endif +#if __has_include() +#import +#else +#import "TDCalibratedTime.h" +#endif +#if __has_include() +#import +#else +#import "TDCoreDeviceInfo.h" +#endif +#if __has_include() +#import +#else +#import "NSString+TDCore.h" +#endif + +#if __has_include() +#import +#else +#import "TDNotificationManager+Networking.h" +#endif + +#if __has_include() +#import +#else +#import "TDMediator+Analytics.h" +#endif + +#import "TDConfig.h" +#import "TDPublicConfig.h" +#import "TDFile.h" +#import "TDCheck.h" +#import "TDAppState.h" +#import "TDEventRecord.h" +#import "TDAppLifeCycle.h" +#import "TDAnalytics+Public.h" +#import "TDConfigPrivate.h" + +#if !__has_feature(objc_arc) +#error The ThinkingSDK library must be compiled with ARC enabled +#endif + +@interface TDPresetProperties (ThinkingAnalytics) + +- (instancetype)initWithDictionary:(NSDictionary *)dict; +- (void)updateValuesWithDictionary:(NSDictionary *)dict; + +@end + +@interface ThinkingAnalyticsSDK () +@property (nonatomic, strong) TDEventTracker *eventTracker; +@property (nonatomic, strong) TDFile *file; +@property (nonatomic, strong) TDSuperProperty *superProperty; +@property (nonatomic, strong) TDPropertyPluginManager *propertyPluginManager; +@property (nonatomic, strong) TDAppLifeCycle *appLifeCycle; +@property (atomic, assign) BOOL isOptOut; +@property (nonatomic, strong, nullable) NSTimer *timer; +@property (nonatomic, strong) TDTrackTimer *trackTimer; +@property (atomic, strong) TDSqliteDataQueue *dataQueue; + +@end + +@implementation ThinkingAnalyticsSDK + +static NSLock *g_lock; +static NSMutableDictionary *g_instances; +static NSString *defaultProjectAppid; +static dispatch_queue_t td_trackQueue; + ++ (NSString *)defaultAppId { + return defaultProjectAppid; +} + ++ (void)initialize { + static dispatch_once_t ThinkingOnceToken; + dispatch_once(&ThinkingOnceToken, ^{ + td_trackQueue = dispatch_queue_create("cn.thinkingdata.analytics.track", DISPATCH_QUEUE_SERIAL); + g_lock = [[NSLock alloc] init]; + }); +} + ++ (dispatch_queue_t)sharedTrackQueue { + return td_trackQueue; +} + ++ (dispatch_queue_t)sharedNetworkQueue { + return [TDEventTracker td_networkQueue]; +} + +- (ThinkingAnalyticsSDK *)innerCreateLightInstance { + ThinkingAnalyticsSDK *lightInstance = [[LightThinkingAnalyticsSDK alloc] initWithAPPID:self.config.appid withServerURL:self.config.serverUrl withConfig:self.config]; + lightInstance.identifyId = [TDDeviceInfo sharedManager].uniqueId; + lightInstance.propertyPluginManager = self.propertyPluginManager; + return lightInstance; +} + +- (instancetype)initLight:(NSString *)appid withServerURL:(NSString *)serverURL withConfig:(TDConfig *)config { + if (self = [self init]) { + self.isEnabled = YES; + self.config = [config copy]; + + // random instance name + NSString *instanceName = [NSUUID UUID].UUIDString; + self.config.name = instanceName; + + self.config.appid = appid; + self.config.serverUrl = serverURL; + + NSString *instanceIdentify = [self instanceAliasNameOrAppId]; + if (!instanceIdentify) { + return nil; + } + + [g_lock lock]; + g_instances[instanceIdentify] = self; + [g_lock unlock]; + + self.superProperty = [[TDSuperProperty alloc] initWithToken:instanceIdentify isLight:YES]; + + self.trackTimer = [[TDTrackTimer alloc] init]; + + self.dataQueue = [TDSqliteDataQueue sharedInstanceWithAppid:appid]; + if (self.dataQueue == nil) { + TDLogError(@"SqliteException: init SqliteDataQueue failed"); + } + + self.eventTracker = [[TDEventTracker alloc] initWithQueue:td_trackQueue instanceToken:instanceIdentify]; + } + return self; +} + +- (instancetype)initWithConfig:(TDConfig *)config { + if (self = [super init]) { + if (!config) { + return nil; + } + self.config = config; + + NSString *instanceAliasName = [self instanceAliasNameOrAppId]; + if (!instanceAliasName) { + return nil; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + g_instances = [NSMutableDictionary dictionary]; + defaultProjectAppid = instanceAliasName; + }); + + [g_lock lock]; + g_instances[instanceAliasName] = self; + [g_lock unlock]; + + self.file = [[TDFile alloc] initWithAppid:instanceAliasName]; + [self retrievePersistedData]; + + self.superProperty = [[TDSuperProperty alloc] initWithToken:instanceAliasName isLight:NO]; + + dispatch_async(td_trackQueue, ^{ + self.dataQueue = [TDSqliteDataQueue sharedInstanceWithAppid:instanceAliasName]; + if (self.dataQueue == nil) { + TDLogError(@"SqliteException: init SqliteDataQueue failed"); + } + + self.propertyPluginManager = [[TDPropertyPluginManager alloc] init]; + TDPresetPropertyPlugin *presetPlugin = [[TDPresetPropertyPlugin alloc] init]; + presetPlugin.instanceToken = [self instanceAliasNameOrAppId]; + [self.propertyPluginManager registerPropertyPlugin:presetPlugin]; + }); + + self.config.getInstanceName = ^NSString * _Nonnull{ + return instanceAliasName; + }; + +#if TARGET_OS_IOS + dispatch_async(td_trackQueue, ^{ + if (self.config.innerEnableEncrypt) { + self.encryptManager = [[TDEncryptManager alloc] initWithSecretKey:self.config.innerSecretKey]; + } + __weak __typeof(self)weakSelf = self; + [self.config innerUpdateConfig:^(NSDictionary * _Nonnull secretKey) { + if (weakSelf.config.innerEnableEncrypt && secretKey) { + [weakSelf.encryptManager handleEncryptWithConfig:secretKey]; + } + }]; + [self.config innerUpdateIPMap]; + }); +#elif TARGET_OS_OSX + [self.config innerUpdateConfig:^(NSDictionary * _Nonnull secretKey) {}]; +#endif + + self.trackTimer = [[TDTrackTimer alloc] init]; + + self.ignoredViewControllers = [[NSMutableSet alloc] init]; + self.ignoredViewTypeList = [[NSMutableSet alloc] init]; + + self.eventTracker = [[TDEventTracker alloc] initWithQueue:td_trackQueue instanceToken:instanceAliasName]; + + [self startFlushTimer]; + + [TDAppLifeCycle startMonitor]; + + [self registerAppLifeCycleListener]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkStatusChangedNotification:) name:kNetworkNotificationNameStatusChange object:nil]; + +#if TARGET_OS_IOS + NSDictionary *ops = [TDAppLaunchReason getAppPushDic]; + if(ops != nil){ + TDPushClickEvent *pushEvent = [[TDPushClickEvent alloc]initWithName: @"te_ops_push_click"]; + pushEvent.ops = ops; + [self autoTrackWithEvent:pushEvent properties:@{}]; + [self innerFlush]; + } + [TDAppLaunchReason clearAppPushParams]; +#endif + + TDLogInfo(@"initialize success. Mode: %@\n AppID: %@\n ServerUrl: %@\n TimeZone: %@\n DeviceID: %@\n Lib: %@\n LibVersion: %@", [self modeEnumToString:self.config.mode], self.config.appid, self.config.serverUrl, self.config.defaultTimeZone ?: [NSTimeZone localTimeZone], [TDAnalytics getDeviceId], [[TDDeviceInfo sharedManager] libName] ,[[TDDeviceInfo sharedManager] libVersion]); + + [TDNotificationManager postAnalyticsInitEventWithAppId:instanceAliasName serverUrl:self.config.serverUrl]; + + [[TDMediator sharedInstance] registerSuccessWithTargetName:kTDMediatorTargetAnalytics]; + } + return self; +} + +- (void)registerAppLifeCycleListener { + NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; + + [notificationCenter addObserver:self selector:@selector(appStateWillChangeNotification:) name:kTDAppLifeCycleStateWillChangeNotification object:nil]; + [notificationCenter addObserver:self selector:@selector(appStateDidChangeNotification:) name:kTDAppLifeCycleStateDidChangeNotification object:nil]; +} + +- (void)networkStatusChangedNotification:(NSNotification *)notification { + NSString *status = [notification.userInfo objectForKey:kNetworkNotificationParamsNetworkType]; + if (![status isEqualToString:@"NULL"]) { + [self innerFlush]; + } +} + +- (NSString*)modeEnumToString:(TDMode)enumVal { + NSArray *modeEnumArray = [[NSArray alloc] initWithObjects:@"Normal", @"DebugOnly", @"Debug", nil]; + return [modeEnumArray objectAtIndex:enumVal]; +} + +- (NSString *)instanceAliasNameOrAppId { + return [self.config innerGetMapInstanceToken]; +} + +- (NSString *)description { + return [NSString stringWithFormat:@"[ThinkingAnalyticsSDK] AppID: %@, ServerUrl: %@, Mode: %@, TimeZone: %@, DeviceID: %@, Lib: %@, LibVersion: %@", self.config.appid, self.config.serverUrl, [self modeEnumToString:self.config.mode], self.config.defaultTimeZone, [TDAnalytics getDeviceId], [[TDDeviceInfo sharedManager] libName] ,[[TDDeviceInfo sharedManager] libVersion]]; +} + +- (BOOL)hasDisabled { + return !self.isEnabled || self.isOptOut; +} + +- (void)doOptOutTracking { + self.isOptOut = YES; + +#if TARGET_OS_IOS + @synchronized (self.autoTrackSuperProperty) { + [self.autoTrackSuperProperty clearSuperProperties]; + } +#endif + + [self.superProperty registerDynamicSuperProperties:nil]; + + void(^block)(void) = ^{ + @synchronized (TDSqliteDataQueue.class) { + [self.dataQueue deleteAll:[self instanceAliasNameOrAppId]]; + } + [self.trackTimer clear]; + [self.superProperty clearSuperProperties]; + self.identifyId = [TDDeviceInfo sharedManager].uniqueId; + self.accountId = nil; + + [self.file archiveAccountID:nil]; + [self.file archiveIdentifyId:nil]; + [self.file archiveSuperProperties:nil]; + [self.file archiveOptOut:YES]; + }; + if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(td_trackQueue)) { + block(); + } else { + dispatch_async(td_trackQueue, block); + } +} + +#pragma mark - Persistence +- (void)retrievePersistedData { + self.accountId = [self.file unarchiveAccountID]; + self.identifyId = [self.file unarchiveIdentifyID]; + self.trackPause = [self.file unarchiveTrackPause]; + self.isEnabled = [self.file unarchiveEnabled]; + self.isOptOut = [self.file unarchiveOptOut]; + self.config.uploadSize = [self.file unarchiveUploadSize]; + self.config.uploadInterval = [self.file unarchiveUploadInterval]; + if (self.identifyId.length == 0) { + self.identifyId = [TDDeviceInfo sharedManager].uniqueId; + } + if (self.accountId.length == 0) { + [self.file deleteOldLoginId]; + } +} + +- (void)deleteAll { + dispatch_async(td_trackQueue, ^{ + @synchronized (TDSqliteDataQueue.class) { + [self.dataQueue deleteAll:[self instanceAliasNameOrAppId]]; + } + }); +} + +//MARK: - AppLifeCycle + +- (void)appStateWillChangeNotification:(NSNotification *)notification { + TDAppLifeCycleState newState = [[notification.userInfo objectForKey:kTDAppLifeCycleNewStateKey] integerValue]; + + if (newState == TDAppLifeCycleStateEnd) { + [self stopFlushTimer]; + } +} + +- (void)appStateDidChangeNotification:(NSNotification *)notification { + TDAppLifeCycleState newState = [[notification.userInfo objectForKey:kTDAppLifeCycleNewStateKey] integerValue]; + + if (newState == TDAppLifeCycleStateStart) { + [self startFlushTimer]; + NSTimeInterval systemUpTime = [TDCoreDeviceInfo bootTime]; + [self.trackTimer enterForegroundWithSystemUptime:systemUpTime]; + } else if (newState == TDAppLifeCycleStateEnd) { + NSTimeInterval systemUpTime = [TDCoreDeviceInfo bootTime]; + [self.trackTimer enterBackgroundWithSystemUptime:systemUpTime]; + +#if TARGET_OS_IOS + UIApplication *application = [TDAppState sharedApplication];; + __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = UIBackgroundTaskInvalid; + void (^endBackgroundTask)(void) = ^() { + [application endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + }; + backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:endBackgroundTask]; + + [self.eventTracker _asyncWithCompletion:endBackgroundTask]; +#else + [self.eventTracker flush]; +#endif + + } else if (newState == TDAppLifeCycleStateTerminate) { + dispatch_sync(td_trackQueue, ^{}); + [self.eventTracker flush]; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + dispatch_queue_t networkQueue = [TDEventTracker td_networkQueue]; + dispatch_async(networkQueue, ^{ + dispatch_semaphore_signal(semaphore); + }); + dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC))); + } +} + +// MARK: - + ++ (NSString *)getNetWorkStates { +#if TARGET_OS_IOS + return [TDCoreDeviceInfo networkType]; +#else + return @"--"; +#endif +} + +#pragma mark - Private + +- (void)asyncTrackEventObject:(TDTrackEvent *)event properties:(NSDictionary * _Nullable)properties isH5:(BOOL)isH5 { + + event.isEnabled = self.isEnabled; + event.trackPause = self.isTrackPause; + event.isOptOut = self.isOptOut; + event.accountId = self.accountId; + event.distinctId = self.identifyId; + + [self handleTimeEvent:event]; + [self calibratedTimeWithEvent:event]; + + dispatch_async(td_trackQueue, ^{ + @autoreleasepool { + event.dynamicSuperProperties = [self.superProperty obtainDynamicSuperProperties]; + [self trackEvent:event properties:[properties copy] isH5:isH5]; + } + }); +} + +- (void)asyncUserEventObject:(TDUserEvent *)event properties:(NSDictionary * _Nullable)properties isH5:(BOOL)isH5 { + + event.isEnabled = self.isEnabled; + event.trackPause = self.isTrackPause; + event.isOptOut = self.isOptOut; + event.accountId = self.accountId; + event.distinctId = self.identifyId; + + [self calibratedTimeWithEvent:event]; + + dispatch_async(td_trackQueue, ^{ + @autoreleasepool { + [self trackUserEvent:event properties:[properties copy] isH5:NO]; + } + }); +} + +- (void)calibratedTimeWithEvent:(TDBaseEvent *)event { + if (event.timeValueType == TDEventTimeValueTypeNone) { + event.time = [TDCalibratedTime now]; + } +} + ++ (BOOL)isTrackEvent:(NSString *)eventType { + return [TD_EVENT_TYPE_TRACK isEqualToString:eventType] + || [TD_EVENT_TYPE_TRACK_FIRST isEqualToString:eventType] + || [TD_EVENT_TYPE_TRACK_UPDATE isEqualToString:eventType] + || [TD_EVENT_TYPE_TRACK_OVERWRITE isEqualToString:eventType] + ; +} + +//MARK: - + +- (void)trackUserEvent:(TDUserEvent *)event properties:(NSDictionary *)properties isH5:(BOOL)isH5 { + + if (!event.isEnabled || event.isOptOut) { + return; + } + + if ([TDAppState shareInstance].relaunchInBackground && !self.config.trackRelaunchedInBackgroundEvents) { + return; + } + + [event.properties addEntriesFromDictionary:[TDPropertyValidator validateProperties:properties validator:event]]; + + if (event.timeZone == nil) { + event.timeZone = self.config.defaultTimeZone ?: [NSTimeZone localTimeZone]; + } + + NSDictionary *jsonObj = [event formatDateWithDict:event.jsonObject]; + + [self.eventTracker track:jsonObj immediately:event.immediately saveOnly:event.isTrackPause]; + TDLogInfo(@"user event success"); +} + +- (void)trackEvent:(TDTrackEvent *)event properties:(NSDictionary *)properties isH5:(BOOL)isH5 { + + if (!event.isEnabled || event.isOptOut) { + return; + } + + if ([TDAppState shareInstance].relaunchInBackground && !self.config.trackRelaunchedInBackgroundEvents && [event.eventName isEqualToString:TD_APP_START_BACKGROUND_EVENT]) { + return; + } + + NSError *error = nil; + [event validateWithError:&error]; + if (error) { + return; + } + + if ([self.config.disableEvents containsObject:event.eventName]) { + return; + } + + + if ([TDAppState shareInstance].relaunchInBackground) { + event.properties[@"#relaunched_in_background"] = @YES; + } + + NSMutableDictionary *pluginProperties = [self.propertyPluginManager propertiesWithEventType:event.eventType]; + + NSDictionary *superProperties = [TDPropertyValidator validateProperties:self.superProperty.currentSuperProperties validator:event]; + + NSDictionary *dynamicSuperProperties = [TDPropertyValidator validateProperties:event.dynamicSuperProperties validator:event]; + + if (event.timeZone == nil) { + event.timeZone = self.config.defaultTimeZone ?: [NSTimeZone localTimeZone]; + } + + NSMutableDictionary *jsonObj = [NSMutableDictionary dictionary]; + + if (isH5) { + event.properties = [superProperties mutableCopy]; + [event.properties addEntriesFromDictionary:dynamicSuperProperties]; + [event.properties addEntriesFromDictionary:properties]; + [event.properties addEntriesFromDictionary:pluginProperties]; + + jsonObj = event.jsonObject; + + if (event.h5TimeString) { + jsonObj[@"#time"] = event.h5TimeString; + } + if (event.h5ZoneOffSet) { + jsonObj[@"#zone_offset"] = event.h5ZoneOffSet; + } + } else { + [event.properties addEntriesFromDictionary:pluginProperties]; + [event.properties addEntriesFromDictionary:superProperties]; +#if TARGET_OS_IOS + if ([event isKindOfClass:[TDAutoTrackEvent class]]) { + TDAutoTrackEvent *autoEvent = (TDAutoTrackEvent *)event; + NSDictionary *autoSuperProperties = [self.autoTrackSuperProperty currentSuperPropertiesWithEventName:event.eventName]; + autoSuperProperties = [TDPropertyValidator validateProperties:autoSuperProperties validator:autoEvent]; + [event.properties addEntriesFromDictionary:autoSuperProperties]; + } +#endif + [event.properties addEntriesFromDictionary:dynamicSuperProperties]; + + properties = [TDPropertyValidator validateProperties:properties validator:event]; + [event.properties addEntriesFromDictionary:properties]; + + jsonObj = event.jsonObject; + } + + jsonObj = [event formatDateWithDict:jsonObj]; + + [TDNotificationManager postAnalyticsTrackWithAppId:self.config.appid event:jsonObj]; + + if (event.isDebug) { + [self.eventTracker trackDebugEvent:jsonObj]; + } else { + [self.eventTracker track:jsonObj immediately:event.immediately saveOnly:event.isTrackPause]; + } + TDLogInfo(@"track success"); +} + +#pragma mark - innerFlush control +- (void)startFlushTimer { + [self stopFlushTimer]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.config.uploadInterval > 0) { + self.timer = [NSTimer scheduledTimerWithTimeInterval:[self.config.uploadInterval integerValue] + target:self + selector:@selector(autoFlushWithTimer:) + userInfo:nil + repeats:YES]; + } + }); +} + +- (void)stopFlushTimer { + dispatch_async(dispatch_get_main_queue(), ^{ + if (self.timer) { + [self.timer invalidate]; + self.timer = nil; + } + }); +} + +#if TARGET_OS_IOS + +//MARK: - Auto Track + +- (void)autoTrackWithEvent:(TDAutoTrackEvent *)event properties:(NSDictionary *)properties { + [self handleTimeEvent:event]; + [self asyncAutoTrackEventObject:event properties:properties]; +} + +/// Add event to event queue +- (void)asyncAutoTrackEventObject:(TDAutoTrackEvent *)event properties:(NSDictionary *)properties { + event.isEnabled = self.isEnabled; + event.trackPause = self.isTrackPause; + event.isOptOut = self.isOptOut; + event.accountId = self.accountId; + event.distinctId = self.identifyId; + + [self calibratedTimeWithEvent:event]; + + NSDictionary *dynamicProperties = [self.superProperty obtainDynamicSuperProperties]; + + NSMutableDictionary *autoTrackDynamicProperties = [NSMutableDictionary dictionary]; + [autoTrackDynamicProperties addEntriesFromDictionary:[self.autoTrackSuperProperty obtainAutoTrackDynamicSuperProperties]]; + [autoTrackDynamicProperties addEntriesFromDictionary:[self.autoTrackSuperProperty obtainDynamicSuperPropertiesWithType:event.autoTrackEventType currentProperties:event.properties]]; + + NSMutableDictionary *unionProperties = [NSMutableDictionary dictionary]; + if (dynamicProperties) { + [unionProperties addEntriesFromDictionary:dynamicProperties]; + } + if (autoTrackDynamicProperties) { + [unionProperties addEntriesFromDictionary:autoTrackDynamicProperties]; + } + event.dynamicSuperProperties = unionProperties; + dispatch_async(td_trackQueue, ^{ + [self trackEvent:event properties:[properties copy] isH5:NO]; + }); +} + +- (BOOL)isViewControllerIgnored:(UIViewController *)viewController { + if (viewController == nil) { + return false; + } + NSString *screenName = NSStringFromClass([viewController class]); + if (_ignoredViewControllers != nil && _ignoredViewControllers.count > 0) { + if ([_ignoredViewControllers containsObject:screenName]) { + return true; + } + } + return false; +} + +- (TDAutoTrackSuperProperty *)autoTrackSuperProperty { + if (!_autoTrackSuperProperty) { + _autoTrackSuperProperty = [[TDAutoTrackSuperProperty alloc] init]; + } + return _autoTrackSuperProperty; +} + +#endif + +//MARK: - Private + +- (void)handleTimeEvent:(TDTrackEvent *)trackEvent { + BOOL isTrackDuration = [self.trackTimer isExistEvent:trackEvent.eventName]; + BOOL isEndEvent = [trackEvent.eventName isEqualToString:TD_APP_END_EVENT]; + BOOL isStartEvent = [trackEvent.eventName isEqualToString:TD_APP_START_EVENT]; + BOOL isStateInit = [TDAppLifeCycle shareInstance].state == TDAppLifeCycleStateInit; + + if (isStateInit) { + trackEvent.foregroundDuration = [self.trackTimer foregroundDurationOfEvent:trackEvent.eventName isActive:YES systemUptime:trackEvent.systemUpTime]; + [self.trackTimer removeEvent:trackEvent.eventName]; + } else if (isStartEvent) { + trackEvent.backgroundDuration = [self.trackTimer backgroundDurationOfEvent:trackEvent.eventName isActive:NO systemUptime:trackEvent.systemUpTime]; + [self.trackTimer removeEvent:trackEvent.eventName]; + } else if (isEndEvent) { + trackEvent.foregroundDuration = [self.trackTimer foregroundDurationOfEvent:trackEvent.eventName isActive:YES systemUptime:trackEvent.systemUpTime]; + [self.trackTimer removeEvent:trackEvent.eventName]; + } else if (isTrackDuration) { + BOOL isActive = [TDAppState shareInstance].isActive; + trackEvent.foregroundDuration = [self.trackTimer foregroundDurationOfEvent:trackEvent.eventName isActive:isActive systemUptime:trackEvent.systemUpTime]; + trackEvent.backgroundDuration = [self.trackTimer backgroundDurationOfEvent:trackEvent.eventName isActive:isActive systemUptime:trackEvent.systemUpTime]; + [self.trackTimer removeEvent:trackEvent.eventName]; + } else { + if (trackEvent.eventName == TD_APP_END_EVENT) { + return; + } + } +} + ++ (NSMutableDictionary *)_getAllInstances { + NSMutableDictionary *dict = nil; + [g_lock lock]; + dict = [g_instances mutableCopy]; + [g_lock unlock]; + return dict; +} + ++ (void)track_crashEventWithMessage:(NSString *)msg { +#if TARGET_OS_IOS + [ThinkingExceptionHandler trackCrashWithMessage:msg]; +#endif +} + +//MARK: - SDK instance + ++ (nullable ThinkingAnalyticsSDK *)defaultInstance { + NSString *appId = [self defaultAppId]; + return [self instanceWithAppid:appId]; +} + ++ (nullable ThinkingAnalyticsSDK *)instanceWithAppid:(NSString *)appid { + appid = appid.td_trim; + if (appid == nil || appid.length == 0) { + appid = [ThinkingAnalyticsSDK defaultAppId]; + } + ThinkingAnalyticsSDK *sdk = nil; + [g_lock lock]; + sdk = g_instances[appid]; + [g_lock unlock]; + return sdk; +} + +//MARK: - track event + +- (void)innerTrack:(NSString *)event { + [self innerTrack:event properties:nil time:nil timeZone:nil]; +} +- (void)innerTrack:(NSString *)event properties:(NSDictionary *)propertieDict { + [self innerTrack:event properties:propertieDict time:nil timeZone:nil]; +} +- (void)innerTrackDebug:(NSString *)event properties:(NSDictionary *)propertieDict { + TDTrackEvent *trackEvent = [[TDTrackEvent alloc] initWithName:event]; + trackEvent.isDebug = YES; + [self handleTimeEvent:trackEvent]; + [self asyncTrackEventObject:trackEvent properties:propertieDict isH5:NO]; +} +- (void)innerTrack:(NSString *)event properties:(NSDictionary * _Nullable)propertieDict time:(NSDate * _Nullable)time timeZone:(NSTimeZone * _Nullable)timeZone { + TDTrackEvent *trackEvent = [[TDTrackEvent alloc] initWithName:event]; + if (time) { + trackEvent.time = time; + trackEvent.timeValueType = TDEventTimeValueTypeTimeOnly; + if (timeZone) { + trackEvent.timeZone = timeZone; + trackEvent.timeValueType = TDEventTimeValueTypeTimeAndZone; + } + } + + [self asyncTrackEventObject:trackEvent properties:propertieDict isH5:NO]; +} +- (void)innerTrackWithEventModel:(TDEventModel *)eventModel { + TDTrackEvent *baseEvent = nil; + if ([eventModel.eventType isEqualToString:TD_EVENT_TYPE_TRACK_FIRST]) { + TDTrackFirstEvent *trackEvent = [[TDTrackFirstEvent alloc] initWithName:eventModel.eventName]; + trackEvent.firstCheckId = eventModel.extraID; + baseEvent = trackEvent; + } else if ([eventModel.eventType isEqualToString:TD_EVENT_TYPE_TRACK_UPDATE]) { + TDTrackUpdateEvent *trackEvent = [[TDTrackUpdateEvent alloc] initWithName:eventModel.eventName]; + trackEvent.eventId = eventModel.extraID; + baseEvent = trackEvent; + } else if ([eventModel.eventType isEqualToString:TD_EVENT_TYPE_TRACK_OVERWRITE]) { + TDTrackOverwriteEvent *trackEvent = [[TDTrackOverwriteEvent alloc] initWithName:eventModel.eventName]; + trackEvent.eventId = eventModel.extraID; + baseEvent = trackEvent; + } else if ([eventModel.eventType isEqualToString:TD_EVENT_TYPE_TRACK]) { + TDTrackEvent *trackEvent = [[TDTrackEvent alloc] initWithName:eventModel.eventName]; + baseEvent = trackEvent; + } + + if (eventModel.time) { + baseEvent.time = eventModel.time; + baseEvent.timeValueType = TDEventTimeValueTypeTimeOnly; + if (eventModel.timeZone) { + baseEvent.timeZone = eventModel.timeZone; + baseEvent.timeValueType = TDEventTimeValueTypeTimeAndZone; + } + } + + [self asyncTrackEventObject:baseEvent properties:eventModel.properties isH5:NO]; +} +- (void)innerTimeEvent:(NSString *)event { + if ([self hasDisabled]) { + return; + } + NSError *error = nil; + [TDPropertyValidator validateEventOrPropertyName:event withError:&error]; + if (error) { + return; + } + [self.trackTimer trackEvent:event withSystemUptime:[TDCoreDeviceInfo bootTime]]; +} + +//MARK: - user id + +- (void)innerSetIdentify:(NSString *)distinctId { + if ([self hasDisabled]) { + return; + } + if (![distinctId isKindOfClass:[NSString class]]) { + TDLogError(@"identify cannot null", distinctId); + return; + } + NSString *trimmedId = [distinctId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (trimmedId.length == 0) { + TDLogError(@"accountId invald", distinctId); + return; + } + + TDLogInfo(@"Set distinct ID, Distinct Id = %@", distinctId); + + @synchronized (self.file) { + self.identifyId = distinctId; + [self.file archiveIdentifyId:distinctId]; + [TDNotificationManager postAnalyticsSetDistinctIdEventWithAppId:self.config.appid accountId:self.accountId distinctId:self.identifyId]; + } +} + +- (NSString *)innerDistinctId { + return self.identifyId; +} + +- (NSString *)innerAccountId { + return self.accountId; +} + +// TAThirdParty model used. +- (NSString *)getAccountId { + return [self innerAccountId]; +} + +- (void)innerLogin:(NSString *)accountId { + if ([self hasDisabled]) { + return; + } + if (![accountId isKindOfClass:[NSString class]]) { + TDLogError(@"accountId invald", accountId); + return; + } + NSString *trimmedId = [accountId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (trimmedId.length == 0) { + TDLogError(@"accountId invald", accountId); + return; + } + + TDLogInfo(@"Login SDK, AccountId = %@", accountId); + + @synchronized (self.file) { + self.accountId = accountId; + [self.file archiveAccountID:accountId]; + [TDNotificationManager postAnalyticsLoginEventWithAppId:self.config.appid accountId:self.accountId distinctId:self.identifyId]; + } +} +- (void)innerLogout { + if ([self hasDisabled]) { + return; + } + + TDLogInfo(@"Logout SDK."); + + @synchronized (self.file) { + self.accountId = nil; + [self.file archiveAccountID:nil]; + [TDNotificationManager postAnalyticsLogoutEventWithAppId:self.config.appid distinctId:self.identifyId]; + } +} + +//MARK: - user profile + +- (void)innerUserSet:(NSDictionary *)properties { + TDUserEventSet *event = [[TDUserEventSet alloc] init]; + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)innerUserUnset:(NSString *)propertyName { + if ([propertyName isKindOfClass:[NSString class]] && propertyName.length > 0) { + NSDictionary *properties = @{propertyName: @0}; + TDUserEventUnset *event = [[TDUserEventUnset alloc] init]; + [self asyncUserEventObject:event properties:properties isH5:NO]; + } +} +- (void)innerUserUnsets:(NSArray *)propertyNames { + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + for (NSString *name in propertyNames) { + if ([name isKindOfClass:[NSString class]] && name.length > 0) { + dict[name] = @0; + } + } + if (dict.count > 0) { + TDUserEventUnset *event = [[TDUserEventUnset alloc] init]; + [self asyncUserEventObject:event properties:dict isH5:NO]; + } +} +- (void)innerUserSetOnce:(NSDictionary *)properties { + TDUserEventSetOnce *event = [[TDUserEventSetOnce alloc] init]; + [self asyncUserEventObject:event properties:properties isH5:NO]; +} + +- (void)innerUserAdd:(NSDictionary *)properties { + TDUserEventAdd *event = [[TDUserEventAdd alloc] init]; + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)innerUserAdd:(NSString *)propertyName andPropertyValue:(NSNumber *)propertyValue { + if (propertyName && propertyValue) { + [self innerUserAdd:@{propertyName: propertyValue}]; + } +} +- (void)innerUserDelete { + TDUserEventDelete *event = [[TDUserEventDelete alloc] init]; + [self asyncUserEventObject:event properties:nil isH5:NO]; +} +- (void)innerUserAppend:(NSDictionary *)properties { + TDUserEventAppend *event = [[TDUserEventAppend alloc] init]; + [self asyncUserEventObject:event properties:properties isH5:NO]; +} +- (void)innerUserUniqAppend:(NSDictionary *)properties { + TDUserEventUniqueAppend *event = [[TDUserEventUniqueAppend alloc] init]; + [self asyncUserEventObject:event properties:properties isH5:NO]; +} + +//MARK: - super properties + +- (void)innerSetSuperProperties:(NSDictionary *)properties { + if ([self hasDisabled]) { + return; + } + + dispatch_async(td_trackQueue, ^{ + [self.superProperty registerSuperProperties:properties]; + }); +} +- (void)innerUnsetSuperProperty:(NSString *)property { + if ([self hasDisabled]) { + return; + } + dispatch_async(td_trackQueue, ^{ + [self.superProperty unregisterSuperProperty:property]; + }); +} +- (void)innerClearSuperProperties { + if ([self hasDisabled]) { + return; + } + dispatch_async(td_trackQueue, ^{ + [self.superProperty clearSuperProperties]; + }); +} +- (NSDictionary *)innerCurrentSuperProperties { + return [self.superProperty currentSuperProperties]; +} + +- (void)innerRegisterDynamicSuperProperties:(NSDictionary *(^)(void))dynamicSuperProperties { + if ([self hasDisabled]) { + return; + } + if (!dynamicSuperProperties) { + TDLogError(@"Ignoring empty"); + return; + } + @synchronized (self.superProperty) { + [self.superProperty registerDynamicSuperProperties:dynamicSuperProperties]; + } +} + +- (TDPresetProperties *)innerGetPresetProperties { + NSMutableDictionary *presetDic = [NSMutableDictionary dictionary]; + + NSDictionary *pluginProperties = [self.propertyPluginManager currentPropertiesForPluginClasses:@[TDPresetPropertyPlugin.class]]; + [presetDic addEntriesFromDictionary:pluginProperties]; + + NSDateFormatter *timeFormatter = [[NSDateFormatter alloc] init]; + timeFormatter.dateFormat = kDefaultTimeFormat; + timeFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]; + timeFormatter.calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; + timeFormatter.timeZone = self.config.defaultTimeZone; + presetDic = [TDJSONUtil formatDateWithFormatter:timeFormatter dict:presetDic]; + + return [[TDPresetProperties alloc] initWithDictionary:presetDic]; +} + +//MARK: - SDK error callback + +- (void)innerRegisterErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback { + self.errorCallback = errorCallback; +} + +//MARK: - + +- (BOOL)innerIsViewTypeIgnored:(Class)aClass { + return [self.ignoredViewTypeList containsObject:aClass]; +} + +- (void)autoFlushWithTimer:(NSTimer *)timer { + if ([self hasDisabled] || self.isTrackPause) { + return; + } + [self.eventTracker flush]; +} + +- (void)innerFlush { + if ([self hasDisabled] || self.isTrackPause) { + return; + } + TDLogInfo(@"flush success. By manual."); + [self.eventTracker flush]; +} + +- (void)innerSetNetworkType:(TDReportingNetworkType)type { + if ([self hasDisabled]) { + return; + } + self.config.reportingNetworkType = type; +} + +- (void)innerSetTrackStatus: (TDTrackStatus)status { + switch (status) { + case TDTrackStatusPause: { + TDLogInfo(@"Change status to Pause") + self.isEnabled = NO; + dispatch_async(td_trackQueue, ^{ + [self.file archiveIsEnabled:NO]; + }); + break; + } + case TDTrackStatusStop: { + TDLogInfo(@"Change status to Stop") + [self doOptOutTracking]; + break; + } + case TDTrackStatusSaveOnly: { + TDLogInfo(@"Change status to SaveOnly") + self.trackPause = YES; + self.isEnabled = YES; + self.isOptOut = NO; + dispatch_async(td_trackQueue, ^{ + [self.file archiveTrackPause:YES]; + [self.file archiveIsEnabled:YES]; + [self.file archiveOptOut:NO]; + }); + break; + } + case TDTrackStatusNormal: { + TDLogInfo(@"Change status to Normal") + self.trackPause = NO; + self.isEnabled = YES; + self.isOptOut = NO; + dispatch_async(td_trackQueue, ^{ + [self.file archiveTrackPause:NO]; + [self.file archiveIsEnabled:self.isEnabled]; + [self.file archiveOptOut:NO]; + }); + [self innerFlush]; + break; + } + default: + break; + } +} + +- (NSString *)innetGetTimeString:(NSDate *)date { + return [date td_formatWithTimeZone:self.config.defaultTimeZone formatString:kDefaultTimeFormat]; +} + +@end diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.m.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.m.meta new file mode 100644 index 0000000..bae4200 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDK.m.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: b5b9d9a9bb04b48a7958705ab2237622 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDKPrivate.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDKPrivate.h new file mode 100644 index 0000000..c312e4e --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDKPrivate.h @@ -0,0 +1,152 @@ +#if __has_include() +#import +#else +#import "ThinkingAnalyticsSDK.h" +#endif + +#import +#import +#import +#import +#import + +#if TARGET_OS_IOS +#import "ThinkingExceptionHandler.h" +#import "TDAutoTrackEvent.h" +#import "TDAutoTrackSuperProperty.h" +#import "TDEncrypt.h" +#else +#import "TDAutoTrackConst.h" +#endif + +#import "TDLogging.h" +#import "TDDeviceInfo.h" +#import "TDCommonUtil.h" +#import "TDConfig.h" +#import "TDSqliteDataQueue.h" +#import "TDEventModel.h" + +#import "TDTrackTimer.h" +#import "TDSuperProperty.h" +#import "TDTrackEvent.h" +#import "TDTrackFirstEvent.h" +#import "TDTrackOverwriteEvent.h" +#import "TDTrackUpdateEvent.h" +#import "TDUserPropertyHeader.h" +#import "TDPropertyPluginManager.h" +#import "TDPresetPropertyPlugin.h" +#import "TDBaseEvent+H5.h" +#import "TDEventTracker.h" +#import "TDAppLifeCycle.h" + +#if __has_include() +#import +#else +#import "NSDate+TDCore.h" +#endif + +NS_ASSUME_NONNULL_BEGIN + +#ifndef td_dispatch_main_sync_safe +#define td_dispatch_main_sync_safe(block)\ +if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {\ +block();\ +} else {\ +dispatch_sync(dispatch_get_main_queue(), block);\ +} +#endif + +#define kDefaultTimeFormat @"yyyy-MM-dd HH:mm:ss.SSS" + +@interface ThinkingAnalyticsSDK () + +@property (atomic, copy, nullable) NSString *accountId; +@property (atomic, copy) NSString *identifyId; +/// TD error callback +@property (atomic, copy) void(^errorCallback)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext); +@property (atomic, assign, getter=isTrackPause) BOOL trackPause; +@property (atomic, assign) BOOL isEnabled; +@property (nonatomic, strong) TDConfig *config; +@property (atomic, strong) NSMutableSet *ignoredViewControllers; +@property (atomic, strong) NSMutableSet *ignoredViewTypeList; + +#if TARGET_OS_IOS +@property (nonatomic, strong) TDAutoTrackSuperProperty *autoTrackSuperProperty; +@property (nonatomic, strong) TDEncryptManager *encryptManager; +- (void)autoTrackWithEvent:(TDAutoTrackEvent *)event properties:(nullable NSDictionary *)properties; +- (BOOL)isViewControllerIgnored:(UIViewController *)viewController; +#endif + + ++ (dispatch_queue_t)sharedTrackQueue; ++ (dispatch_queue_t)sharedNetworkQueue; + +// TAThirdParty model used. +- (NSString *)getAccountId; +- (BOOL)hasDisabled; ++ (BOOL)isTrackEvent:(NSString *)eventType; +- (void)startFlushTimer; ++ (NSMutableDictionary *)_getAllInstances; ++ (NSString *)defaultAppId; +- (void)asyncTrackEventObject:(TDTrackEvent *)event properties:(NSDictionary * _Nullable)properties isH5:(BOOL)isH5; +- (void)asyncUserEventObject:(TDUserEvent *)event properties:(NSDictionary * _Nullable)properties isH5:(BOOL)isH5; + +- (instancetype)initWithConfig:(TDConfig *)config; +- (instancetype)initLight:(NSString *)appid withServerURL:(NSString *)serverURL withConfig:(TDConfig *)config; + ++ (nullable ThinkingAnalyticsSDK *)defaultInstance; ++ (nullable ThinkingAnalyticsSDK *)instanceWithAppid:(NSString *)appid; + +- (void)innerTrack:(NSString *)event; +- (void)innerTrack:(NSString *)event properties:(NSDictionary * _Nullable)propertieDict; +- (void)innerTrack:(NSString *)event properties:(NSDictionary * _Nullable)propertieDict time:(NSDate * _Nullable)time timeZone:(NSTimeZone * _Nullable)timeZone; +- (void)innerTrackWithEventModel:(TDEventModel *)eventModel; +- (void)innerTrackDebug:(NSString *)event properties:(NSDictionary * _Nullable)propertieDict; +- (void)innerTimeEvent:(NSString *)event; +- (NSString *)innerAccountId; +- (NSString *)innerDistinctId; +- (void)innerSetIdentify:(NSString *)distinctId; +- (void)innerLogin:(NSString *)accountId; +- (void)innerLogout; +- (void)innerUserSet:(NSDictionary *)properties; +- (void)innerUserUnset:(NSString *)propertyName; +- (void)innerUserUnsets:(NSArray *)propertyNames; +- (void)innerUserSetOnce:(NSDictionary *)properties; +- (void)innerUserAdd:(NSDictionary *)properties; +- (void)innerUserAdd:(NSString *)propertyName andPropertyValue:(NSNumber *)propertyValue; +- (void)innerUserDelete; +- (void)innerUserAppend:(NSDictionary *)properties; +- (void)innerUserUniqAppend:(NSDictionary *)properties; + +- (void)innerSetSuperProperties:(NSDictionary *)properties; +- (void)innerUnsetSuperProperty:(NSString *)property; +- (void)innerClearSuperProperties; +- (NSDictionary *)innerCurrentSuperProperties; +- (void)innerRegisterDynamicSuperProperties:(NSDictionary *(^)(void))dynamicSuperProperties; +- (void)innerRegisterErrorCallback:(void(^)(NSInteger code, NSString * _Nullable errorMsg, NSString * _Nullable ext))errorCallback; +- (TDPresetProperties *)innerGetPresetProperties; +- (void)innerSetNetworkType:(TDReportingNetworkType)type; + +- (BOOL)innerIsViewTypeIgnored:(Class)aClass; + +- (void)innerFlush; +- (void)innerSetTrackStatus:(TDTrackStatus)status; +- (ThinkingAnalyticsSDK *)innerCreateLightInstance; +- (NSString *)innetGetTimeString:(NSDate *)date; +- (NSString *)instanceAliasNameOrAppId; +@end + +@interface TDEventModel () +@property (nonatomic, copy) NSString *extraID; +@property (nonatomic, strong) NSDate *time; +@property (nonatomic, strong) NSTimeZone *timeZone; +- (instancetype _Nonnull )initWithEventName:(NSString * _Nullable)eventName eventType:(kEDEventTypeName _Nonnull )eventType; +@end + +@interface LightThinkingAnalyticsSDK : ThinkingAnalyticsSDK + +- (instancetype)initWithAPPID:(NSString *)appID withServerURL:(NSString *)serverURL withConfig:(TDConfig *)config; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDKPrivate.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDKPrivate.h.meta new file mode 100644 index 0000000..41a7507 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingAnalyticsSDKPrivate.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 1b247f06bcd1a43b5b044a21027ec051 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingSDK.h b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingSDK.h new file mode 100644 index 0000000..ca7b353 --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingSDK.h @@ -0,0 +1,68 @@ + +#import + +#if __has_include() +#import +#else +#import "ThinkingAnalyticsSDK.h" +#endif + +#if __has_include() +#import +#else +#import "TDFirstEventModel.h" +#endif + +#if __has_include() +#import +#else +#import "TDEditableEventModel.h" +#endif + +#if __has_include() +#import +#else +#import "TDConfig.h" +#endif + +#if __has_include() +#import +#else +#import "TDPresetProperties.h" +#endif + +#if __has_include() +#import +#else +#import "TDDeviceInfo.h" +#endif + +#if __has_include() +#import +#else +#import "TDAnalytics+Public.h" +#endif + +#if __has_include() +#import +#else +#import "TDAnalytics+Multiple.h" +#endif + +#if __has_include() +#import +#else +#import "TDAnalytics+WebView.h" +#endif + +#if __has_include() +#import +#else +#import "TDAnalytics+ThirdParty.h" +#endif + +#if __has_include() +#import +#else +#import "ThinkingAnalyticsSDK+OldPublic.h" +#endif diff --git a/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingSDK.h.meta b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingSDK.h.meta new file mode 100644 index 0000000..44a1c4b --- /dev/null +++ b/Assets/Plugins/iOS/ThinkingSDK/Source/main/ThinkingSDK.h.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: 8e46d5322f9ed4eb6902a67f0c199583 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a b/Assets/Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a new file mode 100644 index 0000000..e4aaaa7 Binary files /dev/null and b/Assets/Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a differ diff --git a/Assets/Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a.meta b/Assets/Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a.meta new file mode 100644 index 0000000..bd6a80c --- /dev/null +++ b/Assets/Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: b78f32d3909244bc819df359420806fb +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a +timeCreated: 1480838400 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 0 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 0 + settings: + CPU: None + Linux64: + enabled: 0 + settings: + CPU: None + LinuxUniversal: + enabled: 0 + settings: + CPU: None + OSXIntel: + enabled: 0 + settings: + CPU: None + OSXIntel64: + enabled: 0 + settings: + CPU: None + OSXUniversal: + enabled: 0 + settings: + CPU: None + Web: + enabled: 0 + settings: {} + WebStreamed: + enabled: 0 + settings: {} + Win: + enabled: 0 + settings: + CPU: None + Win64: + enabled: 0 + settings: + CPU: None + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + iOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + tvOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample.meta b/Assets/Sample.meta new file mode 100644 index 0000000..f4b4128 --- /dev/null +++ b/Assets/Sample.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d6e178afec714cd393bf6735910293d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/Assets.meta b/Assets/Sample/Assets.meta new file mode 100644 index 0000000..554efb8 --- /dev/null +++ b/Assets/Sample/Assets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b29c81236c1a545488a2ac4eb6d5f598 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/Assets/button.png b/Assets/Sample/Assets/button.png new file mode 100644 index 0000000..0cdf516 Binary files /dev/null and b/Assets/Sample/Assets/button.png differ diff --git a/Assets/Sample/Assets/button.png.meta b/Assets/Sample/Assets/button.png.meta new file mode 100644 index 0000000..eafaa7c --- /dev/null +++ b/Assets/Sample/Assets/button.png.meta @@ -0,0 +1,123 @@ +fileFormatVersion: 2 +guid: a57a02d0faa91492bb9147668fed8c00 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 1024 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 3, y: 5, z: 6, w: 6} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: 4 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/Assets/button_down.png b/Assets/Sample/Assets/button_down.png new file mode 100644 index 0000000..f5cd005 Binary files /dev/null and b/Assets/Sample/Assets/button_down.png differ diff --git a/Assets/Sample/Assets/button_down.png.meta b/Assets/Sample/Assets/button_down.png.meta new file mode 100644 index 0000000..5712fdb --- /dev/null +++ b/Assets/Sample/Assets/button_down.png.meta @@ -0,0 +1,123 @@ +fileFormatVersion: 2 +guid: 937c96556f7574eaaa1751e2092f0b63 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 1024 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: 4 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/Assets/button_hover.png b/Assets/Sample/Assets/button_hover.png new file mode 100644 index 0000000..751844f Binary files /dev/null and b/Assets/Sample/Assets/button_hover.png differ diff --git a/Assets/Sample/Assets/button_hover.png.meta b/Assets/Sample/Assets/button_hover.png.meta new file mode 100644 index 0000000..08f2dbd --- /dev/null +++ b/Assets/Sample/Assets/button_hover.png.meta @@ -0,0 +1,123 @@ +fileFormatVersion: 2 +guid: aac4f7023d2ef4295ac6071b8e1d8853 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 1 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 1024 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: 4 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/Assets/td_logo.png b/Assets/Sample/Assets/td_logo.png new file mode 100644 index 0000000..03b5dc2 Binary files /dev/null and b/Assets/Sample/Assets/td_logo.png differ diff --git a/Assets/Sample/Assets/td_logo.png.meta b/Assets/Sample/Assets/td_logo.png.meta new file mode 100644 index 0000000..7e27c84 --- /dev/null +++ b/Assets/Sample/Assets/td_logo.png.meta @@ -0,0 +1,123 @@ +fileFormatVersion: 2 +guid: 1c8be89e83f14479081250d0c4806b85 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 10 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 1024 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: 1 + mipBias: -100 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: iPhone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: 4 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 0 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: ae3eea2b77eaa4081a2c018523da8fc8 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/Assets/td_skin.guiskin b/Assets/Sample/Assets/td_skin.guiskin new file mode 100644 index 0000000..2b9def7 --- /dev/null +++ b/Assets/Sample/Assets/td_skin.guiskin @@ -0,0 +1,1428 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12001, guid: 0000000000000000e000000000000000, type: 0} + m_Name: td_skin + m_EditorClassIdentifier: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_box: + m_Name: box + m_Normal: + m_Background: {fileID: 11001, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.79999995, g: 0.79999995, b: 0.79999995, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_button: + m_Name: button + m_Normal: + m_Background: {fileID: 2800000, guid: a57a02d0faa91492bb9147668fed8c00, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9, g: 0.9, b: 0.9, a: 1} + m_Hover: + m_Background: {fileID: 2800000, guid: aac4f7023d2ef4295ac6071b8e1d8853, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 2800000, guid: 937c96556f7574eaaa1751e2092f0b63, type: 3} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9, g: 0.9, b: 0.9, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 11005, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9019608, g: 0.9019608, b: 0.9019608, a: 1} + m_OnHover: + m_Background: {fileID: 11004, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 11002, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9, g: 0.9, b: 0.9, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 24 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 28 + m_FontStyle: 0 + m_Alignment: 4 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 80 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_toggle: + m_Name: toggle + m_Normal: + m_Background: {fileID: 11018, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.89112896, g: 0.89112896, b: 0.89112896, a: 1} + m_Hover: + m_Background: {fileID: 11014, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Active: + m_Background: {fileID: 11013, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 11016, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.8901961, g: 0.8901961, b: 0.8901961, a: 1} + m_OnHover: + m_Background: {fileID: 11015, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnActive: + m_Background: {fileID: 11017, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 14 + m_Right: 0 + m_Top: 14 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 15 + m_Right: 0 + m_Top: 3 + m_Bottom: 0 + m_Overflow: + m_Left: -1 + m_Right: 0 + m_Top: -4 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_label: + m_Name: label + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9, g: 0.9, b: 0.9, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 3 + m_Bottom: 3 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 1 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_textField: + m_Name: textfield + m_Normal: + m_Background: {fileID: 11024, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.79999995, g: 0.79999995, b: 0.79999995, a: 1} + m_Hover: + m_Background: {fileID: 11026, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9, g: 0.9, b: 0.9, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 11026, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnNormal: + m_Background: {fileID: 11025, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 3 + m_Right: 3 + m_Top: 3 + m_Bottom: 3 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 3 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_textArea: + m_Name: textarea + m_Normal: + m_Background: {fileID: 11024, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.9019608, g: 0.9019608, b: 0.9019608, a: 1} + m_Hover: + m_Background: {fileID: 11026, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0.79999995, g: 0.79999995, b: 0.79999995, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 11025, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 3 + m_Right: 3 + m_Top: 3 + m_Bottom: 3 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 1 + m_RichText: 0 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_window: + m_Name: window + m_Normal: + m_Background: {fileID: 11023, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 11022, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 1, g: 1, b: 1, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 8 + m_Right: 8 + m_Top: 18 + m_Bottom: 8 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 10 + m_Right: 10 + m_Top: 20 + m_Bottom: 10 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 1 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: -18} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalSlider: + m_Name: horizontalslider + m_Normal: + m_Background: {fileID: 11009, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 3 + m_Right: 3 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: -1 + m_Right: -1 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: -2 + m_Bottom: -3 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 12 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalSliderThumb: + m_Name: horizontalsliderthumb + m_Normal: + m_Background: {fileID: 11011, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 11012, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 11010, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 4 + m_Right: 4 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 7 + m_Right: 7 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: -1 + m_Right: -1 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 12 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalSlider: + m_Name: verticalslider + m_Normal: + m_Background: {fileID: 11021, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 3 + m_Bottom: 3 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: -1 + m_Bottom: -1 + m_Overflow: + m_Left: -2 + m_Right: -3 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 12 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 1 + m_verticalSliderThumb: + m_Name: verticalsliderthumb + m_Normal: + m_Background: {fileID: 11011, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 11012, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 11010, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 7 + m_Bottom: 7 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: -1 + m_Bottom: -1 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 12 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 1 + m_horizontalScrollbar: + m_Name: horizontalscrollbar + m_Normal: + m_Background: {fileID: 11008, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 9 + m_Right: 9 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 4 + m_Right: 4 + m_Top: 1 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 15 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalScrollbarThumb: + m_Name: horizontalscrollbarthumb + m_Normal: + m_Background: {fileID: 11007, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 6 + m_Right: 6 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: -1 + m_Bottom: 1 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 13 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalScrollbarLeftButton: + m_Name: horizontalscrollbarleftbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_horizontalScrollbarRightButton: + m_Name: horizontalscrollbarrightbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalScrollbar: + m_Name: verticalscrollbar + m_Normal: + m_Background: {fileID: 11020, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 9 + m_Bottom: 9 + m_Margin: + m_Left: 1 + m_Right: 4 + m_Top: 4 + m_Bottom: 4 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 1 + m_Bottom: 1 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 15 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalScrollbarThumb: + m_Name: verticalscrollbarthumb + m_Normal: + m_Background: {fileID: 11019, guid: 0000000000000000e000000000000000, type: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 6 + m_Right: 6 + m_Top: 6 + m_Bottom: 6 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 6 + m_Bottom: 6 + m_Overflow: + m_Left: -1 + m_Right: -1 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 2 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 15 + m_FixedHeight: 0 + m_StretchWidth: 0 + m_StretchHeight: 1 + m_verticalScrollbarUpButton: + m_Name: verticalscrollbarupbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_verticalScrollbarDownButton: + m_Name: verticalscrollbardownbutton + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_ScrollView: + m_Name: scrollview + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 1 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_CustomStyles: + - m_Name: + m_Normal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Hover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Active: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Focused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnNormal: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnHover: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnActive: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_OnFocused: + m_Background: {fileID: 0} + m_ScaledBackgrounds: [] + m_TextColor: {r: 0, g: 0, b: 0, a: 1} + m_Border: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Margin: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Overflow: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_Font: {fileID: 0} + m_FontSize: 0 + m_FontStyle: 0 + m_Alignment: 0 + m_WordWrap: 0 + m_RichText: 1 + m_TextClipping: 0 + m_ImagePosition: 0 + m_ContentOffset: {x: 0, y: 0} + m_FixedWidth: 0 + m_FixedHeight: 0 + m_StretchWidth: 1 + m_StretchHeight: 0 + m_Settings: + m_DoubleClickSelectsWord: 1 + m_TripleClickSelectsLine: 1 + m_CursorColor: {r: 1, g: 1, b: 1, a: 1} + m_CursorFlashSpeed: -1 + m_SelectionColor: {r: 1, g: 0.38403907, b: 0, a: 0.7} diff --git a/Assets/Sample/Assets/td_skin.guiskin.meta b/Assets/Sample/Assets/td_skin.guiskin.meta new file mode 100644 index 0000000..c4fb420 --- /dev/null +++ b/Assets/Sample/Assets/td_skin.guiskin.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 48b9be70902884a76ba1b53926fd3e37 +NativeFormatImporter: + userData: diff --git a/Assets/Sample/OtherScene.cs b/Assets/Sample/OtherScene.cs new file mode 100644 index 0000000..8710fb7 --- /dev/null +++ b/Assets/Sample/OtherScene.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; +using ThinkingData.Analytics; + +public class OtherScene : MonoBehaviour +{ + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } + + void OnGUI() + { + if (GUI.Button(new Rect(20, 40, 300, 50), "Back To TDAnalyticsDemo")) + { + SceneManager.LoadScene("TDAnalyticsDemo", LoadSceneMode.Single); + } + if (GUI.Button(new Rect(20*2+300, 40, 300, 50), "TrackEvent")) + { + TDAnalytics.Track("TA", new Dictionary() { { "other_scene", "OtherScene" } }); + } + } +} diff --git a/Assets/Sample/OtherScene.cs.meta b/Assets/Sample/OtherScene.cs.meta new file mode 100644 index 0000000..12f3f26 --- /dev/null +++ b/Assets/Sample/OtherScene.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 157108d09ae574dedb267eedc3438757 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/OtherScene.unity b/Assets/Sample/OtherScene.unity new file mode 100644 index 0000000..c8a7683 --- /dev/null +++ b/Assets/Sample/OtherScene.unity @@ -0,0 +1,316 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 0 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0.18018606, g: 0.22559257, b: 0.30678663, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 2 + m_BakeResolution: 40 + m_AtlasSize: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 256 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 1 + m_PVRDenoiserTypeDirect: 1 + m_PVRDenoiserTypeIndirect: 1 + m_PVRDenoiserTypeAO: 1 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 0} +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &1123045975 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1123045978} + - component: {fileID: 1123045977} + - component: {fileID: 1123045976} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1123045976 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1123045975} + m_Enabled: 0 +--- !u!20 &1123045977 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1123045975} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.0039215684, g: 0.3612774, b: 1, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &1123045978 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1123045975} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1248963544 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1248963546} + - component: {fileID: 1248963545} + - component: {fileID: 1248963547} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1248963545 +Light: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1248963544} + m_Enabled: 1 + serializedVersion: 10 + m_Type: 1 + m_Shape: 0 + m_Color: {r: 0.003921569, g: 0.28235295, b: 1, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_InnerSpotAngle: 21.80208 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_CullingMatrixOverride: + e00: 1 + e01: 0 + e02: 0 + e03: 0 + e10: 0 + e11: 1 + e12: 0 + e13: 0 + e20: 0 + e21: 0 + e22: 1 + e23: 0 + e30: 0 + e31: 0 + e32: 0 + e33: 1 + m_UseCullingMatrixOverride: 0 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingLayerMask: 1 + m_Lightmapping: 4 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} + m_UseBoundingSphereOverride: 0 + m_UseViewFrustumForShadowCasterCull: 1 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1248963546 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1248963544} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!114 &1248963547 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1248963544} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 157108d09ae574dedb267eedc3438757, type: 3} + m_Name: + m_EditorClassIdentifier: diff --git a/Assets/Sample/OtherScene.unity.meta b/Assets/Sample/OtherScene.unity.meta new file mode 100644 index 0000000..a39b6ff --- /dev/null +++ b/Assets/Sample/OtherScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 667cb3338b0414099b222ac71a908e8e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/TAExample.cs b/Assets/Sample/TAExample.cs new file mode 100644 index 0000000..cd2827a --- /dev/null +++ b/Assets/Sample/TAExample.cs @@ -0,0 +1,384 @@ +using UnityEngine; +using UnityEngine.SceneManagement; +using ThinkingAnalytics; +using System.Collections.Generic; +using System; + +public class TAExample : MonoBehaviour, IDynamicSuperProperties, IAutoTrackEventCallback +{ + + + public GUISkin skin; + private Vector2 scrollPosition = Vector2.zero; + //private static Color MainColor = new Color(0, 0,0); + private static Color MainColor = new Color(84f / 255, 116f / 255, 241f / 255); + private static Color TextColor = new Color(153f / 255, 153f / 255, 153f / 255); + static int Margin = 20; + static int Height = 60; + static float ContainerWidth = Screen.width - 2 * Margin; + // dynamic super properties interface implementation + public Dictionary GetDynamicSuperProperties() + { + return new Dictionary() + { + {"dynamic_property", DateTime.Now} + }; + } + // auto-tracking events interface implementation + public Dictionary AutoTrackEventCallback(int type, Dictionaryproperties) + { + return new Dictionary() + { + {"auto_track_dynamic", DateTime.Today} + }; + } + + private void Awake() + { + } + private void Start() + { + // When automatically initializing ThinkingAnalytics, you can call EnableAutoTrack() in Start() to enable auto-tracking events + // enable auto-tracking events + // ThinkingAnalyticsAPI.EnableAutoTrack(AUTO_TRACK_EVENTS.ALL); + } + + void OnGUI() + { + GUILayout.BeginArea(new Rect(Margin, Screen.height * 0.15f, Screen.width-2*Margin, Screen.height)); + scrollPosition = GUILayout.BeginScrollView(new Vector2(0, 0), GUILayout.Width(Screen.width - 2 * Margin), GUILayout.Height(Screen.height - 100)); + GUIStyle style = GUI.skin.label; + style.fontSize = 25; + GUILayout.Label("Initialization / UserIDSetting",style); + + GUIStyle buttonStyle = GUI.skin.button; + buttonStyle.fontSize = 20; + GUILayout.BeginHorizontal(GUI.skin.box,GUILayout.Height(Height)); + if (GUILayout.Button("ManualInitialization", GUILayout.Height(Height))) + { + // 1. Manual initialization (ThinkingAnalytics prefab loaded) + // ThinkingAnalyticsAPI.StartThinkingAnalytics(); + + + // 2. Manual initialization (dynamically loading ThinkingAnalyticsAPI script) + new GameObject("ThinkingAnalytics", typeof(ThinkingAnalyticsAPI)); + + // 2.1 Set instance parameters + string appId = "22e445595b0f42bd8c5fe35bc44b88d6"; + string serverUrl = "https://receiver-ta-dev.thinkingdata.cn"; + ThinkingAnalyticsAPI.StartThinkingAnalytics(appId, serverUrl); + + // 2.1 Set personalized instance parameters + // string appId = "22e445595b0f42bd8c5fe35bc44b88d6"; + // string serverUrl = "https://receiver-ta-dev.thinkingdata.cn"; + // ThinkingAnalyticsAPI.TAMode mode = ThinkingAnalyticsAPI.TAMode.NORMAL; + // ThinkingAnalyticsAPI.TATimeZone timeZone = ThinkingAnalyticsAPI.TATimeZone.Local; + // ThinkingAnalyticsAPI.Token token = new ThinkingAnalyticsAPI.Token(appId, serverUrl, mode, timeZone); + // Enable encrypted transmission (only iOS/Android) + // token.enableEncrypt = true; + // token.encryptVersion = 0; + // token.encryptPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIPi6aHymT1jdETRci6f1ck535n13IX3p9XNLFu5xncfzNFl6kFVMiMSXMIwWSW2lF6ELtIlDJ0B00qE9C02n6YbIAV+VvVkchydbWrm8VdnEJk/6tIydoUxGyM9pDT6U/PaoEiItl/BawDj3/+KW6U7AejYPij9uTQ4H3bQqj1wIDAQAB"; + // ThinkingAnalyticsAPI.StartThinkingAnalytics(token); + + // 2.2 Multi-project support + // string appId_2 = "1b1c1fef65e3482bad5c9d0e6a823356"; + // string serverUrl_2 = "https://receiver-ta-dev.thinkingdata.cn"; + // ThinkingAnalyticsAPI.TAMode mode_2 = ThinkingAnalyticsAPI.TAMode.NORMAL; + // ThinkingAnalyticsAPI.TATimeZone timeZone_2 = ThinkingAnalyticsAPI.TATimeZone.Local; + // ThinkingAnalyticsAPI.Token token_2 = new ThinkingAnalyticsAPI.Token(appId_2, serverUrl_2, mode_2, timeZone_2); + + // ThinkingAnalyticsAPI.Token[] tokens = new ThinkingAnalyticsAPI.Token[2]; + // tokens[0] = token; + // tokens[1] = token_2; + // ThinkingAnalyticsAPI.StartThinkingAnalytics(tokens); + + // Multi-item track events + // ThinkingAnalyticsAPI.Track("test_event"); + // ThinkingAnalyticsAPI.Track("test_event_2", appId:appId_2); + + + // Enable auto-tracking events + // ThinkingAnalyticsAPI.EnableAutoTrack(AUTO_TRACK_EVENTS.ALL); + // Enable auto-tracking events, and set properties + // ThinkingAnalyticsAPI.SetAutoTrackProperties(AUTO_TRACK_EVENTS.ALL, new Dictionary() + // { + // {"auto_track_static_1", "value_1"} + // }); + // ThinkingAnalyticsAPI.EnableAutoTrack(AUTO_TRACK_EVENTS.ALL, new Dictionary() + // { + // {"auto_track_static_2", "value_2"} + // }); + // Enable auto-tracking events, and set callback + // ThinkingAnalyticsAPI.EnableAutoTrack(AUTO_TRACK_EVENTS.ALL, this); + } + GUILayout.Space(20); + if (GUILayout.Button("SetAccountID", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.Login("TA"); + } + GUILayout.Space(20); + if (GUILayout.Button("SetDistinctID", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.Identify("TA_DistinctID"); + Debug.Log("DistinctID: " + ThinkingAnalyticsAPI.GetDistinctId()); + } + GUILayout.Space(20); + if (GUILayout.Button("ClearAccountID", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.Logout(); + } + GUILayout.EndHorizontal(); + + GUILayout.Space(20); + GUILayout.Label("EventTracking", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("TrackEvent", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary(); + properties["channel"] = "ta";//string + properties["age"] = 1;//number - int + properties["weight"] = 5.46;//number - float + properties["balance"] = -0.4;//number - negative + properties["isVip"] = true;//bool + properties["birthday"] = new DateTime(2022,01,01);//date + properties["object"] = new Dictionary() { { "key", "value" } };//object + properties["object_arr"] = new List() { new Dictionary() { { "key", "value" } } };//object array + properties["arr"] = new List() { "value" };//array + + ThinkingAnalyticsAPI.Track("TA", properties); + } + GUILayout.Space(20); + if (GUILayout.Button("TrackFirstEvent", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary(); + properties["status"] = 1; + TDFirstEvent firstEvent = new TDFirstEvent("DEVICE_FIRST", properties); + ThinkingAnalyticsAPI.Track(firstEvent); + } + GUILayout.Space(20); + if (GUILayout.Button("TrackUpdateEvent", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary(); + properties["status"] = 2; + TDUpdatableEvent updatableEvent = new TDUpdatableEvent("UPDATABLE_EVENT", properties, "test_event_id"); + updatableEvent.EventTime = DateTime.Now; + updatableEvent.EventTimeZone = TimeZoneInfo.Local; + ThinkingAnalyticsAPI.Track(updatableEvent); + } + + GUILayout.Space(20); + if (GUILayout.Button("TrackOverwriteEvent", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary(); + properties["status"] = 3; + TDOverWritableEvent overWritableEvent = new TDOverWritableEvent("OVERWRITABLE_EVENT", properties, "test_event_id"); + overWritableEvent.EventTime = DateTime.Now; + overWritableEvent.EventTimeZone = TimeZoneInfo.Utc; + ThinkingAnalyticsAPI.Track(overWritableEvent); + } + + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("TimeEvent", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.TimeEvent("TATimeEvent"); + } + + GUILayout.Space(20); + if (GUILayout.Button("Track-TimeEvent", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.Track("TATimeEvent"); + } + + GUILayout.Space(20); + if (GUILayout.Button("TrackEventWithDate", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary(); + ThinkingAnalyticsAPI.Track("TA_Utc", properties, DateTime.Now.AddDays(1), TimeZoneInfo.Utc); + ThinkingAnalyticsAPI.Track("TA_Local", properties, DateTime.Now.AddDays(1), TimeZoneInfo.Local); + } + + GUILayout.Space(20); + if (GUILayout.Button("TrackEventWithLightInstance", GUILayout.Height(Height))) + { + string lightToken = ThinkingAnalyticsAPI.CreateLightInstance(); + ThinkingAnalyticsAPI.Login("light_account", lightToken); + ThinkingAnalyticsAPI.Track("light_event", lightToken); + } + GUILayout.EndHorizontal(); + + + + + GUILayout.Space(20); + GUILayout.Label("UserProperty", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("UserSet", GUILayout.Height(Height))) + { + Dictionary userProperties = new Dictionary(); + userProperties["age"] = 1; + ThinkingAnalyticsAPI.UserSet(userProperties); + } + + GUILayout.Space(20); + if (GUILayout.Button("UserSetOnce", GUILayout.Height(Height))) + { + Dictionary userProperties = new Dictionary(); + userProperties["gender"] = 1; + ThinkingAnalyticsAPI.UserSetOnce(userProperties); + + } + GUILayout.Space(20); + if (GUILayout.Button("UserAdd", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.UserAdd("usercoin", 1); + } + GUILayout.Space(20); + if (GUILayout.Button("UserUnset", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.UserUnset("usercoin"); + } + GUILayout.Space(20); + if (GUILayout.Button("UserDelete", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.UserDelete(); + } + GUILayout.Space(20); + if (GUILayout.Button("UserAppend", GUILayout.Height(Height))) + { + List propList = new List(); + propList.Add("ball"); + Dictionary userProperties = new Dictionary(); + userProperties["prop"] = propList; + ThinkingAnalyticsAPI.UserAppend(userProperties); + } + GUILayout.Space(20); + if (GUILayout.Button("UserUniqAppend", GUILayout.Height(Height))) + { + List propList = new List(); + propList.Add("apple"); + Dictionary userProperties = new Dictionary(); + userProperties["prop"] = propList; + ThinkingAnalyticsAPI.UserUniqAppend(userProperties); + } + GUILayout.EndHorizontal(); + + + + GUILayout.Space(20); + GUILayout.Label("OtherSetting", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("Flush", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.Flush(); + } + GUILayout.Space(20); + if (GUILayout.Button("GetDeviceID", GUILayout.Height(Height))) + { + Debug.Log("DeviceID: " + ThinkingAnalyticsAPI.GetDeviceId()); + } + GUILayout.Space(20); + if (GUILayout.Button("Pause", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.SetTrackStatus(TA_TRACK_STATUS.PAUSE); + } + GUILayout.Space(20); + if (GUILayout.Button("Stop", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.SetTrackStatus(TA_TRACK_STATUS.STOP); + } + GUILayout.Space(20); + if (GUILayout.Button("SaveOnly", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.SetTrackStatus(TA_TRACK_STATUS.SAVE_ONLY); + } + GUILayout.Space(20); + if (GUILayout.Button("Normal", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.SetTrackStatus(TA_TRACK_STATUS.NORMAL); + } + GUILayout.Space(20); + if (GUILayout.Button("CalibrateTime", GUILayout.Height(Height))) + { + //currnt Unix timestamp, units Ms, e.g: 1608782412000 -> 2020-12-24 12:00:12 + ThinkingAnalyticsAPI.CalibrateTime(1608782412000); + + //NTP server, e.g: time.apple.com + ThinkingAnalyticsAPI.CalibrateTimeWithNtp("time.apple.com"); + //ThinkingAnalyticsAPI.CalibrateTimeWithNtp("time1.google.com"); + } + GUILayout.EndHorizontal(); + + GUILayout.Space(20); + GUILayout.Label("PropertiesSetting", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("SetSuperProperties", GUILayout.Height(Height))) + { + Dictionary superProperties = new Dictionary(); + superProperties["VipLevel"] = 1; + superProperties["VipTitle"] = "Supreme King"; + ThinkingAnalyticsAPI.SetSuperProperties(superProperties); + } + GUILayout.Space(20); + if (GUILayout.Button("UpdateSuperProperties", GUILayout.Height(Height))) + { + Dictionary superProperties = new Dictionary(); + superProperties["VipLevel"] = 2; + ThinkingAnalyticsAPI.SetSuperProperties(superProperties); + } + + GUILayout.Space(20); + if (GUILayout.Button("ClearSuperProperties", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.UnsetSuperProperty("VipLevel"); + } + + GUILayout.Space(20); + if (GUILayout.Button("ClearAllSuperProperties", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.ClearSuperProperties(); + } + + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("SetDynamicSuperProperties", GUILayout.Height(Height))) + { + ThinkingAnalyticsAPI.SetDynamicSuperProperties(this); + } + + GUILayout.Space(20); + if (GUILayout.Button("GetSuperProperties", GUILayout.Height(Height))) + { + Dictionary eventSuperProperties = ThinkingAnalyticsAPI.GetSuperProperties(); + string propertiesStr = " "; + foreach (KeyValuePair kv in eventSuperProperties) + { + propertiesStr = propertiesStr + kv.Key + " = " + kv.Value + "\n "; + } + Debug.Log("SuperProperties: \n" + propertiesStr); + } + GUILayout.Space(20); + if (GUILayout.Button("GetPresetProperties", GUILayout.Height(Height))) + { + TDPresetProperties presetProperties = ThinkingAnalyticsAPI.GetPresetProperties(); + string deviceModel = presetProperties.DeviceModel; + Debug.Log("TDPresetProperties DeviceModel is " + deviceModel); + Dictionary eventPresetProperties = presetProperties.ToEventPresetProperties(); + string propertiesStr = " "; + foreach (KeyValuePair kv in eventPresetProperties) + { + propertiesStr = propertiesStr + kv.Key + " = " + kv.Value + "\n "; + } + Debug.Log("PresetProperties: \n" + propertiesStr); + } + + GUILayout.Space(20); + if (GUILayout.Button("LoadScene", GUILayout.Height(Height))) + { + SceneManager.LoadScene("OtherScene", LoadSceneMode.Single); + } + GUILayout.EndHorizontal(); + GUILayout.EndScrollView(); + GUILayout.EndArea(); + } +} diff --git a/Assets/Sample/TAExample.cs.meta b/Assets/Sample/TAExample.cs.meta new file mode 100644 index 0000000..87cf226 --- /dev/null +++ b/Assets/Sample/TAExample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 87d98871b303b4786b3dac3fd1b6e6eb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/TDAnalyticsDemo.cs b/Assets/Sample/TDAnalyticsDemo.cs new file mode 100644 index 0000000..39e49f5 --- /dev/null +++ b/Assets/Sample/TDAnalyticsDemo.cs @@ -0,0 +1,518 @@ +using UnityEngine; +using UnityEngine.SceneManagement; +using ThinkingData.Analytics; +using System.Collections.Generic; +using System; +using System.Threading; +using System.Collections; +using ThinkingAnalytics; +public class TDAnalyticsDemo : MonoBehaviour, TDDynamicSuperPropertiesHandler, TDAutoTrackEventHandler +{ + + + public GUISkin skin; + private Vector2 scrollPosition = Vector2.zero; + //private static Color MainColor = new Color(0, 0,0); + private static Color MainColor = new Color(84f / 255, 116f / 255, 241f / 255); + private static Color TextColor = new Color(153f / 255, 153f / 255, 153f / 255); + static int Margin = 20; + static int Height = 60; + static float ContainerWidth = Screen.width - 2 * Margin; + // dynamic super properties interface implementation + public Dictionary GetDynamicSuperProperties() + { + Thread currentThread = Thread.CurrentThread; + // 输出当前线程的信息 + Debug.Log("当前线程ID: " + currentThread.ManagedThreadId); + return new Dictionary() + { + {"dynamic_property", DateTime.Now}, + {"dynamic_property1", DateTime.Now}, + {"dynamic_property2", DateTime.Now}, + {"dynamic_property3", DateTime.Now}, + {"dynamicTime4", DateTime.Now} + }; + } + // auto-tracking events interface implementation + public Dictionary GetAutoTrackEventProperties(int type, Dictionaryproperties) + { + return new Dictionary() + { + {"auto_track_dynamic", DateTime.Today} + }; + } + + private void Awake() + { + } + private void Start() + { + // When automatically initializing ThinkingAnalytics, you can call EnableAutoTrack() in Start() to enable auto-tracking events + // enable auto-tracking events + // TDAnalytics.EnableAutoTrack(TDAutoTrackEventType.ALL); + } + private void Update() + { + + } + + private void SampleDemo() + { + //Init SDK + string appId = "your-app-id"; + string serverUrl = "https://your.server.url"; + TDAnalytics.Init(appId, serverUrl); + + //Login SDK + TDAnalytics.Login("Tiki"); + + //Set Super Properties + //Dictionary superProperties = new Dictionary() { + // { "channel", "Apple Store" }, + // { "vip_level", 10 }, + // { "is_svip", true } + //}; + //TDAnalytics.SetSuperProperties(superProperties); + + + //Track Event + Dictionary eventProperties = new Dictionary() + { + { "product_name", "Majin Taito" }, + { "product_price", 6 }, + { "is_on_sale", true }, + { "begin_time", DateTime.Now }, + { "skins_name", new List() { + "Master Alchemist", + "Knights of the Round Table", + "Taotie", + "Glam Rock" + } } + }; + TDAnalytics.Track("product_buy", eventProperties); + + + //Track User Properties + Dictionary userProperties = new Dictionary() + { + { "email", "tiki@thinkingdata.cn" }, + { "diamond", 888 }, + { "is_svip", true }, + { "last_payment_time", DateTime.Now }, + { "owned_skins", new List() { + "Gun of Travel", + "Bow of Demigods", + "Golden Sagittarius" + } } + }; + TDAnalytics.UserSet(userProperties); + + } + + void OnGUI() + { + GUILayout.BeginArea(new Rect(Margin, Screen.height * 0.15f, Screen.width-2*Margin, Screen.height)); + scrollPosition = GUILayout.BeginScrollView(new Vector2(0, 0), GUILayout.Width(Screen.width - 2 * Margin), GUILayout.Height(Screen.height - 100)); + GUIStyle style = GUI.skin.label; + style.fontSize = 25; + GUILayout.Label("Initialization / UserIDSetting",style); + + GUIStyle buttonStyle = GUI.skin.button; + buttonStyle.fontSize = 20; + GUILayout.BeginHorizontal(GUI.skin.box,GUILayout.Height(Height)); + if (GUILayout.Button("ManualInitialization", GUILayout.Height(Height))) + { + // 1. Manual initialization (ThinkingAnalytics prefab loaded) + //TDAnalytics.Init(); + + + // 2. Manual initialization (dynamically loading TDAnalytics script) + //this.gameObject.AddComponent(); + + // 2.1 Set instance parameters + //string appId = "22e445595b0f42bd8c5fe35bc44b88d6"; + //string serverUrl = "https://receiver-ta-dev.thinkingdata.cn"; + //TDAnalytics.Init(appId, serverUrl); + + + // 2.1 Set personalized instance parameters + string appId = "1b1c1fef65e3482bad5c9d0e6a823356"; + string serverUrl = "https://receiver.ta.thinkingdata.cn"; + TDConfig tDConfig = new TDConfig(appId, serverUrl); + //tDConfig.mode = TDMode.Normal; + tDConfig.timeZone = TDTimeZone.Asia_Shanghai; + //Enable encrypted transmission(only iOS / Android) + int encryptVersion = 0; + string encryptPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIPi6aHymT1jdETRci6f1ck535n13IX3p9XNLFu5xncfzNFl6kFVMiMSXMIwWSW2lF6ELtIlDJ0B00qE9C02n6YbIAV+VvVkchydbWrm8VdnEJk/6tIydoUxGyM9pDT6U/PaoEiItl/BawDj3/+KW6U7AejYPij9uTQ4H3bQqj1wIDAQAB"; + tDConfig.EnableEncrypt(encryptPublicKey, encryptVersion); + TDAnalytics.Init(tDConfig); + //TDAnalytics.SetNetworkType(TDNetworkType.Wifi); + TDAnalytics.SetDynamicSuperProperties(this); + //TDAnalytics.EnableAutoTrack(TDAutoTrackEventType.AppInstall | TDAutoTrackEventType.AppStart | TDAutoTrackEventType.AppEnd); + TDAnalytics.EnableAutoTrack(TDAutoTrackEventType.All); + + + //new GameObject("ThinkingAnalytics", typeof(ThinkingAnalyticsAPI)); + //string appId = "40eddce753cd4bef9883a01e168c3df0"; + //string serverUrl = "https://receiver-ta-preview.thinkingdata.cn"; + //ThinkingAnalyticsAPI.StartThinkingAnalytics(appId, serverUrl); + //ThinkingAnalyticsAPI.SetNetworkType(ThinkingAnalyticsAPI.NetworkType.WIFI); + //ThinkingAnalyticsAPI.EnableAutoTrack(AUTO_TRACK_EVENTS.ALL); + + // 2.2 Multi-project support + // string appId_2 = "cf918051b394495ca85d1b7787ad7243"; + // string serverUrl_2 = "https://receiver-ta-dev.thinkingdata.cn"; + // TDConfig tDConfig_2 = new TDConfig(appId_2, serverUrl_2); + + // TDAnalytics.Init(tDConfig_2); + + // Multi-item track events + // TDAnalytics.Track("test_event"); + // TDAnalytics.Track("test_event_2", appId:appId_2); + + + // Enable auto-tracking events + //TDAnalytics.EnableAutoTrack(TDAutoTrackEventType.All); + // Enable auto-tracking events, and set properties + // TDAnalytics.SetAutoTrackProperties(TDAutoTrackEventType.All, new Dictionary() + // { + // {"auto_track_static_1", "value_1"} + // }); + // TDAnalytics.EnableAutoTrack(TDAutoTrackEventType.All, new Dictionary() + // { + // {"auto_track_static_2", "value_2"} + // }); + // Enable auto-tracking events, and set callback + // TDAnalytics.EnableAutoTrack(TDAutoTrackEventType.All, this); + } + GUILayout.Space(20); + if (GUILayout.Button("SetAccountID", GUILayout.Height(Height))) + { + TDAnalytics.Login("TA"); + } + GUILayout.Space(20); + if (GUILayout.Button("SetDistinctID", GUILayout.Height(Height))) + { + TDAnalytics.SetDistinctId("TD_DistinctID"); + string distinctId = TDAnalytics.GetDistinctId(); + Debug.Log("Current Distinct ID is : " + distinctId); + } + GUILayout.Space(20); + if (GUILayout.Button("ClearAccountID", GUILayout.Height(Height))) + { + TDAnalytics.Logout(); + } + GUILayout.EndHorizontal(); + + GUILayout.Space(20); + GUILayout.Label("EventTracking", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("TrackEvent", GUILayout.Height(Height))) + { + Debug.Log("======1" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); + //Dictionary properties = new Dictionary(); + //properties["channel"] = "ta";//string + //properties["age"] = 1;//number - int + //properties["weight"] = 5.46;//number - float + //properties["balance"] = -0.4;//number - negative + //properties["isVip"] = true;//bool + //properties["birthday"] = new DateTime(2022,01,01);//date + //properties["birthday1"] = new DateTime();//date + //properties["birthday2"] = new DateTime(2023, 05, 01);//date + //properties["birthday3"] = new DateTime(2023, 05, 03);//date + //properties["object"] = new Dictionary() { { "key", "value" },{ "key1", DateTime.Now }, { "key2", DateTime.Now } };//object + //properties["object_arr"] = new List() { new Dictionary() { { "key", "value" }, { "key3", DateTime.Now }, { "key4", DateTime.Now } } };//object array + //properties["arr"] = new List() { "value" };//array + //TDAnalytics.Track("TA", properties); + Decimal a = 1; + Dictionary properties = new Dictionary(); + properties["channel"] = "ta";//string + properties["age"] = 1;//number - int + properties["weight"] = 5.46;//number - float + properties["balance"] = -0.4;//number - negative + properties["isVip"] = true;//bool + properties["date1"] = new DateTime(); + properties["date2"] = new DateTime(); + properties["date3"] = new DateTime(); + properties["date4"] = new DateTime(); + properties["date5"] = new DateTime(); + properties["date6"] = DateTime.Now; + properties["num"] = a; + properties["birthday"] = new DateTime(2022, 01, 01);//date + properties["object"] = new Dictionary() { { "key", "value" }, { "data1", new DateTime() }, { "data2", new DateTime() }, { "data3", new DateTime() }, { "data4", new DateTime() }, { "data5", new DateTime() } };//object + properties["object_arr"] = new List() { new Dictionary() { { "key", "value" }, { "data1", new DateTime() }, { "data2", new DateTime() }, { "data3", new DateTime() }, { "data4", new DateTime() }, { "data5", new DateTime() } } };//object array + properties["arr"] = new List() { "value", new DateTime(), new DateTime(), new DateTime(), new DateTime(), new DateTime() };//array + TDAnalytics.Track("TA", properties); + Debug.Log("======2" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()); + } + GUILayout.Space(20); + if (GUILayout.Button("TrackFirstEvent", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary() { { "status",1 } }; + TDFirstEventModel firstEvent = new TDFirstEventModel("first_event"); + firstEvent.Properties = properties; + TDAnalytics.Track(firstEvent); + Dictionary properties_2 = new Dictionary() { { "status", 11 } }; + TDFirstEventModel firstEvent_2 = new TDFirstEventModel("first_event", "first_check_id"); + firstEvent_2.Properties = properties_2; + TDAnalytics.Track(firstEvent_2); + } + GUILayout.Space(20); + if (GUILayout.Button("TrackUpdateEvent", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary() { { "status", 2 } }; + TDUpdatableEventModel updatableEvent = new TDUpdatableEventModel("updatable_event", "test_event_id"); + updatableEvent.Properties = properties; + updatableEvent.SetTime(DateTime.Now, TimeZoneInfo.Local); + TDAnalytics.Track(updatableEvent); + } + + GUILayout.Space(20); + if (GUILayout.Button("TrackOverwriteEvent", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary() { { "status", 3 } }; + TDOverwritableEventModel overWritableEvent = new TDOverwritableEventModel("overwritable_event", "test_event_id"); + overWritableEvent.Properties = properties; + overWritableEvent.SetTime(DateTime.Now, TimeZoneInfo.Utc); + TDAnalytics.Track(overWritableEvent); + } + + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("TimeEvent", GUILayout.Height(Height))) + { + TDAnalytics.TimeEvent("TATimeEvent"); + } + + GUILayout.Space(20); + if (GUILayout.Button("Track-TimeEvent", GUILayout.Height(Height))) + { + TDAnalytics.Track("TATimeEvent"); + } + + GUILayout.Space(20); + if (GUILayout.Button("TrackEventWithDate", GUILayout.Height(Height))) + { + Dictionary properties = new Dictionary(); + TDAnalytics.Track("TA_Utc", properties, DateTime.Now.AddDays(1), TimeZoneInfo.Utc); + TDAnalytics.Track("TA_Local", properties, DateTime.Now.AddDays(1), TimeZoneInfo.Local); + } + + GUILayout.Space(20); + if (GUILayout.Button("TrackEvent-LightInstance", GUILayout.Height(Height))) + { + string lightToken = TDAnalytics.LightInstance(); + TDAnalytics.Login("light_account", lightToken); + TDAnalytics.Track("light_event", lightToken); + TDAnalytics.Flush(); + } + GUILayout.Space(20); + if (GUILayout.Button("TrackEvent-MultiInstance", GUILayout.Height(Height))) + { + string appId_2 = "cf918051b394495ca85d1b7787ad7243"; + string serverUrl_2 = "https://receiver-ta-dev.thinkingdata.cn"; + TDConfig token_2 = new TDConfig(appId_2, serverUrl_2); + token_2.mode = TDMode.Normal; + token_2.timeZone = TDTimeZone.UTC; + // initial multi-instance + TDAnalytics.Init(token_2); + // login account + TDAnalytics.Login("Tiki", appId_2); + // track normal event + TDAnalytics.Track("TA", appId_2); + // track user properties + TDAnalytics.UserSet(new Dictionary() { { "age", 18 } }, appId_2); + // flush data + TDAnalytics.Flush(appId_2); + + string instanceName = "ThinkingData"; + TDConfig token_3 = new TDConfig(appId_2, serverUrl_2); + token_3.name = instanceName; + // initial multi-instance + TDAnalytics.Init(token_3); + // login account + TDAnalytics.Login("Thinker", instanceName); + // track normal event + TDAnalytics.Track("TA", instanceName); + // track user properties + TDAnalytics.UserSet(new Dictionary() { { "age", 18 } }, instanceName); + // flush data + TDAnalytics.Flush(instanceName); + } + GUILayout.EndHorizontal(); + + + + + GUILayout.Space(20); + GUILayout.Label("UserProperty", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("UserSet", GUILayout.Height(Height))) + { + Dictionary userProperties = new Dictionary() { { "age", 18 } }; + TDAnalytics.UserSet(userProperties); + } + + GUILayout.Space(20); + if (GUILayout.Button("UserSetOnce", GUILayout.Height(Height))) + { + Dictionary userProperties = new Dictionary() { { "gender", 1 } }; + TDAnalytics.UserSetOnce(userProperties); + + } + GUILayout.Space(20); + if (GUILayout.Button("UserAdd", GUILayout.Height(Height))) + { + TDAnalytics.UserAdd("user_coin", 1); + } + GUILayout.Space(20); + if (GUILayout.Button("UserUnset", GUILayout.Height(Height))) + { + TDAnalytics.UserUnset("user_coin"); + TDAnalytics.UserUnset(new List() { "user_coin", "user_vip" }); + } + GUILayout.Space(20); + if (GUILayout.Button("UserDelete", GUILayout.Height(Height))) + { + TDAnalytics.UserDelete(); + } + GUILayout.Space(20); + if (GUILayout.Button("UserAppend", GUILayout.Height(Height))) + { + List propList = new List() { "apple", "ball" }; + Dictionary userProperties = new Dictionary() { { "prop", propList } }; + TDAnalytics.UserAppend(userProperties); + } + GUILayout.Space(20); + if (GUILayout.Button("UserUniqAppend", GUILayout.Height(Height))) + { + List propList = new List() { "apple", "banana" }; + Dictionary userProperties = new Dictionary() { { "prop", propList } }; + TDAnalytics.UserUniqAppend(userProperties); + } + GUILayout.EndHorizontal(); + + + + GUILayout.Space(20); + GUILayout.Label("OtherSetting", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("Flush", GUILayout.Height(Height))) + { + TDAnalytics.Flush(); + } + GUILayout.Space(20); + if (GUILayout.Button("GetDeviceID", GUILayout.Height(Height))) + { + string deviceId = TDAnalytics.GetDeviceId(); + Debug.Log("Current Device ID is : " + deviceId); + } + GUILayout.Space(20); + if (GUILayout.Button("Pause", GUILayout.Height(Height))) + { + TDAnalytics.SetTrackStatus(TDTrackStatus.Pause); + } + GUILayout.Space(20); + if (GUILayout.Button("Stop", GUILayout.Height(Height))) + { + TDAnalytics.SetTrackStatus(TDTrackStatus.Stop); + } + GUILayout.Space(20); + if (GUILayout.Button("SaveOnly", GUILayout.Height(Height))) + { + TDAnalytics.SetTrackStatus(TDTrackStatus.SaveOnly); + } + GUILayout.Space(20); + if (GUILayout.Button("Normal", GUILayout.Height(Height))) + { + TDAnalytics.SetTrackStatus(TDTrackStatus.Normal); + } + GUILayout.Space(20); + if (GUILayout.Button("CalibrateTime", GUILayout.Height(Height))) + { + //currnt Unix timestamp, units Ms, e.g: 1672531200000 -> 2023-01-01 08:00:00 + TDAnalytics.CalibrateTime(1672531200000); + } + GUILayout.Space(20); + if (GUILayout.Button("CalibrateTime-NTP", GUILayout.Height(Height))) + { + //NTP server, e.g: time.apple.com + TDAnalytics.CalibrateTimeWithNtp("time.apple.com"); + } + GUILayout.EndHorizontal(); + + GUILayout.Space(20); + GUILayout.Label("PropertiesSetting", GUI.skin.label); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("SetSuperProperties", GUILayout.Height(Height))) + { + Dictionary superProperties = new Dictionary() { + { "vip_level", 1 }, + { "vip_title", "Supreme King" } + }; + TDAnalytics.SetSuperProperties(superProperties); + } + GUILayout.Space(20); + if (GUILayout.Button("UpdateSuperProperties", GUILayout.Height(Height))) + { + Dictionary superProperties = new Dictionary() { + { "vip_level", 2 } + }; + TDAnalytics.SetSuperProperties(superProperties); + } + + GUILayout.Space(20); + if (GUILayout.Button("ClearSuperProperties", GUILayout.Height(Height))) + { + TDAnalytics.UnsetSuperProperty("vip_level"); + } + + GUILayout.Space(20); + if (GUILayout.Button("ClearAllSuperProperties", GUILayout.Height(Height))) + { + TDAnalytics.ClearSuperProperties(); + } + + GUILayout.EndHorizontal(); + GUILayout.BeginHorizontal(GUI.skin.textArea, GUILayout.Height(Height)); + if (GUILayout.Button("SetDynamicSuperProperties", GUILayout.Height(Height))) + { + TDAnalytics.SetDynamicSuperProperties(this); + } + + GUILayout.Space(20); + if (GUILayout.Button("GetSuperProperties", GUILayout.Height(Height))) + { + Dictionary eventSuperProperties = TDAnalytics.GetSuperProperties(); + string propertiesStr = " "; + foreach (KeyValuePair kv in eventSuperProperties) + { + propertiesStr = propertiesStr + kv.Key + " = " + kv.Value + "\n "; + } + Debug.Log("SuperProperties: \n" + propertiesStr); + } + GUILayout.Space(20); + if (GUILayout.Button("GetPresetProperties", GUILayout.Height(Height))) + { + //TDPresetProperties presetProperties = TDAnalytics.GetPresetProperties(); + //string deviceModel = presetProperties.DeviceModel; + //Debug.Log("TDPresetProperties: DeviceModel is " + deviceModel); + //Dictionary eventPresetProperties = presetProperties.ToDictionary(); + //string propertiesStr = " "; + //foreach (KeyValuePair kv in eventPresetProperties) + //{ + // propertiesStr = propertiesStr + kv.Key + " = " + kv.Value + "\n "; + //} + //Debug.Log("PresetProperties: \n" + propertiesStr); + } + + GUILayout.Space(20); + if (GUILayout.Button("LoadScene", GUILayout.Height(Height))) + { + SceneManager.LoadScene("OtherScene", LoadSceneMode.Single); + } + GUILayout.EndHorizontal(); + GUILayout.EndScrollView(); + GUILayout.EndArea(); + } +} diff --git a/Assets/Sample/TDAnalyticsDemo.cs.meta b/Assets/Sample/TDAnalyticsDemo.cs.meta new file mode 100644 index 0000000..bd3b0fa --- /dev/null +++ b/Assets/Sample/TDAnalyticsDemo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc3b54d5c2d4a455fbc56ab57ca985c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sample/TDAnalyticsDemo.unity b/Assets/Sample/TDAnalyticsDemo.unity new file mode 100644 index 0000000..8923cff --- /dev/null +++ b/Assets/Sample/TDAnalyticsDemo.unity @@ -0,0 +1,513 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_UseRadianceAmbientProbe: 0 +--- !u!157 &4 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 12 + m_Resolution: 1 + m_BakeResolution: 50 + m_AtlasSize: 1024 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAmbientOcclusion: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 0 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVRBounces: 2 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVREnvironmentMIS: 0 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_LightProbeSampleCountMultiplier: 4 + m_LightingDataAsset: {fileID: 0} + m_LightingSettings: {fileID: 679135154} +--- !u!196 &5 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666666 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + maxJobWorkers: 0 + preserveTilesOutsideBounds: 0 + debug: + m_Flags: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &269916751 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 269916752} + - component: {fileID: 269916753} + m_Layer: 0 + m_Name: td_logo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &269916752 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 269916751} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 4, z: 0} + m_LocalScale: {x: 1.3, y: 1.3, z: 1.3} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1608319071} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &269916753 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 269916751} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: 21300000, guid: 1c8be89e83f14479081250d0c4806b85, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 5, y: 1.89} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!1001 &278149140 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_RootOrder + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 57277738888238098, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1362306111410183020, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: enableLog + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1362306111410183020, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: networkType + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1362306111410183020, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: startManually + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1362306111410183020, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: tokens.Array.data[0].mode + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 1362306111410183020, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: tokens.Array.data[0].appid + value: cf918051b394495ca85d1b7787ad7243 + objectReference: {fileID: 0} + - target: {fileID: 1362306111410183020, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: tokens.Array.data[0].timeZone + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 1362306111410183020, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: tokens.Array.data[0].serverUrl + value: https://receiver-ta-dev.thinkingdata.cn + objectReference: {fileID: 0} + - target: {fileID: 3471622134282543401, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_Name + value: TDAnalytics + objectReference: {fileID: 0} + - target: {fileID: 3471622134282543401, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 986ad473b78d14e08b1f05d368cb1591, type: 3} +--- !u!1 &541060113 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 541060118} + - component: {fileID: 541060117} + - component: {fileID: 541060115} + - component: {fileID: 541060114} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &541060114 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 541060113} + m_Enabled: 1 +--- !u!124 &541060115 +Behaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 541060113} + m_Enabled: 1 +--- !u!20 &541060117 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 541060113} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 2 + m_BackGroundColor: {r: 0.32941177, g: 0.45490196, b: 0.94509804, a: 0.019607844} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!4 &541060118 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 541060113} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!850595691 &679135154 +LightingSettings: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Settings.lighting + serializedVersion: 4 + m_GIWorkflowMode: 1 + m_EnableBakedLightmaps: 1 + m_EnableRealtimeLightmaps: 0 + m_RealtimeEnvironmentLighting: 1 + m_BounceScale: 1 + m_AlbedoBoost: 1 + m_IndirectOutputScale: 1 + m_UsingShadowmask: 0 + m_BakeBackend: 0 + m_LightmapMaxSize: 1024 + m_BakeResolution: 50 + m_Padding: 2 + m_LightmapCompression: 0 + m_AO: 1 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_ExtractAO: 0 + m_MixedBakeMode: 1 + m_LightmapsBakeMode: 1 + m_FilterMode: 1 + m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} + m_ExportTrainingData: 0 + m_TrainingDataDestination: TrainingData + m_RealtimeResolution: 1 + m_ForceWhiteAlbedo: 0 + m_ForceUpdates: 0 + m_FinalGather: 0 + m_FinalGatherRayCount: 256 + m_FinalGatherFiltering: 1 + m_PVRCulling: 1 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 512 + m_PVREnvironmentSampleCount: 512 + m_PVREnvironmentReferencePointCount: 2048 + m_LightProbeSampleCountMultiplier: 4 + m_PVRBounces: 2 + m_PVRMinBounces: 1 + m_PVREnvironmentMIS: 0 + m_PVRFilteringMode: 0 + m_PVRDenoiserTypeDirect: 0 + m_PVRDenoiserTypeIndirect: 0 + m_PVRDenoiserTypeAO: 0 + m_PVRFilterTypeDirect: 0 + m_PVRFilterTypeIndirect: 0 + m_PVRFilterTypeAO: 0 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousPositionSigmaDirect: 0.5 + m_PVRFilteringAtrousPositionSigmaIndirect: 2 + m_PVRFilteringAtrousPositionSigmaAO: 1 + m_PVRTiledBaking: 0 +--- !u!1 &1608319069 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1608319071} + - component: {fileID: 1608319070} + - component: {fileID: 1608319072} + m_Layer: 0 + m_Name: ThingkingAnalyticsExample + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1608319070 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1608319069} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc3b54d5c2d4a455fbc56ab57ca985c6, type: 3} + m_Name: + m_EditorClassIdentifier: + skin: {fileID: 11400000, guid: 48b9be70902884a76ba1b53926fd3e37, type: 2} +--- !u!4 &1608319071 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1608319069} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 269916752} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1608319072 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1608319069} + m_Enabled: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 87d98871b303b4786b3dac3fd1b6e6eb, type: 3} + m_Name: + m_EditorClassIdentifier: + skin: {fileID: 0} diff --git a/Assets/Sample/TDAnalyticsDemo.unity.meta b/Assets/Sample/TDAnalyticsDemo.unity.meta new file mode 100644 index 0000000..2bcad43 --- /dev/null +++ b/Assets/Sample/TDAnalyticsDemo.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 741c7d08d0bfd46ae96dff68cdd17f99 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scenes/GameScene.unity b/Assets/Scenes/GameScene.unity index 23ab8a1..cfdaf42 100644 --- a/Assets/Scenes/GameScene.unity +++ b/Assets/Scenes/GameScene.unity @@ -38,7 +38,6 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &3 LightmapSettings: @@ -104,7 +103,7 @@ NavMeshSettings: serializedVersion: 2 m_ObjectHideFlags: 0 m_BuildSettings: - serializedVersion: 2 + serializedVersion: 3 agentTypeID: 0 agentRadius: 0.5 agentHeight: 2 @@ -117,7 +116,7 @@ NavMeshSettings: cellSize: 0.16666667 manualTileSize: 0 tileSize: 256 - accuratePlacement: 0 + buildHeightMesh: 0 maxJobWorkers: 0 preserveTilesOutsideBounds: 0 debug: @@ -154,7 +153,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 2018301549} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -236,7 +234,6 @@ RectTransform: m_Children: - {fileID: 1715967758} m_Father: {fileID: 1332931146} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -377,9 +374,17 @@ Camera: m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 m_SensorSize: {x: 36, y: 24} m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 x: 0 @@ -413,13 +418,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 519420028} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1222376247 GameObject: @@ -481,13 +486,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1222376247} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1332931142 GameObject: @@ -568,6 +573,7 @@ Canvas: m_SortingBucketNormalizedSize: 0 m_VertexColorAlwaysGammaSpace: 0 m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 m_SortingLayerID: 0 m_SortingOrder: 0 m_TargetDisplay: 0 @@ -586,7 +592,6 @@ RectTransform: - {fileID: 231270963} - {fileID: 2018301549} m_Father: {fileID: 0} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} @@ -636,7 +641,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 231270963} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 1, y: 1} @@ -718,7 +722,6 @@ RectTransform: m_Children: - {fileID: 138126178} m_Father: {fileID: 1332931146} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -829,6 +832,7 @@ GameObject: m_Component: - component: {fileID: 2137923634} - component: {fileID: 2137923635} + - component: {fileID: 2137923636} m_Layer: 0 m_Name: '[SDKManager]' m_TagString: Untagged @@ -843,13 +847,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2137923633} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2137923635 MonoBehaviour: @@ -864,3 +868,23 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: IsMoreAdsBidding: 0 +--- !u!114 &2137923636 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2137923633} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a550f9677d329f940876ee3d139f8289, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 519420032} + - {fileID: 2137923634} + - {fileID: 1332931146} + - {fileID: 1222376250} diff --git a/Assets/Script/FirebaseManager.meta b/Assets/Script/SDKManager/FirebaseManager.meta similarity index 100% rename from Assets/Script/FirebaseManager.meta rename to Assets/Script/SDKManager/FirebaseManager.meta diff --git a/Assets/Script/FirebaseManager/FireBaseAnalyticsManager.cs b/Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs similarity index 100% rename from Assets/Script/FirebaseManager/FireBaseAnalyticsManager.cs rename to Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs diff --git a/Assets/Script/FirebaseManager/FireBaseAnalyticsManager.cs.meta b/Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs.meta similarity index 100% rename from Assets/Script/FirebaseManager/FireBaseAnalyticsManager.cs.meta rename to Assets/Script/SDKManager/FirebaseManager/FireBaseAnalyticsManager.cs.meta diff --git a/Assets/Script/FirebaseManager/FireBaseRemoteConfigManager.cs b/Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs similarity index 86% rename from Assets/Script/FirebaseManager/FireBaseRemoteConfigManager.cs rename to Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs index 3dcc11d..424cb61 100644 --- a/Assets/Script/FirebaseManager/FireBaseRemoteConfigManager.cs +++ b/Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs @@ -6,24 +6,6 @@ using UnityEngine; public static class FireBaseRemoteConfigManager { - private static bool isInit = false; - - public async static void Init() - { - // 只初始化Firebase核心功能,不初始化Remote Config - var dependencyStatus = await FirebaseApp.CheckAndFixDependenciesAsync(); - - if (dependencyStatus == DependencyStatus.Available) - { - isInit = true; - Debug.Log("Firebase initialized successfully (without Remote Config defaults)"); - } - else - { - Debug.LogError($"Could not resolve Firebase dependencies: {dependencyStatus}"); - } - } - /// /// 获取int参数 /// @@ -32,7 +14,7 @@ public static class FireBaseRemoteConfigManager /// public static async Task GetRemoteConfigInt(string key, int defaultValue = 0) { - if (!isInit) + if (!FireBaseSDKManager.Instance.IsInit) { return defaultValue; } @@ -70,7 +52,7 @@ public static class FireBaseRemoteConfigManager /// public static async Task GetRemoteConfigString(string key, string defaultValue = "") { - if (!isInit) + if (!FireBaseSDKManager.Instance.IsInit) { return defaultValue; } @@ -108,7 +90,7 @@ public static class FireBaseRemoteConfigManager /// public static async Task GetRemoteConfigBool(string key, bool defaultValue = false) { - if (!isInit) + if (!FireBaseSDKManager.Instance.IsInit) { return defaultValue; } @@ -146,7 +128,7 @@ public static class FireBaseRemoteConfigManager /// public static async Task GetRemoteConfigBool(string key, float defaultValue = 0) { - if (!isInit) + if (!FireBaseSDKManager.Instance.IsInit) { return defaultValue; } diff --git a/Assets/Script/FirebaseManager/FireBaseRemoteConfigManager.cs.meta b/Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs.meta similarity index 100% rename from Assets/Script/FirebaseManager/FireBaseRemoteConfigManager.cs.meta rename to Assets/Script/SDKManager/FirebaseManager/FireBaseRemoteConfigManager.cs.meta diff --git a/Assets/Script/SDKManager/FirebaseManager/FireBaseSDKManager.cs b/Assets/Script/SDKManager/FirebaseManager/FireBaseSDKManager.cs new file mode 100644 index 0000000..0f12ef2 --- /dev/null +++ b/Assets/Script/SDKManager/FirebaseManager/FireBaseSDKManager.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Collections.Generic; +using Firebase; +using UnityEngine; + +public class FireBaseSDKManager : MonoBehaviour +{ + public static FireBaseSDKManager Instance; + + public bool IsInit {private set; get; } + + private void Awake() + { + Instance = this; + InitSDK(); + } + + private async void InitSDK() + { + var dependencyStatus = await FirebaseApp.CheckAndFixDependenciesAsync(); + + if (dependencyStatus == DependencyStatus.Available) + { + IsInit = true; + Debug.Log("Firebase initialized successfully (without Remote Config defaults)"); + } + else + { + Debug.LogError($"Could not resolve Firebase dependencies: {dependencyStatus}"); + } + } +} diff --git a/Assets/Script/SDKManager/FirebaseManager/FireBaseSDKManager.cs.meta b/Assets/Script/SDKManager/FirebaseManager/FireBaseSDKManager.cs.meta new file mode 100644 index 0000000..da204b5 --- /dev/null +++ b/Assets/Script/SDKManager/FirebaseManager/FireBaseSDKManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a550f9677d329f940876ee3d139f8289 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/ShuShuMangage.meta b/Assets/Script/SDKManager/ShuShuMangage.meta new file mode 100644 index 0000000..092813a --- /dev/null +++ b/Assets/Script/SDKManager/ShuShuMangage.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fa0ed228357266f4988a9f871e872723 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/ShuShuMangage/ShuShuEvent.cs b/Assets/Script/SDKManager/ShuShuMangage/ShuShuEvent.cs new file mode 100644 index 0000000..d4f0dd1 --- /dev/null +++ b/Assets/Script/SDKManager/ShuShuMangage/ShuShuEvent.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using ThinkingData.Analytics; + +public static class ShuShuEvent +{ + /// + /// 设置用户属性 + /// + public static void UserSet(Dictionary dic) + { + TDAnalytics.UserSet(dic); + } + + /// + /// 设置公共事件属性 + /// + /// + public static void SetSuperProperties(Dictionary superProperties) + { + TDAnalytics.SetSuperProperties(superProperties);//设置公共事件属性 + } + + /// + /// 发送事件 + /// + public static void Track(string eventName) + { + TDAnalytics.Track(eventName); + } + + /// + /// 发送事件 + /// + public static void Track(string eventName, Dictionary properties) + { + TDAnalytics.Track(eventName, properties); + } +} \ No newline at end of file diff --git a/Assets/Script/SDKManager/ShuShuMangage/ShuShuEvent.cs.meta b/Assets/Script/SDKManager/ShuShuMangage/ShuShuEvent.cs.meta new file mode 100644 index 0000000..6fcca9a --- /dev/null +++ b/Assets/Script/SDKManager/ShuShuMangage/ShuShuEvent.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c8805dfdca0f41a6925658078a82a69d +timeCreated: 1756546330 \ No newline at end of file diff --git a/Assets/Script/SDKManager/ShuShuMangage/ShuShuMangage.cs b/Assets/Script/SDKManager/ShuShuMangage/ShuShuMangage.cs new file mode 100644 index 0000000..83e9fdb --- /dev/null +++ b/Assets/Script/SDKManager/ShuShuMangage/ShuShuMangage.cs @@ -0,0 +1,21 @@ +using System.Collections; +using System.Collections.Generic; +using ThinkingData.Analytics; +using UnityEngine; + +public class ShuShuMangage : MonoBehaviour +{ + private const string appid = "80f6819a81c743cbad667ecf242f3133"; + private const string server = ""; + + private void Start() + { + // 初始化SDK + TDAnalytics.Init(appid, server); + //开启自动采集事件 + TDAnalytics.EnableAutoTrack(TDAutoTrackEventType.AppInstall | TDAutoTrackEventType.AppStart | TDAutoTrackEventType.AppEnd); + //如果用户已登录,可以设置用户的账号ID作为身份唯一标识 + TDAnalytics.Login("TA"); + } + +} diff --git a/Assets/Script/SDKManager/ShuShuMangage/ShuShuMangage.cs.meta b/Assets/Script/SDKManager/ShuShuMangage/ShuShuMangage.cs.meta new file mode 100644 index 0000000..d53521a --- /dev/null +++ b/Assets/Script/SDKManager/ShuShuMangage/ShuShuMangage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5019ae7cf0c6d3d4c89b8921e4beab15 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets.meta b/Assets/StreamingAssets.meta new file mode 100644 index 0000000..ddec8e7 --- /dev/null +++ b/Assets/StreamingAssets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b79abdaa780b2c4bacc34065090f709 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/StreamingAssets/google-services-desktop.json b/Assets/StreamingAssets/google-services-desktop.json new file mode 100644 index 0000000..e6e64dc --- /dev/null +++ b/Assets/StreamingAssets/google-services-desktop.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "601745472008", + "project_id": "ag787cd54047-e0ac1-gp", + "storage_bucket": "ag787cd54047-e0ac1-gp.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:601745472008:android:768b7c2f79e2e93725afbd", + "android_client_info": { + "package_name": "com.rush.cash.earn.fast.real.money.game" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyCbVg7dxQbatGTDomrKq4AkQAP4aH1vr4Y" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/Assets/StreamingAssets/google-services-desktop.json.meta b/Assets/StreamingAssets/google-services-desktop.json.meta new file mode 100644 index 0000000..ef0889d --- /dev/null +++ b/Assets/StreamingAssets/google-services-desktop.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1d355797e637f624b9148b20da4b2a10 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics.meta b/Assets/ThinkingAnalytics.meta new file mode 100644 index 0000000..da98201 --- /dev/null +++ b/Assets/ThinkingAnalytics.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 60b198fb61dd042d5b21af809183759f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Exception.meta b/Assets/ThinkingAnalytics/Exception.meta new file mode 100644 index 0000000..6e3b94b --- /dev/null +++ b/Assets/ThinkingAnalytics/Exception.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f347e0b07c5d64926ac64031c3bba013 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Exception/TDException.cs b/Assets/ThinkingAnalytics/Exception/TDException.cs new file mode 100644 index 0000000..8c0a8f2 --- /dev/null +++ b/Assets/ThinkingAnalytics/Exception/TDException.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace ThinkingData.Analytics.TDException +{ + public class TDExceptionHandler + { + + //Whether to exit the program when an exception occurs + public static bool IsQuitWhenException = false; + + //Whether the exception catch has been registered + public static bool IsRegistered = false; + private static TDAutoTrackEventHandler mEventCallback; + private static Dictionary mProperties; + + + public static void SetAutoTrackProperties(Dictionary properties) + { + if (!(mProperties is Dictionary)) + { + mProperties = new Dictionary(); + } + + foreach (var item in properties) + { + if (!mProperties.ContainsKey(item.Key)) + { + mProperties.Add(item.Key, item.Value); + } + } + } + + public static void RegisterTAExceptionHandler(TDAutoTrackEventHandler eventCallback) + { + mEventCallback = eventCallback; + //Register exception handling delegate + try + { + if (!IsRegistered) + { + Application.logMessageReceived += _LogHandler; + AppDomain.CurrentDomain.UnhandledException += _UncaughtExceptionHandler; + IsRegistered = true; + } + } + catch + { + } + } + + public static void RegisterTAExceptionHandler(Dictionary properties) + { + SetAutoTrackProperties(properties); + //Register exception handling delegate + try + { + if (!IsRegistered) + { + Application.logMessageReceived += _LogHandler; + AppDomain.CurrentDomain.UnhandledException += _UncaughtExceptionHandler; + IsRegistered = true; + } + } + catch + { + } + } + + public static void UnregisterTAExceptionHandler () + { + //Clear exception handling delegate + try + { + Application.logMessageReceived -= _LogHandler; + System.AppDomain.CurrentDomain.UnhandledException -= _UncaughtExceptionHandler; + } + catch + { + } + } + + + private static void _LogHandler( string logString, string stackTrace, LogType type ) + { + if( type == LogType.Error || type == LogType.Exception || type == LogType.Assert ) + { + //Report exception event + string reasonStr = "exception_type: " + type.ToString() + "
" + "exception_message: " + logString + "
" + "stack_trace: " + stackTrace + "
" ; + Dictionary properties = new Dictionary(){ + {"#app_crashed_reason", reasonStr} + }; + properties = MergeProperties(properties); + TDAnalytics.Track("ta_app_crash", properties); + + if ( IsQuitWhenException ) + { + Application.Quit(); + } + } + } + + private static void _UncaughtExceptionHandler (object sender, System.UnhandledExceptionEventArgs args) + { + if (args == null || args.ExceptionObject == null) + { + return; + } + + try + { + if (args.ExceptionObject.GetType () != typeof(System.Exception)) + { + return; + } + } + catch + { + return; + } + + System.Exception e = (System.Exception)args.ExceptionObject; + + //Report exception event + string reasonStr = "exception_type: " + e.GetType().Name + "
" + "exception_message: " + e.Message + "
" + "stack_trace: " + e.StackTrace + "
" ; + Dictionary properties = new Dictionary(){ + {"#app_crashed_reason", reasonStr} + }; + properties = MergeProperties(properties); + TDAnalytics.Track("ta_app_crash", properties); + + if ( IsQuitWhenException ) + { + Application.Quit(); + } + } + + private static Dictionary MergeProperties(Dictionary properties) + { + + if (mEventCallback is TDAutoTrackEventHandler) + { + Dictionary callbackProperties = mEventCallback.GetAutoTrackEventProperties((int)TDAutoTrackEventType.AppCrash, properties); + foreach (var item in callbackProperties) + { + if (!properties.ContainsKey(item.Key)) + { + properties.Add(item.Key, item.Value); + } + } + } + + if (mProperties is Dictionary) + { + foreach (var item in mProperties) + { + if (!properties.ContainsKey(item.Key)) + { + properties.Add(item.Key, item.Value); + } + } + } + + return properties; + } + } +} diff --git a/Assets/ThinkingAnalytics/Exception/TDException.cs.meta b/Assets/ThinkingAnalytics/Exception/TDException.cs.meta new file mode 100644 index 0000000..766222b --- /dev/null +++ b/Assets/ThinkingAnalytics/Exception/TDException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 76f285e49c9584fce99e9fe1536fea17 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Resources.meta b/Assets/ThinkingAnalytics/Resources.meta new file mode 100644 index 0000000..7f3bdf2 --- /dev/null +++ b/Assets/ThinkingAnalytics/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4e5d07cff2f9b45d6afa9ab9a879fbff +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Resources/ta_public_config.xml b/Assets/ThinkingAnalytics/Resources/ta_public_config.xml new file mode 100644 index 0000000..3f98eff --- /dev/null +++ b/Assets/ThinkingAnalytics/Resources/ta_public_config.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Assets/ThinkingAnalytics/Resources/ta_public_config.xml.meta b/Assets/ThinkingAnalytics/Resources/ta_public_config.xml.meta new file mode 100644 index 0000000..d130ea4 --- /dev/null +++ b/Assets/ThinkingAnalytics/Resources/ta_public_config.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b67db39cd532b4f08b95b2cf5938553f +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/TDAnalytics.asmdef b/Assets/ThinkingAnalytics/TDAnalytics.asmdef new file mode 100644 index 0000000..5ca02cd --- /dev/null +++ b/Assets/ThinkingAnalytics/TDAnalytics.asmdef @@ -0,0 +1,16 @@ +{ + "name": "ThinkingAnalytics", + "rootNamespace": "", + "references": [ + "GUID:0a958a7eb80a248e1b8bc4553787c209" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/TDAnalytics.asmdef.meta b/Assets/ThinkingAnalytics/TDAnalytics.asmdef.meta new file mode 100644 index 0000000..5415231 --- /dev/null +++ b/Assets/ThinkingAnalytics/TDAnalytics.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ff4bf6c59d1ac413a8f34ced5be76ecd +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/TDAnalytics.cs b/Assets/ThinkingAnalytics/TDAnalytics.cs new file mode 100644 index 0000000..cddfbfe --- /dev/null +++ b/Assets/ThinkingAnalytics/TDAnalytics.cs @@ -0,0 +1,1617 @@ +/* + * + Copyright 2019, ThinkingData, Inc + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + SDK VERSION:3.2.2 + */ + +/** +\mainpage + +\section main_introduction Introduction + +ThinkingData Analytics SDK for Unity. + +This is the [ThinkingData](https://www.thinkingdata.cn)™ Analytics SDK for Unity. Documentation is available on our help center in the following languages: + +- [English](https://docs.thinkingdata.cn/ta-manual/latest/en/installation/installation_menu/client_sdk/game_engine_sdk_installation/unity_sdk_installation/unity_sdk_installation.html) +- [中文](https://docs.thinkingdata.cn/ta-manual/latest/installation/installation_menu/client_sdk/game_engine_sdk_installation/unity_sdk_installation/unity_sdk_installation.html) + + */ + +#if !(UNITY_5_4_OR_NEWER) +#define DISABLE_TA +#warning "Your Unity version is not supported by us - ThinkingAnalyticsSDK disabled" +#endif + +using System; +using System.Collections.Generic; +using ThinkingData.Analytics.Utils; +using ThinkingData.Analytics.Wrapper; +using UnityEngine; +using ThinkingData.Analytics.TDException; +using UnityEngine.SceneManagement; + +namespace ThinkingData.Analytics +{ + /// + /// ThinkingData Analytics SDK for Unity. + /// + [DisallowMultipleComponent] + public class TDAnalytics : MonoBehaviour + { + #region settings + //[System.Serializable] + //public class TDConfig + //{ + // public string appId; + // public string serverUrl; + // public TDMode mode; + // public TDTimeZone timeZone; + // public string timeZoneId; + // public bool enableEncrypt; // enable data encryption, default is false (iOS/Android only) + // public int encryptVersion; // secret key version (iOS/Android only) + // public string encryptPublicKey; // public secret key (iOS/Android only) + // public TDSSLPinningMode pinningMode; // SSL Pinning mode, default is NONE (iOS/Android only) + // public bool allowInvalidCertificates; // allow invalid certificates, default is false (iOS/Android only) + // public bool validatesDomainName; // enable to verify domain name, default is true (iOS/Android only) + // private string sName; + // public string name { set { if (!string.IsNullOrEmpty(value)) sName = value.Replace(" ", ""); } get { return sName; } } // instances name + + // //public TDConfig(string appId, string serverUrl, TDMode mode = TDMode.Normal, TDTimeZone timeZone = TDTimeZone.Local, string timeZoneId = null, string instanceName = null) + // public TDConfig(string appId, string serverUrl) + // { + // this.appId = appId.Replace(" ", ""); + // this.serverUrl = serverUrl; + // this.mode = TDMode.Normal; + // this.timeZone = TDTimeZone.Local; + // this.timeZoneId = null; + // this.enableEncrypt = false; + // this.encryptVersion = 0; + // this.encryptPublicKey = null; + // this.pinningMode = TDSSLPinningMode.NONE; + // this.allowInvalidCertificates = false; + // this.validatesDomainName = true; + // //if (!string.IsNullOrEmpty(instanceName)) + // //{ + // // instanceName = instanceName.Replace(" ", ""); + // //} + // } + + // //public string GetInstanceName() + // //{ + // // return this.instanceName; + // //} + + // public string getTimeZoneId() + // { + // switch (timeZone) + // { + // case TDTimeZone.UTC: + // return "UTC"; + // case TDTimeZone.Asia_Shanghai: + // return "Asia/Shanghai"; + // case TDTimeZone.Asia_Tokyo: + // return "Asia/Tokyo"; + // case TDTimeZone.America_Los_Angeles: + // return "America/Los_Angeles"; + // case TDTimeZone.America_New_York: + // return "America/New_York"; + // case TDTimeZone.Other: + // return timeZoneId; + // default: + // break; + // } + // return null; + // } + //} + + //public enum TDTimeZone + //{ + // Local, + // UTC, + // Asia_Shanghai, + // Asia_Tokyo, + // America_Los_Angeles, + // America_New_York, + // Other = 100 + //} + + //public enum TDMode + //{ + // Debug = 1, + // DebugOnly = 2, + // Normal = 0 + //} + + //public enum TDNetworkType + //{ + // Wifi = 1, + // All = 0 + //} + + [Header("Configuration")] + [Tooltip("Enable Start SDK Manually")] + public bool startManually = true; + + [Tooltip("Enable Log")] + public bool enableLog = true; + [Tooltip("Sets the Network Type")] + public TDNetworkType networkType = TDNetworkType.All; + + [Header("Project")] + [Tooltip("Project Setting, APP ID is given when the project is created")] + [HideInInspector] + public TDConfig[] configs = new TDConfig[1]; + + #endregion + + /// + /// Whether to enable logs + /// + /// enable logs + public static void EnableLog(bool enable) + { + if (sThinkingData != null) + { + sThinkingData.enableLog = enable; + TDLog.EnableLog(enable); + TDWrapper.EnableLog(enable); + } + } + /// + /// Set custom distinct ID, to replace the distinct ID generated by the system + /// + /// distinct ID + /// project ID (optional) + public static void SetDistinctId(string distinctId, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetDistinctId(distinctId, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { distinctId, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Returns the current distinct ID + /// + /// distinct ID + /// project ID (optional) + public static string GetDistinctId(string appId = "") + { + if (tracking_enabled) + { + return TDWrapper.GetDistinctId(appId); + } + return null; + } + + /// + /// Set account ID. This method does not upload Login events + /// + /// account ID + /// project ID (optional) + public static void Login(string account, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Login(account, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { account, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Clear account ID. This method does not upload Logout events + /// + /// project ID (optional) + public static void Logout(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Logout(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Enable auto-tracking + /// + /// auto-tracking eventType + /// properties for auto-tracking events (optional) + /// project ID (optional) + public static void EnableAutoTrack(TDAutoTrackEventType eventType, Dictionary properties = null, string appId = "") + { + if (tracking_enabled) + { + if (properties == null) + { + properties = new Dictionary(); + } + TDWrapper.EnableAutoTrack(eventType, properties, appId); + if ((eventType & TDAutoTrackEventType.AppCrash) != 0 && !TDPublicConfig.DisableCSharpException) + { + TDExceptionHandler.RegisterTAExceptionHandler(properties); + } + if ((eventType & TDAutoTrackEventType.AppSceneLoad) != 0) + { + SceneManager.sceneLoaded -= TDAnalytics.OnSceneLoaded; + SceneManager.sceneLoaded += TDAnalytics.OnSceneLoaded; + } + if ((eventType & TDAutoTrackEventType.AppSceneUnload) != 0) + { + SceneManager.sceneUnloaded -= TDAnalytics.OnSceneUnloaded; + SceneManager.sceneUnloaded += TDAnalytics.OnSceneUnloaded; + } + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventType, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Enable auto-tracking + /// + /// auto-tracking eventType + /// callback for auto-tracking events + /// project ID (optional) + public static void EnableAutoTrack(TDAutoTrackEventType eventType, TDAutoTrackEventHandler eventHandler, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.EnableAutoTrack(eventType, eventHandler, appId); + if ((eventType & TDAutoTrackEventType.AppCrash) != 0 && !TDPublicConfig.DisableCSharpException) + { + TDExceptionHandler.RegisterTAExceptionHandler(eventHandler); + } + if ((eventType & TDAutoTrackEventType.AppSceneLoad) != 0) + { + SceneManager.sceneLoaded -= TDAnalytics.OnSceneLoaded; + SceneManager.sceneLoaded += TDAnalytics.OnSceneLoaded; + } + if ((eventType & TDAutoTrackEventType.AppSceneUnload) != 0) + { + SceneManager.sceneUnloaded -= TDAnalytics.OnSceneUnloaded; + SceneManager.sceneUnloaded += TDAnalytics.OnSceneUnloaded; + } + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventType, eventHandler, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Set properties for auto-tracking events + /// + /// auto-tracking eventType + /// properties for auto-tracking events + /// project ID (optional) + public static void SetAutoTrackProperties(TDAutoTrackEventType eventType, Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetAutoTrackProperties(eventType, properties, appId); + if ((eventType & TDAutoTrackEventType.AppCrash) != 0 && !TDPublicConfig.DisableCSharpException) + { + TDExceptionHandler.SetAutoTrackProperties(properties); + } + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventType, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Track a Event + /// + /// event name + /// project ID (optional) + public static void Track(string eventName, string appId = "") + { + Track(eventName, null, appId); + } + + /// + /// Track a Event + /// + /// the event name + /// properties for the event + /// project ID (optional) + public static void Track(string eventName, Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Track(eventName, properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Track a Event + /// + /// the event name + /// properties for the event + /// date for the event + /// project ID (optional) + //[Obsolete("Method is deprecated, please use Track(string eventName, Dictionary properties, DateTime date, TimeZoneInfo timeZone, string appId = \"\") instead.")] + //public static void Track(string eventName, Dictionary properties, DateTime date, string appId = "") + //{ + // if (tracking_enabled) + // { + // TDWrapper.Track(eventName, properties, date, appId); + // } + // else + // { + // System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + // object[] parameters = new object[] { eventName, properties, date, appId }; + // eventCaches.Add(new Dictionary() { + // { "method", method}, + // { "parameters", parameters} + // }); + // } + //} + + public static void TrackStr(string eventName, string properties = "", string appId = "") + { + if (tracking_enabled) + { + TDWrapper.TrackStr(eventName, properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + + /// + /// Track a Event + /// + /// the event name + /// properties for the event + /// date for the event + /// time zone for the event + /// project ID (optional) + public static void Track(string eventName, Dictionary properties, DateTime time, TimeZoneInfo timeZone, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Track(eventName, properties, time, timeZone, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, time, timeZone, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Track a Special Event (First Event/Updatable Event/Overwritable Event) + /// + /// the special event + /// project ID (optional) + public static void Track(TDEventModel eventModel, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Track(eventModel, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventModel, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Quickly track a Special Event + /// + /// the event name, 'SceneView' for scene view event, 'AppClick' for click event + /// event properties + /// + public static void QuickTrack(string eventName, Dictionary properties = null, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.QuickTrack(eventName, properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Report events data to TE server immediately + /// + /// project ID (optional) + public static void Flush(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Flush(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Scenes load Delegate + /// + /// the load scene + /// the scene loading mode + public static void OnSceneLoaded(Scene scene, LoadSceneMode mode) + { + if (tracking_enabled) + { + TDWrapper.TrackSceneLoad(scene); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { scene, mode }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Scenes unload Delegate + /// + /// the unload scene + public static void OnSceneUnloaded(Scene scene) + { + if (tracking_enabled) + { + TDWrapper.TrackSceneUnload(scene); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { scene }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Super Properties, refer to properties that would be uploaded by each event + /// + /// super properties for events + /// project ID (optional) + public static void SetSuperProperties(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetSuperProperties(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + public static void SetSuperProperties(string properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetSuperProperties(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Delete Property form current Super Properties + /// + /// property name + /// project ID (optional) + public static void UnsetSuperProperty(string property, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UnsetSuperProperty(property, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { property, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Returns current Super Properties + /// + /// current super properties + /// project ID (optional) + public static Dictionary GetSuperProperties(string appId = "") + { + if (tracking_enabled) + { + return TDWrapper.GetSuperProperties(appId); + } + return null; + } + + /// + /// Clear current Super Properties + /// + /// project ID (optional) + public static void ClearSuperProperties(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.ClearSuperProperty(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Returns current Preset Properties + /// + /// current preset properties + /// project ID (optional) + public static TDPresetProperties GetPresetProperties(string appId = "") + { + if (tracking_enabled) + { + Dictionary properties = TDWrapper.GetPresetProperties(appId); + TDPresetProperties presetProperties = new TDPresetProperties(properties); + return presetProperties; + } + return null; + } + + /// + /// Sets the Dynamic Super Properties. + /// + /// dynamic super properties interface + /// project ID (optional) + public static void SetDynamicSuperProperties(TDDynamicSuperPropertiesHandler propertiesHandler, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetDynamicSuperProperties(propertiesHandler, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { propertiesHandler, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Records Event Duration, call TimeEvent to start timing for the Event, call Track to end timing + /// + /// the event name + /// project ID (optional) + public static void TimeEvent(string eventName, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.TimeEvent(eventName, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Sets User Properties, this will overwrite the original properties value + /// + /// user properties + /// project ID (optional) + public static void UserSet(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSet(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + public static void UserSet(string properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSet(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + + /// + /// Sets User Properties, this will overwrite the original properties value + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserSet(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSet(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties , dateTime, appId}; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Unsets one of User Porperties, this would not create properties that have not been created in TE + /// + /// the user property name + /// project ID (optional) + public static void UserUnset(string property, string appId = "") + { + List properties = new List(); + properties.Add(property); + UserUnset(properties, appId); + } + + + /// + /// Unsets some of User Porperties, this would not create properties that have not been created in TE + /// + /// the user properties name + /// project ID (optional) + public static void UserUnset(List properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUnset(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Unsets some of User Porperties, this would not create properties that have not been created in TE + /// + /// the user properties name + /// date time + /// project ID (optional) + public static void UserUnset(List properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUnset(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Sets User Properties for Once. This message would be neglected, if such property had been set before + /// + /// user properties + /// project ID (optional) + public static void UserSetOnce(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSetOnce(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + public static void UserSetOnce(string properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSetOnce(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Sets User Properties for Once. The property would be neglected, if such property had been set before + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserSetOnce(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSetOnce(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime,appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Accumulates the property. If the property has not been set, it would be given a value of 0 before computing. + /// + /// the property name + /// value of the property + /// project ID (optional) + public static void UserAdd(string property, object value, string appId = "") + { + Dictionary properties = new Dictionary() + { + { property, value } + }; + UserAdd(properties, appId); + } + + /// + /// Accumulates the property. If the property has not been set, it would be given a value of 0 before computing. + /// + /// user properties + /// project ID (optional) + public static void UserAdd(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAdd(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + public static void UserAddStr(string properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAddStr(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + + /// + /// Accumulates the property, type of Number. If the property has not been set, it would be given a value of 0 before computing. + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserAdd(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAdd(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Appends the property, type of List. + /// + /// user properties + /// project ID (optional) + public static void UserAppend(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAppend(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + public static void UserAppend(string properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAppend(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + + /// + /// Appends the property, type of List. + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserAppend(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAppend(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Appends the property Uniquely, type of List. If the property has been set, it would be neglected + /// + /// user properties + /// project ID (optional) + public static void UserUniqAppend(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUniqAppend(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + public static void UserUniqAppend(string properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUniqAppend(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Appends the property Uniquely, type of List. If the property has been set, it would be neglected + /// + /// user prpoerties + /// date time + /// project ID (optional) + public static void UserUniqAppend(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUniqAppend(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Deletes All Properties for a user, the events triggered by the user are still exist + /// + /// project ID (optional) + public static void UserDelete(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserDelete(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Deletes All Properties for a user, the events triggered by the user are still exist + /// + /// date time + /// project ID (optional) + //public static void UserDelete(DateTime dateTime, string appId = "") + //{ + // if (tracking_enabled) + // { + // TDWrapper.UserDelete(dateTime, appId); + // } + // else + // { + // System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + // object[] parameters = new object[] { dateTime, appId }; + // eventCaches.Add(new Dictionary() { + // { "method", method}, + // { "parameters", parameters} + // }); + // } + //} + + /// + /// Sets Network Type for report date to TE + /// + /// network type, see TDNetworkType + /// project ID (optional) + public static void SetNetworkType(TDNetworkType networkType, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetNetworkType(networkType); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { networkType, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Gets TDAnalytics SDK version + /// + /// SDK version + public static string GetSDKVersion() + { + return TDPublicConfig.LIB_VERSION; + } + + /// + /// Gets the device identifier. + /// + /// The device identifier. + public static string GetDeviceId() + { + if (tracking_enabled) + { + return TDWrapper.GetDeviceId(); + } + return null; + } + + /// + /// Sets Data Report Status + /// + /// data report status, see TDTrackStatus + /// project ID (optional) + public static void SetTrackStatus(TDTrackStatus status, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetTrackStatus(status, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { status, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Stops Report Event Data, and Clear Cache Data (include unreported event data, custom distinct ID, account ID, Super Properties) + /// + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void OptOutTracking(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.OptOutTracking(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Stops Report Event Data, and Clear Cache Data (include unreported event data, custom distinct ID, account ID, super properties), and Delete User + /// + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void OptOutTrackingAndDeleteUser(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.OptOutTrackingAndDeleteUser(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Resumes Report Event Data + /// + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void OptInTracking(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.OptInTracking(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Enable Report Event Data + /// + /// Whether to enable reported data + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void EnableTracking(bool enabled, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.EnableTracking(enabled, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { enabled, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Creats Light Instance, it has same project ID to main instance, diffent distinct ID, account ID, super properties + /// + /// project ID (optional) + /// light instance token + public static string LightInstance(string appId = "") { + if (tracking_enabled) + { + return TDWrapper.CreateLightInstance(); + } + return null; + } + + /// + /// Calibrate Event Time, calibrated times are used for events after that + /// If both CalibrateTime and CalibrateTimeWithNtp are called, the event time is based on the CalibrateTimeWithNtp result. + /// + /// currnt Unix timestamp, units Ms + public static void CalibrateTime(long timestamp) + { + TDWrapper.CalibrateTime(timestamp); + } + + /// + /// Calibrate Event Time, calibrated times are used for events after that + /// If NTP server is not returns in 3s, the time will not be re-calibrated + /// If both CalibrateTime and CalibrateTimeWithNtp are called, the event time is based on the CalibrateTimeWithNtp result. + /// + /// NTP server, e.g 'time.asia.apple.com' + public static void CalibrateTimeWithNtp(string ntpServer) + { + TDWrapper.CalibrateTimeWithNtp(ntpServer); + } + + /// + /// Cross Platform + /// Share TE account system info to other platforms + /// + /// type of platforms, see TDThirdPartyType + /// properties of platforms + /// project ID (optional) + public static void EnableThirdPartySharing(TDThirdPartyType shareType, Dictionary properties = null, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.EnableThirdPartySharing(shareType, properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { shareType }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Gets the Local Country/Region Code + /// the two-letter code defined in ISO 3166 for the country/region + /// + /// country/region code + public static string GetLocalRegion() + { + return System.Globalization.RegionInfo.CurrentRegion.TwoLetterISORegionName; + } + + /// + /// Start Thinking Analytics SDK + /// + /// project ID + /// project URL + public static void Init(string appId, string serverUrl) + { + TDConfig tDConfig = new TDConfig(appId, serverUrl); + Init(tDConfig); + } + + /// + /// Start Thinking Analytics SDK + /// + /// project setting, see TDConfig + public static void Init(TDConfig config) + { + new GameObject("ThinkingData", typeof(TDAnalytics)); + TDConfig[] configs = new TDConfig[1]; + configs[0] = config; + TDAnalytics.Init(configs); + } + + /// + /// Start Thinking Analytics SDK + /// + /// projects setting, see TDConfig + public static void Init(TDConfig[] configs = null) + { + #if DISABLE_TA + tracking_enabled = false; + #else + tracking_enabled = true; + #endif + + if (tracking_enabled) + { + TDPublicConfig.GetPublicConfig(); + TDLog.EnableLog(sThinkingData.enableLog); + TDWrapper.EnableLog(sThinkingData.enableLog); + TDWrapper.SetVersionInfo(TDPublicConfig.LIB_VERSION); + if (configs == null) + { + configs = sThinkingData.configs; + } + try + { + for (int i = 0; i < configs.Length; i++) + { + TDConfig config = configs[i]; + if (!string.IsNullOrEmpty(config.appId)) + { + config.appId = config.appId.Replace(" ", ""); + TDWrapper.ShareInstance(config, sThinkingData); + TDWrapper.SetNetworkType(sThinkingData.networkType); + if (TDLog.GetEnable()) TDLog.i(string.Format("TDAnalytics SDK initialize success, AppId = {0}, ServerUrl = {1}, Mode = {2}, TimeZone = {3}, DeviceId = {4}, Lib = Unity, LibVersion = {5}{6}", config.appId, config.serverUrl, config.mode, config.timeZone, GetDeviceId(), GetSDKVersion(), (config.name != null ? (", Name = " + config.name) : ""))); + } + } + } + catch (Exception ex) + { + if(TDLog.GetEnable()) TDLog.i("ThinkingAnalytics start Error: " + ex.Message); + } + } + + FlushEventCaches(); + } + + #region internal + private static void FlushEventCaches() + { + List> tmpEventCaches = new List>(eventCaches); + eventCaches.Clear(); + foreach (Dictionary eventCache in tmpEventCaches) + { + if (eventCache.ContainsKey("method") && eventCache.ContainsKey("parameters")) + { + System.Reflection.MethodBase method = (System.Reflection.MethodBase)eventCache["method"]; + object[] parameters = (object[])eventCache["parameters"]; + method.Invoke(null, parameters); + } + } + } + + private void Awake() + { + if (sThinkingData == null) + { + sThinkingData = this; + DontDestroyOnLoad(gameObject); + } + else + { + Destroy(gameObject); + return; + } + + if (this.startManually == false) + { + TDAnalytics.Init(); + } + } + + private void Start() + { + } + + private void OnApplicationQuit() + { + //Scene scene = SceneManager.GetActiveScene(); + //if (scene != null) + //{ + // OnSceneUnloaded(scene); + //} + } + + private static TDAnalytics sThinkingData; + private static bool tracking_enabled = false; + private static List> eventCaches = new List>(); + #endregion + } + + /// + /// SDK Configuration information class + /// + [System.Serializable] + public class TDConfig + { + /// + /// Project ID + /// + public string appId; + /// + /// Project URL + /// + public string serverUrl; + /// + /// SDK Mode + /// + public TDMode mode; + /// + /// TIme Zone Type + /// + public TDTimeZone timeZone; + /// + /// Time Zone ID + /// + public string timeZoneId; + /// + /// enable data encryption, default is false (iOS/Android only) + /// + internal bool enableEncrypt; + /// + /// secret key version (iOS/Android only) + /// + internal int encryptVersion; + /// + /// public secret key (iOS/Android only) + /// + internal string encryptPublicKey; + internal string symType; + internal string asymType; + /// + /// SSL Pinning mode, default is NONE (iOS/Android only) + /// + public TDSSLPinningMode pinningMode; + /// + /// allow invalid certificates, default is false (iOS/Android only) + /// + public bool allowInvalidCertificates; + /// + /// enable to verify domain name, default is true (iOS/Android only) + /// + public bool validatesDomainName; + /// + /// SDK instance name, to call SDK quickly + /// + public string name { set { if (!string.IsNullOrEmpty(value)) sName = value.Replace(" ", ""); } get { return sName; } } // instances name + private string sName; + + /// + /// Construct TDConfig instance + /// + /// project ID + /// project URL + public TDConfig(string appId, string serverUrl) + { + this.appId = appId.Replace(" ", ""); + this.serverUrl = serverUrl; + this.mode = TDMode.Normal; + this.timeZone = TDTimeZone.Local; + this.timeZoneId = null; + this.enableEncrypt = false; + this.encryptPublicKey = null; + this.encryptVersion = 0; + this.symType = null; + this.asymType = null; + this.pinningMode = TDSSLPinningMode.NONE; + this.allowInvalidCertificates = false; + this.validatesDomainName = true; + } + + public void EnableEncrypt(string publicKey, int version = 0, string symType = "", string asymType = "") + { + this.enableEncrypt = true; + this.encryptVersion = version; + this.encryptPublicKey = publicKey; + this.symType = symType; + this.asymType = asymType; + } + + /// + /// Get Time Zone Identify Code in SDK + /// + /// Time Zone ID + public string getTimeZoneId() + { + switch (timeZone) + { + case TDTimeZone.UTC: + return "UTC"; + case TDTimeZone.Asia_Shanghai: + return "Asia/Shanghai"; + case TDTimeZone.Asia_Tokyo: + return "Asia/Tokyo"; + case TDTimeZone.America_Los_Angeles: + return "America/Los_Angeles"; + case TDTimeZone.America_New_York: + return "America/New_York"; + case TDTimeZone.Other: + return timeZoneId; + default: + break; + } + return null; + } + } + +} diff --git a/Assets/ThinkingAnalytics/TDAnalytics.cs.meta b/Assets/ThinkingAnalytics/TDAnalytics.cs.meta new file mode 100644 index 0000000..97dbead --- /dev/null +++ b/Assets/ThinkingAnalytics/TDAnalytics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7df5c5e5307f460e917e72bf75ec567 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/TDAnalytics.prefab b/Assets/ThinkingAnalytics/TDAnalytics.prefab new file mode 100644 index 0000000..6b69e88 --- /dev/null +++ b/Assets/ThinkingAnalytics/TDAnalytics.prefab @@ -0,0 +1,61 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3471622134282543401 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 57277738888238098} + - component: {fileID: 1362306111410183020} + m_Layer: 0 + m_Name: TDAnalytics + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &57277738888238098 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3471622134282543401} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1362306111410183020 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3471622134282543401} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7df5c5e5307f460e917e72bf75ec567, type: 3} + m_Name: + m_EditorClassIdentifier: + startManually: 1 + enableLog: 1 + networkType: 1 + configs: + - appId: 1b1c1fef65e3482bad5c9d0e6a823356 + serverUrl: https://receiver.ta.thinkingdata.cn + mode: 0 + timeZone: 0 + timeZoneId: + enableEncrypt: 0 + encryptVersion: 0 + encryptPublicKey: + pinningMode: 0 + allowInvalidCertificates: 0 + validatesDomainName: 0 diff --git a/Assets/ThinkingAnalytics/TDAnalytics.prefab.meta b/Assets/ThinkingAnalytics/TDAnalytics.prefab.meta new file mode 100644 index 0000000..4413269 --- /dev/null +++ b/Assets/ThinkingAnalytics/TDAnalytics.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 986ad473b78d14e08b1f05d368cb1591 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/TDEnum.cs b/Assets/ThinkingAnalytics/TDEnum.cs new file mode 100644 index 0000000..7ed5d6e --- /dev/null +++ b/Assets/ThinkingAnalytics/TDEnum.cs @@ -0,0 +1,64 @@ +using System; + +namespace ThinkingData.Analytics +{ + /// + /// Time Zone in SDK options + /// + public enum TDTimeZone + { + Local, + UTC, + Asia_Shanghai, + Asia_Tokyo, + America_Los_Angeles, + America_New_York, + Other = 100 + } + + /// + /// SDK running mode options + /// + public enum TDMode + { + Debug = 1, + DebugOnly = 2, + Normal = 0 + } + + /// + /// Data post options + /// + public enum TDNetworkType + { + Wifi = 2, + All = 1 + } + + /// + /// Auto-tracking Events Type options + /// + [Flags] + 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 + } +} \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/TDEnum.cs.meta b/Assets/ThinkingAnalytics/TDEnum.cs.meta new file mode 100644 index 0000000..5fcf5d1 --- /dev/null +++ b/Assets/ThinkingAnalytics/TDEnum.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d704b4acc93944242809914ff26be411 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/TDEvent.cs b/Assets/ThinkingAnalytics/TDEvent.cs new file mode 100644 index 0000000..d143e1d --- /dev/null +++ b/Assets/ThinkingAnalytics/TDEvent.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; + +namespace ThinkingData.Analytics +{ + /// + /// Special event class for internal use, do not use this class directly. + /// + public abstract class TDEventModel + { + public enum TDEventType + { + First, + Updatable, + Overwritable + } + + public TDEventModel(string eventName) + { + EventName = eventName; + } + + public TDEventType? EventType { get; set; } + public string EventName { get; } + public Dictionary Properties { get; set; } + public string StrProperties { get; set; } + + private DateTime EventTime { get; set; } + private TimeZoneInfo EventTimeZone { get; set; } + protected string ExtraId { get; set; } + + /// + /// Set date time and timezone for the event + /// + /// date time + /// timezone + public void SetTime(DateTime time, TimeZoneInfo timeZone) + { + EventTime = time; + EventTimeZone = timeZone; + } + + /// + /// Get date time for the event + /// + /// + public DateTime GetEventTime() + { + return EventTime; + } + + /// + /// Get timezone for the event + /// + /// + public TimeZoneInfo GetEventTimeZone() + { + return EventTimeZone; + } + + /// + /// Get identify code for the event + /// + /// + public string GetEventId() + { + return ExtraId; + } + } + + /// + /// First Event Model + /// + public class TDFirstEventModel : TDEventModel + { + /// + /// Construct TDFirstEventModel instance + /// + /// name for the event + public TDFirstEventModel(string eventName) : base(eventName) + { + EventType = TDEventType.First; + } + + /// + /// Construct TDFirstEventModel instance + /// + /// name for the event + /// check ID for the first event + public TDFirstEventModel(string eventName, string firstCheckId) : base(eventName) + { + EventType = TDEventType.First; + ExtraId = firstCheckId; + } + } + + /// + /// Updatable Event Model + /// + public class TDUpdatableEventModel : TDEventModel + { + /// + /// Construct TDUpdatableEventModel instance + /// + /// name for the event + /// ID for the event + public TDUpdatableEventModel(string eventName, string eventId) : base(eventName) + { + EventType = TDEventType.Updatable; + ExtraId = eventId; + } + } + + /// + /// Overwritable Event Model + /// + public class TDOverwritableEventModel : TDEventModel + { + /// + /// Construct TDOverwritableEventModel instance + /// + /// name for the event + /// ID for the event + public TDOverwritableEventModel(string eventName, string eventId) : base(eventName) + { + EventType = TDEventType.Overwritable; + ExtraId = eventId; + } + } + +} \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/TDEvent.cs.meta b/Assets/ThinkingAnalytics/TDEvent.cs.meta new file mode 100644 index 0000000..77f698f --- /dev/null +++ b/Assets/ThinkingAnalytics/TDEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e80e3a99b3f0414187c8b3e448b4d66 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/TDInterface.cs b/Assets/ThinkingAnalytics/TDInterface.cs new file mode 100644 index 0000000..88f33f1 --- /dev/null +++ b/Assets/ThinkingAnalytics/TDInterface.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace ThinkingData.Analytics +{ + /// + /// Dynamic super properties interfaces. + /// + public interface TDDynamicSuperPropertiesHandler + { + /// + /// Dynamically gets event properties + /// + /// event properties + Dictionary GetDynamicSuperProperties(); + } + + /// + /// Auto track event callback interfaces. + /// + public interface TDAutoTrackEventHandler + { + /// + /// Get Auto track event properties + /// + /// auto track event type + /// event properties + /// event properties + Dictionary GetAutoTrackEventProperties(int type, Dictionary properties); + } +} \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/TDInterface.cs.meta b/Assets/ThinkingAnalytics/TDInterface.cs.meta new file mode 100644 index 0000000..96f6ca1 --- /dev/null +++ b/Assets/ThinkingAnalytics/TDInterface.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bba307e0084684dc08b109bd32fb415f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/TDPresetProperties.cs b/Assets/ThinkingAnalytics/TDPresetProperties.cs new file mode 100644 index 0000000..c60dd58 --- /dev/null +++ b/Assets/ThinkingAnalytics/TDPresetProperties.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; + +namespace ThinkingData.Analytics +{ + /// + /// Preset Properties + /// + public class TDPresetProperties + { + /// + /// Construct TDPresetProperties instance + /// + /// preset properties + public TDPresetProperties(Dictionary properties) + { + properties = TDEncodeDate(properties); + mPresetProperties = properties; + } + /// + /// Returns Preset Properties + /// The key starts with "#", it is not recommended to use it directly as a user properties + /// + /// preset properties + public Dictionary ToDictionary() + { + return mPresetProperties; + } + /// + /// Application Version Number + /// + public string AppVersion + { + get { return (string)(mPresetProperties.ContainsKey("#app_version") ? mPresetProperties["#app_version"] : ""); } + } + /// + /// Application Bundle Identify + /// + public string BundleId + { + get { return (string)(mPresetProperties.ContainsKey("#bundle_id") ? mPresetProperties["#bundle_id"] : ""); } + } + /// + /// Device Network Carrier + /// + public string Carrier + { + get { return (string)(mPresetProperties.ContainsKey("#carrier") ? mPresetProperties["#carrier"] : ""); } + } + /// + /// Device Identify + /// + public string DeviceId + { + get { return (string)(mPresetProperties.ContainsKey("#device_id") ? mPresetProperties["#device_id"] : ""); } + } + /// + /// Device Model Name + /// + public string DeviceModel + { + get { return (string)(mPresetProperties.ContainsKey("#device_model") ? mPresetProperties["#device_model"] : ""); } + } + /// + /// Device Hardware Manufacturer + /// + public string Manufacturer + { + get { return (string)(mPresetProperties.ContainsKey("#manufacturer") ? mPresetProperties["#manufacturer"] : ""); } + } + /// + /// Device Network Type + /// + public string NetworkType + { + get { return (string)(mPresetProperties.ContainsKey("#network_type") ? mPresetProperties["#network_type"] : ""); } + } + /// + /// Device System OS Name + /// + public string OS + { + get { return (string)(mPresetProperties.ContainsKey("#os") ? mPresetProperties["#os"] : ""); } + } + /// + /// Device System OS Version Number + /// + public string OSVersion + { + get { return (string)(mPresetProperties.ContainsKey("#os_version") ? mPresetProperties["#os_version"] : ""); } + } + /// + /// Screen Height + /// + public double ScreenHeight + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#screen_height") ? mPresetProperties["#screen_height"] : 0); } + } + /// + /// Screen Width + /// + public double ScreenWidth + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#screen_width") ? mPresetProperties["#screen_width"] : 0); } + } + /// + /// Device System Language Code + /// + public string SystemLanguage + { + get { return (string)(mPresetProperties.ContainsKey("#system_language") ? mPresetProperties["#system_language"] : ""); } + } + /// + /// Time Zone Offset With UTC + /// + public double ZoneOffset + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#zone_offset") ? mPresetProperties["#zone_offset"] : 0); } + } + /// + /// Application Install Time + /// + public string InstallTime + { + get { return (string)(mPresetProperties.ContainsKey("#install_time") ? mPresetProperties["#install_time"] : ""); } + } + /// + /// Device Disk Size + /// + public string Disk + { + get { return (string)(mPresetProperties.ContainsKey("#disk") ? mPresetProperties["#disk"] : ""); } + } + /// + /// Device Ram Size + /// + public string Ram + { + get { return (string)(mPresetProperties.ContainsKey("#ram") ? mPresetProperties["#ram"] : ""); } + } + /// + /// Device FPS + /// + public double Fps + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#fps") ? mPresetProperties["#fps"] : 0); } + } + /// + /// Device is an Simulator + /// + public bool Simulator + { + get { return (bool)(mPresetProperties.ContainsKey("#simulator") ? mPresetProperties["#simulator"] : false); } + } + + private Dictionary mPresetProperties { get; set; } + private Dictionary TDEncodeDate(Dictionary properties) + { + Dictionary mProperties = new Dictionary(); + foreach (KeyValuePair kv in properties) + { + if (kv.Value is DateTime) + { + DateTime dateTime = (DateTime)kv.Value; + mProperties.Add(kv.Key, dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture)); + } + else + { + mProperties.Add(kv.Key, kv.Value); + } + } + return mProperties; + } + } +} \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/TDPresetProperties.cs.meta b/Assets/ThinkingAnalytics/TDPresetProperties.cs.meta new file mode 100644 index 0000000..bdf2e3b --- /dev/null +++ b/Assets/ThinkingAnalytics/TDPresetProperties.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 23d7545160a0c4e67be49833c78690e3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/ThinkingAnalyticsAPI.cs b/Assets/ThinkingAnalytics/ThinkingAnalyticsAPI.cs new file mode 100644 index 0000000..aa63d54 --- /dev/null +++ b/Assets/ThinkingAnalytics/ThinkingAnalyticsAPI.cs @@ -0,0 +1,1753 @@ +/* + * + Copyright 2019, ThinkingData, Inc + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + SDK VERSION:3.2.2 + */ +#if !(UNITY_5_4_OR_NEWER) +#define DISABLE_TA +#warning "Your Unity version is not supported by us - ThinkingAnalyticsSDK disabled" +#endif + +using System; +using System.Collections.Generic; +using ThinkingData.Analytics; +using ThinkingData.Analytics.Utils; +using ThinkingData.Analytics.Wrapper; +using UnityEngine; +using ThinkingData.Analytics.TDException; +using UnityEngine.SceneManagement; + +namespace ThinkingAnalytics +{ + [DisallowMultipleComponent] + [Obsolete("ThinkingAnalyticsAPI is deprecated, please use ThinkingData.Analytics instead.")] + public class ThinkingAnalyticsAPI : MonoBehaviour, TDDynamicSuperPropertiesHandler, TDAutoTrackEventHandler + { + #region settings + [System.Serializable] + public struct Token + { + public string appid; + public string serverUrl; + public TAMode mode; + public TATimeZone timeZone; + public string timeZoneId; + public bool enableEncrypt; // enable data encryption, default is false (iOS/Android only) + public int encryptVersion; // secret key version (iOS/Android only) + public string encryptPublicKey; // public secret key (iOS/Android only) + public TDSSLPinningMode pinningMode; // SSL Pinning mode, default is NONE (iOS/Android only) + public bool allowInvalidCertificates; // allow invalid certificates, default is false (iOS/Android only) + public bool validatesDomainName; // enable to verify domain name, default is true (iOS/Android only) + private string instanceName; // instances name + + public Token(string appId, string serverUrl, TAMode mode = TAMode.NORMAL, TATimeZone timeZone = TATimeZone.Local, string timeZoneId = null, string instanceName = null) + { + this.appid = appId.Replace(" ", ""); + this.serverUrl = serverUrl; + this.mode = mode; + this.timeZone = timeZone; + this.timeZoneId = timeZoneId; + this.enableEncrypt = false; + this.encryptVersion = 0; + this.encryptPublicKey = null; + this.pinningMode = TDSSLPinningMode.NONE; + this.allowInvalidCertificates = false; + this.validatesDomainName = true; + if (!string.IsNullOrEmpty(instanceName)) + { + instanceName = instanceName.Replace(" ", ""); + } + this.instanceName = instanceName; + } + + public string GetInstanceName() + { + return this.instanceName; + } + + public string getTimeZoneId() + { +#if UNITY_STANDALONE_WIN + switch (timeZone) + { + case TATimeZone.UTC: + return "UTC"; + case TATimeZone.Asia_Shanghai: + return "China Standard Time"; + case TATimeZone.Asia_Tokyo: + return "Tokyo Standard Time"; + case TATimeZone.America_Los_Angeles: + return "Pacific Standard Time"; + case TATimeZone.America_New_York: + return "Eastern Standard Time"; + case TATimeZone.Other: + return timeZoneId; + default: + break; + } +#else + switch (timeZone) + { + case TATimeZone.UTC: + return "UTC"; + case TATimeZone.Asia_Shanghai: + return "Asia/Shanghai"; + case TATimeZone.Asia_Tokyo: + return "Asia/Tokyo"; + case TATimeZone.America_Los_Angeles: + return "America/Los_Angeles"; + case TATimeZone.America_New_York: + return "America/New_York"; + case TATimeZone.Other: + return timeZoneId; + default: + break; + } +#endif + return null; + } + + internal TDConfig ToTDConfig() + { + TDConfig config = new TDConfig(this.appid, this.serverUrl); + config.mode = (TDMode)this.mode; + config.timeZone = (TDTimeZone)this.timeZone; + config.timeZoneId = this.timeZoneId; + config.pinningMode = this.pinningMode; + config.allowInvalidCertificates = this.allowInvalidCertificates; + config.validatesDomainName = this.validatesDomainName; + config.name = this.instanceName; + if(this.enableEncrypt){ + config.EnableEncrypt(this.encryptPublicKey, this.encryptVersion); + } + return config; + } + } + + public enum TATimeZone + { + Local, + UTC, + Asia_Shanghai, + Asia_Tokyo, + America_Los_Angeles, + America_New_York, + Other = 100 + } + + public enum TAMode + { + NORMAL = 0, + DEBUG = 1, + DEBUG_ONLY = 2 + } + + public enum NetworkType + { + DEFAULT = 1, + WIFI = 2, + ALL = 3 + } + + [Header("Configuration")] + [Tooltip("Enable Start SDK Manually")] + public bool startManually = true; + + [Tooltip("Enable Log")] + public bool enableLog = true; + [Tooltip("Sets the Network Type")] + public NetworkType networkType = NetworkType.DEFAULT; + + [Header("Project")] + [Tooltip("Project Setting, APP ID is given when the project is created")] + [HideInInspector] + public Token[] tokens = new Token[1]; + +#endregion + + /// + /// Whether to enable logs + /// + /// enable logs + public static void EnableLog(bool enable, string appId = "") + { + if (sThinkingAnalyticsAPI != null) + { + sThinkingAnalyticsAPI.enableLog = enable; + TDLog.EnableLog(enable); + TDWrapper.EnableLog(enable); + } + } + /// + /// Set custom distinct ID, to replace the distinct ID generated by the system + /// + /// distinct ID + /// project ID (optional) + public static void Identify(string distinctId, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetDistinctId(distinctId, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { distinctId, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Returns the current distinct ID + /// + /// distinct ID + /// project ID (optional) + public static string GetDistinctId(string appId = "") + { + if (tracking_enabled) + { + return TDWrapper.GetDistinctId(appId); + } + return null; + } + + /// + /// Set account ID. This method does not upload Login events + /// + /// account ID + /// project ID (optional) + public static void Login(string account, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Login(account, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { account, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Clear account ID. This method does not upload Logout events + /// + /// project ID (optional) + public static void Logout(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Logout(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Enable auto-tracking + /// + /// auto-tracking events + /// properties for auto-tracking events (optional) + /// project ID (optional) + public static void EnableAutoTrack(AUTO_TRACK_EVENTS events, Dictionary properties = null, string appId = "") + { + if (tracking_enabled) + { + if (properties == null) + { + properties = new Dictionary(); + } + TDWrapper.EnableAutoTrack((TDAutoTrackEventType)events, properties, appId); + if ((events & AUTO_TRACK_EVENTS.AppCrash) != 0 && !TDPublicConfig.DisableCSharpException) + { + TDExceptionHandler.RegisterTAExceptionHandler(properties); + } + if ((events & AUTO_TRACK_EVENTS.AppSceneLoad) != 0) + { + SceneManager.sceneLoaded -= ThinkingAnalyticsAPI.OnSceneLoaded; + SceneManager.sceneLoaded += ThinkingAnalyticsAPI.OnSceneLoaded; + } + if ((events & AUTO_TRACK_EVENTS.AppSceneUnload) != 0) + { + SceneManager.sceneUnloaded -= ThinkingAnalyticsAPI.OnSceneUnloaded; + SceneManager.sceneUnloaded += ThinkingAnalyticsAPI.OnSceneUnloaded; + } + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { events, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Enable auto-tracking + /// + /// auto-tracking events + /// callback for auto-tracking events (optional) + /// project ID (optional) + public static void EnableAutoTrack(AUTO_TRACK_EVENTS events, IAutoTrackEventCallback eventCallback, string appId = "") + { + if (tracking_enabled) + { + sThinkingAnalyticsAPI._eventCallback = eventCallback; + TDWrapper.EnableAutoTrack((TDAutoTrackEventType)events, sThinkingAnalyticsAPI, appId); + if ((events & AUTO_TRACK_EVENTS.AppCrash) != 0 && !TDPublicConfig.DisableCSharpException) + { + TDExceptionHandler.RegisterTAExceptionHandler(sThinkingAnalyticsAPI); + } + if ((events & AUTO_TRACK_EVENTS.AppSceneLoad) != 0) + { + SceneManager.sceneLoaded -= ThinkingAnalyticsAPI.OnSceneLoaded; + SceneManager.sceneLoaded += ThinkingAnalyticsAPI.OnSceneLoaded; + } + if ((events & AUTO_TRACK_EVENTS.AppSceneUnload) != 0) + { + SceneManager.sceneUnloaded -= ThinkingAnalyticsAPI.OnSceneUnloaded; + SceneManager.sceneUnloaded += ThinkingAnalyticsAPI.OnSceneUnloaded; + } + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { events, eventCallback, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Set properties for auto-tracking events + /// + /// auto-tracking events + /// properties for auto-tracking events + /// project ID (optional) + public static void SetAutoTrackProperties(AUTO_TRACK_EVENTS events, Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetAutoTrackProperties((TDAutoTrackEventType)events, properties, appId); + if ((events & AUTO_TRACK_EVENTS.AppCrash) != 0 && !TDPublicConfig.DisableCSharpException) + { + TDWrapper.SetAutoTrackProperties((TDAutoTrackEventType)events ,properties, appId); + } + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { events, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Track a Event + /// + /// event name + /// project ID (optional) + public static void Track(string eventName, string appId = "") + { + Track(eventName, null, appId); + } + + /// + /// Track a Event + /// + /// the event name + /// properties for the event + /// project ID (optional) + public static void Track(string eventName, Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Track(eventName, properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Track a Event + /// + /// the event name + /// properties for the event + /// date for the event + /// project ID (optional) + [Obsolete("Method is deprecated, please use Track(string eventName, Dictionary properties, DateTime date, TimeZoneInfo timeZone, string appId = \"\") instead.")] + public static void Track(string eventName, Dictionary properties, DateTime date, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Track(eventName, properties, date, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, date, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Track a Event + /// + /// the event name + /// properties for the event + /// date for the event + /// time zone for the event + /// project ID (optional) + public static void Track(string eventName, Dictionary properties, DateTime date, TimeZoneInfo timeZone, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Track(eventName, properties, date, timeZone, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, date, timeZone, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Track a Special Event (First Event/Updatable Event/Overwritable Event) + /// + /// the special event + /// project ID (optional) + public static void Track(ThinkingAnalyticsEvent analyticsEvent, string appId = "") + { + if (tracking_enabled) + { + TDEventModel eventModel; + if (analyticsEvent.EventType == ThinkingAnalyticsEvent.Type.UPDATABLE) + { + eventModel = new TDUpdatableEventModel(analyticsEvent.EventName, analyticsEvent.ExtraId); + } + else if (analyticsEvent.EventType == ThinkingAnalyticsEvent.Type.OVERWRITABLE) + { + eventModel = new TDUpdatableEventModel(analyticsEvent.EventName, analyticsEvent.ExtraId); + } + else + { + if (string.IsNullOrEmpty(analyticsEvent.ExtraId)) + { + eventModel = new TDFirstEventModel(analyticsEvent.EventName); + } + else + { + eventModel = new TDFirstEventModel(analyticsEvent.EventName, analyticsEvent.ExtraId); + } + } + eventModel.Properties = analyticsEvent.Properties; + eventModel.SetTime(analyticsEvent.EventTime, analyticsEvent.EventTimeZone); + TDWrapper.Track(eventModel, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { analyticsEvent, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Quickly track a Special Event + /// + /// the event name, 'SceneView' for scene view event, 'AppClick' for click event + /// event properties + /// + public static void QuickTrack(string eventName, Dictionary properties = null, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.QuickTrack(eventName, properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Report events data to TE server immediately + /// + /// project ID (optional) + public static void Flush(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.Flush(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Scenes load Delegate + /// + /// the load scene + /// the scene loading mode + public static void OnSceneLoaded(Scene scene, LoadSceneMode mode) + { + if (tracking_enabled) + { + TDWrapper.TrackSceneLoad(scene); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { scene, mode }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Scenes unload Delegate + /// + /// the unload scene + public static void OnSceneUnloaded(Scene scene) + { + if (tracking_enabled) + { + TDWrapper.TrackSceneUnload(scene); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { scene }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Super Properties, refer to properties that would be uploaded by each event + /// + /// super properties for events + /// project ID (optional) + public static void SetSuperProperties(Dictionary superProperties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetSuperProperties(superProperties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { superProperties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Delete Property form current Super Properties + /// + /// property name + /// project ID (optional) + public static void UnsetSuperProperty(string property, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UnsetSuperProperty(property, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { property, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Returns current Super Properties + /// + /// current super properties + /// project ID (optional) + public static Dictionary GetSuperProperties(string appId = "") + { + if (tracking_enabled) + { + return TDWrapper.GetSuperProperties(appId); + } + return null; + } + + /// + /// Clear current Super Properties + /// + /// project ID (optional) + public static void ClearSuperProperties(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.ClearSuperProperty(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Returns current Preset Properties + /// + /// current preset properties + /// project ID (optional) + public static TDPresetProperties GetPresetProperties(string appId = "") + { + if (tracking_enabled) + { + Dictionary properties = TDWrapper.GetPresetProperties(appId); + TDPresetProperties presetProperties = new TDPresetProperties(properties); + return presetProperties; + } + return null; + } + + /// + /// Sets the Dynamic Super Properties. + /// + /// dynamic super properties interface + /// project ID (optional) + public static void SetDynamicSuperProperties(IDynamicSuperProperties dynamicSuperProperties, string appId = "") + { + if (tracking_enabled) + { + sThinkingAnalyticsAPI._dynamicSuperProperties = dynamicSuperProperties; + TDWrapper.SetDynamicSuperProperties(sThinkingAnalyticsAPI, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { dynamicSuperProperties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Records Event Duration, call TimeEvent to start timing for the Event, call Track to end timing + /// + /// the event name + /// project ID (optional) + public static void TimeEvent(string eventName, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.TimeEvent(eventName, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { eventName, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Sets User Properties, this will overwrite the original properties value + /// + /// user properties + /// project ID (optional) + public static void UserSet(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSet(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Sets User Properties, this will overwrite the original properties value + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserSet(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSet(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties , dateTime, appId}; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Unsets one of User Porperties, this would not create properties that have not been created in TE + /// + /// the user property name + /// project ID (optional) + public static void UserUnset(string property, string appId = "") + { + List properties = new List(); + properties.Add(property); + UserUnset(properties, appId); + } + + + /// + /// Unsets some of User Porperties, this would not create properties that have not been created in TE + /// + /// the user properties name + /// project ID (optional) + public static void UserUnset(List properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUnset(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Unsets some of User Porperties, this would not create properties that have not been created in TE + /// + /// the user properties name + /// date time + /// project ID (optional) + public static void UserUnset(List properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUnset(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Sets User Properties for Once. This message would be neglected, if such property had been set before + /// + /// user properties + /// project ID (optional) + public static void UserSetOnce(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSetOnce(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Sets User Properties for Once. The property would be neglected, if such property had been set before + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserSetOnce(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserSetOnce(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime,appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + + } + + /// + /// Accumulates the property. If the property has not been set, it would be given a value of 0 before computing. + /// + /// the property name + /// value of the property + /// project ID (optional) + public static void UserAdd(string property, object value, string appId = "") + { + Dictionary properties = new Dictionary() + { + { property, value } + }; + UserAdd(properties, appId); + } + + /// + /// Accumulates the property. If the property has not been set, it would be given a value of 0 before computing. + /// + /// user properties + /// project ID (optional) + public static void UserAdd(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAdd(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Accumulates the property, type of Number. If the property has not been set, it would be given a value of 0 before computing. + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserAdd(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAdd(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Appends the property, type of List. + /// + /// user properties + /// project ID (optional) + public static void UserAppend(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAppend(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Appends the property, type of List. + /// + /// user properties + /// date time + /// project ID (optional) + public static void UserAppend(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserAppend(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Appends the property Uniquely, type of List. If the property has been set, it would be neglected + /// + /// user properties + /// project ID (optional) + public static void UserUniqAppend(Dictionary properties, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUniqAppend(properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Appends the property Uniquely, type of List. If the property has been set, it would be neglected + /// + /// user prpoerties + /// date time + /// project ID (optional) + public static void UserUniqAppend(Dictionary properties, DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserUniqAppend(properties, dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { properties, dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Deletes All Properties for a user, the events triggered by the user are still exist + /// + /// project ID (optional) + public static void UserDelete(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserDelete(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Deletes All Properties for a user, the events triggered by the user are still exist + /// + /// date time + /// project ID (optional) + public static void UserDelete(DateTime dateTime, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.UserDelete(dateTime, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { dateTime, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Sets Network Type for report date to TE + /// + /// network type, see NetworkType + /// project ID (optional) + public static void SetNetworkType(NetworkType networkType, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetNetworkType((TDNetworkType)networkType); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { networkType, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Gets the device identifier. + /// + /// The device identifier. + public static string GetDeviceId() + { + if (tracking_enabled) + { + return TDWrapper.GetDeviceId(); + } + return null; + } + + /// + /// Sets Data Report Status + /// + /// data report status, see TA_TRACK_STATUS + /// project ID (optional) + public static void SetTrackStatus(TA_TRACK_STATUS status, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.SetTrackStatus((TDTrackStatus)status, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { status, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Stops Report Event Data, and Clear Cache Data (include unreported event data, custom distinct ID, account ID, Super Properties) + /// + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void OptOutTracking(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.OptOutTracking(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Stops Report Event Data, and Clear Cache Data (include unreported event data, custom distinct ID, account ID, super properties), and Delete User + /// + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void OptOutTrackingAndDeleteUser(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.OptOutTrackingAndDeleteUser(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Resumes Report Event Data + /// + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void OptInTracking(string appId = "") + { + if (tracking_enabled) + { + TDWrapper.OptInTracking(appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Enable Report Event Data + /// + /// Whether to enable reported data + /// project ID (optional) + [Obsolete("Method is deprecated, please use SetTrackStatus() instead.")] + public static void EnableTracking(bool enabled, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.EnableTracking(enabled, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { enabled, appId }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Creats Light Instance, it has same project ID to main instance, diffent distinct ID, account ID, super properties + /// + /// project ID (optional) + /// light instance token + public static string CreateLightInstance(string appId = "") { + if (tracking_enabled) + { + return TDWrapper.CreateLightInstance(); + } + return null; + } + + /// + /// Calibrate Event Time, calibrated times are used for events after that + /// + /// currnt Unix timestamp, units Ms + public static void CalibrateTime(long timestamp) + { + TDWrapper.CalibrateTime(timestamp); + } + + /// + /// Calibrate Event Time, calibrated times are used for events after that + /// If NTP server is not returns in 3s, the time will not be re-calibrated + /// + /// NTP server, e.g 'time.asia.apple.com' + public static void CalibrateTimeWithNtp(string ntpServer) + { + TDWrapper.CalibrateTimeWithNtp(ntpServer); + } + + /// + /// Cross Platform + /// Share TE account system info to other platforms + /// + /// type of platforms, see TAThirdPartyShareType + /// properties of platforms + /// project ID (optional) + public static void EnableThirdPartySharing(TAThirdPartyShareType shareType, Dictionary properties = null, string appId = "") + { + if (tracking_enabled) + { + TDWrapper.EnableThirdPartySharing((TDThirdPartyType)shareType, properties, appId); + } + else + { + System.Reflection.MethodBase method = System.Reflection.MethodBase.GetCurrentMethod(); + object[] parameters = new object[] { shareType }; + eventCaches.Add(new Dictionary() { + { "method", method}, + { "parameters", parameters} + }); + } + } + + /// + /// Gets the Local Country/Region Code + /// the two-letter code defined in ISO 3166 for the country/region + /// + /// country/region code + public static string GetLocalRegion() + { + return System.Globalization.RegionInfo.CurrentRegion.TwoLetterISORegionName; + } + + /// + /// Start Thinking Analytics SDK + /// + /// project ID + /// project URL + public static void StartThinkingAnalytics(string appId, string serverUrl) + { + ThinkingAnalyticsAPI.TAMode mode = ThinkingAnalyticsAPI.TAMode.NORMAL; + ThinkingAnalyticsAPI.TATimeZone timeZone = ThinkingAnalyticsAPI.TATimeZone.Local; + ThinkingAnalyticsAPI.Token token = new ThinkingAnalyticsAPI.Token(appId, serverUrl, mode, timeZone); + ThinkingAnalyticsAPI.StartThinkingAnalytics(token); + } + + /// + /// Start Thinking Analytics SDK + /// + /// project setting, see ThinkingAnalyticsAPI.Token + public static void StartThinkingAnalytics(ThinkingAnalyticsAPI.Token token) + { + ThinkingAnalyticsAPI.Token[] tokens = new ThinkingAnalyticsAPI.Token[1]; + tokens[0] = token; + ThinkingAnalyticsAPI.StartThinkingAnalytics(tokens); + } + + /// + /// Start Thinking Analytics SDK + /// + /// projects setting, see ThinkingAnalyticsAPI.Token + public static void StartThinkingAnalytics(Token[] tokens = null) + { +#if DISABLE_TA + tracking_enabled = false; +#else + tracking_enabled = true; +#endif + + if (tracking_enabled) + { + TDPublicConfig.GetPublicConfig(); + TDLog.EnableLog(sThinkingAnalyticsAPI.enableLog); + TDWrapper.EnableLog(sThinkingAnalyticsAPI.enableLog); + TDWrapper.SetVersionInfo(TDPublicConfig.LIB_VERSION); + if (tokens == null) + { + tokens = sThinkingAnalyticsAPI.tokens; + } + try + { + for (int i = 0; i < tokens.Length; i++) + { + Token token = tokens[i]; + if (!string.IsNullOrEmpty(token.appid)) + { + token.appid = token.appid.Replace(" ", ""); + if(TDLog.GetEnable()) TDLog.d("ThinkingAnalytics start with APPID: " + token.appid + ", SERVERURL: " + token.serverUrl + ", MODE: " + token.mode); + TDWrapper.ShareInstance(token.ToTDConfig(), sThinkingAnalyticsAPI); + TDWrapper.SetNetworkType((TDNetworkType)sThinkingAnalyticsAPI.networkType); + } + } + } + catch (Exception ex) + { + if(TDLog.GetEnable()) TDLog.d("ThinkingAnalytics start Error: " + ex.Message); + } + } + + FlushEventCaches(); + } + + #region internal + private static void FlushEventCaches() + { + List> tmpEventCaches = new List>(eventCaches); + eventCaches.Clear(); + foreach (Dictionary eventCache in tmpEventCaches) + { + if (eventCache.ContainsKey("method") && eventCache.ContainsKey("parameters")) + { + System.Reflection.MethodBase method = (System.Reflection.MethodBase)eventCache["method"]; + object[] parameters = (object[])eventCache["parameters"]; + method.Invoke(null, parameters); + } + } + } + + private void Awake() + { + if (sThinkingAnalyticsAPI == null) + { + sThinkingAnalyticsAPI = this; + DontDestroyOnLoad(gameObject); + } + else + { + Destroy(gameObject); + return; + } + + if (this.startManually == false) + { + ThinkingAnalyticsAPI.StartThinkingAnalytics(); + } + } + + private void Start() + { + } + + private void OnApplicationQuit() + { + //Scene scene = SceneManager.GetActiveScene(); + //if (scene != null) + //{ + // OnSceneUnloaded(scene); + //} + } + + private static ThinkingAnalyticsAPI sThinkingAnalyticsAPI; + private static bool tracking_enabled = false; + private static List> eventCaches = new List>(); + private IDynamicSuperProperties _dynamicSuperProperties; + private IAutoTrackEventCallback _eventCallback; + #endregion + + /// + /// Dynamically gets event properties + /// + /// event properties + public Dictionary GetDynamicSuperProperties() + { + if (this._dynamicSuperProperties != null) + { + return this._dynamicSuperProperties.GetDynamicSuperProperties(); + } + else + { + return null; + } + } + /// + /// Get Auto track event properties + /// + /// auto track event type + /// event properties + /// event properties + public Dictionary GetAutoTrackEventProperties(int type, Dictionary properties) + { + if (this._eventCallback != null) + { + return this._eventCallback.AutoTrackEventCallback(type, properties); + } + else + { + return null; + } + } + } + + // Auto-tracking Events Type + [Obsolete("AUTO_TRACK_EVENTS is deprecated, please use ThinkingData.Analytics.TDAutoTrackEventType instead.")] + public enum AUTO_TRACK_EVENTS + { + 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 + [Obsolete("TA_TRACK_STATUS is deprecated, please use ThinkingData.Analytics.TDTrackStatus instead.")] + public enum TA_TRACK_STATUS + { + PAUSE = 1, // pause data reporting + STOP = 2, // stop data reporting, and clear caches + SAVE_ONLY = 3, // data stores in the cache, but not be reported + NORMAL = 4 // resume data reporting + } + + [Obsolete("TAThirdPartyShareType is deprecated, please use ThinkingData.Analytics.Utils.TDThirdPartyType instead.")] + public enum TAThirdPartyShareType + { + NONE = 0, + APPSFLYER = 1 << 0, // AppsFlyer + IRONSOURCE = 1 << 1, // IronSource + ADJUST = 1 << 2, // Adjust + BRANCH = 1 << 3, // Branch + TOPON = 1 << 4, // TopOn + TRACKING = 1 << 5, // ReYun + TRADPLUS = 1 << 6, // TradPlus + }; + + /// + /// Dynamic super properties interfaces. + /// + [Obsolete("IDynamicSuperProperties is deprecated, please use ThinkingData.Analytics.TDDynamicSuperPropertiesHandler instead.")] + public interface IDynamicSuperProperties + { + /// + /// Dynamically gets event properties + /// + /// event properties + Dictionary GetDynamicSuperProperties(); + } + + /// + /// Auto track event callback interfaces. + /// + [Obsolete("IAutoTrackEventCallback is deprecated, please use ThinkingData.Analytics.TDAutoTrackEventHandler instead.")] + public interface IAutoTrackEventCallback + { + /// + /// Get Auto track event properties + /// + /// auto track event type + /// event properties + /// event properties + Dictionary AutoTrackEventCallback(int type, Dictionary properties); + } + + /// + /// Special event class for internal use, do not use this class directly. + /// + [Obsolete("ThinkingAnalyticsEvent is deprecated, please use ThinkingData.Analytics.TDEventModel instead.")] + public class ThinkingAnalyticsEvent + { + public enum Type + { + FIRST, + UPDATABLE, + OVERWRITABLE + } + + public ThinkingAnalyticsEvent(string eventName, Dictionary properties) + { + EventName = eventName; + Properties = properties; + } + + public Type? EventType { get; set; } + public string EventName { get; } + public Dictionary Properties { get; } + + public DateTime EventTime { get; set; } + public TimeZoneInfo EventTimeZone { get; set; } + public string ExtraId { get; set; } + } + + /// + /// First Events + /// + [Obsolete("TDFirstEvent is deprecated, please use ThinkingData.Analytics.TDFirstEventModel instead.")] + public class TDFirstEvent : ThinkingAnalyticsEvent + { + public TDFirstEvent(string eventName, Dictionary properties) : base(eventName, properties) + { + EventType = Type.FIRST; + } + + // First Event Check ID. By default, first events ID are device ID. + public void SetFirstCheckId(string firstCheckId) + { + ExtraId = firstCheckId; + } + } + + /// + /// Updatable Events + /// + [Obsolete("TDUpdatableEvent is deprecated, please use ThinkingData.Analytics.TDUpdatableEventModel instead.")] + public class TDUpdatableEvent : ThinkingAnalyticsEvent + { + public TDUpdatableEvent(string eventName, Dictionary properties, string eventId) : base(eventName, properties) + { + EventType = Type.UPDATABLE; + ExtraId = eventId; + } + } + + /// + /// Overwritable Events + /// + [Obsolete("TDOverWritableEvent is deprecated, please use ThinkingData.Analytics.TDOverwritableEventModel instead.")] + public class TDOverWritableEvent : ThinkingAnalyticsEvent + { + public TDOverWritableEvent(string eventName, Dictionary properties, string eventId) : base(eventName, properties) + { + EventType = Type.OVERWRITABLE; + ExtraId = eventId; + } + } + + /// + /// Preset Properties + /// + [Obsolete("TDPresetProperties is deprecated, please use ThinkingData.Analytics.TDPresetProperties instead.")] + public class TDPresetProperties + { + /// + /// Construct TDPresetProperties instance + /// + /// preset properties + public TDPresetProperties(Dictionary properties) + { + properties = TDEncodeDate(properties); + mPresetProperties = properties; + } + /// + /// Returns Preset Properties + /// The key starts with "#", it is not recommended to use it directly as a user properties + /// + /// preset properties + public Dictionary ToEventPresetProperties() + { + return mPresetProperties; + } + /// + /// Application Version Number + /// + public string AppVersion + { + get { return (string)(mPresetProperties.ContainsKey("#app_version") ? mPresetProperties["#app_version"] : ""); } + } + /// + /// Application Bundle Identify + /// + public string BundleId + { + get { return (string)(mPresetProperties.ContainsKey("#bundle_id") ? mPresetProperties["#bundle_id"] : ""); } + } + /// + /// Device Network Carrier + /// + public string Carrier + { + get { return (string)(mPresetProperties.ContainsKey("#carrier") ? mPresetProperties["#carrier"] : ""); } + } + /// + /// Device Identify + /// + public string DeviceId + { + get { return (string)(mPresetProperties.ContainsKey("#device_id") ? mPresetProperties["#device_id"] : ""); } + } + /// + /// Device Model Name + /// + public string DeviceModel + { + get { return (string)(mPresetProperties.ContainsKey("#device_model") ? mPresetProperties["#device_model"] : ""); } + } + /// + /// Device Hardware Manufacturer + /// + public string Manufacturer + { + get { return (string)(mPresetProperties.ContainsKey("#manufacturer") ? mPresetProperties["#manufacturer"] : ""); } + } + /// + /// Device Network Type + /// + public string NetworkType + { + get { return (string)(mPresetProperties.ContainsKey("#network_type") ? mPresetProperties["#network_type"] : ""); } + } + /// + /// Device System OS Name + /// + public string OS + { + get { return (string)(mPresetProperties.ContainsKey("#os") ? mPresetProperties["#os"] : ""); } + } + /// + /// Device System OS Version Number + /// + public string OSVersion + { + get { return (string)(mPresetProperties.ContainsKey("#os_version") ? mPresetProperties["#os_version"] : ""); } + } + /// + /// Screen Height + /// + public double ScreenHeight + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#screen_height") ? mPresetProperties["#screen_height"] : 0); } + } + /// + /// Screen Width + /// + public double ScreenWidth + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#screen_width") ? mPresetProperties["#screen_width"] : 0); } + } + /// + /// Device System Language Code + /// + public string SystemLanguage + { + get { return (string)(mPresetProperties.ContainsKey("#system_language") ? mPresetProperties["#system_language"] : ""); } + } + /// + /// Time Zone Offset With UTC + /// + public double ZoneOffset + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#zone_offset") ? mPresetProperties["#zone_offset"] : 0); } + } + /// + /// Application Install Time + /// + public string InstallTime + { + get { return (string)(mPresetProperties.ContainsKey("#install_time") ? mPresetProperties["#install_time"] : ""); } + } + /// + /// Device Disk Size + /// + public string Disk + { + get { return (string)(mPresetProperties.ContainsKey("#disk") ? mPresetProperties["#disk"] : ""); } + } + /// + /// Device Ram Size + /// + public string Ram + { + get { return (string)(mPresetProperties.ContainsKey("#ram") ? mPresetProperties["#ram"] : ""); } + } + /// + /// Device FPS + /// + public double Fps + { + get { return Convert.ToDouble(mPresetProperties.ContainsKey("#fps") ? mPresetProperties["#fps"] : 0); } + } + /// + /// Device is an Simulator + /// + public bool Simulator + { + get { return (bool)(mPresetProperties.ContainsKey("#simulator") ? mPresetProperties["#simulator"] : false); } + } + + private Dictionary mPresetProperties { get; set; } + private Dictionary TDEncodeDate(Dictionary properties) + { + Dictionary mProperties = new Dictionary(); + foreach (KeyValuePair kv in properties) + { + if (kv.Value is DateTime) + { + DateTime dateTime = (DateTime)kv.Value; + mProperties.Add(kv.Key, dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture)); + } + else + { + mProperties.Add(kv.Key, kv.Value); + } + } + return mProperties; + } + } +} diff --git a/Assets/ThinkingAnalytics/ThinkingAnalyticsAPI.cs.meta b/Assets/ThinkingAnalytics/ThinkingAnalyticsAPI.cs.meta new file mode 100644 index 0000000..b1c95d0 --- /dev/null +++ b/Assets/ThinkingAnalytics/ThinkingAnalyticsAPI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3281a13f4ff754b019604465fadd63ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Utils.meta b/Assets/ThinkingAnalytics/Utils.meta new file mode 100644 index 0000000..31f6fa6 --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: efe5e95f8073844fcbaedf8453895210 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Utils/TDCommonUtils.cs b/Assets/ThinkingAnalytics/Utils/TDCommonUtils.cs new file mode 100644 index 0000000..41448dd --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDCommonUtils.cs @@ -0,0 +1,86 @@ +using System; +namespace ThinkingData.Analytics.Utils +{ + public class TDCommonUtils + { + 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); + } + try + { + DateTime dateNew = univDateTime + timeSpan; + return dateNew.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture); + } + catch (Exception) + { + } + return univDateTime.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture); + } + + public static string FormatDate(DateTime dateTime, TDTimeZone timeZone) { + DateTime univDateTime = dateTime.ToUniversalTime(); + TimeSpan span; + switch (timeZone) + { + case TDTimeZone.Local: + span = TimeZoneInfo.Local.BaseUtcOffset; + break; + case TDTimeZone.UTC: + span = TimeSpan.Zero; + break; + case TDTimeZone.Asia_Shanghai: + span = TimeSpan.FromHours(8); + break; + case TDTimeZone.Asia_Tokyo: + span = TimeSpan.FromHours(9); + break; + case TDTimeZone.America_Los_Angeles: + span = TimeSpan.FromHours(-7); + break; + case TDTimeZone.America_New_York: + span = TimeSpan.FromHours(-4); + break; + default: + span = TimeSpan.Zero; + break; + } + try + { + DateTime dateNew = univDateTime + span; + return dateNew.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture); + } + catch (Exception) { + } + return univDateTime.ToString("yyyy-MM-dd HH:mm:ss.fff", System.Globalization.CultureInfo.InvariantCulture); + } + } +} + diff --git a/Assets/ThinkingAnalytics/Utils/TDCommonUtils.cs.meta b/Assets/ThinkingAnalytics/Utils/TDCommonUtils.cs.meta new file mode 100644 index 0000000..d0a11be --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDCommonUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56ef1531e6e06454aa9a6700b418632d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Utils/TDLog.cs b/Assets/ThinkingAnalytics/Utils/TDLog.cs new file mode 100644 index 0000000..ae46aa7 --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDLog.cs @@ -0,0 +1,51 @@ +using UnityEngine; + +namespace ThinkingData.Analytics.Utils +{ + public class TDLog + { + private static bool enableLog; + public static void EnableLog(bool enabled) + { + enableLog = enabled; + } + + public static bool GetEnable() + { + return enableLog; + } + + + public static void i(string message) + { + if (enableLog) + { + Debug.Log("[ThinkingData] Info: " + message); + } + } + + public static void d(string message) + { + if (enableLog) + { + Debug.Log("[ThinkingData] Debug: " + message); + } + } + + public static void e(string message) + { + if (enableLog) + { + Debug.LogError("[ThinkingData] Error: " + message); + } + } + + public static void w(string message) + { + if (enableLog) + { + Debug.LogWarning("[ThinkingData] Warning: " + message); + } + } + } +} \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/Utils/TDLog.cs.meta b/Assets/ThinkingAnalytics/Utils/TDLog.cs.meta new file mode 100644 index 0000000..68e2f99 --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDLog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b49f9a69526c4417963783322d7e904 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Utils/TDMiniJson.cs b/Assets/ThinkingAnalytics/Utils/TDMiniJson.cs new file mode 100644 index 0000000..d54c573 --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDMiniJson.cs @@ -0,0 +1,610 @@ +/* + * 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 ThinkingData.Analytics.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. + */ + /// + /// 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. + /// + public class TDMiniJson + { + /// + /// Parses the string json into a value + /// + /// A JSON string. + /// An List, a Dictionary, a double, an integer, a string, null, true, or false + public static Dictionary Deserialize(string json) + { + // save the string for debug information + if (json == null) + { + return null; + } + + return Parser.Parse(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 Parse(string jsonString) + { + using (var instance = new Parser(jsonString)) + { + return instance.ParseObject(); + } + } + + public void Dispose() + { + json.Dispose(); + json = null; + } + + Dictionary ParseObject() + { + Dictionary table = new Dictionary(); + + // 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 ParseArray() + { + List array = new List(); + + // 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 && number.IndexOf('E') == -1 && number.IndexOf('e') == -1) + { + long parsedInt; + Int64.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedInt); + return parsedInt; + } + + double parsedDouble; + if (!Double.TryParse(number, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out parsedDouble)) + { + Double.TryParse(number, System.Globalization.NumberStyles.Any, 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; + } + } + } + + /// + /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string + /// + /// A Dictionary / List + /// A JSON encoded string, or null if object 'json' is not serializable + public static string Serialize(object obj, Func func = null) + { + return Serializer.Serialize(obj, func); + } + + sealed class Serializer + { + StringBuilder builder; + Func func; + + Serializer() + { + builder = new StringBuilder(); + } + + public static string Serialize(object obj, Func 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()); + } + } + } + } +} diff --git a/Assets/ThinkingAnalytics/Utils/TDMiniJson.cs.meta b/Assets/ThinkingAnalytics/Utils/TDMiniJson.cs.meta new file mode 100644 index 0000000..90e907a --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDMiniJson.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 03cd5f56606ff4dd694406f5594f0cf2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Utils/TDPropertiesChecker.cs b/Assets/ThinkingAnalytics/Utils/TDPropertiesChecker.cs new file mode 100644 index 0000000..44e7fb0 --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDPropertiesChecker.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace ThinkingData.Analytics.Utils +{ + public class TDPropertiesChecker + { + private static readonly Regex keyPattern = new Regex(@"^[a-zA-Z][a-zA-Z\d_#]{0,49}$"); + private static readonly List propertyNameWhitelist = new List() { "#scene_name", "#scene_path", "#app_crashed_reason" }; + + public static bool IsNumeric(object obj) + { + return obj is sbyte + || obj is byte + || obj is short + || obj is ushort + || obj is int + || obj is uint + || obj is long + || obj is ulong + || obj is double + || obj is decimal + || obj is float; + } + public static bool IsString(object obj) + { + if (obj == null) + return false; + return obj is string; + } + public static bool IsDictionary(object obj) + { + if (obj == null) + return false; + return (obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(Dictionary<,>)); + } + public static bool IsList(object obj) + { + if (obj == null) + return false; + return (obj.GetType().IsGenericType && obj.GetType().GetGenericTypeDefinition() == typeof(List<>)) || obj is Array; + } + public static bool CheckProperties(Dictionary properties) + { + if (properties == null) + { + return true; + } + bool ret = true; + foreach(KeyValuePair kv in properties) + { + if (!CheckString(kv.Key)) + { + ret = false; + } + if (!(kv.Value is string || kv.Value is DateTime || kv.Value is bool || IsNumeric(kv.Value) || IsList(kv.Value) || IsDictionary(kv.Value))) + { + if(TDLog.GetEnable()) TDLog.w("Incorrect property - property values must be one of: String, Numberic, Boolean, DateTime, Array, Row"); + ret = false; + } + if (IsString(kv.Value) && !CheckProperties(kv.Value as string)) + { + ret = false; + } + if (IsNumeric(kv.Value)) { + double number = Convert.ToDouble(kv.Value); + if (!CheckProperties(number)) + { + ret = false; + } + } + if (IsList(kv.Value) && !CheckProperties(kv.Value as List)) { + ret = false; + } + if (IsDictionary(kv.Value) && !CheckProperties(kv.Value as Dictionary)) + { + ret = false; + } + } + return ret; + } + public static bool CheckProperties(List properties) + { + if (properties == null) + { + return true; + } + bool ret = true; + foreach (object value in properties) + { + if (!(value is string || value is DateTime || value is bool || IsNumeric(value) || IsDictionary(value))) + { + if(TDLog.GetEnable()) TDLog.w("Incorrect property - property values in list must be one of: String, Numberic, Boolean, DateTime, Row"); + ret = false; + } + if (IsString(value) && !CheckProperties(value as string)) + { + ret = false; + } + if (IsNumeric(value)) { + double number = Convert.ToDouble(value); + if (!CheckProperties(number)) + { + ret = false; + } + } + if (IsDictionary(value) && !CheckProperties(value as Dictionary)) + { + ret = false; + } + } + return ret; + } + public static bool CheckProperties(List properties) + { + if (properties == null) + { + return true; + } + + bool ret = true; + foreach(string value in properties) + { + if (!CheckProperties(value)) + { + ret = false; + } + } + return ret; + } + public static bool CheckProperties(string properties) + { + if (properties is string && System.Text.Encoding.UTF8.GetBytes(Convert.ToString(properties)).Length > 2048) { + if(TDLog.GetEnable()) TDLog.w("Incorrect properties - the string is too long: " + (string)(object)properties); + return false; + } + return true; + } + public static bool CheckProperties(double properties) + { + if (properties > 9999999999999.999 || properties < -9999999999999.999) + { + if(TDLog.GetEnable()) TDLog.w("Incorrect properties - number value is invalid: " + properties + ", the data range is -9E15 to 9E15, with a maximum of 3 decimal places"); + return false; + } + return true; + } + public static bool CheckString(string eventName) + { + if (string.IsNullOrEmpty(eventName)) + { + if(TDLog.GetEnable()) TDLog.w("Incorrect event name - the string is null"); + return false; + } + if (keyPattern.IsMatch(eventName)) + { + return true; + } + else + { + if (propertyNameWhitelist.Contains(eventName)) + { + return true; + } + if(TDLog.GetEnable()) TDLog.w("Incorrect event name - the string is invalid for TDAnalytics: " + eventName + ", event name and properties name rules: must be character string type, starting with a character and containing figures, characters, and an underline \"_\", with a maximum length of 50 characters"); + return false; + } + } + public static void MergeProperties(Dictionary source, Dictionary dest) + { + if (null == source) return; + foreach (KeyValuePair kv in source) + { + if (dest.ContainsKey(kv.Key)) + { + dest[kv.Key] = kv.Value; + } else + { + dest.Add(kv.Key, kv.Value); + } + } + } + } +} + diff --git a/Assets/ThinkingAnalytics/Utils/TDPropertiesChecker.cs.meta b/Assets/ThinkingAnalytics/Utils/TDPropertiesChecker.cs.meta new file mode 100644 index 0000000..0d18ac9 --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDPropertiesChecker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d887a818e74eb4316a839030f930036b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Utils/TDPublicConfig.cs b/Assets/ThinkingAnalytics/Utils/TDPublicConfig.cs new file mode 100644 index 0000000..d33a81c --- /dev/null +++ b/Assets/ThinkingAnalytics/Utils/TDPublicConfig.cs @@ -0,0 +1,74 @@ +using UnityEngine; +using System; +using System.Xml; +using System.Collections.Generic; + +namespace ThinkingData.Analytics.Utils +{ + // Crosss Platform + public enum TDThirdPartyType + { + NONE = 0, + APPSFLYER = 1 << 0, // AppsFlyer + IRONSOURCE = 1 << 1, // IronSource + ADJUST = 1 << 2, // Adjust + BRANCH = 1 << 3, // Branch + TOPON = 1 << 4, // TopOn + TRACKING = 1 << 5, // ReYun + TRADPLUS = 1 << 6, // TradPlus + }; + + // SSL + public enum TDSSLPinningMode + { + NONE = 0, // Only allow certificates trusted by the system + PUBLIC_KEY = 1 << 0, // Verify public key + CERTIFICATE = 1 << 1 // Verify all contents + } + + public class TDPublicConfig + { + public static bool DisableCSharpException = false; + public static List DisPresetProperties = new List(); + + public static readonly string LIB_VERSION = "3.2.2"; + + public static void GetPublicConfig() + { + TextAsset textAsset = Resources.Load("ta_public_config"); + if (textAsset != null && !string.IsNullOrEmpty(textAsset.text)) + { + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(textAsset.text); + XmlNode root = xmlDoc.SelectSingleNode("resources"); + for (int i=0; i data) { + if (data == null) + { + return ""; + } + + return serilize(data); + } + + private static string getTimeString(DateTime dateTime) { + if (defaultTimeZone == null) + { + return TDCommonUtils.FormatDate(dateTime, defaultTDTimeZone); + } + else { + return TDCommonUtils.FormatDate(dateTime, defaultTimeZone); + } + } + + private static void enableLog(bool enable) { + sdkClass.CallStatic("enableTrackLog", enable); + } + private static void setVersionInfo(string libName, string version) { + sdkClass.CallStatic("setCustomerLibInfo", libName, version); + } + + private static void init(TDConfig token) + { + AndroidJavaObject context = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic("currentActivity"); + string timeZoneId = token.getTimeZoneId(); + defaultTDTimeZone = token.timeZone; + if (null != timeZoneId && timeZoneId.Length > 0) + { + if (defaultTimeZone == null) + { + try + { + defaultTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); + } + catch (Exception) + { + } + } + } + else { + if (defaultTimeZone == null) { + defaultTimeZone = TimeZoneInfo.Local; + } + } + sdkClass.CallStatic("init",context,token.appId,token.serverUrl, (int)token.mode,token.name, timeZoneId, token.encryptVersion,token.encryptPublicKey); + } + + private static void flush(string appId) + { + sdkClass.CallStatic("flush", appId); + } + + private static long getDateTimeStamp(DateTime dateTime) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + return currentMillis; + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, string appId) + { + try + { + sdkClass.CallStatic("track", eventName, getJsonStr(properties), getDateTimeStamp(dateTime), "Local", appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, TimeZoneInfo timeZone, string appId) + { + try + { + if (timeZone == null) + { + sdkClass.CallStatic("track", eventName, getJsonStr(properties), getDateTimeStamp(dateTime), "", appId); + } + else { + sdkClass.CallStatic("track", eventName, getJsonStr(properties), getDateTimeStamp(dateTime), timeZone.Id, appId); + } + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void trackForAll(string eventName, Dictionary properties) + { + string appId = ""; + track(eventName, properties, appId); + } + + private static void track(TDEventModel taEvent, string appId) + { + int eventType = -1; + if (taEvent.EventType == TDEventModel.TDEventType.First) + { + eventType = 0; + } + else if (taEvent.EventType == TDEventModel.TDEventType.Updatable) + { + eventType = 1; + } + else if (taEvent.EventType == TDEventModel.TDEventType.Overwritable) + { + eventType = 2; + } + if (eventType < 0) return; + string jsonStr; + if (taEvent.Properties == null) + { + jsonStr = taEvent.StrProperties; + } + else { + jsonStr = getJsonStr(getFinalEventProperties(taEvent.Properties)); + } + if (taEvent.GetEventTimeZone() == null) + { + sdkClass.CallStatic("trackEvent", eventType, taEvent.EventName, jsonStr, taEvent.GetEventId(), getDateTimeStamp(taEvent.GetEventTime()), "", appId); + } + else + { + sdkClass.CallStatic("trackEvent", eventType, taEvent.EventName, jsonStr, taEvent.GetEventId(), getDateTimeStamp(taEvent.GetEventTime()), taEvent.GetEventTimeZone().Id, appId); + } + } + + private static void track(string eventName, Dictionary properties, string appId) + { + try + { + sdkClass.CallStatic("track", eventName, getJsonStr(properties), 0L, "", appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void trackStr(string eventName, string properties, string appId) + { + try + { + sdkClass.CallStatic("track", eventName, properties, 0L, "", appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void setSuperProperties(Dictionary superProperties, string appId) + { + try + { + sdkClass.CallStatic("setSuperProperties", getJsonStr(superProperties), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void setSuperProperties(string superProperties, string appId) + { + try + { + sdkClass.CallStatic("setSuperProperties", superProperties, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void unsetSuperProperty(string superPropertyName, string appId) + { + sdkClass.CallStatic("unsetSuperProperty", superPropertyName, appId); + } + + private static void clearSuperProperty(string appId) + { + sdkClass.CallStatic("clearSuperProperties", appId); + } + + private static Dictionary getSuperProperties(string appId) + { + Dictionary result = null; + try + { + result = TDMiniJson.Deserialize(sdkClass.CallStatic("getSuperProperties", appId)); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + return result; + } + + private static Dictionary getPresetProperties(string appId) + { + Dictionary result = null; + try + { + result = TDMiniJson.Deserialize(sdkClass.CallStatic("getPresetProperties",appId)); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + return result; + } + + private static void timeEvent(string eventName, string appId) + { + sdkClass.CallStatic("timeEvent", eventName, appId); + } + + private static void timeEventForAll(string eventName) + { + sdkClass.CallStatic("timeEvent", eventName, ""); + } + + private static void identify(string uniqueId, string appId) + { + sdkClass.CallStatic("identify", uniqueId, appId); + } + + private static string getDistinctId(string appId) + { + return sdkClass.CallStatic("getDistinctId", appId); + } + + private static void login(string uniqueId, string appId) + { + sdkClass.CallStatic("login", uniqueId, appId); + } + + private static void userSetOnce(Dictionary properties, string appId) + { + try + { + sdkClass.CallStatic("userSetOnce", getJsonStr(properties), 0L,appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userSetOnce(string properties, string appId) + { + try + { + sdkClass.CallStatic("userSetOnce", properties, 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userSetOnce(Dictionary properties, DateTime dateTime, string appId) + { + try + { + sdkClass.CallStatic("userSetOnce", getJsonStr(properties), getDateTimeStamp(dateTime), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userSet(Dictionary properties, string appId) + { + try + { + sdkClass.CallStatic("userSet", getJsonStr(properties), 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userSet(Dictionary properties, DateTime dateTime, string appId) + { + try + { + sdkClass.CallStatic("userSet", getJsonStr(properties), getDateTimeStamp(dateTime), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userSet(string properties, string appId) + { + try + { + sdkClass.CallStatic("userSet", properties, 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userUnset(List properties, string appId) + { + userUnset(properties, DateTime.Now, appId); + } + + private static void userUnset(List properties, DateTime dateTime, string appId) + { + Dictionary finalProperties = new Dictionary(); + foreach(string s in properties) + { + finalProperties.Add(s, 0); + } + try + { + sdkClass.CallStatic("userUnset", getJsonStr(finalProperties), getDateTimeStamp(dateTime), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userAdd(Dictionary properties, string appId) + { + try + { + sdkClass.CallStatic("userAdd", getJsonStr(properties), 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userAddStr(string properties, string appId) + { + try + { + sdkClass.CallStatic("userAdd", properties, 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userAdd(Dictionary properties, DateTime dateTime, string appId) + { + try + { + sdkClass.CallStatic("userAdd", getJsonStr(properties), getDateTimeStamp(dateTime), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userAppend(Dictionary properties, string appId) + { + try + { + sdkClass.CallStatic("userAppend", getJsonStr(properties), 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userAppend(string properties, string appId) + { + try + { + sdkClass.CallStatic("userAppend", properties, 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userAppend(Dictionary properties, DateTime dateTime, string appId) + { + try + { + sdkClass.CallStatic("userAppend", getJsonStr(properties), getDateTimeStamp(dateTime), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userUniqAppend(Dictionary properties, string appId) + { + try + { + sdkClass.CallStatic("userUniqAppend", getJsonStr(properties), 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userUniqAppend(string properties, string appId) + { + try + { + sdkClass.CallStatic("userUniqAppend", properties, 0L, appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userUniqAppend(Dictionary properties, DateTime dateTime, string appId) + { + try + { + sdkClass.CallStatic("userUniqAppend", getJsonStr(properties), getDateTimeStamp(dateTime), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void userDelete(string appId) + { + sdkClass.CallStatic("userDel", 0L, appId); + } + + private static void userDelete(DateTime dateTime, string appId) + { + try + { + sdkClass.CallStatic("userDel", getDateTimeStamp(dateTime), appId); + } + catch (Exception e) + { + if (TDLog.GetEnable()) TDLog.w("ThinkingAnalytics: unexpected exception: " + e); + } + } + + private static void logout(string appId) + { + sdkClass.CallStatic("logout", appId); + } + + private static string getDeviceId() + { + return sdkClass.CallStatic("getDeviceId"); + } + + private static void setDynamicSuperProperties(TDDynamicSuperPropertiesHandler dynamicSuperProperties, string appId) + { + DynamicListenerAdapter listenerAdapter = new DynamicListenerAdapter(); + sdkClass.CallStatic("setDynamicSuperPropertiesTrackerListener", appId, listenerAdapter); + } + + private static void setNetworkType(TDNetworkType networkType) { + int type; + switch (networkType) + { + case TDNetworkType.Wifi: + type = 1; + break; + case TDNetworkType.All: + type = 0; + break; + default: + type = 0; + break; + + } + sdkClass.CallStatic("setNetworkType", type,""); + } + + private static void enableAutoTrack(TDAutoTrackEventType events, Dictionary properties, string appId) + { + sdkClass.CallStatic("enableAutoTrack", (int)events, TDMiniJson.Serialize(properties), appId); + } + + private static void enableAutoTrack(TDAutoTrackEventType events, TDAutoTrackEventHandler eventCallback, string appId) + { + AutoTrackListenerAdapter listenerAdapter = new AutoTrackListenerAdapter(); + sdkClass.CallStatic("enableAutoTrack", (int)events, listenerAdapter, appId); + } + + private static void setAutoTrackProperties(TDAutoTrackEventType events, Dictionary properties, string appId) + { + sdkClass.CallStatic("setAutoTrackProperties", (int)events, TDMiniJson.Serialize(properties), appId); + } + + private static void setTrackStatus(TDTrackStatus status, string appId) + { + int type; + switch (status) + { + case TDTrackStatus.Pause: + type = 1; + break; + case TDTrackStatus.Stop: + type = 2; + break; + case TDTrackStatus.SaveOnly: + type = 3; + break; + case TDTrackStatus.Normal: + default: + type = 0; + break; + } + sdkClass.CallStatic("setTrackStatus", type, appId); + } + + private static void optOutTracking(string appId) + { + } + + private static void optOutTrackingAndDeleteUser(string appId) + { + } + + private static void optInTracking(string appId) + { + } + + private static void enableTracking(bool enabled, string appId) + { + } + + private static string createLightInstance() + { + return sdkClass.CallStatic("createLightInstance",""); + } + + private static void calibrateTime(long timestamp) + { + sdkClass.CallStatic("calibrateTime", timestamp); + } + + private static void calibrateTimeWithNtp(string ntpServer) + { + sdkClass.CallStatic("calibrateTimeWithNtp", ntpServer); + } + + private static void enableThirdPartySharing(TDThirdPartyType shareType, Dictionary properties, string appId) + { + sdkClass.CallStatic("enableThirdPartySharing", (int)shareType, TDMiniJson.Serialize(properties), appId); + } + + //dynamic super properties + public interface IDynamicSuperPropertiesTrackerListener + { + string getDynamicSuperPropertiesString(); + } + + private class DynamicListenerAdapter : AndroidJavaProxy { + public DynamicListenerAdapter() : base("cn.thinkingdata.analytics.ThinkingAnalyticsProxy$DynamicSuperPropertiesTrackerListener") {} + public string getDynamicSuperPropertiesString() + { + Dictionary ret; + if (TDWrapper.mDynamicSuperProperties != null) { + ret = TDWrapper.mDynamicSuperProperties.GetDynamicSuperProperties(); + } + else { + ret = new Dictionary(); + } + //return TDMiniJson.Serialize(ret); + return serilize(ret); + } + } + + //auto-tracking + public interface IAutoTrackEventTrackerListener + { + string eventCallback(int type, string appId, string properties); + } + + private class AutoTrackListenerAdapter : AndroidJavaProxy { + public AutoTrackListenerAdapter() : base("cn.thinkingdata.analytics.ThinkingAnalyticsProxy$AutoTrackEventTrackerListener") {} + string eventCallback(int type, string appId, string properties) + { + Dictionary ret; + if (TDWrapper.mAutoTrackEventCallbacks.ContainsKey(appId)) + { + Dictionary propertiesDic = TDMiniJson.Deserialize(properties); + ret = TDWrapper.mAutoTrackEventCallbacks[appId].GetAutoTrackEventProperties(type, propertiesDic); + } + else { + ret = new Dictionary(); + } + return serilize(ret); + } + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/Wrapper/TDAndroidWrapper.cs.meta b/Assets/ThinkingAnalytics/Wrapper/TDAndroidWrapper.cs.meta new file mode 100644 index 0000000..2c9773a --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDAndroidWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 03113e111863a4fd68539598dc2dbb97 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Wrapper/TDOpenHarmonyWrapper.cs b/Assets/ThinkingAnalytics/Wrapper/TDOpenHarmonyWrapper.cs new file mode 100644 index 0000000..b86e465 --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDOpenHarmonyWrapper.cs @@ -0,0 +1,407 @@ +#if UNITY_OPENHARMONY && !(UNITY_EDITOR) +using System; +using System.Collections.Generic; +using ThinkingAnalytics; +using ThinkingData.Analytics.Utils; +using UnityEngine; +namespace ThinkingData.Analytics.Wrapper +{ + public partial class TDWrapper + { + private static readonly OpenHarmonyJSClass openHarmonyJsClass = new OpenHarmonyJSClass("TDOpenHarmonyProxy"); + + private static TimeZoneInfo defaultTimeZone = null; + private static TDTimeZone defaultTDTimeZone = TDTimeZone.Local; + + private static void init(TDConfig token) + { + string timeZoneId = token.getTimeZoneId(); + defaultTDTimeZone = token.timeZone; + string timeZone = ""; + if (null != timeZoneId && timeZoneId.Length > 0) + { + timeZone = timeZoneId; + if (defaultTimeZone == null) + { + try + { + defaultTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); + } + catch (Exception) + { + } + } + } + else + { + if (defaultTimeZone == null) + { + defaultTimeZone = TimeZoneInfo.Local; + } + } + openHarmonyJsClass.CallStatic("init", token.appId, token.serverUrl, (int)token.mode, timeZone, token.encryptVersion, token.encryptPublicKey); + + } + + private static string getTimeString(DateTime dateTime) + { + if (defaultTimeZone == null) + { + return TDCommonUtils.FormatDate(dateTime, defaultTDTimeZone); + } + else + { + return TDCommonUtils.FormatDate(dateTime, defaultTimeZone); + } + } + + private static void enableLog(bool enable) + { + openHarmonyJsClass.CallStatic("enableLog", enable); + } + + private static void setVersionInfo(string libName, string version) + { + openHarmonyJsClass.CallStatic("setLibraryInfo", libName, version); + } + + private static void identify(string uniqueId, string appId) + { + openHarmonyJsClass.CallStatic("setDistinctId", uniqueId, appId); + } + + private static string getDistinctId(string appId) + { + return openHarmonyJsClass.CallStatic("getDistinctId", appId); + } + + private static void login(string uniqueId, string appId) + { + openHarmonyJsClass.CallStatic("login", uniqueId, appId); + } + + private static void logout(string appId) + { + openHarmonyJsClass.CallStatic("logout", appId); + } + + private static void enableAutoTrack(TDAutoTrackEventType events, Dictionary properties, string appId) + { + openHarmonyJsClass.CallStatic("enableAutoTrack", (int)events, appId); + } + + private static void enableAutoTrack(TDAutoTrackEventType events, TDAutoTrackEventHandler eventCallback, string appId) + { + + } + + private static void setAutoTrackProperties(TDAutoTrackEventType events, Dictionary properties, string appId) + { + + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, string appId) + { + track(eventName, properties, dateTime, null, appId); + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, TimeZoneInfo timeZone, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + string timeZoneId = ""; + if (timeZone != null) + { + timeZoneId = timeZone.Id; + } + openHarmonyJsClass.CallStatic("track", eventName, serilize(properties), currentMillis, timeZoneId, appId); + } + + private static void track(string eventName, Dictionary properties, string appId) + { + openHarmonyJsClass.CallStatic("track", eventName, serilize(properties), 0, "", appId); + } + + private static void trackForAll(string eventName, Dictionary properties) + { + track(eventName, properties, ""); + } + + private static void track(TDEventModel taEvent, string appId) + { + int eventType = -1; ; + switch (taEvent.EventType) + { + case TDEventModel.TDEventType.First: + eventType = 1; + break; + case TDEventModel.TDEventType.Updatable: + eventType = 2; + break; + case TDEventModel.TDEventType.Overwritable: + eventType = 3; + break; + } + if (eventType < 0) return; + string jsonStr; + if (taEvent.Properties == null) + { + jsonStr = taEvent.StrProperties; + } + else + { + jsonStr = serilize(taEvent.Properties); + } + long eventTime = 0; + if (taEvent.GetEventTime() != null && taEvent.GetEventTime() != DateTime.MinValue) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(taEvent.GetEventTime()).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + eventTime = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + } + string timeZoneId = ""; + if (taEvent.GetEventTimeZone() != null) + { + timeZoneId = taEvent.GetEventTimeZone().Id; + } + openHarmonyJsClass.CallStatic("trackEvent", eventType, taEvent.EventName, jsonStr, taEvent.GetEventId(), eventTime, timeZoneId, appId); + } + + private static void trackStr(string eventName, string properties, string appId) + { + openHarmonyJsClass.CallStatic("track", eventName, properties, 0, "", appId); + } + + private static void setSuperProperties(Dictionary superProperties, string appId) + { + openHarmonyJsClass.CallStatic("setSuperProperties", serilize(superProperties), appId); + } + + private static void setSuperProperties(string superProperties, string appId) + { + openHarmonyJsClass.CallStatic("setSuperProperties", superProperties, appId); + } + + private static void unsetSuperProperty(string superPropertyName, string appId) + { + openHarmonyJsClass.CallStatic("unsetSuperProperty", superPropertyName, appId); + } + + private static void clearSuperProperty(string appId) + { + openHarmonyJsClass.CallStatic("clearSuperProperties", appId); + } + + private static Dictionary getSuperProperties(string appId) + { + string superPropertiesString = openHarmonyJsClass.CallStatic("getSuperProperties", appId); + return TDMiniJson.Deserialize(superPropertiesString); + } + + private static Dictionary getPresetProperties(string appId) + { + string presetPropertiesString = openHarmonyJsClass.CallStatic("getPresetProperties", appId); + return TDMiniJson.Deserialize(presetPropertiesString); + } + + private static void timeEvent(string eventName, string appId) + { + openHarmonyJsClass.CallStatic("timeEvent", eventName, appId); + } + + private static void timeEventForAll(string eventName) + { + openHarmonyJsClass.CallStatic("timeEvent", eventName, ""); + } + + private static void userSet(Dictionary properties, string appId) + { + userSet(properties, new DateTime(), appId); + } + + private static void userSet(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + openHarmonyJsClass.CallStatic("userSet", serilize(properties), currentMillis, appId); + } + + private static void userSet(string properties, string appId) + { + openHarmonyJsClass.CallStatic("userSet", properties, 0, appId); + } + + private static void userSetOnce(Dictionary properties, string appId) + { + userSetOnce(properties, new DateTime(), appId); + } + + private static void userSetOnce(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + openHarmonyJsClass.CallStatic("userSetOnce", serilize(properties), currentMillis, appId); + } + + private static void userSetOnce(string properties, string appId) + { + openHarmonyJsClass.CallStatic("userSetOnce", properties, 0, appId); + } + + private static void userUnset(List properties, string appId) + { + userUnset(properties, new DateTime(), appId); + } + + private static void userUnset(List properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + foreach (string property in properties) + { + openHarmonyJsClass.CallStatic("userUnset", property, currentMillis, appId); + } + } + + private static void userAdd(Dictionary properties, string appId) + { + userAdd(properties, new DateTime(), appId); + } + + private static void userAdd(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + openHarmonyJsClass.CallStatic("userAdd", serilize(properties), currentMillis, appId); + } + + private static void userAddStr(string properties, string appId) + { + openHarmonyJsClass.CallStatic("userAdd", properties, 0, appId); + } + + private static void userAppend(Dictionary properties, string appId) + { + userAppend(properties, new DateTime(), appId); + } + + + private static void userAppend(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + openHarmonyJsClass.CallStatic("userAppend", serilize(properties), currentMillis, appId); + } + + private static void userAppend(string properties, string appId) + { + openHarmonyJsClass.CallStatic("userAppend", properties, 0, appId); + } + + private static void userUniqAppend(Dictionary properties, string appId) + { + userUniqAppend(properties, new DateTime(), appId); + } + + private static void userUniqAppend(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + openHarmonyJsClass.CallStatic("userUniqAppend", serilize(properties), currentMillis, appId); + } + + private static void userUniqAppend(string properties, string appId) + { + openHarmonyJsClass.CallStatic("userUniqAppend", properties, 0, appId); + } + + private static void userDelete(string appId) + { + userDelete(new DateTime(), appId); + } + + private static void userDelete(DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + openHarmonyJsClass.CallStatic("userDelete", currentMillis, appId); + } + + private static void flush(string appId) + { + openHarmonyJsClass.CallStatic("flush", appId); + } + + private static string getDeviceId() + { + return openHarmonyJsClass.CallStatic("getDeviceId"); + } + + private static void setNetworkType(TDNetworkType networkType) + { + openHarmonyJsClass.CallStatic("setNetWorkType", (int)networkType); + } + + private static void setDynamicSuperProperties(TDDynamicSuperPropertiesHandler dynamicSuperProperties, string appId) + { + + } + + private static void setTrackStatus(TDTrackStatus status, string appId) + { + + } + + private static void optOutTracking(string appId) + { + + } + + private static void optOutTrackingAndDeleteUser(string appId) + { + + } + + private static void optInTracking(string appId) + { + + } + + private static void enableTracking(bool enabled, string appId) + { + + } + + private static string createLightInstance() + { + + return ""; + } + + private static void calibrateTime(long timestamp) + { + openHarmonyJsClass.CallStatic("calibrateTime", timestamp); + } + + private static void calibrateTimeWithNtp(string ntpServer) + { + + } + + private static void enableThirdPartySharing(TDThirdPartyType shareType, Dictionary properties, string appId) + { + + } + + } +} + +#endif \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/Wrapper/TDOpenHarmonyWrapper.cs.meta b/Assets/ThinkingAnalytics/Wrapper/TDOpenHarmonyWrapper.cs.meta new file mode 100644 index 0000000..1c5b263 --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDOpenHarmonyWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd865474607df4800a2a0de0ef67be63 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Wrapper/TDPCWrapper.cs b/Assets/ThinkingAnalytics/Wrapper/TDPCWrapper.cs new file mode 100644 index 0000000..52c143d --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDPCWrapper.cs @@ -0,0 +1,492 @@ +#if ((!(UNITY_IOS) || UNITY_EDITOR) && (!(UNITY_ANDROID) || UNITY_EDITOR) && (!(UNITY_OPENHARMONY) || UNITY_EDITOR)) || TE_DISABLE_ANDROID_JAVA || TE_DISABLE_IOS_OC +using System; +using System.Collections.Generic; +using ThinkingData.Analytics.Utils; +using ThinkingSDK.PC.Main; +using ThinkingSDK.PC.Utils; +using ThinkingSDK.PC.DataModel; +using ThinkingSDK.PC.Config; + +namespace ThinkingData.Analytics.Wrapper +{ + public partial class TDWrapper : TDDynamicSuperPropertiesHandler_PC, TDAutoTrackEventHandler_PC + { + static TDAutoTrackEventHandler mEventCallback; + public Dictionary GetDynamicSuperProperties_PC() + { + if (mDynamicSuperProperties != null) + { + return mDynamicSuperProperties.GetDynamicSuperProperties(); + } + else + { + return new Dictionary(); + } + } + + public Dictionary AutoTrackEventCallback_PC(int type, Dictionary properties) + { + if (mEventCallback != null) + { + return mEventCallback.GetAutoTrackEventProperties(type, properties); + } + else + { + return new Dictionary(); + } + } + + private static void init(TDConfig token) + { + ThinkingSDKConfig config = ThinkingSDKConfig.GetInstance(token.appId, token.serverUrl, token.name); + if (!string.IsNullOrEmpty(token.getTimeZoneId())) + { + try + { + config.SetTimeZone(TimeZoneInfo.FindSystemTimeZoneById(token.getTimeZoneId())); + } + catch (Exception) + { + //if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("TimeZoneInfo set failed : " + e.Message); + } + } + if (token.mode == TDMode.Debug) + { + config.SetMode(Mode.DEBUG); + } + else if (token.mode == TDMode.DebugOnly) + { + config.SetMode(Mode.DEBUG_ONLY); + } + ThinkingPCSDK.Init(token.appId, token.serverUrl, token.name, config, sMono); + } + + private static void identify(string uniqueId, string appId) + { + ThinkingPCSDK.Identifiy(uniqueId, appId); + } + + private static string getDistinctId(string appId) + { + return ThinkingPCSDK.DistinctId(appId); + } + + private static void login(string accountId, string appId) + { + ThinkingPCSDK.Login(accountId, appId); + } + + private static void logout(string appId) + { + ThinkingPCSDK.Logout(appId); + } + + private static void flush(string appId) + { + ThinkingPCSDK.Flush(appId); + } + + private static void setVersionInfo(string lib_name, string lib_version) + { + ThinkingPCSDK.SetLibName(lib_name); + ThinkingPCSDK.SetLibVersion(lib_version); + } + + private static void track(TDEventModel taEvent, string appId) + { + ThinkingSDKEventData eventData = null; + switch (taEvent.EventType) + { + case TDEventModel.TDEventType.First: + { + eventData = new ThinkingSDKFirstEvent(taEvent.EventName); + if (!string.IsNullOrEmpty(taEvent.GetEventId())) + { + ((ThinkingSDKFirstEvent)eventData).SetFirstCheckId(taEvent.GetEventId()); + } + } + break; + case TDEventModel.TDEventType.Updatable: + eventData = new ThinkingSDKUpdateEvent(taEvent.EventName, taEvent.GetEventId()); + break; + case TDEventModel.TDEventType.Overwritable: + eventData = new ThinkingSDKOverWritableEvent(taEvent.EventName, taEvent.GetEventId()); + break; + } + if (mDynamicSuperProperties != null) + { + eventData.SetProperties(mDynamicSuperProperties.GetDynamicSuperProperties()); + } + if (taEvent.Properties != null) + { + eventData.SetProperties(taEvent.Properties); + } + if (taEvent.GetEventTime() != null && taEvent.GetEventTimeZone() != null) + { + eventData.SetEventTime(taEvent.GetEventTime()); + eventData.SetTimeZone(taEvent.GetEventTimeZone()); + } + ThinkingPCSDK.Track(eventData, appId); + } + + private static void track(string eventName, Dictionary properties, string appId) + { + ThinkingPCSDK.Track(eventName, properties, appId); + } + + private static void trackStr(string eventName, string properties, string appId) + { + try + { + ThinkingPCSDK.Track(eventName, TDMiniJson.Deserialize(properties), appId); + } + catch (Exception) + { + } + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, string appId) + { + ThinkingPCSDK.Track(eventName, properties, dateTime, appId); + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, TimeZoneInfo timeZone, string appId) + { + ThinkingPCSDK.Track(eventName, properties, dateTime, timeZone, appId); + } + + private static void trackForAll(string eventName, Dictionary properties) + { + ThinkingPCSDK.TrackForAll(eventName, properties); + } + + private static void setSuperProperties(Dictionary superProperties, string appId) + { + ThinkingPCSDK.SetSuperProperties(superProperties, appId); + } + + private static void setSuperProperties(string superProperties, string appId) + { + try + { + ThinkingPCSDK.SetSuperProperties(TDMiniJson.Deserialize(superProperties), appId); + } + catch (Exception) + { + } + } + + private static void unsetSuperProperty(string superPropertyName, string appId) + { + ThinkingPCSDK.UnsetSuperProperty(superPropertyName, appId); + } + + private static void clearSuperProperty(string appId) + { + ThinkingPCSDK.ClearSuperProperties(appId); + } + + private static Dictionary getSuperProperties(string appId) + { + return ThinkingPCSDK.SuperProperties(appId); + } + + private static Dictionary getPresetProperties(string appId) + { + return ThinkingPCSDK.PresetProperties(appId); + } + private static void timeEvent(string eventName, string appId) + { + ThinkingPCSDK.TimeEvent(eventName, appId); + } + private static void timeEventForAll(string eventName) + { + ThinkingPCSDK.TimeEventForAll(eventName); + } + + private static void userSet(Dictionary properties, string appId) + { + ThinkingPCSDK.UserSet(properties, appId); + } + + private static void userSet(string properties, string appId) + { + try + { + ThinkingPCSDK.UserSet(TDMiniJson.Deserialize(properties), appId); + } + catch (Exception) + { + } + } + + private static void userSet(Dictionary properties, DateTime dateTime, string appId) + { + ThinkingPCSDK.UserSet(properties, dateTime, appId); + } + + private static void userUnset(List properties, string appId) + { + ThinkingPCSDK.UserUnset(properties, appId); + } + + private static void userUnset(List properties, DateTime dateTime, string appId) + { + ThinkingPCSDK.UserUnset(properties, dateTime, appId); + } + + private static void userSetOnce(Dictionary properties, string appId) + { + ThinkingPCSDK.UserSetOnce(properties, appId); + } + + private static void userSetOnce(string properties, string appId) + { + try + { + ThinkingPCSDK.UserSetOnce(TDMiniJson.Deserialize(properties), appId); + } + catch (Exception) + { + } + } + + private static void userSetOnce(Dictionary properties, DateTime dateTime, string appId) + { + ThinkingPCSDK.UserSetOnce(properties, dateTime, appId); + } + + private static void userAdd(Dictionary properties, string appId) + { + ThinkingPCSDK.UserAdd(properties, appId); + } + + private static void userAddStr(string properties, string appId) + { + try + { + ThinkingPCSDK.UserAdd(TDMiniJson.Deserialize(properties), appId); + } + catch (Exception) + { + } + } + + private static void userAdd(Dictionary properties, DateTime dateTime, string appId) + { + ThinkingPCSDK.UserAdd(properties, dateTime, appId); + } + + private static void userDelete(string appId) + { + ThinkingPCSDK.UserDelete(appId); + } + + private static void userDelete(DateTime dateTime, string appId) + { + ThinkingPCSDK.UserDelete(dateTime, appId); + } + + private static void userAppend(Dictionary properties, string appId) + { + ThinkingPCSDK.UserAppend(properties, appId); + } + + private static void userAppend(string properties, string appId) + { + try + { + ThinkingPCSDK.UserAppend(TDMiniJson.Deserialize(properties), appId); + } + catch (Exception) + { + } + } + + private static void userAppend(Dictionary properties, DateTime dateTime, string appId) + { + ThinkingPCSDK.UserAppend(properties, dateTime, appId); + } + + private static void userUniqAppend(Dictionary properties, string appId) + { + ThinkingPCSDK.UserUniqAppend(properties, appId); + } + + private static void userUniqAppend(string properties, string appId) + { + try + { + ThinkingPCSDK.UserUniqAppend(TDMiniJson.Deserialize(properties), appId); + } + catch (Exception) + { + } + } + + private static void userUniqAppend(Dictionary properties, DateTime dateTime, string appId) + { + ThinkingPCSDK.UserUniqAppend(properties, dateTime, appId); + } + + private static void setNetworkType(TDNetworkType networkType) + { + + } + + private static string getDeviceId() + { + return ThinkingPCSDK.GetDeviceId(); + } + + private static void setDynamicSuperProperties(TDDynamicSuperPropertiesHandler dynamicSuperProperties, string appId) + { + ThinkingPCSDK.SetDynamicSuperProperties(new TDWrapper()); + } + + private static void setTrackStatus(TDTrackStatus status, string appId) + { + ThinkingPCSDK.SetTrackStatus((ThinkingSDK.PC.Main.TDTrackStatus)status, appId); + } + + private static void optOutTracking(string appId) + { + ThinkingPCSDK.OptTracking(false, appId); + } + + private static void optOutTrackingAndDeleteUser(string appId) + { + ThinkingPCSDK.OptTrackingAndDeleteUser(appId); + } + + private static void optInTracking(string appId) + { + ThinkingPCSDK.OptTracking(true, appId); + } + + private static void enableTracking(bool enabled, string appId) + { + ThinkingPCSDK.EnableTracking(enabled); + } + + private static string createLightInstance() + { + return ThinkingPCSDK.CreateLightInstance(); + } + + private static string getTimeString(DateTime dateTime) + { + + return ThinkingPCSDK.TimeString(dateTime); + } + + private static void enableAutoTrack(TDAutoTrackEventType autoTrackEvents, Dictionary properties, string appId) + { + ThinkingSDK.PC.Main.TDAutoTrackEventType pcAutoTrackEvents = ThinkingSDK.PC.Main.TDAutoTrackEventType.None; + if ((autoTrackEvents & TDAutoTrackEventType.AppInstall) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppInstall; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppStart) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppStart; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppEnd) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppEnd; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppCrash) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppCrash; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppSceneLoad) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppSceneLoad; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppSceneUnload) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppSceneUnload; + } + ThinkingPCSDK.EnableAutoTrack(pcAutoTrackEvents, properties, appId); + } + + private static void enableAutoTrack(TDAutoTrackEventType autoTrackEvents, TDAutoTrackEventHandler eventCallback, string appId) + { + ThinkingSDK.PC.Main.TDAutoTrackEventType pcAutoTrackEvents = ThinkingSDK.PC.Main.TDAutoTrackEventType.None; + if ((autoTrackEvents & TDAutoTrackEventType.AppInstall) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppInstall; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppStart) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppStart; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppEnd) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppEnd; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppCrash) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppCrash; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppSceneLoad) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppSceneLoad; + } + if ((autoTrackEvents & TDAutoTrackEventType.AppSceneUnload) != 0) + { + pcAutoTrackEvents = pcAutoTrackEvents | ThinkingSDK.PC.Main.TDAutoTrackEventType.AppSceneUnload; + } + mEventCallback = eventCallback; + ThinkingPCSDK.EnableAutoTrack(pcAutoTrackEvents, new TDWrapper(), appId); + } + + private static void setAutoTrackProperties(TDAutoTrackEventType autoTrackEvents, Dictionary properties, string appId) + { + if ((autoTrackEvents & TDAutoTrackEventType.AppInstall) != 0) + { + ThinkingPCSDK.SetAutoTrackProperties(ThinkingSDK.PC.Main.TDAutoTrackEventType.AppInstall, properties, appId); + } + if ((autoTrackEvents & TDAutoTrackEventType.AppStart) != 0) + { + ThinkingPCSDK.SetAutoTrackProperties(ThinkingSDK.PC.Main.TDAutoTrackEventType.AppStart, properties, appId); + } + if ((autoTrackEvents & TDAutoTrackEventType.AppEnd) != 0) + { + ThinkingPCSDK.SetAutoTrackProperties(ThinkingSDK.PC.Main.TDAutoTrackEventType.AppEnd, properties, appId); + } + if ((autoTrackEvents & TDAutoTrackEventType.AppCrash) != 0) + { + ThinkingPCSDK.SetAutoTrackProperties(ThinkingSDK.PC.Main.TDAutoTrackEventType.AppCrash, properties, appId); + } + if ((autoTrackEvents & TDAutoTrackEventType.AppSceneLoad) != 0) + { + ThinkingPCSDK.SetAutoTrackProperties(ThinkingSDK.PC.Main.TDAutoTrackEventType.AppSceneLoad, properties, appId); + } + if ((autoTrackEvents & TDAutoTrackEventType.AppSceneUnload) != 0) + { + ThinkingPCSDK.SetAutoTrackProperties(ThinkingSDK.PC.Main.TDAutoTrackEventType.AppSceneUnload, properties, appId); + } + } + + private static void enableLog(bool enable) + { + ThinkingPCSDK.EnableLog(enable); + } + private static void calibrateTime(long timestamp) + { + ThinkingPCSDK.CalibrateTime(timestamp); + } + + private static void calibrateTimeWithNtp(string ntpServer) + { + ThinkingPCSDK.CalibrateTimeWithNtp(ntpServer); + } + + private static void enableThirdPartySharing(TDThirdPartyType shareType, Dictionary properties, string appId) + { + if (ThinkingSDKPublicConfig.IsPrintLog()) ThinkingSDKLogger.Print("Sharing data is not support on PC: " + shareType + ", " + properties + ", " + appId); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/Wrapper/TDPCWrapper.cs.meta b/Assets/ThinkingAnalytics/Wrapper/TDPCWrapper.cs.meta new file mode 100644 index 0000000..9cad8e3 --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDPCWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f9ded317afe443d894852ab82fad3ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Wrapper/TDWrapper.cs b/Assets/ThinkingAnalytics/Wrapper/TDWrapper.cs new file mode 100644 index 0000000..cbad9b5 --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDWrapper.cs @@ -0,0 +1,507 @@ +using System; +using System.Collections.Generic; +using ThinkingData.Analytics.Utils; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace ThinkingData.Analytics.Wrapper +{ + public partial class TDWrapper + { + public static MonoBehaviour sMono; + private static TDDynamicSuperPropertiesHandler mDynamicSuperProperties; + private static Dictionary mAutoTrackEventCallbacks = new Dictionary(); + private static Dictionary> mAutoTrackProperties = new Dictionary>(); + private static Dictionary mAutoTrackEventInfos = new Dictionary(); + private static System.Random rnd = new System.Random(); + + private static string default_appId = null; + + // add Dictionary to Dictionary + public static void AddDictionary(Dictionary originalDic, Dictionary subDic) + { + if (originalDic != subDic) + { + foreach (KeyValuePair kv in subDic) + { + originalDic[kv.Key] = kv.Value; + } + } + } + + private static string serilize(Dictionary data) { + return TDMiniJson.Serialize(data, getTimeString); + } + + public static void ShareInstance(TDConfig token, MonoBehaviour mono, bool initRequired = true) + { + sMono = mono; + if (string.IsNullOrEmpty(default_appId)) default_appId = token.appId; + if (initRequired) init(token); + } + + public static void EnableLog(bool enable) + { + enableLog(enable); + } + + public static void SetVersionInfo(string version) + { + setVersionInfo("Unity", version); + } + + public static void SetDistinctId(string uniqueId, string appId) + { + identify(uniqueId, appId); + } + + public static string GetDistinctId(string appId) + { + return getDistinctId(appId); + } + + public static void Login(string accountId, string appId) + { + login(accountId, appId); + } + + public static void Logout(string appId) + { + logout(appId); + } + + public static void EnableAutoTrack(TDAutoTrackEventType events, Dictionary properties, string appId) + { + if (string.IsNullOrEmpty(appId)) appId = default_appId; + UpdateAutoTrackSceneInfos(events, appId); + SetAutoTrackProperties(events, properties, appId); + enableAutoTrack(events, properties, appId); + if ((events & TDAutoTrackEventType.AppSceneLoad) != 0) + { + TrackSceneLoad(SceneManager.GetActiveScene(), appId); + } + } + + public static void EnableAutoTrack(TDAutoTrackEventType events, TDAutoTrackEventHandler eventCallback, string appId) + { + if (string.IsNullOrEmpty(appId)) appId = default_appId; + UpdateAutoTrackSceneInfos(events, appId); + mAutoTrackEventCallbacks[appId] = eventCallback; + //mAutoTrackEventCallback = eventCallback; + enableAutoTrack(events, eventCallback, appId); + if ((events & TDAutoTrackEventType.AppSceneLoad) != 0) + { + TrackSceneLoad(SceneManager.GetActiveScene(), appId); + } + } + + private static string TDAutoTrackEventType_APP_SCENE_LOAD = "AppSceneLoad"; + private static string TDAutoTrackEventType_APP_SCENE_UNLOAD = "AppSceneUnload"; + public static void SetAutoTrackProperties(TDAutoTrackEventType events, Dictionary properties, string appId) + { + if ((events & TDAutoTrackEventType.AppSceneLoad) != 0) + { + if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_SCENE_LOAD)) + { + AddDictionary(mAutoTrackProperties[TDAutoTrackEventType_APP_SCENE_LOAD], properties); + } + else + mAutoTrackProperties[TDAutoTrackEventType_APP_SCENE_LOAD] = properties; + } + if ((events & TDAutoTrackEventType.AppSceneUnload) != 0) + { + if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_SCENE_UNLOAD)) + { + AddDictionary(mAutoTrackProperties[TDAutoTrackEventType_APP_SCENE_UNLOAD], properties); + } + else + mAutoTrackProperties[TDAutoTrackEventType_APP_SCENE_UNLOAD] = properties; + } + setAutoTrackProperties(events, properties, appId); + } + + public static void TrackSceneLoad(Scene scene, string appId = "") + { + Dictionary properties = new Dictionary() { + { "#scene_name", scene.name }, + { "#scene_path", scene.path } + }; + if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_SCENE_LOAD)) + { + AddDictionary(properties, mAutoTrackProperties[TDAutoTrackEventType_APP_SCENE_LOAD]); + } + if (string.IsNullOrEmpty(appId)) + { + foreach (var kv in mAutoTrackEventInfos) + { + Dictionary finalProperties = new Dictionary(properties); + if (mAutoTrackEventCallbacks.ContainsKey(kv.Key)) + { + AddDictionary(finalProperties, mAutoTrackEventCallbacks[kv.Key].GetAutoTrackEventProperties((int)TDAutoTrackEventType.AppSceneLoad, properties)); + } + if ((kv.Value & TDAutoTrackEventType.AppSceneLoad) != 0) + { + Track("ta_scene_loaded", finalProperties, kv.Key); + } + if ((kv.Value & TDAutoTrackEventType.AppSceneUnload) != 0) + { + TimeEvent("ta_scene_unloaded", kv.Key); + } + } + } + else + { + Dictionary finalProperties = new Dictionary(properties); + if (mAutoTrackEventCallbacks.ContainsKey(appId)) + { + AddDictionary(finalProperties, mAutoTrackEventCallbacks[appId].GetAutoTrackEventProperties((int)TDAutoTrackEventType.AppSceneLoad, properties)); + } + Track("ta_scene_loaded", finalProperties, appId); + TimeEvent("ta_scene_unloaded", appId); + } + } + + public static void TrackSceneUnload(Scene scene, string appId = "") + { + Dictionary properties = new Dictionary() { + { "#scene_name", scene.name }, + { "#scene_path", scene.path } + }; + if (mAutoTrackProperties.ContainsKey(TDAutoTrackEventType_APP_SCENE_UNLOAD)) + { + AddDictionary(properties, mAutoTrackProperties[TDAutoTrackEventType_APP_SCENE_UNLOAD]); + } + foreach (var kv in mAutoTrackEventInfos) + { + Dictionary finalProperties = new Dictionary(properties); + if (mAutoTrackEventCallbacks.ContainsKey(kv.Key)) + { + AddDictionary(finalProperties, mAutoTrackEventCallbacks[kv.Key].GetAutoTrackEventProperties((int)TDAutoTrackEventType.AppSceneUnload, properties)); + } + if ((kv.Value & TDAutoTrackEventType.AppSceneUnload) != 0) + { + Track("ta_scene_unloaded", finalProperties, kv.Key); + } + } + } + + private static void UpdateAutoTrackSceneInfos(TDAutoTrackEventType events, string appId = "") + { + if (string.IsNullOrEmpty(appId)) appId = default_appId; + mAutoTrackEventInfos[appId] = events; + } + + private static Dictionary getFinalEventProperties(Dictionary properties) + { + TDPropertiesChecker.CheckProperties(properties); + + if (null != mDynamicSuperProperties) + { + Dictionary finalProperties = new Dictionary(); + TDPropertiesChecker.MergeProperties(mDynamicSuperProperties.GetDynamicSuperProperties(), finalProperties); + TDPropertiesChecker.MergeProperties(properties, finalProperties); + return finalProperties; + } + else + { + return properties; + } + + } + public static void Track(string eventName, Dictionary properties, string appId) + { + TDPropertiesChecker.CheckString(eventName); + track(eventName, getFinalEventProperties(properties), appId); + } + + public static void TrackStr(string eventName, string properties, string appId) + { + trackStr(eventName, properties, appId); + } + + public static void Track(string eventName, Dictionary properties, DateTime datetime, string appId) + { + TDPropertiesChecker.CheckString(eventName); + track(eventName, getFinalEventProperties(properties), datetime, appId); + } + + public static void Track(string eventName, Dictionary properties, DateTime datetime, TimeZoneInfo timeZone, string appId) + { + TDPropertiesChecker.CheckString(eventName); + track(eventName, getFinalEventProperties(properties), datetime, timeZone, appId); + } + + public static void TrackForAll(string eventName, Dictionary properties) + { + TDPropertiesChecker.CheckString(eventName); + trackForAll(eventName, getFinalEventProperties(properties)); + } + + public static void Track(TDEventModel taEvent, string appId) + { + if (null == taEvent || null == taEvent.EventType) + { + if(TDLog.GetEnable()) TDLog.w("Ignoring invalid TA event"); + return; + } + + if (taEvent.GetEventTime() == null) + { + if(TDLog.GetEnable()) TDLog.w("ppp null..."); + } + TDPropertiesChecker.CheckString(taEvent.EventName); + TDPropertiesChecker.CheckProperties(taEvent.Properties); + track(taEvent, appId); + } + + public static void QuickTrack(string eventName, Dictionary properties, string appId) + { + if ("SceneView" == eventName) + { + if (properties == null) + { + properties = new Dictionary() { }; + } + Scene scene = SceneManager.GetActiveScene(); + if (scene != null) + { + properties.Add("#scene_name", scene.name); + properties.Add("#scene_path", scene.path); + } + Track("ta_scene_view", properties, appId); + } + else if ("AppClick" == eventName) + { + if (properties == null) + { + properties = new Dictionary() { }; + } + Track("ta_app_click", properties, appId); + } + } + + public static void SetSuperProperties(Dictionary superProperties, string appId) + { + TDPropertiesChecker.CheckProperties(superProperties); + setSuperProperties(superProperties, appId); + } + + public static void SetSuperProperties(string superProperties, string appId) + { + setSuperProperties(superProperties, appId); + } + + public static void UnsetSuperProperty(string superPropertyName, string appId) + { + TDPropertiesChecker.CheckString(superPropertyName); + unsetSuperProperty(superPropertyName, appId); + } + + public static void ClearSuperProperty(string appId) + { + clearSuperProperty(appId); + } + + + public static void TimeEvent(string eventName, string appId) + { + TDPropertiesChecker.CheckString(eventName); + timeEvent(eventName, appId); + } + + public static void TimeEventForAll(string eventName) + { + TDPropertiesChecker.CheckString(eventName); + timeEventForAll(eventName); + } + + public static Dictionary GetSuperProperties(string appId) + { + return getSuperProperties(appId); + } + + public static Dictionary GetPresetProperties(string appId) + { + return getPresetProperties(appId); + } + + public static void UserSet(Dictionary properties, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userSet(properties, appId); + } + + public static void UserSet(string properties, string appId) + { + userSet(properties, appId); + } + + public static void UserSet(Dictionary properties, DateTime dateTime, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userSet(properties, dateTime, appId); + } + + public static void UserSetOnce(Dictionary properties, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userSetOnce(properties, appId); + } + + public static void UserSetOnce(string properties, string appId) + { + userSetOnce(properties, appId); + } + + public static void UserSetOnce(Dictionary properties, DateTime dateTime, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userSetOnce(properties, dateTime, appId); + } + + public static void UserUnset(List properties, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userUnset(properties, appId); + } + + public static void UserUnset(List properties, DateTime dateTime, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userUnset(properties, dateTime, appId); + } + + public static void UserAdd(Dictionary properties, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userAdd(properties, appId); + } + + public static void UserAddStr(string properties, string appId) + { + userAddStr(properties, appId); + } + + public static void UserAdd(Dictionary properties, DateTime dateTime, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userAdd(properties, dateTime, appId); + } + + public static void UserAppend(Dictionary properties, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userAppend(properties, appId); + } + + public static void UserAppend(string properties, string appId) + { + userAppend(properties, appId); + } + + public static void UserAppend(Dictionary properties, DateTime dateTime, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userAppend(properties, dateTime, appId); + } + + public static void UserUniqAppend(Dictionary properties, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userUniqAppend(properties, appId); + } + + public static void UserUniqAppend(string properties, string appId) + { + userUniqAppend(properties, appId); + } + + public static void UserUniqAppend(Dictionary properties, DateTime dateTime, string appId) + { + TDPropertiesChecker.CheckProperties(properties); + userUniqAppend(properties, dateTime, appId); + } + + public static void UserDelete(string appId) + { + userDelete(appId); + } + + public static void UserDelete(DateTime dateTime, string appId) + { + userDelete(dateTime, appId); + } + + public static void Flush(string appId) + { + flush(appId); + } + + public static void SetNetworkType(TDNetworkType networkType) + { + setNetworkType(networkType); + } + + public static string GetDeviceId() + { + return getDeviceId(); + } + + public static void SetDynamicSuperProperties(TDDynamicSuperPropertiesHandler dynamicSuperProperties, string appId) + { + if (!TDPropertiesChecker.CheckProperties(dynamicSuperProperties.GetDynamicSuperProperties())) + { + if(TDLog.GetEnable()) TDLog.d("Cannot set dynamic super properties due to invalid properties."); + } + mDynamicSuperProperties = dynamicSuperProperties; + setDynamicSuperProperties(dynamicSuperProperties, appId); + } + + public static void SetTrackStatus(TDTrackStatus status, string appId) + { + setTrackStatus(status, appId); + } + + public static void OptOutTracking(string appId) + { + optOutTracking(appId); + } + + public static void OptOutTrackingAndDeleteUser(string appId) + { + optOutTrackingAndDeleteUser(appId); + } + + public static void OptInTracking(string appId) + { + optInTracking(appId); + } + + public static void EnableTracking(bool enabled, string appId) + { + enableTracking(enabled, appId); + } + + public static string CreateLightInstance() + { + return createLightInstance(); + } + + public static void CalibrateTime(long timestamp) + { + calibrateTime(timestamp); + } + + public static void CalibrateTimeWithNtp(string ntpServer) + { + calibrateTimeWithNtp(ntpServer); + } + + public static void EnableThirdPartySharing(TDThirdPartyType shareType, Dictionary properties = null, string appId = "") + { + if (null == properties) properties = new Dictionary(); + enableThirdPartySharing(shareType, properties, appId); + } + } +} + diff --git a/Assets/ThinkingAnalytics/Wrapper/TDWrapper.cs.meta b/Assets/ThinkingAnalytics/Wrapper/TDWrapper.cs.meta new file mode 100644 index 0000000..3fc816f --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 306f69768d6114f989d144fd22df1b13 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkingAnalytics/Wrapper/TDiOSWrapper.cs b/Assets/ThinkingAnalytics/Wrapper/TDiOSWrapper.cs new file mode 100644 index 0000000..93eb7b5 --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDiOSWrapper.cs @@ -0,0 +1,551 @@ +#if UNITY_IOS && !(UNITY_EDITOR) && !TE_DISABLE_IOS_OC +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using ThinkingData.Analytics.Utils; + +namespace ThinkingData.Analytics.Wrapper +{ + public partial class TDWrapper + { + [DllImport("__Internal")] + private static extern void ta_start(string app_id, string url, int mode, string timezone_id, bool enable_encrypt, int encrypt_version, string encrypt_public_key, int pinning_mode, bool allow_invalid_certificates, bool validates_domain_name, string instance_name); + [DllImport("__Internal")] + private static extern void ta_identify(string app_id, string unique_id); + [DllImport("__Internal")] + private static extern string ta_get_distinct_id(string app_id); + [DllImport("__Internal")] + private static extern void ta_login(string app_id, string account_id); + [DllImport("__Internal")] + private static extern void ta_logout(string app_id); + [DllImport("__Internal")] + private static extern void ta_track(string app_id, string event_name, string properties, long time_stamp_millis, string timezone); + [DllImport("__Internal")] + private static extern void ta_track_event(string app_id, int type, string event_name, string properties, string event_id, long time_stamp_millis, string timezone); + [DllImport("__Internal")] + private static extern void ta_set_super_properties(string app_id, string properties); + [DllImport("__Internal")] + private static extern void ta_unset_super_property(string app_id, string property_name); + [DllImport("__Internal")] + private static extern void ta_clear_super_properties(string app_id); + [DllImport("__Internal")] + private static extern string ta_get_super_properties(string app_id); + [DllImport("__Internal")] + private static extern string ta_get_preset_properties(string app_id); + [DllImport("__Internal")] + private static extern void ta_time_event(string app_id, string event_name); + [DllImport("__Internal")] + private static extern void ta_user_set(string app_id, string properties); + [DllImport("__Internal")] + private static extern void ta_user_set_with_time(string app_id, string properties, long timestamp); + [DllImport("__Internal")] + private static extern void ta_user_unset(string app_id, string properties); + [DllImport("__Internal")] + private static extern void ta_user_unset_with_time(string app_id, string properties, long timestamp); + [DllImport("__Internal")] + private static extern void ta_user_set_once(string app_id, string properties); + [DllImport("__Internal")] + private static extern void ta_user_set_once_with_time(string app_id, string properties, long timestamp); + [DllImport("__Internal")] + private static extern void ta_user_add(string app_id, string properties); + [DllImport("__Internal")] + private static extern void ta_user_add_with_time(string app_id, string properties, long timestamp); + [DllImport("__Internal")] + private static extern void ta_user_delete(string app_id); + [DllImport("__Internal")] + private static extern void ta_user_delete_with_time(string app_id, long timestamp); + [DllImport("__Internal")] + private static extern void ta_user_append(string app_id, string properties); + [DllImport("__Internal")] + private static extern void ta_user_append_with_time(string app_id, string properties, long timestamp); + [DllImport("__Internal")] + private static extern void ta_user_uniq_append(string app_id, string properties); + [DllImport("__Internal")] + private static extern void ta_user_uniq_append_with_time(string app_id, string properties, long timestamp); + [DllImport("__Internal")] + private static extern void ta_flush(string app_id); + [DllImport("__Internal")] + private static extern void ta_set_network_type(int type); + [DllImport("__Internal")] + private static extern void ta_enable_log(bool is_enable); + [DllImport("__Internal")] + private static extern string ta_get_device_id(); + [DllImport("__Internal")] + private static extern void ta_set_dynamic_super_properties(string app_id); + [DllImport("__Internal")] + private static extern void ta_enable_tracking(string app_id, bool enabled); + [DllImport("__Internal")] + private static extern void ta_set_track_status(string app_id, int status); + [DllImport("__Internal")] + private static extern void ta_opt_out_tracking(string app_id); + [DllImport("__Internal")] + private static extern void ta_opt_out_tracking_and_delete_user(string app_id); + [DllImport("__Internal")] + private static extern void ta_opt_in_tracking(string app_id); + [DllImport("__Internal")] + private static extern void ta_create_light_instance(string delegate_token); + [DllImport("__Internal")] + private static extern void ta_enable_autoTrack(string app_id, int events, string properties); + [DllImport("__Internal")] + private static extern void ta_enable_autoTrack_with_callback(string app_id, int events); + [DllImport("__Internal")] + private static extern void ta_set_autoTrack_properties(string app_id, int events, string properties); + [DllImport("__Internal")] + private static extern string ta_get_time_string(long timestamp); + [DllImport("__Internal")] + private static extern void ta_calibrate_time(long timestamp); + [DllImport("__Internal")] + private static extern void ta_calibrate_time_with_ntp(string ntpServer); + [DllImport("__Internal")] + private static extern void ta_config_custom_lib_info(string lib_name, string lib_version); + [DllImport("__Internal")] + private static extern void ta_enable_third_party_sharing(string app_id, int share_type, string properties); + + private static TimeZoneInfo defaultTimeZone = null; + private static TDTimeZone defaultTDTimeZone = TDTimeZone.Local; + + private static void init(TDConfig token) + { + registerRecieveGameCallback(); + ta_start(token.appId, token.serverUrl, (int)token.mode, token.getTimeZoneId(), token.enableEncrypt, token.encryptVersion, token.encryptPublicKey, (int) token.pinningMode, token.allowInvalidCertificates, token.validatesDomainName, token.name); + string timeZoneId = token.getTimeZoneId(); + defaultTDTimeZone = token.timeZone; + if (null != timeZoneId && timeZoneId.Length > 0) + { + if (defaultTimeZone == null) + { + try + { + defaultTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); + } + catch (Exception) + { + } + } + } + else + { + if (defaultTimeZone == null) + { + defaultTimeZone = TimeZoneInfo.Local; + } + } + } + + private static void identify(string uniqueId, string appId) + { + ta_identify(appId, uniqueId); + } + + private static string getDistinctId(string appId) + { + return ta_get_distinct_id(appId); + } + + private static void login(string accountId, string appId) + { + ta_login(appId, accountId); + } + + private static void logout(string appId) + { + ta_logout(appId); + } + + private static void flush(string appId) + { + ta_flush(appId); + } + + private static void enableLog(bool enable) + { + ta_enable_log(enable); + } + + private static void setVersionInfo(string lib_name, string lib_version) { + ta_config_custom_lib_info(lib_name, lib_version); + } + + private static void track(TDEventModel taEvent, string appId) + { + int type = -1; + switch (taEvent.EventType) + { + case TDEventModel.TDEventType.First: + type = 0; + break; + case TDEventModel.TDEventType.Updatable: + type = 1; + break; + case TDEventModel.TDEventType.Overwritable: + type = 2; + break; + } + string jsonStr; + if (taEvent.Properties == null) + { + jsonStr = taEvent.StrProperties; + } + else + { + jsonStr = serilize(taEvent.Properties); + } + long currentMillis = 0; + if (taEvent.GetEventTime() != null && taEvent.GetEventTime() != DateTime.MinValue) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(taEvent.GetEventTime()).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + } + string timeZoneId = ""; + if (taEvent.GetEventTimeZone() != null) + { + timeZoneId = taEvent.GetEventTimeZone().Id; + } + ta_track_event(appId, type, taEvent.EventName, jsonStr, taEvent.GetEventId(), currentMillis, timeZoneId); + } + + private static void track(string eventName, Dictionary properties, string appId) + { + ta_track(appId, eventName, serilize(properties), 0, ""); + } + + private static void trackStr(string eventName, string properties, string appId) + { + ta_track(appId, eventName, properties, 0, ""); + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + string tz = ""; + ta_track(appId, eventName, serilize(properties), currentMillis, tz); + } + + private static void track(string eventName, Dictionary properties, DateTime dateTime, TimeZoneInfo timeZone, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + string tz = ""; + if (timeZone != null) + { + tz = timeZone.Id; + } + ta_track(appId, eventName, serilize(properties), currentMillis, tz); + } + + private static void trackForAll(string eventName, Dictionary properties) + { + string appId = ""; + track(eventName, properties, appId); + } + + private static void setSuperProperties(Dictionary superProperties, string appId) + { + ta_set_super_properties(appId, serilize(superProperties)); + } + + private static void setSuperProperties(string superProperties, string appId) + { + ta_set_super_properties(appId, superProperties); + } + + private static void unsetSuperProperty(string superPropertyName, string appId) + { + ta_unset_super_property(appId, superPropertyName); + } + + private static void clearSuperProperty(string appId) + { + ta_clear_super_properties(appId); + } + + private static Dictionary getSuperProperties(string appId) + { + string superPropertiesString = ta_get_super_properties(appId); + return TDMiniJson.Deserialize(superPropertiesString); + } + + private static Dictionary getPresetProperties(string appId) + { + string presetPropertiesString = ta_get_preset_properties(appId); + return TDMiniJson.Deserialize(presetPropertiesString); + } + + private static void timeEvent(string eventName, string appId) + { + ta_time_event(appId, eventName); + } + + private static void timeEventForAll(string eventName) + { + ta_time_event("", eventName); + } + + private static void userSet(Dictionary properties, string appId) + { + ta_user_set(appId, serilize(properties)); + } + + private static void userSet(string properties, string appId) + { + ta_user_set(appId, properties); + } + + private static void userSet(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + ta_user_set_with_time(appId, serilize(properties), currentMillis); + } + + private static void userUnset(List properties, string appId) + { + foreach (string property in properties) + { + ta_user_unset(appId, property); + } + } + + private static void userUnset(List properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + foreach (string property in properties) + { + ta_user_unset_with_time(appId, property, currentMillis); + } + } + + private static void userSetOnce(Dictionary properties, string appId) + { + ta_user_set_once(appId, serilize(properties)); + } + + private static void userSetOnce(string properties, string appId) + { + ta_user_set_once(appId, properties); + } + + private static void userSetOnce(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + ta_user_set_once_with_time(appId, serilize(properties), currentMillis); + } + + private static void userAdd(Dictionary properties, string appId) + { + ta_user_add(appId, serilize(properties)); + } + + private static void userAddStr(string properties, string appId) + { + ta_user_add(appId, properties); + } + + private static void userAdd(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + ta_user_add_with_time(appId, serilize(properties), currentMillis); + } + + private static void userDelete(string appId) + { + ta_user_delete(appId); + } + + private static void userDelete(DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + ta_user_delete_with_time(appId, currentMillis); + } + + private static void userAppend(Dictionary properties, string appId) + { + ta_user_append(appId, serilize(properties)); + } + + private static void userAppend(string properties, string appId) + { + ta_user_append(appId, properties); + } + + private static void userAppend(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + ta_user_append_with_time(appId, serilize(properties), currentMillis); + } + + private static void userUniqAppend(Dictionary properties, string appId) + { + ta_user_uniq_append(appId, serilize(properties)); + } + + private static void userUniqAppend(string properties, string appId) + { + ta_user_uniq_append(appId, properties); + } + + private static void userUniqAppend(Dictionary properties, DateTime dateTime, string appId) + { + long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + ta_user_uniq_append_with_time(appId, serilize(properties), currentMillis); + } + + private static void setNetworkType(TDNetworkType networkType) + { + ta_set_network_type((int)networkType); + } + + private static string getDeviceId() + { + return ta_get_device_id(); + } + + private static void setDynamicSuperProperties(TDDynamicSuperPropertiesHandler dynamicSuperProperties, string appId) + { + ta_set_dynamic_super_properties(appId); + } + + private static void setTrackStatus(TDTrackStatus status, string appId) + { + ta_set_track_status(appId, (int)status); + } + + private static void optOutTracking(string appId) + { + ta_opt_out_tracking(appId); + } + + private static void optOutTrackingAndDeleteUser(string appId) + { + ta_opt_out_tracking_and_delete_user(appId); + } + + private static void optInTracking(string appId) + { + ta_opt_in_tracking(appId); + } + + private static void enableTracking(bool enabled, string appId) + { + ta_enable_tracking(appId, enabled); + } + + private static string createLightInstance() + { + string randomID = System.Guid.NewGuid().ToString("N"); + ta_create_light_instance(randomID); + return randomID; + } + + private static string getTimeString(DateTime dateTime) + { + //long dateTimeTicksUTC = TimeZoneInfo.ConvertTimeToUtc(dateTime).Ticks; + //DateTime dtFrom = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + //long currentMillis = (dateTimeTicksUTC - dtFrom.Ticks) / 10000; + //return ta_get_time_string(currentMillis); + if (defaultTimeZone == null) + { + return TDCommonUtils.FormatDate(dateTime, defaultTDTimeZone); + } + else + { + return TDCommonUtils.FormatDate(dateTime, defaultTimeZone); + } + } + + private static void enableAutoTrack(TDAutoTrackEventType autoTrackEvents, Dictionary properties, string appId) + { + ta_enable_autoTrack(appId, (int)autoTrackEvents, serilize(properties)); + } + + private static void enableAutoTrack(TDAutoTrackEventType autoTrackEvents, TDAutoTrackEventHandler eventCallback, string appId) + { + ta_enable_autoTrack_with_callback(appId, (int)autoTrackEvents); + } + + private static void setAutoTrackProperties(TDAutoTrackEventType autoTrackEvents, Dictionary properties, string appId) + { + ta_set_autoTrack_properties(appId, (int)autoTrackEvents, serilize(properties)); + } + + private static void calibrateTime(long timestamp) + { + ta_calibrate_time(timestamp); + } + + private static void calibrateTimeWithNtp(string ntpServer) + { + ta_calibrate_time_with_ntp(ntpServer); + } + + private static void enableThirdPartySharing(TDThirdPartyType shareType, Dictionary properties, string appId) + { + ta_enable_third_party_sharing(appId, (int) shareType, serilize(properties)); + } + + private static void registerRecieveGameCallback() + { + ResultHandler handler = new ResultHandler(resultHandler); + IntPtr handlerPointer = Marshal.GetFunctionPointerForDelegate(handler); + RegisterRecieveGameCallback(handlerPointer); + } + + [DllImport("__Internal")] + public static extern void RegisterRecieveGameCallback + ( + IntPtr handlerPointer + ); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate string ResultHandler(string type, string jsonData); + + [AOT.MonoPInvokeCallback(typeof(ResultHandler))] + static string resultHandler(string type, string jsonData) + { + if (type == "AutoTrackProperties") + { + Dictionaryproperties = TDMiniJson.Deserialize(jsonData); + string appId = properties["AppID"].ToString(); + int eventType = Convert.ToInt32(properties["EventType"]); + if (!string.IsNullOrEmpty(appId) && mAutoTrackEventCallbacks.ContainsKey(appId)) + { + properties.Remove("EventType"); + properties.Remove("AppID"); + DictionaryautoTrackProperties = mAutoTrackEventCallbacks[appId].GetAutoTrackEventProperties(eventType, properties); + //return TDMiniJson.Serialize(autoTrackProperties); + return serilize(autoTrackProperties); + } + } + else if (type == "DynamicSuperProperties") + { + if (mDynamicSuperProperties != null) + { + DictionarydynamicSuperProperties = mDynamicSuperProperties.GetDynamicSuperProperties(); + //return TDMiniJson.Serialize(dynamicSuperProperties); + return serilize(dynamicSuperProperties); + } + } + return "{}"; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ThinkingAnalytics/Wrapper/TDiOSWrapper.cs.meta b/Assets/ThinkingAnalytics/Wrapper/TDiOSWrapper.cs.meta new file mode 100644 index 0000000..680368f --- /dev/null +++ b/Assets/ThinkingAnalytics/Wrapper/TDiOSWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e2049ce2b30da48328f05872adacceed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/google-services.json b/Assets/google-services.json new file mode 100644 index 0000000..e6e64dc --- /dev/null +++ b/Assets/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "601745472008", + "project_id": "ag787cd54047-e0ac1-gp", + "storage_bucket": "ag787cd54047-e0ac1-gp.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:601745472008:android:768b7c2f79e2e93725afbd", + "android_client_info": { + "package_name": "com.rush.cash.earn.fast.real.money.game" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyCbVg7dxQbatGTDomrKq4AkQAP4aH1vr4Y" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/Assets/google-services.json.meta b/Assets/google-services.json.meta new file mode 100644 index 0000000..58066ac --- /dev/null +++ b/Assets/google-services.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7b27930e2fb6bc84e96b66bdceb0c41e +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml b/Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml new file mode 100644 index 0000000..93226a4 --- /dev/null +++ b/Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + Assets/Firebase/m2repository + + + + diff --git a/Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml.meta b/Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml.meta new file mode 100644 index 0000000..a66b439 --- /dev/null +++ b/Assets/rd3/Firebase/Editor/CrashlyticsDependencies.xml.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be690db6bda046a89e38b20ef9bfe06c +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Editor/CrashlyticsDependencies.xml +timeCreated: 1480838400 +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.dll b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.dll new file mode 100644 index 0000000..9081133 Binary files /dev/null and b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.dll differ diff --git a/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.dll.meta b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.dll.meta new file mode 100644 index 0000000..df448f6 --- /dev/null +++ b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.dll.meta @@ -0,0 +1,118 @@ +fileFormatVersion: 2 +guid: 3781f2218eef4d5a823dba406baa434b +labels: +- gvh +- gvh_targets-editor +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Editor/Firebase.Crashlytics.Editor.dll +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 0 + platformData: + - first: + : Linux + second: + enabled: 0 + settings: + CPU: None + - first: + : LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + : OSXIntel + second: + enabled: 0 + settings: + CPU: None + - first: + : OSXIntel64 + second: + enabled: 0 + settings: + CPU: None + - first: + : Web + second: + enabled: 0 + settings: {} + - first: + : WebStreamed + second: + enabled: 0 + settings: {} + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.pdb b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.pdb new file mode 100644 index 0000000..9a396b2 Binary files /dev/null and b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.pdb differ diff --git a/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.pdb.meta b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.pdb.meta new file mode 100644 index 0000000..7c4263c --- /dev/null +++ b/Assets/rd3/Firebase/Editor/Firebase.Crashlytics.Editor.pdb.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 78466de0dce747f9bf1d009be141cf6f +labels: +- gvh +- gvh_rename_to_disable +- gvh_targets-editor +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Editor/Firebase.Crashlytics.Editor.pdb +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/Editor/FirebaseCrashlytics_version-13.1.0_manifest.txt b/Assets/rd3/Firebase/Editor/FirebaseCrashlytics_version-13.1.0_manifest.txt new file mode 100644 index 0000000..1fe8551 --- /dev/null +++ b/Assets/rd3/Firebase/Editor/FirebaseCrashlytics_version-13.1.0_manifest.txt @@ -0,0 +1,68 @@ +Assets/Editor Default Resources/Firebase/fb_analytics.png +Assets/Editor Default Resources/Firebase/fb_analytics_dark.png +Assets/Editor Default Resources/Firebase/fb_auth.png +Assets/Editor Default Resources/Firebase/fb_auth_dark.png +Assets/Editor Default Resources/Firebase/fb_cloud_messaging.png +Assets/Editor Default Resources/Firebase/fb_cloud_messaging_dark.png +Assets/Editor Default Resources/Firebase/fb_config.png +Assets/Editor Default Resources/Firebase/fb_config_dark.png +Assets/Editor Default Resources/Firebase/fb_crashlytics.png +Assets/Editor Default Resources/Firebase/fb_crashlytics_dark.png +Assets/Editor Default Resources/Firebase/fb_database.png +Assets/Editor Default Resources/Firebase/fb_database_dark.png +Assets/Editor Default Resources/Firebase/fb_functions.png +Assets/Editor Default Resources/Firebase/fb_functions_dark.png +Assets/Editor Default Resources/Firebase/fb_storage.png +Assets/Editor Default Resources/Firebase/fb_storage_dark.png +Assets/Editor Default Resources/Firebase/firebase_lockup.png +Assets/Editor Default Resources/Firebase/firebase_lockup_dark.png +Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.dll +Assets/ExternalDependencyManager/Editor/1.2.186/Google.IOSResolver.pdb +Assets/ExternalDependencyManager/Editor/1.2.186/Google.JarResolver.dll +Assets/ExternalDependencyManager/Editor/1.2.186/Google.JarResolver.pdb +Assets/ExternalDependencyManager/Editor/1.2.186/Google.PackageManagerResolver.dll +Assets/ExternalDependencyManager/Editor/1.2.186/Google.PackageManagerResolver.pdb +Assets/ExternalDependencyManager/Editor/1.2.186/Google.VersionHandlerImpl.dll +Assets/ExternalDependencyManager/Editor/1.2.186/Google.VersionHandlerImpl.pdb +Assets/ExternalDependencyManager/Editor/CHANGELOG.md +Assets/ExternalDependencyManager/Editor/Google.VersionHandler.dll +Assets/ExternalDependencyManager/Editor/Google.VersionHandler.pdb +Assets/ExternalDependencyManager/Editor/LICENSE +Assets/ExternalDependencyManager/Editor/README.md +Assets/ExternalDependencyManager/Editor/external-dependency-manager_version-1.2.186_manifest.txt +Assets/Firebase/Editor/AppDependencies.xml +Assets/Firebase/Editor/CrashlyticsDependencies.xml +Assets/Firebase/Editor/Firebase.Crashlytics.Editor.dll +Assets/Firebase/Editor/Firebase.Crashlytics.Editor.pdb +Assets/Firebase/Editor/Firebase.Editor.dll +Assets/Firebase/Editor/Firebase.Editor.pdb +Assets/Firebase/Editor/generate_xml_from_google_services_json.exe +Assets/Firebase/Editor/generate_xml_from_google_services_json.py +Assets/Firebase/Editor/network_request.exe +Assets/Firebase/Editor/network_request.py +Assets/Firebase/Plugins/Firebase.App.dll +Assets/Firebase/Plugins/Firebase.App.pdb +Assets/Firebase/Plugins/Firebase.Crashlytics.dll +Assets/Firebase/Plugins/Firebase.Crashlytics.pdb +Assets/Firebase/Plugins/Firebase.Platform.dll +Assets/Firebase/Plugins/Firebase.Platform.pdb +Assets/Firebase/Plugins/Firebase.TaskExtension.dll +Assets/Firebase/Plugins/Firebase.TaskExtension.pdb +Assets/Firebase/Plugins/Google.MiniJson.dll +Assets/Firebase/Plugins/iOS/Firebase.App.dll +Assets/Firebase/Plugins/iOS/Firebase.App.pdb +Assets/Firebase/Plugins/iOS/Firebase.Crashlytics.dll +Assets/Firebase/Plugins/iOS/Firebase.Crashlytics.pdb +Assets/Firebase/Plugins/x86_64/FirebaseCppApp-13_1_0.bundle +Assets/Firebase/Plugins/x86_64/FirebaseCppApp-13_1_0.dll +Assets/Firebase/Plugins/x86_64/FirebaseCppApp-13_1_0.so +Assets/Firebase/m2repository/com/google/firebase/firebase-app-unity/13.1.0/firebase-app-unity-13.1.0.pom +Assets/Firebase/m2repository/com/google/firebase/firebase-app-unity/13.1.0/firebase-app-unity-13.1.0.srcaar +Assets/Firebase/m2repository/com/google/firebase/firebase-app-unity/maven-metadata.xml +Assets/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom +Assets/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar +Assets/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml +Assets/Plugins/iOS/Firebase/libFirebaseCppApp.a +Assets/Plugins/iOS/Firebase/libFirebaseCppCrashlytics.a +Assets/Plugins/tvOS/Firebase/libFirebaseCppApp.a +Assets/Plugins/tvOS/Firebase/libFirebaseCppCrashlytics.a diff --git a/Assets/rd3/Firebase/Editor/FirebaseCrashlytics_version-13.1.0_manifest.txt.meta b/Assets/rd3/Firebase/Editor/FirebaseCrashlytics_version-13.1.0_manifest.txt.meta new file mode 100644 index 0000000..5556e84 --- /dev/null +++ b/Assets/rd3/Firebase/Editor/FirebaseCrashlytics_version-13.1.0_manifest.txt.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 633e555af13a40a1bf61c19d3cea7b30 +labels: +- gvh +- gvh_manifest +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Editor/FirebaseCrashlytics_version-13.1.0_manifest.txt +- gvhp_manifestname-0Firebase Crashlytics +- gvhp_manifestname-1FirebaseCrashlytics +timeCreated: 0 diff --git a/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.dll b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.dll new file mode 100644 index 0000000..7bf651c Binary files /dev/null and b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.dll differ diff --git a/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.dll.meta b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.dll.meta new file mode 100644 index 0000000..acdb7ec --- /dev/null +++ b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.dll.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: 4a712f6ef12f441e9d8b053a3c30ad55 +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Plugins/Firebase.Crashlytics.dll +timeCreated: 1480838400 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 1 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 1 + settings: + CPU: x86 + Linux64: + enabled: 1 + settings: + CPU: x86_64 + LinuxUniversal: + enabled: 1 + settings: + CPU: AnyCPU + OSXIntel: + enabled: 1 + settings: + CPU: x86 + OSXIntel64: + enabled: 1 + settings: + CPU: x86_64 + OSXUniversal: + enabled: 1 + settings: + CPU: AnyCPU + Web: + enabled: 0 + settings: {} + WebStreamed: + enabled: 0 + settings: {} + Win: + enabled: 1 + settings: + CPU: x86 + Win64: + enabled: 1 + settings: + CPU: x86_64 + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + iOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + tvOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.pdb b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.pdb new file mode 100644 index 0000000..ed153c7 Binary files /dev/null and b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.pdb differ diff --git a/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.pdb.meta b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.pdb.meta new file mode 100644 index 0000000..f38520d --- /dev/null +++ b/Assets/rd3/Firebase/Plugins/Firebase.Crashlytics.pdb.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: cf098bb37bd1464083da05173619936e +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Plugins/Firebase.Crashlytics.pdb +timeCreated: 1480838400 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 1 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 1 + settings: + CPU: x86 + Linux64: + enabled: 1 + settings: + CPU: x86_64 + LinuxUniversal: + enabled: 1 + settings: + CPU: AnyCPU + OSXIntel: + enabled: 1 + settings: + CPU: x86 + OSXIntel64: + enabled: 1 + settings: + CPU: x86_64 + OSXUniversal: + enabled: 1 + settings: + CPU: AnyCPU + Web: + enabled: 0 + settings: {} + WebStreamed: + enabled: 0 + settings: {} + Win: + enabled: 1 + settings: + CPU: x86 + Win64: + enabled: 1 + settings: + CPU: x86_64 + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + iOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + tvOS: + enabled: 0 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/Plugins/iOS.meta b/Assets/rd3/Firebase/Plugins/iOS.meta index 8e0fc5e..acbd86a 100644 --- a/Assets/rd3/Firebase/Plugins/iOS.meta +++ b/Assets/rd3/Firebase/Plugins/iOS.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 4e6478208fc84764e947ae503b7aa849 +guid: 5d820efe2a91b314ca249e3cd8e391d8 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.dll b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.dll new file mode 100644 index 0000000..fdebe59 Binary files /dev/null and b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.dll differ diff --git a/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.dll.meta b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.dll.meta new file mode 100644 index 0000000..4a48b99 --- /dev/null +++ b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.dll.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: 3c83c9a9845245cfbbab5a52932b5045 +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Plugins/iOS/Firebase.Crashlytics.dll +timeCreated: 1480838400 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 0 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 0 + settings: + CPU: None + Linux64: + enabled: 0 + settings: + CPU: None + LinuxUniversal: + enabled: 0 + settings: + CPU: None + OSXIntel: + enabled: 0 + settings: + CPU: None + OSXIntel64: + enabled: 0 + settings: + CPU: None + OSXUniversal: + enabled: 0 + settings: + CPU: None + Web: + enabled: 0 + settings: {} + WebStreamed: + enabled: 0 + settings: {} + Win: + enabled: 0 + settings: + CPU: None + Win64: + enabled: 0 + settings: + CPU: None + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + iOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + tvOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.pdb b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.pdb new file mode 100644 index 0000000..d2d90c6 Binary files /dev/null and b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.pdb differ diff --git a/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.pdb.meta b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.pdb.meta new file mode 100644 index 0000000..7772bc1 --- /dev/null +++ b/Assets/rd3/Firebase/Plugins/iOS/Firebase.Crashlytics.pdb.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: fc067b050957416ea05be8e76ac98a69 +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/Plugins/iOS/Firebase.Crashlytics.pdb +timeCreated: 1480838400 +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + platformData: + Android: + enabled: 0 + settings: + CPU: AnyCPU + Any: + enabled: 0 + settings: {} + Editor: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + Linux: + enabled: 0 + settings: + CPU: None + Linux64: + enabled: 0 + settings: + CPU: None + LinuxUniversal: + enabled: 0 + settings: + CPU: None + OSXIntel: + enabled: 0 + settings: + CPU: None + OSXIntel64: + enabled: 0 + settings: + CPU: None + OSXUniversal: + enabled: 0 + settings: + CPU: None + Web: + enabled: 0 + settings: {} + WebStreamed: + enabled: 0 + settings: {} + Win: + enabled: 0 + settings: + CPU: None + Win64: + enabled: 0 + settings: + CPU: None + WindowsStoreApps: + enabled: 0 + settings: + CPU: AnyCPU + iOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + tvOS: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/m2repository/com.meta b/Assets/rd3/Firebase/m2repository/com.meta index 03f8f60..dbb5378 100644 --- a/Assets/rd3/Firebase/m2repository/com.meta +++ b/Assets/rd3/Firebase/m2repository/com.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: bd4bb8f7b21d83945a529785442ad476 +guid: a03680944a70bd645bd7d1dbdf2a0c32 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/rd3/Firebase/m2repository/com/google.meta b/Assets/rd3/Firebase/m2repository/com/google.meta index 2723a01..46cc707 100644 --- a/Assets/rd3/Firebase/m2repository/com/google.meta +++ b/Assets/rd3/Firebase/m2repository/com/google.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8cbdb7918f043994a9eed3435e3ab3e7 +guid: 17a890ddad2c71941be3cd4c54417aa8 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase.meta b/Assets/rd3/Firebase/m2repository/com/google/firebase.meta index fce46eb..9c3d19d 100644 --- a/Assets/rd3/Firebase/m2repository/com/google/firebase.meta +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 187d24513d48523459a2744fb57c9a5e +guid: 60ff2816b32efb846a2676821700f989 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity.meta b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity.meta new file mode 100644 index 0000000..7c66951 --- /dev/null +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0dc9525fe3d784645add9b1dbbf8c054 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0.meta b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0.meta new file mode 100644 index 0000000..fc120e3 --- /dev/null +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 420f611864d0eaa49af58bc665ac82e7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom new file mode 100644 index 0000000..7befe3c --- /dev/null +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom @@ -0,0 +1,13 @@ + + 4.0.0 + com.google.firebase + firebase-crashlytics-unity + 13.1.0 + aar + + + + diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom.meta b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom.meta new file mode 100644 index 0000000..27ba1b6 --- /dev/null +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22d139e4dda4455aa678b0397461628f +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.pom +timeCreated: 1480838400 +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar new file mode 100644 index 0000000..e726ad6 Binary files /dev/null and b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar differ diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar.meta b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar.meta new file mode 100644 index 0000000..a49bfe5 --- /dev/null +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f9ade58d5a5a42fea2cdb4e62b915b30 +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/13.1.0/firebase-crashlytics-unity-13.1.0.srcaar +timeCreated: 1480838400 +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml new file mode 100644 index 0000000..12d85ee --- /dev/null +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml @@ -0,0 +1,9 @@ + + com.google.firebase + firebase-crashlytics-unity + + 13.1.0 + 13.1.0 + + + diff --git a/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml.meta b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml.meta new file mode 100644 index 0000000..a6bfbbd --- /dev/null +++ b/Assets/rd3/Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eda65244fc1b407e8948b25b31c17991 +labels: +- gvh +- gvh_version-13.1.0 +- gvhp_exportpath-Firebase/m2repository/com/google/firebase/firebase-crashlytics-unity/maven-metadata.xml +timeCreated: 1480838400 +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/AndroidResolverDependencies.xml b/ProjectSettings/AndroidResolverDependencies.xml new file mode 100644 index 0000000..053901c --- /dev/null +++ b/ProjectSettings/AndroidResolverDependencies.xml @@ -0,0 +1,66 @@ + + + androidx.annotation:annotation:1.2.0 + androidx.appcompat:appcompat:1.6.1 + androidx.browser:browser:1.4.0 + androidx.constraintlayout:constraintlayout:2.1.4 + androidx.lifecycle:lifecycle-process:2.6.2 + androidx.media3:media3-exoplayer:1.0.0-alpha01 + androidx.recyclerview:recyclerview:1.1.0 + androidx.recyclerview:recyclerview:1.2.1 + com.applovin.mediation:bigoads-adapter:5.5.1.2 + com.applovin.mediation:bytedance-adapter:7.5.0.3.0 + com.applovin.mediation:fyber-adapter:8.3.8.0 + com.applovin.mediation:google-adapter:[24.5.0.0] + com.applovin.mediation:google-ad-manager-adapter:[24.5.0.0] + com.applovin.mediation:mintegral-adapter:16.9.91.0 + com.applovin.mediation:moloco-adapter:4.0.0.0 + com.applovin.mediation:unityads-adapter:4.16.1.0 + com.applovin.mediation:vungle-adapter:7.5.1.0 + com.applovin:applovin-sdk:13.3.1 + com.bigossp:bigo-ads:5.0.0 + com.bigossp:bigo-ads:5.3.0 + com.fyber:marketplace-sdk:8.3.7 + com.google.android.gms:play-services-ads:24.4.0 + com.google.android.gms:play-services-ads:24.5.0 + com.google.android.gms:play-services-ads-identifier:18.0.1 + com.google.android.gms:play-services-ads-identifier:18.2.0 + com.google.android.gms:play-services-base:18.7.2 + com.google.android.gms:play-services-basement:18.1.0 + com.google.android.material:material:1.2.1 + com.google.android.ump:user-messaging-platform:3.2.0 + com.google.firebase:firebase-analytics:23.0.0 + com.google.firebase:firebase-analytics-unity:13.1.0 + com.google.firebase:firebase-app-unity:13.1.0 + com.google.firebase:firebase-common:22.0.0 + com.google.firebase:firebase-config:23.0.0 + com.google.firebase:firebase-config-unity:13.1.0 + com.google.firebase:firebase-crashlytics-ndk:20.0.0 + com.google.firebase:firebase-crashlytics-unity:13.1.0 + com.mbridge.msdk.oversea:mbridge_android_sdk:16.9.71 + com.pangle.global:pag-sdk:7.2.0.6 + com.unity3d.ads:unity-ads:4.14.0 + com.vungle:vungle-ads:7.5.0 + io.github.kwainetwork:adApi:1.2.19 + io.github.kwainetwork:adImpl:1.2.19 + org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.10 + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ProjectSettings/GvhProjectSettings.xml b/ProjectSettings/GvhProjectSettings.xml index c5e8f98..47b0a3f 100644 --- a/ProjectSettings/GvhProjectSettings.xml +++ b/ProjectSettings/GvhProjectSettings.xml @@ -1,5 +1,6 @@ + diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index e16162b..2ddb3b9 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -163,7 +163,7 @@ PlayerSettings: androidSupportedAspectRatio: 1 androidMaxAspectRatio: 2.1 applicationIdentifier: - Android: com.money.unitysdk + Android: com.rush.cash.earn.fast.real.money.game Standalone: com.DefaultCompany.2DProject buildNumber: Standalone: 0