update: 重构 自打点属性上报逻辑, CodeReview

Signed-off-by: huyufei <yufei.hu@castbox.fm>
胡宇飞 2024-08-07 03:28:07 +08:00
parent ca036ba584
commit d37c1c4216
19 changed files with 1017 additions and 244 deletions

View File

@ -18,7 +18,7 @@ namespace Guru
public const string K_IAP_PURCHASE = "iap_purchase"; // 固定点位事件 public const string K_IAP_PURCHASE = "iap_purchase"; // 固定点位事件
public const string K_SUB_PURCHASE = "sub_purchase"; // 固定点位事件 public const string K_SUB_PURCHASE = "sub_purchase"; // 固定点位事件
private static Action<string> _onInitComplete; private static Action<string, string, string> _onInitComplete;
private static Action<string> _onGetGoogleAdidHandler; private static Action<string> _onGetGoogleAdidHandler;
private static string _googleAdId = ""; private static string _googleAdId = "";
@ -60,7 +60,7 @@ namespace Guru
/// <param name="onDeeplinkCallback"></param> /// <param name="onDeeplinkCallback"></param>
/// <param name="onGetGoogleAdIdCallback"></param> /// <param name="onGetGoogleAdIdCallback"></param>
public static void StartService(string appToken, string fbAppId = "", string firebaseId = "", string deviceId = "", public static void StartService(string appToken, string fbAppId = "", string firebaseId = "", string deviceId = "",
Action<string> onInitComplete = null, Action<string> onDeeplinkCallback = null, Action<string> onGetGoogleAdIdCallback = null) Action<string, string, string> onInitComplete = null, Action<string> onDeeplinkCallback = null, Action<string> onGetGoogleAdIdCallback = null)
{ {
if (string.IsNullOrEmpty(appToken)) if (string.IsNullOrEmpty(appToken))
{ {
@ -79,6 +79,7 @@ namespace Guru
config.setDelayStart(DelayTime); config.setDelayStart(DelayTime);
config.setPreinstallTrackingEnabled(true); // Adjust Preinstall config.setPreinstallTrackingEnabled(true); // Adjust Preinstall
config.setSessionSuccessDelegate(OnSessionSuccessCallback); // SessionSuccess config.setSessionSuccessDelegate(OnSessionSuccessCallback); // SessionSuccess
config.setSessionFailureDelegate(OnSessionFailureCallback); // SessionFailed
if(onDeeplinkCallback != null) if(onDeeplinkCallback != null)
config.setDeferredDeeplinkDelegate(onDeeplinkCallback); config.setDeferredDeeplinkDelegate(onDeeplinkCallback);
@ -91,7 +92,6 @@ namespace Guru
config.setLogDelegate(log => LogI(LOG_TAG, log)); config.setLogDelegate(log => LogI(LOG_TAG, log));
config.setEventSuccessDelegate(OnEventSuccessCallback); config.setEventSuccessDelegate(OnEventSuccessCallback);
config.setEventFailureDelegate(OnEventFailureCallback); config.setEventFailureDelegate(OnEventFailureCallback);
config.setSessionFailureDelegate(OnSessionFailureCallback);
config.setAttributionChangedDelegate(OnAttributionChangedCallback); config.setAttributionChangedDelegate(OnAttributionChangedCallback);
#endif #endif
// 检查场景实例 // 检查场景实例
@ -182,7 +182,7 @@ namespace Guru
var adid = sessionSuccessData.Adid; var adid = sessionSuccessData.Adid;
_adjustId = adid; _adjustId = adid;
_isReady = true; _isReady = true;
_onInitComplete?.Invoke(adid); _onInitComplete?.Invoke(adid, Adjust.getIdfv(), Adjust.getIdfa());
} }
@ -305,7 +305,7 @@ namespace Guru
private static void OnSessionFailureCallback(AdjustSessionFailure sessionFailureData) private static void OnSessionFailureCallback(AdjustSessionFailure sessionFailureData)
{ {
LogI(LOG_TAG,"Session tracking failed!"); LogE(LOG_TAG,"Session tracking failed!");
if (sessionFailureData.Message != null) if (sessionFailureData.Message != null)
{ {

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 8009d3bf70bb4438599a32f6ea601f9d guid: b4c3c75418e9c43c0a14510620fadda4
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -1,8 +1,9 @@
// ============================================== // ==============================================
// U3DConsent.mm // U3DAnalytics 1.12.0
// UnityFramework // 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. // Copyright © 2022 guru. All rights reserved.
// ============================================== // ==============================================
@ -26,7 +27,7 @@ static GuruAnalytics *_analytics;
@implementation U3DAnalytics @implementation U3DAnalytics
// Const value define // Const value define
NSString * const Version = @"1.9.0"; NSString * const Version = @"1.12.0";
static const double kUploadPeriodInSecond = 60.0; static const double kUploadPeriodInSecond = 60.0;
static const int kBatchLimit = 15; static const int kBatchLimit = 15;
@ -89,6 +90,7 @@ NSString * const TchError = @"tch_error";
[GuruAnalytics registerInternalEventObserverWithReportCallback:^(NSInteger code, NSString * info){ [GuruAnalytics registerInternalEventObserverWithReportCallback:^(NSInteger code, NSString * info){
[U3DAnalytics onEventCallback:code andInfo:info]; [U3DAnalytics onEventCallback:code andInfo:info];
}]; }];
} }
} }
@ -241,7 +243,6 @@ NSString * const TchError = @"tch_error";
//--------------------------- //---------------------------
@end @end
//============================ UNITY PUBLIC API ============================ //============================ UNITY PUBLIC API ============================
@ -249,7 +250,7 @@ NSString * const TchError = @"tch_error";
extern "C" { extern "C" {
// 请求GDPR // 请求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"); // NSLog(@"--- [iOS] init Analytics libs");
[GuruAnalytics initializeLibWithUploadPeriodInSecond:kUploadPeriodInSecond [GuruAnalytics initializeLibWithUploadPeriodInSecond:kUploadPeriodInSecond
@ -297,6 +298,11 @@ extern "C" {
[GuruAnalytics setDeviceId:[U3DAnalytics charToString:did]]; [GuruAnalytics setDeviceId:[U3DAnalytics charToString:did]];
} }
// 设置 EndHostUrl
void unitySetEndPointWithHost(const char *host){
[GuruAnalytics setEventsUploadEndPointWithHost:[U3DAnalytics charToString:host]];
}
// 设置用户属性 // 设置用户属性
void unitySetUserProperty(const char *key, const char *value){ void unitySetUserProperty(const char *key, const char *value){
[GuruAnalytics setUserProperty:[U3DAnalytics charToString:value] [GuruAnalytics setUserProperty:[U3DAnalytics charToString:value]

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 621002eb5acb547ec95af0d804cfb17f guid: 504c48c6ad50247199d9301760f9c1a5
PluginImporter: PluginImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -29,7 +29,6 @@ GuruAnalyticsLib 的 Unity 插件库
- Pod 库改为 本地文件引用 (配合外部发行项目) - Pod 库改为 本地文件引用 (配合外部发行项目)
### 1.11.0 ### 1.11.0
- Android 端对齐 `1.0.3` - Android 端对齐 `1.0.3`
> Hash: 1978686dbcba38b7b0421d8b6b2bef111356366b > Hash: 1978686dbcba38b7b0421d8b6b2bef111356366b

View File

@ -224,7 +224,7 @@ namespace Guru
} }
public void SetAndroidID(string androidId) public void SetAndroidId(string androidId)
{ {
if (!_isReady) return; if (!_isReady) return;
if (string.IsNullOrEmpty(androidId)) return; if (string.IsNullOrEmpty(androidId)) return;

View File

@ -98,30 +98,29 @@ namespace Guru
{ {
_isDebug = isDebug; _isDebug = isDebug;
string bundleId = Application.identifier; string bundleId = Application.identifier;
CallSDKInit(appId, deviceInfo, bundleId, baseUrl, uploadIpAddress , true, false, _isDebug); // 调用接口 CallSDKInit(appId, deviceInfo, bundleId, _isDebug, baseUrl, uploadIpAddress , true, false); // 调用接口
onInitComplete?.Invoke(); onInitComplete?.Invoke();
} }
/********* Android API ********** /********* Android API **********
public static void init(String appId, public static void init(String appId,
String deviceInfo, String deviceInfo,
String bundleId, String bundleId,
boolean debug, boolean debug,
boolean useWorker,
boolean enabledCronet,
String baseUrl, String baseUrl,
List<String> uploadIpAddress) String uploadIpAddressStr,
boolean useWorker,
boolean enabledCronet)
*/ */
private void CallSDKInit(string appId, private void CallSDKInit(string appId,
string deviceInfo, string deviceInfo,
string bundleId, string bundleId,
bool isDebug = false,
string baseUrl = "", string baseUrl = "",
string[] uploadIpAddress = null, string[] uploadIpAddress = null,
bool useWorker = true, bool useWorker = true,
bool useCronet = false, bool useCronet = false)
bool isDebug = false)
{ {
CallStatic("init", appId, deviceInfo, bundleId, isDebug, useWorker, useCronet, baseUrl, string.Join(",", uploadIpAddress ?? Array.Empty<string>())); // 调用接口 CallStatic("init", appId, deviceInfo, bundleId, isDebug, useWorker, useCronet, baseUrl, string.Join(",", uploadIpAddress ?? Array.Empty<string>())); // 调用接口
} }

View File

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace Guru namespace Guru
{ {
public enum ELevelResult public enum ELevelResult
@ -12,7 +14,7 @@ namespace Guru
//打点常量定义 //打点常量定义
public static partial class Analytics public static partial class Analytics
{ {
public const string TAG = "Analytics"; public const string TAG = "[GA]";
// 美元符号 // 美元符号
public const string USD = "USD"; public const string USD = "USD";
// 广告平台 // 广告平台
@ -113,20 +115,41 @@ namespace Guru
public const string PropertyLastPlayedLevel = "last_played_level"; public const string PropertyLastPlayedLevel = "last_played_level";
public const string PropertyGrade = "grade"; //当游戏玩家角色升级时触发 public const string PropertyGrade = "grade"; //当游戏玩家角色升级时触发
public const string PropertyIsIAPUser = "is_iap_user"; //付费成功后设置属性参数为true如果没有发生付费可以不用设置该属性 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 PropertyIAPCoin = "iap_coin"; //付费所得的总金币数(iap获取累计值)\
public const string PropertyNonIAPCoin = "noniap_coin"; //非付费iap获取累计值 public const string PropertyNonIAPCoin = "noniap_coin"; //非付费iap获取累计值
public const string PropertyCoin = "coin"; //当前金币数 public const string PropertyCoin = "coin"; //当前金币数
public const string PropertyExp = "exp"; // 经验值 public const string PropertyExp = "exp"; // 经验值
public const string PropertyHp = "hp"; // 生命值/体力 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 PropertyIDFV = "idfv"; // iOS 平台 IDFV
public const string PropertyIDFA = "idfa"; // iOS 平台 IDFA public const string PropertyIDFA = "idfa"; // iOS 平台 IDFA
public const string PropertyPicture = "picture"; // 玩家在主线的mapid public const string PropertyPicture = "picture"; // 玩家在主线的mapid
public const string PropertyNoAds = "no_ads"; // 玩家是否去广告 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 PropertyGDPR = "gdpr"; // GDPR状态
public const string PropertySignUpMethod = "sign_up_method"; // 用户登录方式 public const string PropertySignUpMethod = "sign_up_method"; // 用户登录方式
public const string PropertyFirebaseId = "firebase_id"; // FirebaseID
public const string PropertyGoogleAdId = "ad_id"; // FirebaseID
public static HashSet<string> PredefinedMidWareProperties = new HashSet<string>()
{
PropertyFirstOpenTime,
PropertyDeviceID,
PropertyUserID,
PropertyIsIAPUser,
PropertyNetwork,
PropertyAdjustId,
PropertyAndroidId,
PropertyIDFV,
PropertyIDFA,
PropertyAttStatus,
PropertyNotiPerm,
PropertyFirebaseId,
PropertyGoogleAdId,
};
// 经济相关 // 经济相关
public const string ParameterBalance = "balance"; // 用于余额 public const string ParameterBalance = "balance"; // 用于余额

View File

@ -1,24 +1,16 @@
namespace Guru namespace Guru
{ {
using System; using System;
using Firebase.Analytics;
using Firebase.Crashlytics; using Firebase.Crashlytics;
using Firebase.Extensions;
using UnityEngine; using UnityEngine;
/// <summary> /// <summary>
/// 自打点逻辑 /// 自打点逻辑
/// </summary> /// </summary>
public partial class Analytics 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 DateTime _lastReportRateDate; //上次上报信息的日期
private static double _reportSuccessInterval; // 上报频率 private static double _reportSuccessInterval; // 上报频率
#if UNITY_IOS #if UNITY_IOS
@ -37,12 +29,7 @@ namespace Guru
{ {
string appId = IPMConfig.IPM_X_APP_ID; string appId = IPMConfig.IPM_X_APP_ID;
string deviceInfo = new DeviceInfoData().ToString(); string deviceInfo = new DeviceInfoData().ToString();
_hasSetFirebaseId = false;
_hasSetAdId = false;
_hasSetAdjustId = false;
_hasSetDeviceId = false;
_hasSetUid = false;
_lastReportRateDate = DateTime.Now; _lastReportRateDate = DateTime.Now;
_reportSuccessInterval = 120; // 2分钟上报一次 _reportSuccessInterval = 120; // 2分钟上报一次
@ -53,7 +40,7 @@ namespace Guru
OnGuruAnalyticsInitComplete(); OnGuruAnalyticsInitComplete();
Debug.Log($"{TAG} [guru_analytic]--- Guru EXP: GroupId: {GuruAnalytics.Instance.ExperimentGroupId}"); Debug.Log($"{TAG} [guru_analytic]--- Guru EXP: GroupId: {GuruAnalytics.Instance.ExperimentGroupId}");
SetUserProperty(GuruAnalyticsConfigManager.KEY_GURU_ANALYTICS_EXP, GuruAnalytics.Instance.ExperimentGroupId); SetUserProperty(GuruAnalyticsConfigManager.KEY_GURU_ANALYTICS_EXP, GuruAnalytics.Instance.ExperimentGroupId);
ApplyAllUserProperties(); ApplyAllMidWareProperties();
}, IsDebug, firebaseId); // Android 初始化 }, IsDebug, firebaseId); // Android 初始化
} }
@ -62,193 +49,6 @@ namespace Guru
LogCrashlytics(ex); LogCrashlytics(ex);
} }
} }
#region 各ID上报信息
/// <summary>
/// 设置用户ID
/// </summary>
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;
}
/// <summary>
/// 设置设备ID
/// </summary>
private static void SetDeviceId(string deviceId)
{
if (_hasSetDeviceId) return;
if (string.IsNullOrEmpty(deviceId)) return;
if (!GuruAnalytics.IsReady) return;
GuruAnalytics.Instance.SetDeviceId(deviceId);
_hasSetDeviceId = true;
}
/// <summary>
/// 设置 AdjustId
/// </summary>
private static void SetAdjustId(string adjustId)
{
if (_hasSetAdjustId) return;
if (string.IsNullOrEmpty(adjustId)) return;
if (!GuruAnalytics.IsReady) return;
GuruAnalytics.Instance.SetAdjustId(adjustId);
_hasSetAdjustId = true;
}
/// <summary>
/// 设置 AdId
/// </summary>
private static void SetAdId(string adId)
{
if (_hasSetAdId) return;
if (string.IsNullOrEmpty(adId)) return;
if (!GuruAnalytics.IsReady) return;
GuruAnalytics.Instance.SetAdId(adId);
_hasSetAdId = true;
}
/// <summary>
/// 设置FirebaseId
/// </summary>
private static void SetFirebaseId(string firebaseId)
{
if (_hasSetFirebaseId) return;
if (string.IsNullOrEmpty(firebaseId)) return;
if (!GuruAnalytics.IsReady) return;
GuruAnalytics.Instance.SetFirebaseId(firebaseId);
_hasSetFirebaseId = true;
}
/// <summary>
/// 获取FirebaseID
/// </summary>
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
/// <summary>
/// 更新ATT状态 (Only IOS 有效)
/// </summary>
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
/// <summary>
/// 更新 Android ID 的参数
/// </summary>
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
/// <summary>
/// 上报中台打点的用户属性
/// </summary>
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();
}
/// <summary>
/// 上报事件成功率
/// </summary>
private static void ReportEventSuccessRate()
{
var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds;
if (interval > _reportSuccessInterval)
{
GuruAnalytics.Instance.ReportEventSuccessRate();
_lastReportRateDate = DateTime.Now;
}
}
#endregion
#region 设置太极02 值 #region 设置太极02 值

View File

@ -1,11 +1,21 @@
namespace Guru namespace Guru
{ {
using System;
using UnityEngine; using UnityEngine;
using Firebase.Analytics;
using System.Collections.Generic;
/// <summary>
/// 上报用户属性逻辑
/// 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
/// </summary>
public static partial class Analytics public static partial class Analytics
{ {
#region Old Properties
/// <summary> /// <summary>
/// B_Level 属性 /// B_Level 属性
/// </summary> /// </summary>
@ -38,5 +48,543 @@ namespace Guru
return stamp; return stamp;
} }
} }
#endregion
#region Update all neccessary properties
//---------------- 设置所有必要的属性 ---------------------
/// <summary>
/// 应用所有的中台属性
/// </summary>
private static void ApplyAllMidWareProperties()
{
MidWarePropertiesManager.Instance.ApplyAllProperties();
}
/// <summary>
/// 设置用户ID
/// </summary>
public static void SetUid(string uid)
{
MidWarePropertiesManager.Instance.ReportUid(uid);
}
/// <summary>
/// 设置设备ID
/// (Firebase, Guru)
/// </summary>
private static void SetDeviceId(string deviceId)
{
MidWarePropertiesManager.Instance.ReportDeviceId(deviceId);
}
/// <summary>
/// 设置首次启动时间
/// </summary>
/// <param name="firstOpenTime"></param>
private static void SetFirstOpenTime(string firstOpenTime)
{
MidWarePropertiesManager.Instance.ReportFirstOpenTime(firstOpenTime);
}
/// <summary>
/// 设置 IsIapUser
/// (Firebase, Guru)
/// </summary>
public static void SetIsIapUser(bool isIapUser)
{
MidWarePropertiesManager.Instance.ReportIsIapUser(isIapUser);
}
/// <summary>
/// 设置 Network
/// (Firebase, Guru)
/// </summary>
public static void SetNetworkStatus(string networkStatus)
{
MidWarePropertiesManager.Instance.ReportNetworkStatus(networkStatus);
}
/// <summary>
/// 设置 AdjustId
/// (Firebase)
/// </summary>
public static void SetAdjustId(string adjustId)
{
MidWarePropertiesManager.Instance.ReportAdjustId(adjustId);
}
/// <summary>
/// 设置 AndroidId
/// (Firebase)
/// </summary>
public static void SetAndroidId(string androidId)
{
MidWarePropertiesManager.Instance.ReportAndroidId(androidId);
}
/// <summary>
/// 设置 AttStatus
/// (Firebase)
/// </summary>
public static void SetAttStatus(string attStatus)
{
MidWarePropertiesManager.Instance.ReportAttStatus(attStatus);
}
/// <summary>
/// 设置 AttStatus
/// (Firebase)
/// </summary>
public static void SetNotiPerm(string notiPrem)
{
MidWarePropertiesManager.Instance.ReportNotiPerm(notiPrem);
}
/// <summary>
/// 设置 AdId
/// </summary>
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 中台属性管理
/// <summary>
/// 中台必要用户属性对象
/// </summary>
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();
}
}
}
/// <summary>
/// UID
/// </summary>
private class MidWarePropertyUid : AbstractMidWareProperty
{
public MidWarePropertyUid(string value)
: base(PropertyUserID, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
_firebaseEventDriver.SetUid(value);
_guruEventDriver.SetUid(value);
}
}
/// <summary>
/// DeviceId
/// </summary>
private class MidWarePropertyDeviceId : AbstractMidWareProperty
{
public MidWarePropertyDeviceId(string value)
: base(PropertyDeviceID, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
_guruEventDriver.SetDeviceId(value);
}
}
/// <summary>
/// FirstOpenTime
/// </summary>
private class MidWarePropertyFirstOpenTime : AbstractMidWareProperty
{
public MidWarePropertyFirstOpenTime(string value)
: base(PropertyFirstOpenTime, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
}
}
/// <summary>
/// IsIapUser
/// </summary>
private class MidWarePropertyIsIapUser : AbstractMidWareProperty
{
public MidWarePropertyIsIapUser(bool value)
: base(PropertyIsIAPUser, value?"true":"false", ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty() { }
}
/// <summary>
/// Network
/// </summary>
private class MidWarePropertyNetwork : AbstractMidWareProperty
{
public MidWarePropertyNetwork(string value)
: base(PropertyNetwork, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty() { }
}
/// <summary>
/// AdjustId
/// </summary>
private class MidWarePropertyAdjustId : AbstractMidWareProperty
{
public MidWarePropertyAdjustId(string value)
: base(PropertyAdjustId, value, ReportPropertyTarget.Firebase)
{
}
protected override void BeforeReportProperty()
{
_guruEventDriver.SetAdjustId(value);
}
}
/// <summary>
/// AttStatus
/// </summary>
private class MidWarePropertyAttStatus : AbstractMidWareProperty
{
public MidWarePropertyAttStatus(string value)
: base(PropertyAttStatus, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
}
}
/// <summary>
/// AttStatus
/// </summary>
private class MidWarePropertyNotiPerm : AbstractMidWareProperty
{
public MidWarePropertyNotiPerm(string value)
: base(PropertyNotiPerm, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
}
}
/// <summary>
/// AndroidId
/// </summary>
private class MidWarePropertyAndroidId : AbstractMidWareProperty
{
public MidWarePropertyAndroidId(string value)
: base(PropertyAndroidId, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
_guruEventDriver.SetAndroidId(value);
}
}
/// <summary>
/// FirebaseId
/// </summary>
private class MidWarePropertyGoogleAdId : AbstractMidWareProperty
{
public MidWarePropertyGoogleAdId(string value)
: base(PropertyGoogleAdId, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
_guruEventDriver.SetGoogleAdId(value);
}
}
/// <summary>
/// IDFV
/// </summary>
private class MidWarePropertyIDFV : AbstractMidWareProperty
{
public MidWarePropertyIDFV(string value)
: base(PropertyIDFV, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
_guruEventDriver.SetIDFV(value);
}
}
/// <summary>
/// IDFV
/// </summary>
private class MidWarePropertyIDFA : AbstractMidWareProperty
{
public MidWarePropertyIDFA(string value)
: base(PropertyIDFA, value, ReportPropertyTarget.Both)
{
}
protected override void BeforeReportProperty()
{
_guruEventDriver.SetIDFA(value);
}
}
/// <summary>
/// 必要属性上报配置
/// </summary>
internal enum ReportPropertyTarget
{
Firebase = 1,
Guru = 2,
Both = 3,
}
/// <summary>
/// 全部属性集合
/// </summary>
internal class MidWarePropertiesManager
{
private static MidWarePropertiesManager _instance;
public static MidWarePropertiesManager Instance
{
get
{
if (_instance == null) _instance = new MidWarePropertiesManager();
return _instance;
}
}
private readonly Dictionary<string, AbstractMidWareProperty> _propertyMap = new Dictionary<string, AbstractMidWareProperty>(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();
}
/// <summary>
/// 应用所有中台打点的用户属性
/// </summary>
public void ApplyAllProperties()
{
// 应用所有用户属性
Debug.Log($"{TAG} --- UpdateAllValues ---");
foreach (var prop in _propertyMap.Values)
{
prop.Report();
}
ReportEventSuccessRate();
}
/// <summary>
/// 上报事件成功率
/// </summary>
private static void ReportEventSuccessRate()
{
var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds;
if (interval > _reportSuccessInterval)
{
GuruAnalytics.Instance.ReportEventSuccessRate();
_lastReportRateDate = DateTime.Now;
}
}
}
#endregion
} }
} }

View File

@ -47,6 +47,7 @@ namespace Guru
private static bool IsDebug => PlatformUtil.IsDebug(); private static bool IsDebug => PlatformUtil.IsDebug();
private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized; private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized;
private static bool IsGuruAnalyticsReady => GuruAnalytics.IsReady;
private static AdjustEventDriver _adjustEventDriver; private static AdjustEventDriver _adjustEventDriver;
private static FBEventDriver _fbEventDriver; private static FBEventDriver _fbEventDriver;
@ -68,6 +69,9 @@ namespace Guru
_fbEventDriver = new FBEventDriver(); _fbEventDriver = new FBEventDriver();
_firebaseEventDriver = new FirebaseEventDriver(); _firebaseEventDriver = new FirebaseEventDriver();
_guruEventDriver = new GuruEventDriver(); _guruEventDriver = new GuruEventDriver();
SetDeviceId(IPMConfig.IPM_DEVICE_ID);
SetFirstOpenTime(IPMConfig.FIRST_OPEN_TIME);
} }
/// <summary> /// <summary>
@ -100,9 +104,19 @@ namespace Guru
_adjustEventDriver.TriggerFlush(); _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); _guruEventDriver.AddProperty(key, value);
_firebaseEventDriver.AddProperty(key, value); _firebaseEventDriver.AddProperty(key, value);
// 更新所有必要的用户属性 // 更新所有必要的用户属性
ApplyAllUserProperties(); ApplyAllMidWareProperties();
Debug.Log($"{TAG} --- SetUserProperty -> propertyName:{key}, propertyValue:{value}"); Debug.Log($"{TAG} --- SetUserProperty -> propertyName:{key}, propertyValue:{value}");
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,3 +1,7 @@
using System;
using System.Collections;
using UnityEngine;
namespace Guru namespace Guru
{ {
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -13,15 +17,47 @@ namespace Guru
void AddProperty(string key, string value); void AddProperty(string key, string value);
} }
internal class MidWarePropertyDelayedAction
{
internal readonly string key;
private readonly string value;
private readonly Action<string> reportAction;
internal MidWarePropertyDelayedAction(string key, string value, Action<string> 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 public abstract class AbstractEventDriver: IEventDriver, IPropertyCollector
{ {
private readonly GuruEventBuffer<TrackingEvent> _eventBuffer = new GuruEventBuffer<TrackingEvent>(); private readonly GuruEventBuffer<TrackingEvent> _eventBuffer = new GuruEventBuffer<TrackingEvent>();
private readonly ConcurrentDictionary<string, string> _userPropertyMap = new ConcurrentDictionary<string, string>(); private readonly ConcurrentDictionary<string, string> _userPropertyMap = new ConcurrentDictionary<string, string>();
private readonly HashSet<MidWarePropertyDelayedAction> _predefinedPropertyDelayedActions = new HashSet<MidWarePropertyDelayedAction>();
// Firebase 是否可用 // Firebase 是否可用
private bool _isDriverReady; private bool _isDriverReady;
public bool IsReady => _isDriverReady;
public void TriggerFlush() public void TriggerFlush()
{ {
@ -79,17 +115,26 @@ namespace Guru
{ {
while(_eventBuffer.Pop(out var trackingEvent)) while(_eventBuffer.Pop(out var trackingEvent))
{ {
Debug.Log($"[ANU] --- GuruAnalytics: FlushAll Events: {trackingEvent.eventName}");
FlushTrackingEvent(trackingEvent); FlushTrackingEvent(trackingEvent);
} }
foreach (var key in _userPropertyMap.Keys) foreach (var key in _userPropertyMap.Keys)
{ {
Debug.Log($"[ANU] --- GuruAnalytics: FlushAll Properties: {key}:{ _userPropertyMap[key]}");
SetUserProperty(key, _userPropertyMap[key]); SetUserProperty(key, _userPropertyMap[key]);
} }
_userPropertyMap.Clear(); _userPropertyMap.Clear();
foreach (var propertyAction in _predefinedPropertyDelayedActions)
{
Debug.Log($"[ANU] --- GuruAnalytics: FlushAll predefined Properties: {propertyAction.key}:{ propertyAction}");
propertyAction.Execute();
}
_predefinedPropertyDelayedActions.Clear();
} }
/// <summary> /// <summary>
/// 发送事件 /// 发送事件
/// </summary> /// </summary>
@ -98,7 +143,151 @@ namespace Guru
protected abstract void SetUserProperty(string key, string value); protected abstract void SetUserProperty(string key, string value);
/// <summary>
/// 设置用户ID
/// </summary>
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));
}
}
/// <summary>
/// 设置 AdjustId
/// (Firebase)
/// </summary>
public void SetAdjustId(string adjustId)
{
if (_isDriverReady)
{
ReportAdjustId(adjustId);
}
else
{
_predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyAdjustId, adjustId, ReportAdjustId));
}
}
/// <summary>
/// 设置 AdId
/// </summary>
public void SetGoogleAdId(string googleAdId)
{
if (_isDriverReady)
{
ReportGoogleAdId(googleAdId);
}
else
{
_predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyGoogleAdId, googleAdId, ReportGoogleAdId));
}
}
/// <summary>
/// 设置 AndroidId
/// </summary>
/// <param name="androidId"></param>
public void SetAndroidId(string androidId)
{
if (_isDriverReady)
{
ReportAndroidId(androidId);
}
else
{
_predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyAndroidId, androidId, ReportAndroidId));
}
}
/// <summary>
/// 设置 IDFV
/// </summary>
public void SetIDFV(string idfv)
{
if (_isDriverReady)
{
ReportIDFV(idfv);
}
else
{
_predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyIDFV, idfv, ReportIDFV));
}
}
/// <summary>
/// 设置 IDFA
/// </summary>
public void SetIDFA(string idfa)
{
if (_isDriverReady)
{
ReportIDFA(idfa);
}
else
{
_predefinedPropertyDelayedActions.Add(new MidWarePropertyDelayedAction(Analytics.PropertyIDFA, idfa, ReportIDFA));
}
}
/// <summary>
/// 设置用户ID
/// (Firebase, Guru)
/// </summary>
protected abstract void ReportUid(string uid);
/// <summary>
/// 设置设备ID
/// (Firebase, Guru)
/// </summary>
protected abstract void ReportDeviceId(string deviceId);
/// <summary>
/// 设置 AdjustId
/// (Firebase)
/// </summary>
protected abstract void ReportAdjustId(string adjustId);
/// <summary>
/// 设置 googleAdId
/// </summary>
protected abstract void ReportGoogleAdId(string googleAdId);
/// <summary>
/// 设置 AndroidId
/// </summary>
protected abstract void ReportAndroidId(string androidId);
/// <summary>
/// 设置 IDFV
/// </summary>
protected abstract void ReportIDFV(string idfv);
/// <summary>
/// 设置 IDFA
/// </summary>
protected abstract void ReportIDFA(string idfa);
} }

