Compare commits

...

5 Commits

Author SHA1 Message Date
胡宇飞 8ee9b8e9cf fix: 修改androidx.room:room-runtime 的 Deps 版本, 目前先适配 API 33
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-24 17:19:56 +08:00
胡宇飞 548959dd34 update: 修改androidx.work:work-runtime 的 Deps 版本, 目前先适配 API 33
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-24 16:55:56 +08:00
胡宇飞 9de443249d fix: 优化实验策略,数据读取逻辑
--story=1021087 --user=yufei.hu 【中台】【自打点】升级自打点原生库至 1.1.1,并在 Water1 中落地验证 https://www.tapd.cn/33527076/s/1159023

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-24 13:26:28 +08:00
胡宇飞 6dd2574763 update: 更新打包日志,完善云控参数读取, 重构本地测试逻辑, 规范日志
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-24 10:35:27 +08:00
胡宇飞 bd39fb09f1 update: 升级自打点库Native至1.1.1, 内置 AB 测试逻辑
--story=1021087 --user=yufei.hu 【中台】【自打点】升级自打点原生库至 1.1.1,并在 Water1 中落地验证 https://www.tapd.cn/33527076/s/1158888

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-23 20:04:47 +08:00
23 changed files with 614 additions and 113 deletions

View File

@ -8,18 +8,20 @@ Sample Dependencies.xml:
<androidPackage spec="androidx.core:core:1.7.0" />
<!-- <androidPackage spec="androidx.appcompat:appcompat:1.5.1" />-->
<androidPackage spec="androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" />
<androidPackage spec="androidx.work:work-runtime:2.7.1" />
<androidPackage spec="androidx.work:work-runtime-ktx:2.7.1" />
<androidPackage spec="androidx.work:work-rxjava2:2.7.1" />
<androidPackage spec="androidx.work:work-runtime:2.8.1" />
<androidPackage spec="androidx.work:work-runtime-ktx:2.8.1" />
<androidPackage spec="androidx.work:work-rxjava2:2.8.1" />
<androidPackage spec="androidx.lifecycle:lifecycle-process:2.4.0" />
<androidPackage spec="com.jakewharton.timber:timber:4.7.1" />
<androidPackage spec="com.google.code.gson:gson:2.8.5" />
<androidPackage spec="androidx.room:room-runtime:2.4.3" />
<androidPackage spec="androidx.room:room-rxjava2:2.4.3" />
<androidPackage spec="androidx.room:room-runtime:2.5.1" />
<androidPackage spec="androidx.room:room-rxjava2:2.5.1" />
<androidPackage spec="com.squareup.retrofit2:retrofit:2.7.1" />
<androidPackage spec="com.squareup.retrofit2:converter-gson:2.7.1" />
<androidPackage spec="com.squareup.retrofit2:adapter-rxjava2:2.7.1" />
<androidPackage spec="com.squareup.okhttp3:okhttp:4.9.3" />
<androidPackage spec="com.squareup.okhttp3:okhttp:4.12.0" />
<androidPackage spec="com.squareup.okhttp3:okhttp-dnsoverhttps:4.12.0" />
<androidPackage spec="com.google.net.cronet:cronet-okhttp:0.1.0" />
<!-- <androidPackage spec="com.mapzen:on-the-road:0.8.1" />-->
<!-- <androidPackage spec="com.squareup.retrofit2:retrofit:2.7.1" />-->
</androidPackages>

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 07cf2335bd298401b8015718fca55265
guid: 32eda01e213614348899eefe856392d3
PluginImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: caf6ff09835a4a75bff1b4b068f664ef
timeCreated: 1717117895

View File

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

View File

@ -16,6 +16,14 @@ GuruAnalyticsLib 的 Unity 插件库
## Change Logs
### 1.11.1
- Android 端对齐 `1.1.1`
> Hash: 8791b946c441a081b80248aadbf65b515a8d2a10
- iOS 端对齐 `0.3.6`
> Hash: 0cd5ce7aa64e12caa7413c938a3164687b973843
- Pod 库改为 本地文件引用 (配合外部发行项目)
### 1.11.0
- Android 端对齐 `1.0.3`
> Hash: 1978686dbcba38b7b0421d8b6b2bef111356366b

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f6d79ccb59bc4a5791121a696d6695b0
timeCreated: 1721722422

