From 6dd2574763c0e9f5b7225933fa336b52999ddc62 Mon Sep 17 00:00:00 2001 From: huyufei Date: Wed, 24 Jul 2024 10:35:27 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E6=9B=B4=E6=96=B0=E6=89=93=E5=8C=85?= =?UTF-8?q?=E6=97=A5=E5=BF=97=EF=BC=8C=E5=AE=8C=E5=96=84=E4=BA=91=E6=8E=A7?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E8=AF=BB=E5=8F=96=EF=BC=8C=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E6=9C=AC=E5=9C=B0=E6=B5=8B=E8=AF=95=E9=80=BB=E8=BE=91?= =?UTF-8?q?,=20=E8=A7=84=E8=8C=83=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: huyufei --- Runtime/GuruAnalytics/Editor/Dependencies.xml | 14 +- .../Plugins/Android/U3DAnalytics-1.11.1.aar | Bin 13029 -> 13146 bytes .../Script/Experiment/GuruAnalyticsExp.cs | 147 ++++++++++++++++-- .../Runtime/Script/GuruAnalytics.cs | 2 +- .../Script/Impl/AnalyticsAgentAndroid.cs | 8 +- .../Runtime/Analytics/Analytics.Custom.cs | 41 ++++- .../GuruCore/Runtime/Analytics/Analytics.cs | 37 +++-- .../Firebase/FirebaseUtil.Crashlytics.cs | 6 + .../GuruCore/Runtime/Firebase/FirebaseUtil.cs | 54 ++----- .../Runtime/Reporter/CrashlyticsAgent.cs | 6 +- 10 files changed, 235 insertions(+), 80 deletions(-) diff --git a/Runtime/GuruAnalytics/Editor/Dependencies.xml b/Runtime/GuruAnalytics/Editor/Dependencies.xml index 0828d2a..3c3900c 100644 --- a/Runtime/GuruAnalytics/Editor/Dependencies.xml +++ b/Runtime/GuruAnalytics/Editor/Dependencies.xml @@ -8,18 +8,20 @@ Sample Dependencies.xml: - - - + + + - - + + - + + + diff --git a/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar b/Runtime/GuruAnalytics/Plugins/Android/U3DAnalytics-1.11.1.aar index 4886e8ce4d5cca1dfe136d773262df7dc713e45c..955b3913ce8041ef8727f5b44941d62b86a6b9f5 100644 GIT binary patch delta 12501 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 f3c(E3u_!PA01h&fNisbRMnGGkOl<<`lmqw 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 JfiVC8003j4^yB~l diff --git a/Runtime/GuruAnalytics/Runtime/Script/Experiment/GuruAnalyticsExp.cs b/Runtime/GuruAnalytics/Runtime/Script/Experiment/GuruAnalyticsExp.cs index 81174a2..8ec7220 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/Experiment/GuruAnalyticsExp.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/Experiment/GuruAnalyticsExp.cs @@ -1,16 +1,37 @@ - - namespace Guru { - using Guru; using System; using UnityEngine; using Random = UnityEngine.Random; - using System.Collections.Generic; + using Firebase.RemoteConfig; + using System.Linq; public class GuruAnalyticsExp { - + + private const string Tag = "[SDK][ANU][EXP]"; + + private static bool IsDebug + { + get + { +#if UNITY_EDITOR || DEBUG + return true; +#endif + return false; + } + } + + private static string SavedGuruAnalyticsExpGroupId + { + get => PlayerPrefs.GetString(nameof(SavedGuruAnalyticsExpGroupId), ""); + set + { + PlayerPrefs.SetString(nameof(SavedGuruAnalyticsExpGroupId), value); + PlayerPrefs.Save(); + } + } + /** * 原始数据 private const string JSON_GROUP_B = @@ -25,7 +46,7 @@ namespace Guru /// /// /// - public static GuruAnalyticsExpData Parse(string json) + private static GuruAnalyticsExpData Parse(string json) { if (string.IsNullOrEmpty(json)) return null; return JsonParser.ToObject(json); @@ -50,24 +71,132 @@ namespace Guru }] }"; - public static GuruAnalyticsExpData DefaultData => Parse(DEFAULT_GURU_ANALYTICS_EXP); + /// + /// 获取默认数据 + /// + private static GuruAnalyticsExpData DefaultData => Parse(DEFAULT_GURU_ANALYTICS_EXP); + + + /// + /// 在当前版本中,随机获取线上配置的值 + /// 若无法获取线上配置,则默认是 B 分组 + /// + /// + /// + /// + /// + public static void GetGuruAnalyticsExpParams(out string groupId, out string baseUrl, out string[] uploadIpAddress, out bool isEnable) + { + groupId = ""; + baseUrl = ""; + uploadIpAddress = null; + isEnable = true; + string localGroup = ""; + string remoteGroup = ""; + GuruAnalyticsExpData expData = null; + bool usingLocalData = false; + + var gid = SavedGuruAnalyticsExpGroupId; + if(IsDebug) Debug.LogWarning($"{Tag} --- #0 Analytics EXP saved groupId :{gid}"); + + // 拉取云控数据 + var json = ""; + if(FirebaseUtil.IsFirebaseInitialized && FirebaseRemoteConfig.DefaultInstance.Keys.Contains(KEY_GURU_ANALYTICS_EXP)) + json = FirebaseRemoteConfig.DefaultInstance.GetValue(GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP).StringValue; + + if (string.IsNullOrEmpty(json)) + { + if(IsDebug) Debug.LogWarning($"{Tag} --- #1 Analytics EXP json is Null -> using DefaultData"); + expData = DefaultData; + usingLocalData = true; + } + else + { + if(IsDebug) Debug.LogWarning($"{Tag} --- #2 Analytics EXP Try to get remote json -> {json}"); + expData = Parse(json); + usingLocalData = false; + } + + GuruAnalyticsExpConfig config = null; + if (string.IsNullOrEmpty(gid)) + { + config = expData.GetRandomConfig(); + if(IsDebug) Debug.LogWarning($"{Tag} --- #3 no group Id, get random one: id: {config?.groupId ?? "NULL"}"); + } + else + { + config = expData.GetConfig(gid); + if (config == null) + { + config = expData.GetRandomConfig(); + if(IsDebug) Debug.LogWarning($"{Tag} --- #4 Get old Config failed: {gid}, change to random: id: {config?.groupId ?? "NULL"}"); + } + } + + if (config == null) { + config = DefaultData.exps[0]; // 默认是 B 组 + if(IsDebug) Debug.LogWarning($"{Tag} --- #6 Get all config is Null -> using Default config B"); + } + + + baseUrl = config.baseUrl; + groupId = config.groupId; + uploadIpAddress = config.uploadIpAddress; + SavedGuruAnalyticsExpGroupId = groupId; + Debug.Log($"{Tag} --- Analytics EXP params:: groupId:{groupId} baseUrl:{baseUrl} uploadIpAddress:[{string.Join(",", uploadIpAddress)}]"); + } } /// /// 实验数据主题 /// - public class GuruAnalyticsExpData + internal class GuruAnalyticsExpData { public bool enable = true; // 默认是打开的状态 public GuruAnalyticsExpConfig[] exps; // 实验列表 public string ToJson() => JsonParser.ToJson(this); // 转换成 JSON 字符串 + /// + /// 获取随机分组 + /// + /// public GuruAnalyticsExpConfig GetRandomConfig() { if (exps == null || exps.Length == 0) return null; return exps[Random.Range(0, exps.Length)]; } + + /// + /// 根据分组名称获取分组 + /// + /// + /// + public GuruAnalyticsExpConfig GetConfig(string groupId) + { + foreach (var g in exps) + { + if (g.groupId == groupId) return g; + } + + return null; + } + + + /// + /// 分组是否存在 + /// + /// + /// + public bool IsGroupExists(string groupId) + { + foreach (var g in exps) + { + if (g.groupId == groupId) return true; + } + return false; + } + } /// @@ -77,7 +206,7 @@ namespace Guru { public string groupId; public string baseUrl; - public List uploadIpAddress; + public string[] uploadIpAddress; } } \ No newline at end of file diff --git a/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs b/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs index fa325f9..251f180 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/GuruAnalytics.cs @@ -105,7 +105,7 @@ namespace Guru /// /// /// - public static void InitWithConfig(string appId, string deviceInfo, string baseUrl, List uploadIpAddress, bool isEnable = true, bool enableErrorLog = true, bool isDebug = false) + public static void InitWithConfig(string appId, string deviceInfo, string baseUrl, string[] uploadIpAddress, bool isEnable = true, bool enableErrorLog = true, bool isDebug = false) { _enableErrorLog = enableErrorLog; #if UNITY_ANDROID diff --git a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs index 12d1cb2..edc9bcc 100644 --- a/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs +++ b/Runtime/GuruAnalytics/Runtime/Script/Impl/AnalyticsAgentAndroid.cs @@ -88,7 +88,7 @@ namespace Guru bool useWorker = true; bool useCronet = false; string baseUrl = ""; - List uploadIpAddress = null; + string[] uploadIpAddress = null; CallSDKInit(appId, deviceInfo, bundleId, baseUrl, uploadIpAddress , useWorker, useCronet, isDebug); // 调用接口 } @@ -101,7 +101,7 @@ namespace Guru /// /// /// - public void InitWithConfig(string appId, string deviceInfo, string baseUrl, List uploadIpAddress, bool isDebug = false) + public void InitWithConfig(string appId, string deviceInfo, string baseUrl, string[]uploadIpAddress, bool isDebug = false) { _isDebug = isDebug; string bundleId = Application.identifier; @@ -125,12 +125,12 @@ namespace Guru string deviceInfo, string bundleId, string baseUrl = "", - List uploadIpAddress = null, + string[] uploadIpAddress = null, bool useWorker = true, bool useCronet = false, bool isDebug = false) { - CallStatic("init", appId, deviceInfo, bundleId, isDebug, useWorker, useCronet, baseUrl, uploadIpAddress); // 调用接口 + CallStatic("init", appId, deviceInfo, bundleId, isDebug, useWorker, useCronet, baseUrl, string.Join(",", uploadIpAddress)); // 调用接口 } diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs index 1e76f4a..f7fa546 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.Custom.cs @@ -39,11 +39,13 @@ namespace Guru } - public static void InitGuruAnalyticService(string baseUrl, List uploadIpAddress, bool isEnable = true, bool isDebug = false, + public static void InitGuruAnalyticService(string baseUrl, string[] uploadIpAddress, bool isEnable = true, bool isDebug = false, bool enableErrorLog = false, string firebaseId = "") { if (_hasInited) return; + Debug.Log($"{TAG} --- InstallGuruAnalytics baseUrl: {baseUrl} enableErrorLog: {enableErrorLog} firebaseId:{firebaseId}"); + try { #if UNITY_EDITOR @@ -89,7 +91,7 @@ namespace Guru { Debug.Log($"---[ANA] UID: {IPMConfig.IPM_UID}"); GuruAnalytics.SetUid(IPMConfig.IPM_UID); - FirebaseAnalytics.SetUserProperty(PropertyUserID, IPMConfig.IPM_UID); + FirebaseSetUserProperty(PropertyUserID, IPMConfig.IPM_UID); _hasGotUid = true; } @@ -105,7 +107,7 @@ namespace Guru if (!string.IsNullOrEmpty(IPMConfig.IPM_DEVICE_ID)) { GuruAnalytics.SetDeviceId(IPMConfig.IPM_DEVICE_ID); - FirebaseAnalytics.SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID); + FirebaseSetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID); _hasGotDeviceId = true; } } @@ -194,6 +196,8 @@ namespace Guru /// private static void FetchFirebaseId() { + if (!IsFirebaseReady) return; + FirebaseAnalytics.GetAnalyticsInstanceIdAsync() .ContinueWithOnMainThread(task => { @@ -259,6 +263,8 @@ namespace Guru /// private static void UpdateAllValues() { + + Debug.Log($"{TAG} --- UpdateAllValues"); SetUid(); SetDeviceId(); SetAdjustId(); @@ -306,9 +312,16 @@ namespace Guru GuruAnalytics.SetUserProperty(key, value); UpdateAllValues(); // 同步所有的ID } - catch (Exception e) + catch (Exception ex) { - Crashlytics.LogException(e); + if (IsFirebaseReady) + { + Crashlytics.LogException(ex); + } + else + { + Debug.LogException(ex); + } } } @@ -328,7 +341,14 @@ namespace Guru } catch (Exception e) { - Crashlytics.LogException(e); + if (IsFirebaseReady) + { + Crashlytics.LogException(e); + } + else + { + Debug.LogWarning(e); + } } } @@ -352,7 +372,14 @@ namespace Guru } catch (Exception e) { - Crashlytics.LogException(e); + if (IsFirebaseReady) + { + Crashlytics.LogException(e); + } + else + { + Debug.LogWarning(e); + } } } diff --git a/Runtime/GuruCore/Runtime/Analytics/Analytics.cs b/Runtime/GuruCore/Runtime/Analytics/Analytics.cs index eb7db7b..3421397 100644 --- a/Runtime/GuruCore/Runtime/Analytics/Analytics.cs +++ b/Runtime/GuruCore/Runtime/Analytics/Analytics.cs @@ -1,6 +1,7 @@ using System.Collections; +using UnityEngine; namespace Guru { @@ -28,12 +29,14 @@ namespace Guru public static bool IsDebugMode => PlatformUtil.IsDebug(); + public static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized; + private static bool IsEnable { get { //Firebase服务没有初始化完成不上报打点 - if (!FirebaseUtil.IsFirebaseInitialized) + if (!IsFirebaseReady) return false; //Analytics没有初始化不上报打点 @@ -50,7 +53,7 @@ namespace Guru #region 初始化 - public static void InitAnalytics(string baseUrl = "", List uploadIpAddress = null, bool isEnable = false, bool enableErrorLog = false, string firebaseId = "") + public static void InitAnalytics(string baseUrl = "", string[] uploadIpAddress = null, bool isEnable = false, bool enableErrorLog = false, string firebaseId = "") { if (_isInited) return; _isInited = true; @@ -121,8 +124,7 @@ namespace Guru { Log.I(TAG,$"SetUserIDProperty -> userID:{userID}"); if (!IsEnable) return; - - FirebaseAnalytics.SetUserId(userID); + if (IsFirebaseReady) FirebaseAnalytics.SetUserId(userID); } /// @@ -132,13 +134,30 @@ namespace Guru { Log.I(TAG,$"SetUserProperty -> propertyName:{propertyName}, propertyValue:{propertyValue}"); - if (!IsEnable) - return; - - FirebaseAnalytics.SetUserProperty(propertyName, propertyValue); + if (!IsEnable) return; + FirebaseSetUserProperty(propertyName, propertyValue); CustomSetUserProperty(propertyName, propertyValue); } + + /// + /// Firebase 上报用户属性 + /// + /// + /// + private static void FirebaseSetUserProperty(string propertyName, string propertyValue) + { + if (IsFirebaseReady) + { + FirebaseAnalytics.SetUserProperty(propertyName, propertyValue); + } + else + { + Debug.Log($"{TAG} --- Firebase not ready, call Firebase Init first!"); + } + } + + #endregion #region 打点上报 @@ -375,7 +394,7 @@ namespace Guru } catch (Exception ex) { - Crashlytics.LogException(ex); + if(IsFirebaseReady) Crashlytics.LogException(ex); } } diff --git a/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.Crashlytics.cs b/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.Crashlytics.cs index 1fa140c..7db3c36 100644 --- a/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.Crashlytics.cs +++ b/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.Crashlytics.cs @@ -5,6 +5,8 @@ namespace Guru { public static partial class FirebaseUtil { + + public static void InitCrashlytics() { if(!string.IsNullOrEmpty(IPMConfig.IPM_UID)) @@ -17,6 +19,7 @@ namespace Guru /// public static void SetUserID(string userID) { + if (!IsFirebaseInitialized) return; Crashlytics.SetUserId(userID); } @@ -26,6 +29,7 @@ namespace Guru /// public static void SetCustomData(string key, string value) { + if (!IsFirebaseInitialized) return; Crashlytics.SetCustomKey(key, value); } @@ -34,6 +38,7 @@ namespace Guru /// public static void LogMessage(string message) { + if (!IsFirebaseInitialized) return; Crashlytics.Log(message); } @@ -42,6 +47,7 @@ namespace Guru /// public static void LogException(Exception exception) { + if (!IsFirebaseInitialized) return; Crashlytics.LogException(exception); } } diff --git a/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs b/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs index f2cf0be..42e17fb 100644 --- a/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs +++ b/Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs @@ -14,7 +14,7 @@ namespace Guru private static readonly string LOG_TAG = "Firebase"; private static bool _isDebug = false; private static bool _isReady = false; - public static bool IsReady => _isReady; + public static bool IsReady => _isReady && IsFirebaseInitialized; public static DependencyStatus DependencyStatus = DependencyStatus.UnavailableOther; public static bool IsFirebaseInitialized => DependencyStatus == DependencyStatus.Available; @@ -106,6 +106,9 @@ namespace Guru private static void InitAssetByFirebaseIdAsync() { + + Debug.Log($"[SDK] --- InitAssetByFirebaseIdAsync"); + // 异步获取 FirebaseID FirebaseAnalytics.GetAnalyticsInstanceIdAsync() .ContinueWithOnMainThread(task => @@ -115,12 +118,12 @@ namespace Guru { // 保存本地ID备份 IPMConfig.FIREBASE_ID = fid; // 保存FirebaseID - Debug.Log($"[SDk] --- Get FirebaseID: {fid}"); + Debug.Log($"[SDK] --- Get FirebaseID: {fid}"); GuruAnalytics.SetFirebaseId(fid); } else { - Debug.LogError($"[SDk] --- Fetch FirebaseID failed on start!"); + Debug.LogError($"[SDK] --- Fetch FirebaseID failed on start!"); } //--- 结束后启动相关的服务 --- @@ -157,7 +160,7 @@ namespace Guru var enableErrorLog = true; // 开启日志上报 // 随机抽取本地分组获取数据 - GetGuruAnalyticsExpConfig(out string groupId, out string baseUrl, out List uploadIpAddress, out bool isEnable); + GuruAnalyticsExp.GetGuruAnalyticsExpParams(out string groupId, out string baseUrl, out string[] uploadIpAddress, out bool isEnable); // 自打点启动前,先上报一下分数数据 GuruAnalytics.SetUserProperty(GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP, groupId); // 设置实验分组 @@ -178,45 +181,14 @@ namespace Guru // 添加默认的云控参数 private static void InitGuruAnalyticsExpDefaultRemoteValue() { - AppendDefaultValue(GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP, GuruAnalyticsExp.DEFAULT_GURU_ANALYTICS_EXP); + // AppendDefaultValue(GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP, GuruAnalyticsExp.DEFAULT_GURU_ANALYTICS_EXP); + FirebaseRemoteConfig.DefaultInstance.SetDefaultsAsync(new Dictionary() + { + { GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP, GuruAnalyticsExp.DEFAULT_GURU_ANALYTICS_EXP } + }); } - /// - /// 在当前版本中,随机获取线上配置的值 - /// 若无法获取线上配置,则默认是 B 分组 - /// - /// - /// - /// - /// - private static void GetGuruAnalyticsExpConfig(out string groupId, out string baseUrl, out List uploadIpAddress, out bool isEnable) - { - groupId = ""; - baseUrl = ""; - uploadIpAddress = null; - isEnable = true; - - // 如果云测关闭 - var json = FirebaseRemoteConfig.DefaultInstance.GetValue(GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP).StringValue; - var expData = GuruAnalyticsExp.Parse(json); - var defaultExpData = GuruAnalyticsExp.DefaultData; - - GuruAnalyticsExpConfig config = null; - if (expData == null) - { - config = defaultExpData.exps[0]; // 默认是 B 组 - } - else - { - config = expData.GetRandomConfig(); - if (config == null) config = defaultExpData.exps[0]; // 默认是 B 组 - } - - baseUrl = config.baseUrl; - groupId = config.groupId; - uploadIpAddress = config.uploadIpAddress; - Debug.Log($"[SDK][ANU] --- Analytics EXP Group: {groupId} baseUrl:{baseUrl} uploadIpAddress:[{string.Join(",", uploadIpAddress)}]"); - } + #endif #endregion diff --git a/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs b/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs index ef0017b..e6bdfbe 100644 --- a/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs +++ b/Runtime/GuruCore/Runtime/Reporter/CrashlyticsAgent.cs @@ -101,7 +101,7 @@ namespace Guru public static void LogException(Exception ex) { - if (!_isReady) + if (!_isReady || !FirebaseUtil.IsReady) { Install(); _expCache.Enqueue(ex); @@ -119,7 +119,7 @@ namespace Guru public static void Log(string msg) { if (!_isReady) return; - Crashlytics.Log(msg); + if(FirebaseUtil.IsReady) Crashlytics.Log(msg); // CheckSetUser(); } @@ -127,7 +127,7 @@ namespace Guru public static void SetCustomKey(string key, string value) { if (!_isReady) return; - Crashlytics.SetCustomKey(key, value); + if(FirebaseUtil.IsReady) Crashlytics.SetCustomKey(key, value); }