View File

@ -31,5 +31,53 @@ namespace Guru
{ {
} }
//---------------- 单独实现所有的独立属性打点 ------------------
/// <summary>
/// 设置用户ID
/// </summary>
protected override void ReportUid(string uid)
{
}
protected override void ReportDeviceId(string deviceId)
{
}
/// <summary>
/// 设置 AdjustId
/// (Firebase)
/// </summary>
protected override void ReportAdjustId(string adjustId)
{
}
/// <summary>
/// 设置 AdId
/// </summary>
protected override void ReportGoogleAdId(string adId)
{
}
protected override void ReportAndroidId(string androidId)
{
}
/// <summary>
/// 设置 IDFV
/// </summary>
protected override void ReportIDFV(string idfv)
{
}
/// <summary>
/// 设置 IDFA
/// </summary>
protected override void ReportIDFA(string idfa)
{
}
} }
} }

View File

@ -1,8 +1,9 @@
using System;
using UnityEngine;
namespace Guru namespace Guru
{ {
using UnityEngine;
public class FBEventDriver: AbstractEventDriver public class FBEventDriver: AbstractEventDriver
{ {
/// <summary> /// <summary>
@ -22,5 +23,57 @@ namespace Guru
{ {
} }
//---------------- 单独实现所有的独立属性打点 ------------------
/// <summary>
/// 设置用户ID
/// </summary>
protected override void ReportUid(string uid)
{
}
protected override void ReportDeviceId(string deviceId)
{
}
/// <summary>
/// 设置 AdjustId
/// (Firebase)
/// </summary>
protected override void ReportAdjustId(string adjustId)
{
}
/// <summary>
/// 设置 AdId
/// </summary>
protected override void ReportGoogleAdId(string adId)
{
}
protected override void ReportAndroidId(string adId)
{
}
/// <summary>
/// 设置 IDFV
/// </summary>
protected override void ReportIDFV(string idfv)
{
}
/// <summary>
/// 设置 IDFA
/// </summary>
protected override void ReportIDFA(string idfa)
{
}
} }
} }