View File

@ -0,0 +1,242 @@
namespace Guru
{
using System;
using UnityEngine;
using Random = UnityEngine.Random;
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 =
"{\"cap\":\"firebase|facebook|guru\",\"init_delay_s\":10,\"experiment\":\"B\",\"guru_upload_ip_address\":[\"13.248.248.135\", \"3.33.195.44\"]}";
private const string JSON_GROUP_C =
"{\"cap\":\"firebase|facebook|guru\",\"init_delay_s\":10,\"experiment\":\"C\",\"guru_upload_ip_address\":[\"34.107.185.54\"],\"guru_event_url\":\"https://collect3.saas.castbox.fm\"}";
**/
/// <summary>
/// 解析 JSON 字符串
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
private static GuruAnalyticsExpData Parse(string json)
{
if (string.IsNullOrEmpty(json)) return null;
return JsonParser.ToObject<GuruAnalyticsExpData>(json);
}
public const string KEY_GURU_ANALYTICS_EXP = "guru_analytics_exp";
/// <summary>
/// 默认的本地配置
/// </summary>
private static string DEFAULT_GURU_ANALYTICS_EXP = @"{
""enable"": true,
""exps"": [{
""groupId"": ""B"",
""baseUrl"": ""https://collect.saas.castbox.fm"",
""uploadIpAddress"": [""13.248.248.135"", ""3.33.195.44""]
}, {
""groupId"": ""C"",
""baseUrl"": ""https://collect3.saas.castbox.fm"",
""uploadIpAddress"": [""34.107.185.54""]
}]
}";
/// <summary>
/// 获取默认数据
/// </summary>
private static GuruAnalyticsExpData DefaultData => Parse(DEFAULT_GURU_ANALYTICS_EXP);
/// <summary>
/// 在当前版本中,随机获取线上配置的值
/// 若无法获取线上配置,则默认是 B 分组
/// </summary>
/// <param name="groupId"></param>
/// <param name="baseUrl"></param>
/// <param name="uploadIpAddress"></param>
/// <param name="isEnable"></param>
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;
GuruAnalyticsExpConfig config = null;
if(IsDebug) Debug.LogWarning($"{Tag} --- #0 Analytics EXP saved groupId :{SavedGuruAnalyticsExpGroupId}");
// 拉取云控数据
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");
config = GetDefaultGuruAnalyticsExpConfig();
}
else
{
if(IsDebug) Debug.LogWarning($"{Tag} --- #2 Analytics EXP Try to get remote json -> {json}");
expData = Parse(json);
if (expData == null)
{
if(IsDebug) Debug.LogWarning($"{Tag} --- #2.1 Analytics EXP Parse failed -> using DefaultData");
config = GetDefaultGuruAnalyticsExpConfig();
}
else
{
if (!expData.enable)
{
Debug.LogWarning($"{Tag} --- #2.2 Analytics EXP Disabled -> using DefaultData");
expData = DefaultData;
}
config = expData.GetFirstConfig();
}
}
if (config == null) {
config = DefaultData.GetFirstConfig(); // 默认是 B 组
if(IsDebug) Debug.LogWarning($"{Tag} --- #3 Try get config is Null -> using Default config");
}
if (config != null)
{
baseUrl = config.baseUrl;
groupId = config.groupId;
uploadIpAddress = config.uploadIpAddress;
SavedGuruAnalyticsExpGroupId = groupId;
}
else
{
isEnable = false;
}
Debug.Log($"{Tag} --- Analytics EXP params:: groupId:{groupId} baseUrl:{baseUrl} uploadIpAddress:[{string.Join(",", uploadIpAddress)}]");
}
private static GuruAnalyticsExpConfig GetDefaultGuruAnalyticsExpConfig()
{
GuruAnalyticsExpConfig config = null;
if (!string.IsNullOrEmpty(SavedGuruAnalyticsExpGroupId))
{
config = DefaultData.GetConfig(SavedGuruAnalyticsExpGroupId); // 非空则取值
}
else
{
config = DefaultData.GetRandomConfig(); // 随机获取本地的 Config
}
if(IsDebug) Debug.LogWarning($"{Tag} --- #1.1 using Default GropId: {config?.groupId ?? "NULL"}");
return config;
}
}
/// <summary>
/// 实验数据主题
/// </summary>
internal class GuruAnalyticsExpData
{
public bool enable = true; // 默认是打开的状态
public GuruAnalyticsExpConfig[] exps; // 实验列表
public string ToJson() => JsonParser.ToJson(this); // 转换成 JSON 字符串
/// <summary>
/// 获取随机分组
/// </summary>
/// <returns></returns>
public GuruAnalyticsExpConfig GetRandomConfig()
{
if (exps == null || exps.Length == 0) return null;
return exps[Random.Range(0, exps.Length)];
}
/// <summary>
/// 根据分组名称获取分组
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>
public GuruAnalyticsExpConfig GetConfig(string groupId)
{
foreach (var g in exps)
{
if (g.groupId == groupId) return g;
}
return null;
}
/// <summary>
/// 获取首个配置
/// </summary>
/// <returns></returns>
public GuruAnalyticsExpConfig GetFirstConfig()
{
if (exps != null && exps.Length > 0) return exps[0];
return null;
}
/// <summary>
/// 分组是否存在
/// </summary>
/// <param name="groupId"></param>
/// <returns></returns>
public bool IsGroupExists(string groupId)
{
foreach (var g in exps)
{
if (g.groupId == groupId) return true;
}
return false;
}
}
/// <summary>
/// 实验配置
/// </summary>
internal class GuruAnalyticsExpConfig
{
public string groupId;
public string baseUrl;
public string[] uploadIpAddress;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a840d9218d324971b528c639ddfea270
timeCreated: 1721722549

View File

@ -14,10 +14,11 @@ namespace Guru
public class GuruAnalytics
{
// Plugin Version
public const string Version = "1.11.0";
public const string Version = "1.11.1";
public static readonly string Tag = "[ANU]";
private static readonly string ActionName = "logger_error";
internal const int EventPriorityDefault = 10;
private static IAnalyticsAgent _agent;
@ -90,9 +91,54 @@ namespace Guru
_autoSyncProperties = syncProperties;
_enableErrorLog = enableErrorLog;
Agent?.Init(appId, deviceInfo, isDebug);
}
/// <summary>
/// 根据配置初始化接口
/// </summary>
/// <param name="appId"></param>
/// <param name="deviceInfo"></param>
/// <param name="baseUrl"></param>
/// <param name="uploadIpAddress"></param>
/// <param name="isEnable"></param>
/// <param name="enableErrorLog"></param>
/// <param name="isDebug"></param>
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
Debug.Log($"{Tag} [{Version}] --- InitWithConfig ---");
if (isEnable)
{
if (Agent is AnalyticsAgentAndroid andAgent)
{
if (!string.IsNullOrEmpty(baseUrl))
{
Debug.Log($"\t baseUrl:{baseUrl}");
}
if (uploadIpAddress != null)
{
Debug.Log($"\t uploadIpAddress:{uploadIpAddress}");
}
andAgent.InitWithConfig(appId, deviceInfo, baseUrl, uploadIpAddress, isDebug);
}
}
else
{
Init(appId, deviceInfo, isDebug);
}
#else
Init(appId, deviceInfo, isDebug);
#endif
if(_enableErrorLog) InitCallbacks(); // 激活错误日志回调
}
/// <summary>
/// 设置视图名称
/// </summary>
@ -200,7 +246,8 @@ namespace Guru
/// </summary>
/// <param name="eventName">事件名称</param>
/// <param name="data">INT类型的值</param>
public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null)
/// <param name="priority"></param>
public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null, int priority = -1)
{
if(_autoSyncProperties)
UpdateAllUserProperties(); // 每次打点更新用户属性
@ -210,8 +257,9 @@ namespace Guru
{
raw = BuildParamsJson(data);
}
Debug.Log($"{Tag} event:{eventName} | raw: {raw}");
Agent?.LogEvent(eventName, raw);
if (priority < 0) priority = EventPriorityDefault;
Debug.Log($"{Tag} event:{eventName} | raw: {raw} | priority: {priority}");
Agent?.LogEvent(eventName, raw, priority);
}
private static string BuildParamsString(Dictionary<string, dynamic> data)
@ -555,11 +603,13 @@ namespace Guru
case AnalyticsCode.ERROR_ZIP:
case AnalyticsCode.ERROR_DNS_CACHE:
case AnalyticsCode.CRONET_INTERCEPTOR:
case AnalyticsCode.EVENT_LOOKUP:
case AnalyticsCode.EVENT_SESSION_ACTIVE:
canCatch = true;
break;
}
if (code > 100 && code <= 200)
if (!canCatch && code is > 100 and <= 200)
{
// 100 < code <= 200
canCatch = true;
@ -605,21 +655,24 @@ namespace Guru
{
Unknown = -1,
DELETE_EXPIRED = 12,
UPLOAD_FAIL = 14,
Network_Lost = 22,
CRONET_INIT_FAIL = 26,
CRONET_INIT_EXCEPTION = 27,
DELETE_EXPIRED = 12, // 删除过期事件
UPLOAD_FAIL = 14, // 上报事件失败
Network_Lost = 22, // 网络状态不可用
CRONET_INIT_FAIL = 26, // 开启Cronet失败
CRONET_INIT_EXCEPTION = 27, // 开启Cronet报错
ERROR_API = 101,
ERROR_RESPONSE = 102,
ERROR_CACHE_CONTROL = 103,
ERROR_DELETE_EXPIRED = 104,
ERROR_LOAD_MARK = 105,
ERROR_DNS = 106,
ERROR_ZIP = 107,
ERROR_DNS_CACHE = 108,
CRONET_INTERCEPTOR = 109,
ERROR_API = 101, // 调用api出错
ERROR_RESPONSE = 102, // api返回结果错误
ERROR_CACHE_CONTROL = 103, // 设置cacheControl出错
ERROR_DELETE_EXPIRED = 104, // 删除过期事件出错
ERROR_LOAD_MARK = 105, // 从数据库取事件以及更改事件状态为正在上报出错
ERROR_DNS = 106, // dns 错误
ERROR_ZIP = 107, // zip 错误
ERROR_DNS_CACHE = 108, // zip 错误
CRONET_INTERCEPTOR = 109, // cronet拦截器
EVENT_LOOKUP = 1003,
EVENT_SESSION_ACTIVE = 1004,
}
}

