diff --git a/Runtime/GuruAdjust/AdjustService.cs b/Runtime/GuruAdjust/AdjustService.cs index 3da6797..e81f7f1 100644 --- a/Runtime/GuruAdjust/AdjustService.cs +++ b/Runtime/GuruAdjust/AdjustService.cs @@ -18,7 +18,7 @@ namespace Guru public const string K_IAP_PURCHASE = "iap_purchase"; // 固定点位事件 public const string K_SUB_PURCHASE = "sub_purchase"; // 固定点位事件 - private static Action _onInitComplete; + private static Action _onInitComplete; private static Action _onGetGoogleAdidHandler; private static string _googleAdId = ""; @@ -60,7 +60,7 @@ namespace Guru /// /// public static void StartService(string appToken, string fbAppId = "", string firebaseId = "", string deviceId = "", - Action onInitComplete = null, Action onDeeplinkCallback = null, Action onGetGoogleAdIdCallback = null) + Action onInitComplete = null, Action onDeeplinkCallback = null, Action onGetGoogleAdIdCallback = null) { if (string.IsNullOrEmpty(appToken)) { @@ -79,6 +79,7 @@ namespace Guru config.setDelayStart(DelayTime); config.setPreinstallTrackingEnabled(true); // Adjust Preinstall config.setSessionSuccessDelegate(OnSessionSuccessCallback); // SessionSuccess + config.setSessionFailureDelegate(OnSessionFailureCallback); // SessionFailed if(onDeeplinkCallback != null) config.setDeferredDeeplinkDelegate(onDeeplinkCallback); @@ -91,7 +92,6 @@ namespace Guru config.setLogDelegate(log => LogI(LOG_TAG, log)); config.setEventSuccessDelegate(OnEventSuccessCallback); config.setEventFailureDelegate(OnEventFailureCallback); - config.setSessionFailureDelegate(OnSessionFailureCallback); config.setAttributionChangedDelegate(OnAttributionChangedCallback); #endif // 检查场景实例 @@ -182,7 +182,7 @@ namespace Guru var adid = sessionSuccessData.Adid; _adjustId = adid; _isReady = true; - _onInitComplete?.Invoke(adid); + _onInitComplete?.Invoke(adid, Adjust.getIdfv(), Adjust.getIdfa()); } @@ -305,7 +305,7 @@ namespace Guru private static void OnSessionFailureCallback(AdjustSessionFailure sessionFailureData) { - LogI(LOG_TAG,"Session tracking failed!"); + LogE(LOG_TAG,"Session tracking failed!"); if (sessionFailureData.Message != null) { diff --git a/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar b/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar deleted file mode 100644 index 955b391..0000000 Binary files a/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar and /dev/null differ diff --git a/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.2.aar b/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.2.aar new file mode 100644 index 0000000..166b415 Binary files /dev/null and b/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.2.aar differ diff --git a/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar.meta b/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.2.aar.meta similarity index 93% rename from Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar.meta rename to Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.2.aar.meta index 83b45e2..63a23ac 100644 --- a/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar.meta +++ b/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.2.aar.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8009d3bf70bb4438599a32f6ea601f9d +guid: b4c3c75418e9c43c0a14510620fadda4 PluginImporter: externalObjects: {} serializedVersion: 2 diff --git a/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.9.0.mm b/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.12.0.mm similarity index 96% rename from Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.9.0.mm rename to Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.12.0.mm index aea0805..65fa4e3 100644 --- a/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.9.0.mm +++ b/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.12.0.mm @@ -1,8 +1,9 @@ // ============================================== -// U3DConsent.mm -// UnityFramework +// U3DAnalytics 1.12.0 +// Native Framework Version 0.3.6 +// update date: 2024-08-06 -- by HuYufei // -// Created by EricHu on 2022/11/17. +// Created by HuYufei on 2022/11/17. // Copyright © 2022 guru. All rights reserved. // ============================================== @@ -26,7 +27,7 @@ static GuruAnalytics *_analytics; @implementation U3DAnalytics // Const value define -NSString * const Version = @"1.9.0"; +NSString * const Version = @"1.12.0"; static const double kUploadPeriodInSecond = 60.0; static const int kBatchLimit = 15; @@ -89,6 +90,7 @@ NSString * const TchError = @"tch_error"; [GuruAnalytics registerInternalEventObserverWithReportCallback:^(NSInteger code, NSString * info){ [U3DAnalytics onEventCallback:code andInfo:info]; }]; + } } @@ -241,7 +243,6 @@ NSString * const TchError = @"tch_error"; //--------------------------- - @end //============================ UNITY PUBLIC API ============================ @@ -249,7 +250,7 @@ NSString * const TchError = @"tch_error"; extern "C" { // 请求GDPR - void unityInitAnalytics(const char *appId, const char *deviceInfo, bool isDebug) + void unityInitAnalytics(const char *appId, const char *deviceInfo, bool isDebug, const char *baseUrl, const char *uploadIpAddress) { // NSLog(@"--- [iOS] init Analytics libs"); [GuruAnalytics initializeLibWithUploadPeriodInSecond:kUploadPeriodInSecond @@ -297,6 +298,11 @@ extern "C" { [GuruAnalytics setDeviceId:[U3DAnalytics charToString:did]]; } + // 设置 EndHostUrl + void unitySetEndPointWithHost(const char *host){ + [GuruAnalytics setEventsUploadEndPointWithHost:[U3DAnalytics charToString:host]]; + } + // 设置用户属性 void unitySetUserProperty(const char *key, const char *value){ [GuruAnalytics setUserProperty:[U3DAnalytics charToString:value] diff --git a/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.9.0.mm.meta b/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.12.0.mm.meta similarity index 94% rename from Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.9.0.mm.meta rename to Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.12.0.mm.meta index b4ae2ee..19a1c17 100644 --- a/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.9.0.mm.meta +++ b/Runtime/GuruAnalytics/Plugins/iOS/U3DAnalytics_1.12.0.mm.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 621002eb5acb547ec95af0d804cfb17f +guid: 504c48c6ad50247199d9301760f9c1a5 PluginImporter: externalObjects: {} serializedVersion: 2 diff --git a/Runtime/GuruAnalytics/README.md b/Runtime/GuruAnalytics/README.md index 94bdeb5..b715215 100644 --- a/Runtime/GuruAnalytics/README.md +++ b/Runtime/GuruAnalytics/README.md @@ -29,7 +29,6 @@ GuruAnalyticsLib 的 Unity 插件库 - Pod 库改为 本地文件引用 (配合外部发行项目) - ### 1.11.0 - Android 端对齐 `1.0.3` > Hash: 1978686dbcba38b7b0421d8b6b2bef111356366b diff --git a/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs b/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs index b525d22..9eb1ba9 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs @@ -224,7 +224,7 @@ namespace Guru } - public void SetAndroidID(string androidId) + public void SetAndroidId(string androidId) { if (!_isReady) return; if (string.IsNullOrEmpty(androidId)) return; diff --git a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs index 9a4001e..e5ecbcd 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs @@ -98,30 +98,29 @@ namespace Guru { _isDebug = isDebug; string bundleId = Application.identifier; - CallSDKInit(appId, deviceInfo, bundleId, baseUrl, uploadIpAddress , true, false, _isDebug); // 调用接口 - + CallSDKInit(appId, deviceInfo, bundleId, _isDebug, baseUrl, uploadIpAddress , true, false); // 调用接口 onInitComplete?.Invoke(); } /********* Android API ********** - public static void init(String appId, + public static void init(String appId, String deviceInfo, String bundleId, boolean debug, - boolean useWorker, - boolean enabledCronet, String baseUrl, - List uploadIpAddress) + String uploadIpAddressStr, + boolean useWorker, + boolean enabledCronet) */ private void CallSDKInit(string appId, string deviceInfo, string bundleId, + bool isDebug = false, string baseUrl = "", string[] uploadIpAddress = null, bool useWorker = true, - bool useCronet = false, - bool isDebug = false) + bool useCronet = false) { CallStatic("init", appId, deviceInfo, bundleId, isDebug, useWorker, useCronet, baseUrl, string.Join(",", uploadIpAddress ?? Array.Empty())); // 调用接口 } diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs index 84ecb66..b9d42ce 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Const.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; + namespace Guru { public enum ELevelResult @@ -12,7 +14,7 @@ namespace Guru //打点常量定义 public static partial class Analytics { - public const string TAG = "Analytics"; + public const string TAG = "[GA]"; // 美元符号 public const string USD = "USD"; // 广告平台 @@ -113,20 +115,41 @@ namespace Guru public const string PropertyLastPlayedLevel = "last_played_level"; public const string PropertyGrade = "grade"; //当游戏玩家角色升级时触发 public const string PropertyIsIAPUser = "is_iap_user"; //付费成功后设置属性参数为true,如果没有发生付费可以不用设置该属性 + public const string PropertyNetwork = "network"; // network属性 + public const string PropertyAdjustId = "adjust_id"; // network属性 public const string PropertyIAPCoin = "iap_coin"; //付费所得的总金币数(iap获取累计值)\ public const string PropertyNonIAPCoin = "noniap_coin"; //非付费iap获取累计值 public const string PropertyCoin = "coin"; //当前金币数 public const string PropertyExp = "exp"; // 经验值 public const string PropertyHp = "hp"; // 生命值/体力 - public const string PropertyAndroidID = "android_id"; // Android 平台 AndroidID + public const string PropertyAndroidId = "android_id"; // Android 平台 AndroidID public const string PropertyIDFV = "idfv"; // iOS 平台 IDFV public const string PropertyIDFA = "idfa"; // iOS 平台 IDFA public const string PropertyPicture = "picture"; // 玩家在主线的mapid public const string PropertyNoAds = "no_ads"; // 玩家是否去广告 - public const string PropertyATTStatus = "att_status"; // ATT 状态 + public const string PropertyAttStatus = "att_status"; // ATT 状态 + public const string PropertyNotiPerm = "noti_perm"; // ATT 状态 public const string PropertyGDPR = "gdpr"; // GDPR状态 public const string PropertySignUpMethod = "sign_up_method"; // 用户登录方式 + public const string PropertyFirebaseId = "firebase_id"; // FirebaseID + public const string PropertyGoogleAdId = "ad_id"; // FirebaseID + public static HashSet PredefinedMidWareProperties = new HashSet() + { + PropertyFirstOpenTime, + PropertyDeviceID, + PropertyUserID, + PropertyIsIAPUser, + PropertyNetwork, + PropertyAdjustId, + PropertyAndroidId, + PropertyIDFV, + PropertyIDFA, + PropertyAttStatus, + PropertyNotiPerm, + PropertyFirebaseId, + PropertyGoogleAdId, + }; // 经济相关 public const string ParameterBalance = "balance"; // 用于余额 diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs index 2a79633..d884666 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs @@ -1,24 +1,16 @@ namespace Guru { using System; - using Firebase.Analytics; using Firebase.Crashlytics; - using Firebase.Extensions; using UnityEngine; + /// /// 自打点逻辑 /// public partial class Analytics { - private static bool _hasSetFirebaseId; //已取得FirebaseId - private static bool _hasSetAdId; // 已取得AdId - private static bool _hasSetIDFA; // 已取得IDFA - private static bool _hasSetAdjustId; // 已取得AdjustId - private static bool _hasSetDeviceId; // 已取得DeviceId - private static bool _hasSetUid; // 已取得UID - private static bool _hasSetIDFV; // 已经取得 IDFV - private static bool _hasSetAndroidId; // 已取得AndroidId + private static DateTime _lastReportRateDate; //上次上报信息的日期 private static double _reportSuccessInterval; // 上报频率 #if UNITY_IOS @@ -37,12 +29,7 @@ namespace Guru { string appId = IPMConfig.IPM_X_APP_ID; string deviceInfo = new DeviceInfoData().ToString(); - - _hasSetFirebaseId = false; - _hasSetAdId = false; - _hasSetAdjustId = false; - _hasSetDeviceId = false; - _hasSetUid = false; + _lastReportRateDate = DateTime.Now; _reportSuccessInterval = 120; // 2分钟上报一次 @@ -53,7 +40,7 @@ namespace Guru OnGuruAnalyticsInitComplete(); Debug.Log($"{TAG} [guru_analytic]--- Guru EXP: GroupId: {GuruAnalytics.Instance.ExperimentGroupId}"); SetUserProperty(GuruAnalyticsConfigManager.KEY_GURU_ANALYTICS_EXP, GuruAnalytics.Instance.ExperimentGroupId); - ApplyAllUserProperties(); + ApplyAllMidWareProperties(); }, IsDebug, firebaseId); // Android 初始化 } @@ -62,193 +49,6 @@ namespace Guru LogCrashlytics(ex); } } - - - #region 各ID上报信息 - - /// - /// 设置用户ID - /// - public static void SetUid(string uid) - { - if (_hasSetUid) return; - if (string.IsNullOrEmpty(uid)) return; - - if (!IsFirebaseReady) return; - SetFirebaseUserId(uid); - - if (!GuruAnalytics.IsReady) return; - GuruAnalytics.Instance.SetUid(uid); - - Debug.Log($"---[ANA] UID: {uid}"); - _hasSetUid = true; - } - - /// - /// 设置设备ID - /// - private static void SetDeviceId(string deviceId) - { - if (_hasSetDeviceId) return; - if (string.IsNullOrEmpty(deviceId)) return; - - if (!GuruAnalytics.IsReady) return; - GuruAnalytics.Instance.SetDeviceId(deviceId); - _hasSetDeviceId = true; - } - - /// - /// 设置 AdjustId - /// - private static void SetAdjustId(string adjustId) - { - if (_hasSetAdjustId) return; - if (string.IsNullOrEmpty(adjustId)) return; - if (!GuruAnalytics.IsReady) return; - - GuruAnalytics.Instance.SetAdjustId(adjustId); - _hasSetAdjustId = true; - - - } - - /// - /// 设置 AdId - /// - private static void SetAdId(string adId) - { - if (_hasSetAdId) return; - if (string.IsNullOrEmpty(adId)) return; - if (!GuruAnalytics.IsReady) return; - GuruAnalytics.Instance.SetAdId(adId); - _hasSetAdId = true; - - } - - /// - /// 设置FirebaseId - /// - private static void SetFirebaseId(string firebaseId) - { - if (_hasSetFirebaseId) return; - if (string.IsNullOrEmpty(firebaseId)) return; - if (!GuruAnalytics.IsReady) return; - GuruAnalytics.Instance.SetFirebaseId(firebaseId); - _hasSetFirebaseId = true; - } - - /// - /// 获取FirebaseID - /// - private static void FetchFirebaseId() - { - if (!IsFirebaseReady) return; - - FirebaseAnalytics.GetAnalyticsInstanceIdAsync() - .ContinueWithOnMainThread(task => - { - if (task != null && task.IsCompleted) - { - var fid = task.Result; - if (!string.IsNullOrEmpty(fid) - && string.IsNullOrEmpty(IPMConfig.FIREBASE_ID)) - { - IPMConfig.FIREBASE_ID = fid; - } - } - }); - } - -#if UNITY_IOS - /// - /// 更新ATT状态 (Only IOS 有效) - /// - private static void ApplyATTStatus() - { - string status = ATTManager.GetStatus(); - GuruAnalytics.Instance.SetUserProperty(ParameterATTStatus, status); - } - - private static void SetIDFV(string idfv) - { - if (_hasSetIDFV) return; - if (string.IsNullOrEmpty(idfv)) return; - if (!GuruAnalytics.IsReady) return; - GuruAnalytics.Instance.SetIDFV(idfv); - _hasSetIDFV = true; - } - - private static void SetIDFA(string idfa) - { - if (_hasSetIDFA) return; - if (string.IsNullOrEmpty(idfa)) return; - if (!GuruAnalytics.IsReady) return; - - GuruAnalytics.Instance.SetIDFA(idfa); - _hasSetIDFA = true; - } -#endif - -#if UNITY_ANDROID - /// - /// 更新 Android ID 的参数 - /// - private static void SetAndroidId(string androidId) - { - if (_hasSetAndroidId) return; - if (string.IsNullOrEmpty(androidId)) return; - if (!GuruAnalytics.IsReady) return; - GuruAnalytics.Instance.SetAndroidID(androidId); - _hasSetAndroidId = true; - } -#endif - - /// - /// 上报中台打点的用户属性 - /// - private static void ApplyAllUserProperties() - { - - Debug.Log($"{TAG} --- UpdateAllValues"); - SetUid(IPMConfig.IPM_UID); - SetDeviceId(IPMConfig.IPM_DEVICE_ID); - SetAdjustId(IPMConfig.ADJUST_ID); - if (string.IsNullOrEmpty(IPMConfig.FIREBASE_ID)) - { - FetchFirebaseId(); - } - else - { - SetFirebaseId(IPMConfig.FIREBASE_ID); - } - SetAdId(IPMConfig.ADJUST_ADID); - -#if UNITY_ANDROID - SetAndroidId(DeviceIDHelper.AndroidID); -#endif - -#if UNITY_IOS - ApplyATTStatus(); - SetIDFV(IPMConfig.ADJUST_IDFV); - SetIDFA(IPMConfig.ADJUST_IDFA); -#endif - ReportEventSuccessRate(); - } - - /// - /// 上报事件成功率 - /// - private static void ReportEventSuccessRate() - { - var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds; - if (interval > _reportSuccessInterval) - { - GuruAnalytics.Instance.ReportEventSuccessRate(); - _lastReportRateDate = DateTime.Now; - } - } - - #endregion #region 设置太极02 值 diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Property.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Property.cs index 07d4514..14f62dd 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Property.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Property.cs @@ -1,11 +1,21 @@ - - namespace Guru { + using System; using UnityEngine; - + using Firebase.Analytics; + using System.Collections.Generic; + + /// + /// 上报用户属性逻辑 + /// Firebase 中台属性上报: https://docs.google.com/spreadsheets/d/1N47rXgjatRHFvzWWx0Hqv5C1D9NHHGbggi6pQ65c-zQ/edit?gid=1858695240#gid=1858695240 + /// Guru自打点 中台属性上报:https://docs.google.com/spreadsheets/d/1N47rXgjatRHFvzWWx0Hqv5C1D9NHHGbggi6pQ65c-zQ/edit?gid=1736574940#gid=1736574940 + /// public static partial class Analytics { + + + #region Old Properties + /// /// B_Level 属性 /// @@ -38,5 +48,543 @@ namespace Guru return stamp; } } + + + #endregion + + #region Update all neccessary properties + + //---------------- 设置所有必要的属性 --------------------- + + /// + /// 应用所有的中台属性 + /// + private static void ApplyAllMidWareProperties() + { + MidWarePropertiesManager.Instance.ApplyAllProperties(); + } + + + /// + /// 设置用户ID + /// + public static void SetUid(string uid) + { + MidWarePropertiesManager.Instance.ReportUid(uid); + } + + /// + /// 设置设备ID + /// (Firebase, Guru) + /// + private static void SetDeviceId(string deviceId) + { + MidWarePropertiesManager.Instance.ReportDeviceId(deviceId); + } + + /// + /// 设置首次启动时间 + /// + /// + private static void SetFirstOpenTime(string firstOpenTime) + { + MidWarePropertiesManager.Instance.ReportFirstOpenTime(firstOpenTime); + } + + /// + /// 设置 IsIapUser + /// (Firebase, Guru) + /// + public static void SetIsIapUser(bool isIapUser) + { + MidWarePropertiesManager.Instance.ReportIsIapUser(isIapUser); + } + + /// + /// 设置 Network + /// (Firebase, Guru) + /// + public static void SetNetworkStatus(string networkStatus) + { + MidWarePropertiesManager.Instance.ReportNetworkStatus(networkStatus); + } + + /// + /// 设置 AdjustId + /// (Firebase) + /// + public static void SetAdjustId(string adjustId) + { + MidWarePropertiesManager.Instance.ReportAdjustId(adjustId); + } + + /// + /// 设置 AndroidId + /// (Firebase) + /// + public static void SetAndroidId(string androidId) + { + MidWarePropertiesManager.Instance.ReportAndroidId(androidId); + } + + /// + /// 设置 AttStatus + /// (Firebase) + /// + public static void SetAttStatus(string attStatus) + { + MidWarePropertiesManager.Instance.ReportAttStatus(attStatus); + } + + /// + /// 设置 AttStatus + /// (Firebase) + /// + public static void SetNotiPerm(string notiPrem) + { + MidWarePropertiesManager.Instance.ReportNotiPerm(notiPrem); + } + + /// + /// 设置 AdId + /// + public static void SetGoogleAdId(string adId) + { + MidWarePropertiesManager.Instance.ReportGoogleAdId(adId); + } + + public static void SetIDFV(string idfv) + { + MidWarePropertiesManager.Instance.ReportIDFV(idfv); + } + + public static void SetIDFA(string idfa) + { + MidWarePropertiesManager.Instance.ReportIDFA(idfa); + } + + + #endregion + + #region 中台属性管理 + + /// + /// 中台必要用户属性对象 + /// + private abstract class AbstractMidWareProperty + { + public readonly string key; + protected readonly string value; + private readonly ReportPropertyTarget reportTarget; + private bool HasValue => !string.IsNullOrEmpty(value); + + protected AbstractMidWareProperty(string key, string value, + ReportPropertyTarget reportTarget = ReportPropertyTarget.Both) + { + this.key = key; + this.value = value; + this.reportTarget = reportTarget; + } + + + public void Report() + { + if (!HasValue) return; + BeforeReportProperty(); + ReportPropertyByTarget(); + } + + protected abstract void BeforeReportProperty(); + + private void ReportPropertyByTarget() + { + if (!HasValue) return; + switch (reportTarget) + { + case ReportPropertyTarget.Firebase: + // Firebase + _firebaseEventDriver.AddProperty(key, value); + break; + + case ReportPropertyTarget.Guru: + // Guru + _guruEventDriver.AddProperty(key, value); + break; + + case ReportPropertyTarget.Both: + // 双平台上报 + _firebaseEventDriver.AddProperty(key, value); + _guruEventDriver.AddProperty(key, value); + break; + + default: + throw new ArgumentOutOfRangeException(); + } + } + + } + + /// + /// UID + /// + private class MidWarePropertyUid : AbstractMidWareProperty + { + public MidWarePropertyUid(string value) + : base(PropertyUserID, value, ReportPropertyTarget.Both) + { + } + + protected override void BeforeReportProperty() + { + _firebaseEventDriver.SetUid(value); + _guruEventDriver.SetUid(value); + } + } + /// + /// DeviceId + /// + private class MidWarePropertyDeviceId : AbstractMidWareProperty + { + public MidWarePropertyDeviceId(string value) + : base(PropertyDeviceID, value, ReportPropertyTarget.Both) + { + + } + + protected override void BeforeReportProperty() + { + _guruEventDriver.SetDeviceId(value); + } + } + /// + /// FirstOpenTime + /// + private class MidWarePropertyFirstOpenTime : AbstractMidWareProperty + { + public MidWarePropertyFirstOpenTime(string value) + : base(PropertyFirstOpenTime, value, ReportPropertyTarget.Both) + { + + } + + protected override void BeforeReportProperty() + { + } + } + /// + /// IsIapUser + /// + private class MidWarePropertyIsIapUser : AbstractMidWareProperty + { + public MidWarePropertyIsIapUser(bool value) + : base(PropertyIsIAPUser, value?"true":"false", ReportPropertyTarget.Both) + { + + } + + protected override void BeforeReportProperty() { } + } + + /// + /// Network + /// + private class MidWarePropertyNetwork : AbstractMidWareProperty + { + public MidWarePropertyNetwork(string value) + : base(PropertyNetwork, value, ReportPropertyTarget.Both) + { + + } + + protected override void BeforeReportProperty() { } + } + /// + /// AdjustId + /// + private class MidWarePropertyAdjustId : AbstractMidWareProperty + { + public MidWarePropertyAdjustId(string value) + : base(PropertyAdjustId, value, ReportPropertyTarget.Firebase) + { + + } + + protected override void BeforeReportProperty() + { + _guruEventDriver.SetAdjustId(value); + } + } + + /// + /// AttStatus + /// + private class MidWarePropertyAttStatus : AbstractMidWareProperty + { + public MidWarePropertyAttStatus(string value) + : base(PropertyAttStatus, value, ReportPropertyTarget.Both) + { + + } + + protected override void BeforeReportProperty() + { + + } + } + + /// + /// AttStatus + /// + private class MidWarePropertyNotiPerm : AbstractMidWareProperty + { + public MidWarePropertyNotiPerm(string value) + : base(PropertyNotiPerm, value, ReportPropertyTarget.Both) + { + + } + + protected override void BeforeReportProperty() + { + + } + } + + + /// + /// AndroidId + /// + private class MidWarePropertyAndroidId : AbstractMidWareProperty + { + public MidWarePropertyAndroidId(string value) + : base(PropertyAndroidId, value, ReportPropertyTarget.Both) + { + } + + protected override void BeforeReportProperty() + { + _guruEventDriver.SetAndroidId(value); + } + } + + /// + /// FirebaseId + /// + private class MidWarePropertyGoogleAdId : AbstractMidWareProperty + { + public MidWarePropertyGoogleAdId(string value) + : base(PropertyGoogleAdId, value, ReportPropertyTarget.Both) + { + } + + protected override void BeforeReportProperty() + { + _guruEventDriver.SetGoogleAdId(value); + } + } + + /// + /// IDFV + /// + private class MidWarePropertyIDFV : AbstractMidWareProperty + { + public MidWarePropertyIDFV(string value) + : base(PropertyIDFV, value, ReportPropertyTarget.Both) + { + } + + protected override void BeforeReportProperty() + { + _guruEventDriver.SetIDFV(value); + } + } + + /// + /// IDFV + /// + private class MidWarePropertyIDFA : AbstractMidWareProperty + { + public MidWarePropertyIDFA(string value) + : base(PropertyIDFA, value, ReportPropertyTarget.Both) + { + } + + protected override void BeforeReportProperty() + { + _guruEventDriver.SetIDFA(value); + } + } + + /// + /// 必要属性上报配置 + /// + internal enum ReportPropertyTarget + { + Firebase = 1, + Guru = 2, + Both = 3, + } + + + /// + /// 全部属性集合 + /// + internal class MidWarePropertiesManager + { + + private static MidWarePropertiesManager _instance; + + public static MidWarePropertiesManager Instance + { + get + { + if (_instance == null) _instance = new MidWarePropertiesManager(); + return _instance; + } + } + + + private readonly Dictionary _propertyMap = new Dictionary(10); + + + /* + ======= 必打属性 ======== + user_id (F,G) + device_id (F,G) + first_open_time (F,G) + is_iap_user (F,G) + network (F,G) + + adjust_id (F) + att_status (F) + noti_perm (F) + ======= 必打属性 ======== + + ======= 补充属性 ======== + firebase_id + idfv + idfa + ======= 补充属性 ======== + */ + + //-------------------- 设置所有的属性 ----------------------- + + + public void ReportUid(string uid) + { + var prop = new MidWarePropertyUid(uid); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportDeviceId(string deviceId) + { + var prop = new MidWarePropertyDeviceId(deviceId); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportFirstOpenTime(string firstOpenTime) + { + var prop = new MidWarePropertyFirstOpenTime(firstOpenTime); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportIsIapUser(bool isIapUser) + { + var prop = new MidWarePropertyIsIapUser(isIapUser); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportNetworkStatus(string networkStatus) + { + var prop = new MidWarePropertyNetwork(networkStatus); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportAdjustId(string adjustId) + { + var prop = new MidWarePropertyAdjustId(adjustId); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportAttStatus(string attStatus) + { + var prop = new MidWarePropertyAttStatus(attStatus); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportNotiPerm(string notiPerm) + { + var prop = new MidWarePropertyNotiPerm(notiPerm); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportAndroidId(string androidId) + { + var prop = new MidWarePropertyAndroidId(androidId); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportGoogleAdId(string googleAdId) + { + var prop = new MidWarePropertyGoogleAdId(googleAdId); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + public void ReportIDFV(string idfv) + { + var prop = new MidWarePropertyIDFV(idfv); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + public void ReportIDFA(string idfa) + { + var prop = new MidWarePropertyIDFA(idfa); + _propertyMap.TryAdd(prop.key, prop); + prop.Report(); + } + + /// + /// 应用所有中台打点的用户属性 + /// + public void ApplyAllProperties() + { + // 应用所有用户属性 + Debug.Log($"{TAG} --- UpdateAllValues ---"); + + foreach (var prop in _propertyMap.Values) + { + prop.Report(); + } + + ReportEventSuccessRate(); + } + + /// + /// 上报事件成功率 + /// + private static void ReportEventSuccessRate() + { + var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds; + if (interval > _reportSuccessInterval) + { + GuruAnalytics.Instance.ReportEventSuccessRate(); + _lastReportRateDate = DateTime.Now; + } + } + } + + + #endregion } + + } \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.cs index 333e897..04dee84 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.cs @@ -47,6 +47,7 @@ namespace Guru private static bool IsDebug => PlatformUtil.IsDebug(); private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized; + private static bool IsGuruAnalyticsReady => GuruAnalytics.IsReady; private static AdjustEventDriver _adjustEventDriver; private static FBEventDriver _fbEventDriver; @@ -68,6 +69,9 @@ namespace Guru _fbEventDriver = new FBEventDriver(); _firebaseEventDriver = new FirebaseEventDriver(); _guruEventDriver = new GuruEventDriver(); + + SetDeviceId(IPMConfig.IPM_DEVICE_ID); + SetFirstOpenTime(IPMConfig.FIRST_OPEN_TIME); } /// @@ -100,9 +104,19 @@ namespace Guru _adjustEventDriver.TriggerFlush(); } - public static void OnGuruAnalyticsInitComplete() + + private static void OnGuruAnalyticsInitComplete() { - _guruEventDriver.TriggerFlush(); + ShouldFlushGuruEvents(); + } + + + public static void ShouldFlushGuruEvents() + { + if (!string.IsNullOrEmpty(IPMConfig.IPM_UID) && !_guruEventDriver.IsReady) + { + _guruEventDriver.TriggerFlush(); + } } @@ -166,7 +180,7 @@ namespace Guru _guruEventDriver.AddProperty(key, value); _firebaseEventDriver.AddProperty(key, value); // 更新所有必要的用户属性 - ApplyAllUserProperties(); + ApplyAllMidWareProperties(); Debug.Log($"{TAG} --- SetUserProperty -> propertyName:{key}, propertyValue:{value}"); } catch (Exception ex) diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs index 5a6bc8a..f343179 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Events/AbstractEventDriver.cs @@ -1,3 +1,7 @@ +using System; +using System.Collections; +using UnityEngine; + namespace Guru { using System.Collections.Concurrent; @@ -13,15 +17,47 @@ namespace Guru void AddProperty(string key, string value); } + internal class MidWarePropertyDelayedAction + { + internal readonly string key; + private readonly string value; + private readonly Action reportAction; + + internal MidWarePropertyDelayedAction(string key, string value, Action reportAction) + { + this.key = key; + this.value = value; + this.reportAction = reportAction; + } + + internal void Execute() + { + reportAction.Invoke(value); + } + + public override bool Equals(object obj) + { + if (obj is not MidWarePropertyDelayedAction action) return false; + return key == action.key; + } + + public override int GetHashCode() + { + return key.GetHashCode(); + } + } + public abstract class AbstractEventDriver: IEventDriver, IPropertyCollector { private readonly GuruEventBuffer _eventBuffer = new GuruEventBuffer(); private readonly ConcurrentDictionary _userPropertyMap = new ConcurrentDictionary(); + private readonly HashSet _predefinedPropertyDelayedActions = new HashSet(); // Firebase 是否可用 private bool _isDriverReady; + public bool IsReady => _isDriverReady; public void TriggerFlush() { @@ -79,17 +115,26 @@ namespace Guru { while(_eventBuffer.Pop(out var trackingEvent)) { + Debug.Log($"[ANU] --- GuruAnalytics: FlushAll Events: {trackingEvent.eventName}"); FlushTrackingEvent(trackingEvent); } foreach (var key in _userPropertyMap.Keys) { + Debug.Log($"[ANU] --- GuruAnalytics: FlushAll Properties: {key}:{ _userPropertyMap[key]}"); SetUserProperty(key, _userPropertyMap[key]); } _userPropertyMap.Clear(); + + + foreach (var propertyAction in _predefinedPropertyDelayedActions) + { + Debug.Log($"[ANU] --- GuruAnalytics: FlushAll predefined Properties: {propertyAction.key}:{ propertyAction}"); + propertyAction.Execute(); + } + _predefinedPropertyDelayedActions.Clear(); } - /// /// 发送事件 /// @@ -98,7 +143,151 @@ namespace Guru protected abstract void SetUserProperty(string key, string value); + + /// + /// 设置用户ID + /// + public void SetUid(string uid) + { + if (_isDriverReady) + { + ReportUid(uid); + } + else + { + _predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyUserID, uid, ReportUid)); + } + } + public void SetDeviceId(string deviceId) + { + if (_isDriverReady) + { + ReportDeviceId(deviceId); + } + else + { + _predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyDeviceID, deviceId, ReportDeviceId)); + } + } + + /// + /// 设置 AdjustId + /// (Firebase) + /// + public void SetAdjustId(string adjustId) + { + if (_isDriverReady) + { + ReportAdjustId(adjustId); + } + else + { + _predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyAdjustId, adjustId, ReportAdjustId)); + } + + } + + /// + /// 设置 AdId + /// + public void SetGoogleAdId(string googleAdId) + { + if (_isDriverReady) + { + ReportGoogleAdId(googleAdId); + } + else + { + _predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyGoogleAdId, googleAdId, ReportGoogleAdId)); + } + + } + + /// + /// 设置 AndroidId + /// + /// + public void SetAndroidId(string androidId) + { + if (_isDriverReady) + { + ReportAndroidId(androidId); + } + else + { + _predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyAndroidId, androidId, ReportAndroidId)); + } + + } + + /// + /// 设置 IDFV + /// + public void SetIDFV(string idfv) + { + if (_isDriverReady) + { + ReportIDFV(idfv); + } + else + { + _predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyIDFV, idfv, ReportIDFV)); + } + + } + + /// + /// 设置 IDFA + /// + public void SetIDFA(string idfa) + { + if (_isDriverReady) + { + ReportIDFA(idfa); + } + else + { + _predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyIDFA, idfa, ReportIDFA)); + } + } + + /// + /// 设置用户ID + /// (Firebase, Guru) + /// + protected abstract void ReportUid(string uid); + + /// + /// 设置设备ID + /// (Firebase, Guru) + /// + protected abstract void ReportDeviceId(string deviceId); + /// + /// 设置 AdjustId + /// (Firebase) + /// + protected abstract void ReportAdjustId(string adjustId); + + /// + /// 设置 googleAdId + /// + protected abstract void ReportGoogleAdId(string googleAdId); + + /// + /// 设置 AndroidId + /// + protected abstract void ReportAndroidId(string androidId); + + /// + /// 设置 IDFV + /// + protected abstract void ReportIDFV(string idfv); + + /// + /// 设置 IDFA + /// + protected abstract void ReportIDFA(string idfa); } diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs index 7cfe63d..db1e267 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Events/AdjustEventDriver.cs @@ -31,5 +31,53 @@ namespace Guru { } + + //---------------- 单独实现所有的独立属性打点 ------------------ + + /// + /// 设置用户ID + /// + protected override void ReportUid(string uid) + { + } + + protected override void ReportDeviceId(string deviceId) + { + } + + /// + /// 设置 AdjustId + /// (Firebase) + /// + protected override void ReportAdjustId(string adjustId) + { + } + + /// + /// 设置 AdId + /// + protected override void ReportGoogleAdId(string adId) + { + } + + protected override void ReportAndroidId(string androidId) + { + } + + /// + /// 设置 IDFV + /// + protected override void ReportIDFV(string idfv) + { + + } + + /// + /// 设置 IDFA + /// + protected override void ReportIDFA(string idfa) + { + + } } } \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs index d81d61b..08ba8ca 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Events/FBEventDriver.cs @@ -1,8 +1,9 @@ -using System; -using UnityEngine; + namespace Guru { + using UnityEngine; + public class FBEventDriver: AbstractEventDriver { /// @@ -22,5 +23,57 @@ namespace Guru { } + + //---------------- 单独实现所有的独立属性打点 ------------------ + + /// + /// 设置用户ID + /// + protected override void ReportUid(string uid) + { + + } + protected override void ReportDeviceId(string deviceId) + { + + } + + /// + /// 设置 AdjustId + /// (Firebase) + /// + protected override void ReportAdjustId(string adjustId) + { + + } + + /// + /// 设置 AdId + /// + protected override void ReportGoogleAdId(string adId) + { + + } + + protected override void ReportAndroidId(string adId) + { + + } + + /// + /// 设置 IDFV + /// + protected override void ReportIDFV(string idfv) + { + + } + + /// + /// 设置 IDFA + /// + protected override void ReportIDFA(string idfa) + { + + } } } \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs index 2e0bda7..7dbb61a 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Events/FirebaseEventDriver.cs @@ -59,5 +59,33 @@ namespace Guru FirebaseAnalytics.SetUserProperty(key, value); } + protected override void ReportUid(string uid) + { + FirebaseAnalytics.SetUserId(uid); + } + + protected override void ReportDeviceId(string deviceId) + { + } + + protected override void ReportAdjustId(string adjustId) + { + } + + protected override void ReportGoogleAdId(string adId) + { + } + + protected override void ReportAndroidId(string adId) + { + } + + protected override void ReportIDFV(string idfv) + { + } + + protected override void ReportIDFA(string idfa) + { + } } } \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs index 3489d22..ff96e84 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Events/GuruEventDriver.cs @@ -1,5 +1,7 @@ + namespace Guru { + public class GuruEventDriver: AbstractEventDriver { protected override void FlushTrackingEvent(TrackingEvent trackingEvent) @@ -16,6 +18,62 @@ namespace Guru // ReSharper disable once Unity.PerformanceCriticalCodeInvocation GuruAnalytics.Instance.SetUserProperty(key, value); } + + //---------------- 单独实现所有的独立属性打点 ------------------ + + /// + /// 设置用户ID + /// + protected override void ReportUid(string uid) + { + GuruAnalytics.Instance.SetUid(uid); + } + /// + /// 设置设备ID + /// (Firebase, Guru) + /// + protected override void ReportDeviceId(string deviceId) + { + GuruAnalytics.Instance.SetDeviceId(deviceId); + } + + /// + /// 设置 AdjustId + /// (Firebase) + /// + protected override void ReportAdjustId(string adjustId) + { + GuruAnalytics.Instance.SetAdjustId(adjustId); + } + + protected override void ReportAndroidId(string androidId) + { + GuruAnalytics.Instance.SetAndroidId(androidId); + } + + /// + /// 设置 AdId + /// + protected override void ReportGoogleAdId(string adId) + { + GuruAnalytics.Instance.SetAdId(adId); + } + + /// + /// 设置 IDFV + /// + protected override void ReportIDFV(string idfv) + { + GuruAnalytics.Instance.SetIDFV(idfv); + } + + /// + /// 设置 IDFA + /// + protected override void ReportIDFA(string idfa) + { + GuruAnalytics.Instance.SetIDFA(idfa); + } } } \ No newline at end of file diff --git a/Runtime/GuruCore/Runtime/IPM/Scripts/IPMConfig.cs b/Runtime/GuruCore/Runtime/IPM/Scripts/IPMConfig.cs index 2445af1..d3e6a22 100644 --- a/Runtime/GuruCore/Runtime/IPM/Scripts/IPMConfig.cs +++ b/Runtime/GuruCore/Runtime/IPM/Scripts/IPMConfig.cs @@ -261,12 +261,20 @@ namespace Guru get => PlayerPrefs.GetString(nameof(ADJUST_GOOGLE_ADID), ""); set => PlayerPrefs.SetString(nameof(ADJUST_GOOGLE_ADID), value); } - - - public static string FirstOpenTime + + public static string FIRST_OPEN_TIME { - get => PlayerPrefs.GetString(nameof(FirstOpenTime), ""); - set => PlayerPrefs.SetString(nameof(FirstOpenTime), value); + get + { + var value = PlayerPrefs.GetString(nameof(FIRST_OPEN_TIME), ""); + if (string.IsNullOrEmpty(value)) + { + value = TimeUtil.GetCurrentTimeStamp().ToString(); + FIRST_OPEN_TIME = value; + } + return value; + } + set => PlayerPrefs.SetString(nameof(FIRST_OPEN_TIME), value); } } } \ No newline at end of file