View File

@ -59,5 +59,33 @@ namespace Guru
FirebaseAnalytics.SetUserProperty(key, value); 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)
{
}
} }
} }

View File

@ -1,5 +1,7 @@
namespace Guru namespace Guru
{ {
public class GuruEventDriver: AbstractEventDriver public class GuruEventDriver: AbstractEventDriver
{ {
protected override void FlushTrackingEvent(TrackingEvent trackingEvent) protected override void FlushTrackingEvent(TrackingEvent trackingEvent)
@ -16,6 +18,62 @@ namespace Guru
// ReSharper disable once Unity.PerformanceCriticalCodeInvocation // ReSharper disable once Unity.PerformanceCriticalCodeInvocation
GuruAnalytics.Instance.SetUserProperty(key, value); GuruAnalytics.Instance.SetUserProperty(key, value);
} }
//---------------- 单独实现所有的独立属性打点 ------------------
/// <summary>
/// 设置用户ID
/// </summary>
protected override void ReportUid(string uid)
{
GuruAnalytics.Instance.SetUid(uid);
}
/// <summary>
/// 设置设备ID
/// (Firebase, Guru)
/// </summary>
protected override void ReportDeviceId(string deviceId)
{
GuruAnalytics.Instance.SetDeviceId(deviceId);
}
/// <summary>
/// 设置 AdjustId
/// (Firebase)
/// </summary>
protected override void ReportAdjustId(string adjustId)
{
GuruAnalytics.Instance.SetAdjustId(adjustId);
}
protected override void ReportAndroidId(string androidId)
{
GuruAnalytics.Instance.SetAndroidId(androidId);
}
/// <summary>
/// 设置 AdId
/// </summary>
protected override void ReportGoogleAdId(string adId)
{
GuruAnalytics.Instance.SetAdId(adId);
}
/// <summary>
/// 设置 IDFV
/// </summary>
protected override void ReportIDFV(string idfv)
{
GuruAnalytics.Instance.SetIDFV(idfv);
}
/// <summary>
/// 设置 IDFA
/// </summary>
protected override void ReportIDFA(string idfa)
{
GuruAnalytics.Instance.SetIDFA(idfa);
}
} }
} }

View File

@ -261,12 +261,20 @@ namespace Guru
get => PlayerPrefs.GetString(nameof(ADJUST_GOOGLE_ADID), ""); get => PlayerPrefs.GetString(nameof(ADJUST_GOOGLE_ADID), "");
set => PlayerPrefs.SetString(nameof(ADJUST_GOOGLE_ADID), value); set => PlayerPrefs.SetString(nameof(ADJUST_GOOGLE_ADID), value);
} }
public static string FIRST_OPEN_TIME
public static string FirstOpenTime
{ {
get => PlayerPrefs.GetString(nameof(FirstOpenTime), ""); get
set => PlayerPrefs.SetString(nameof(FirstOpenTime), value); {
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);
} }
} }
} }