View File

@ -15,7 +15,7 @@ namespace Guru
void SetUid(string uid);
bool IsDebug { get; }
bool EnableErrorLog { get; set; }
void LogEvent(string eventName, string parameters);
void LogEvent(string eventName, string parameters, int priority = 0);
void ReportEventSuccessRate(); // 上报任务成功率
void SetTch02Value(double value); // 设置太极02数值
void InitCallback(string objName, string method); // 设置回调对象参数

View File

@ -4,6 +4,7 @@ namespace Guru
{
using System;
using UnityEngine;
using System.Collections.Generic;
public class AnalyticsAgentAndroid: IAnalyticsAgent
{
@ -16,8 +17,6 @@ namespace Guru
#endif
private static bool _isDebug = false;
public static bool UseWorker = true;
public static bool UseCronet = false;
public static string BaseUrl = "";
#region 工具方法
@ -76,13 +75,65 @@ namespace Guru
#region 接口实现
/// <summary>
/// 默认的启动参数
/// </summary>
/// <param name="appId"></param>
/// <param name="deviceInfo"></param>
/// <param name="isDebug"></param>
public void Init(string appId, string deviceInfo, bool isDebug = false)
{
_isDebug = isDebug;
string bundleId = Application.identifier;
CallStatic("init", appId, deviceInfo, bundleId, UseWorker, isDebug, UseCronet, BaseUrl); // 调用接口
bool useWorker = true;
bool useCronet = false;
string baseUrl = "";
string[] uploadIpAddress = null;
CallSDKInit(appId, deviceInfo, bundleId, baseUrl, uploadIpAddress , useWorker, useCronet, isDebug); // 调用接口
}
/// <summary>
/// 面向 Android 启动专用的 API
/// </summary>
/// <param name="appId"></param>
/// <param name="deviceInfo"></param>
/// <param name="baseUrl"></param>
/// <param name="uploadIpAddress"></param>
/// <param name="isDebug"></param>
public void InitWithConfig(string appId, string deviceInfo, string baseUrl, string[]uploadIpAddress, bool isDebug = false)
{
_isDebug = isDebug;
string bundleId = Application.identifier;
bool useWorker = true;
bool useCronet = false;
CallSDKInit(appId, deviceInfo, bundleId, baseUrl, uploadIpAddress , useWorker, useCronet, _isDebug); // 调用接口
}
/********* Android API **********
public static void init(String appId,
String deviceInfo,
String bundleId,
boolean debug,
boolean useWorker,
boolean enabledCronet,
String baseUrl,
List<String> uploadIpAddress)
*/
private void CallSDKInit(string appId,
string deviceInfo,
string bundleId,
string baseUrl = "",
string[] uploadIpAddress = null,
bool useWorker = true,
bool useCronet = false,
bool isDebug = false)
{
CallStatic("init", appId, deviceInfo, bundleId, isDebug, useWorker, useCronet, baseUrl, string.Join(",", uploadIpAddress)); // 调用接口
}
public void SetScreen(string screenName)
{
if (string.IsNullOrEmpty(screenName)) return;
@ -124,7 +175,7 @@ namespace Guru
}
public bool IsDebug => CallStatic<bool>("isDebug");
public void LogEvent(string eventName, string parameters) => CallStatic("logEvent", eventName, parameters);
public void LogEvent(string eventName, string parameters, int priority = 0) => CallStatic("logEvent", eventName, parameters, priority);
public void ReportEventSuccessRate() => CallStatic("reportEventRate");
public void SetTch02Value(double value) => CallStatic("setTch02Value", value);
public void InitCallback(string objName, string method) => CallStatic("initCallback", objName, method);

View File

@ -122,7 +122,7 @@ namespace Guru
public bool IsDebug => _isDebug;
public void LogEvent(string eventName, string data)
public void LogEvent(string eventName, string data, int priority = 0)
{
#if UNITY_IOS
unityLogEvent(eventName, data);

View File

@ -87,7 +87,7 @@ namespace Guru
public bool IsDebug => _isDebug;
public void LogEvent(string eventName, string parameters)
public void LogEvent(string eventName, string parameters, int priority = 0)
{
if (_isShowLog)
{

View File

@ -6,6 +6,7 @@ namespace Guru
fail,
timeout,
exit,
replay
}
//打点常量定义

View File

@ -33,41 +33,52 @@ namespace Guru
/// <summary>
/// 初始化Guru自打点系统 (请优先于 Firebase 初始化调用)
/// </summary>
public static void InstallGuruAnalytics(bool isDebug = false, bool enableErrorLog = false)
public static void InstallGuruAnalytics(bool isDebug = false, bool enableErrorLog = false, string firebaseId = "")
{
InitGuruAnalyticService("", null, false, isDebug, enableErrorLog, firebaseId); // Android 初始化
}
public static void InitGuruAnalyticService(string baseUrl, string[] uploadIpAddress, bool isEnable = true, bool isDebug = false,
bool enableErrorLog = false, string firebaseId = "")
{
if (_hasInited) return;
try
{
Debug.Log($"{TAG} --- InstallGuruAnalytics baseUrl: {baseUrl} enableErrorLog: {enableErrorLog} firebaseId:{firebaseId}");
try
{
#if UNITY_EDITOR
IsDebug = true;
IsDebug = true;
#else
IsDebug = isDebug;
#endif
string appId = IPMConfig.IPM_X_APP_ID;
string deviceInfo = new DeviceInfoData().ToString();
GuruAnalytics.Init(appId, deviceInfo, IsDebug, enableErrorLog); // 初始化(带Header)
_hasGotFirebaseId = false;
_hasGotAdId = false;
_hasGotAdjustId = false;
_hasGotDeviceId = false;
_hasGotUid = false;
_lastReportRateDate = DateTime.Now;
_reportSuccessInterval = 120; // 2分钟上报一次
UpdateAllValues();
string appId = IPMConfig.IPM_X_APP_ID;
string deviceInfo = new DeviceInfoData().ToString();
_hasInited = true;
}
catch (Exception ex)
{
LogCrashlytics(ex);
}
_hasGotFirebaseId = false;
_hasGotAdId = false;
_hasGotAdjustId = false;
_hasGotDeviceId = false;
_hasGotUid = false;
_lastReportRateDate = DateTime.Now;
_reportSuccessInterval = 120; // 2分钟上报一次
if(!string.IsNullOrEmpty(firebaseId)) GuruAnalytics.SetFirebaseId(firebaseId);
GuruAnalytics.InitWithConfig(appId, deviceInfo, baseUrl, uploadIpAddress, isEnable, enableErrorLog); // Android 初始化
UpdateAllValues();
_hasInited = true;
}
catch (Exception ex)
{
LogCrashlytics(ex);
}
}
#region 各ID上报信息
#region 各ID上报信息
/// <summary>
/// 设置用户ID
@ -80,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;
}
@ -96,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;
}
}
@ -185,6 +196,8 @@ namespace Guru
/// </summary>
private static void FetchFirebaseId()
{
if (!IsFirebaseReady) return;
FirebaseAnalytics.GetAnalyticsInstanceIdAsync()
.ContinueWithOnMainThread(task =>
{
@ -250,6 +263,8 @@ namespace Guru
/// </summary>
private static void UpdateAllValues()
{
Debug.Log($"{TAG} --- UpdateAllValues");
SetUid();
SetDeviceId();
SetAdjustId();
@ -297,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);
}
}
}
@ -319,7 +341,14 @@ namespace Guru
}
catch (Exception e)
{
Crashlytics.LogException(e);
if (IsFirebaseReady)
{
Crashlytics.LogException(e);
}
else
{
Debug.LogWarning(e);
}
}
}
@ -343,7 +372,14 @@ namespace Guru
}
catch (Exception e)
{
Crashlytics.LogException(e);
if (IsFirebaseReady)
{
Crashlytics.LogException(e);
}
else
{
Debug.LogWarning(e);
}
}
}

View File

@ -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()
public static void InitAnalytics(string baseUrl = "", string[] uploadIpAddress = null, bool isEnable = false, bool enableErrorLog = false, string firebaseId = "")
{
if (_isInited) return;
_isInited = true;
@ -59,7 +62,7 @@ namespace Guru
CrashlyticsAgent.Install();
// ------- 初始化自打点 ----------
InstallGuruAnalytics(IsDebug);
InitGuruAnalyticService(baseUrl, uploadIpAddress, isEnable, IsDebug, enableErrorLog, firebaseId);
if (_defaultEventSetting == null)
{
@ -121,8 +124,7 @@ namespace Guru
{
Log.I(TAG,$"SetUserIDProperty -> userID:{userID}");
if (!IsEnable) return;
FirebaseAnalytics.SetUserId(userID);
if (IsFirebaseReady) FirebaseAnalytics.SetUserId(userID);
}
/// <summary>
@ -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);
}
/// <summary>
/// Firebase 上报用户属性
/// </summary>
/// <param name="propertyName"></param>
/// <param name="propertyValue"></param>
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);
}
}

View File

@ -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
/// </summary>
public static void SetUserID(string userID)
{
if (!IsFirebaseInitialized) return;
Crashlytics.SetUserId(userID);
}
@ -26,6 +29,7 @@ namespace Guru
/// </summary>
public static void SetCustomData(string key, string value)
{
if (!IsFirebaseInitialized) return;
Crashlytics.SetCustomKey(key, value);
}
@ -34,6 +38,7 @@ namespace Guru
/// </summary>
public static void LogMessage(string message)
{
if (!IsFirebaseInitialized) return;
Crashlytics.Log(message);
}
@ -42,6 +47,7 @@ namespace Guru
/// </summary>
public static void LogException(Exception exception)
{
if (!IsFirebaseInitialized) return;
Crashlytics.LogException(exception);
}
}

View File

@ -1,17 +1,22 @@
using System;
using System.Collections.Generic;
using Firebase;
using Firebase.Analytics;
using Firebase.Extensions;
using System.Text.RegularExpressions;
namespace Guru
{
using System;
using System.Collections.Generic;
using Firebase;
using Firebase.Analytics;
using Firebase.Extensions;
using Firebase.RemoteConfig;
using Random = UnityEngine.Random;
using UnityEngine;
public static partial class FirebaseUtil
{
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;
@ -21,14 +26,15 @@ namespace Guru
public static Action<bool> OnUserAuthResult;
/// <summary>
/// 初始化 Firebase 组件
/// </summary>
/// <param name="callback"></param>
/// <param name="isDebug"></param>
public static void InitFirebase(Action callback, bool isDebug = false)
{
_isReady = false;
_isDebug = isDebug;
Analytics.InitAnalytics(); // 打点提前初始化
// Loom.StartUp(); // 确保主线程开启
// 初始化 Fireabse 依赖
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
@ -46,11 +52,16 @@ namespace Guru
onInitComplete?.Invoke(_isReady);
});
}
/// <summary>
/// 初始化 Firebase 组件
/// </summary>
private static void InitializeFirebaseComp()
{
InitCrashlytics(); // 老项目沿用此逻辑
InitRemoteConfig(); // 老项目沿用此逻辑
InitAdjustService(); // 初始化 Firebase 服务
InitAssetByFirebaseIdAsync(); // 获取到 FirebaseID 后异步执行逻辑
if (IPMConfig.IPM_UID.IsNullOrEmpty())
{
@ -93,6 +104,36 @@ namespace Guru
}
}
private static void InitAssetByFirebaseIdAsync()
{
Debug.Log($"[SDK] --- InitAssetByFirebaseIdAsync");
// 异步获取 FirebaseID
FirebaseAnalytics.GetAnalyticsInstanceIdAsync()
.ContinueWithOnMainThread(task =>
{
string fid = task.Result;
if (task.IsCompleted && !string.IsNullOrEmpty(fid))
{
// 保存本地ID备份
IPMConfig.FIREBASE_ID = fid; // 保存FirebaseID
Debug.Log($"[SDK] --- Get FirebaseID: {fid}");
GuruAnalytics.SetFirebaseId(fid);
}
else
{
Debug.LogError($"[SDK] --- Fetch FirebaseID failed on start!");
}
//--- 结束后启动相关的服务 ---
InitAdjustService(); // 启动 AdjustService
InitAnalytics(); // 初始化打点逻辑和实现
});
}
#region 启动 Adjust 服务
/// <summary>
@ -100,33 +141,40 @@ namespace Guru
/// </summary>
private static void InitAdjustService()
{
FirebaseAnalytics.GetAnalyticsInstanceIdAsync()
.ContinueWithOnMainThread(task =>
{
if (task.IsCompleted && !string.IsNullOrEmpty(task.Result))
{
// 保存本地ID备份
string fid = task.Result;
IPMConfig.FIREBASE_ID = fid; // 保存FirebaseID
}
else
{
UnityEngine.Debug.LogError($"Fetch FirebaseID failed on start!");
}
// 启动 AdjustService
string appToken = GuruSettings.Instance.AdjustSetting?.GetAppToken() ?? "";
string fbAppId = GuruSettings.Instance.IPMSetting.FacebookAppId;
AdjustService.StartService(appToken, fbAppId);
});
// 启动 AdjustService
string appToken = GuruSettings.Instance.AdjustSetting?.GetAppToken() ?? "";
string fbAppId = GuruSettings.Instance.IPMSetting.FacebookAppId;
AdjustService.StartService(appToken, fbAppId);
}
#endregion
#region Android 自打点特殊启动方式
// Firebase 初始化才能调用此方法
private static void InitAnalytics()
{
#if UNITY_ANDROID
// Android 平台开始
var fid = IPMConfig.FIREBASE_ID;// 获取 FirebaseID
var enableErrorLog = true; // 开启日志上报
// 随机抽取本地分组获取数据
GuruAnalyticsExp.GetGuruAnalyticsExpParams(out string groupId, out string baseUrl, out string[] uploadIpAddress, out bool isEnable);
// 初始化打点和自打点
Analytics.InitAnalytics(baseUrl, uploadIpAddress, isEnable, enableErrorLog, fid); // 打点提前初始化
Analytics.SetUserProperty(GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP, groupId); // 上报分组数据
#else
// iOS 不参与分组
Analytics.InitAnalytics();
Analytics.SetUserProperty(GuruAnalyticsExp.KEY_GURU_ANALYTICS_EXP, "none"); // 上报分组数据
#endif
}
#endregion
}
}

View File

@ -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);
}