Compare commits

...

25 Commits
main ... dev

Author SHA1 Message Date
胡宇飞 7e499aa26c update: 针对 2021.3.41 优化打包管线和配置
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-30 15:54:22 +08:00
胡宇飞 a67185679b update: 重构 AdImpressionData 用于记录相关的数据
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-30 15:45:48 +08:00
胡宇飞 23eb7ff7b4 update: 删除 x86_64 的目标
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-29 22:15:01 +08:00
胡宇飞 6d3e94cf2f fix: 完善 Android项目自动修改 Unity Project 路径
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-29 21:05:13 +08:00
胡宇飞 6b02f619ce fix: 修复 Guru.AdStatusPresenter.CreateMonitorInfo 报空的问题
NullReferenceException: Object reference not set to an instance of an object. Guru.AdStatusPresenter.CreateMonitorInfo
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-29 20:03:00 +08:00
胡宇飞 11002aaccd update: 更新 SKADNetwork 文件 (2024/6/27)
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-29 19:16:50 +08:00
胡宇飞 88d29fe2f2 update: 暂时移除 UserProguard 修复器
--story=1020956 --user=yufei.hu 【中台】【Android】构建插件 API 升级 34 验证 https://www.tapd.cn/33527076/s/1160300

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-29 19:06:12 +08:00
胡宇飞 15aa840061 update: 更新构建参数赋值
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-29 12:19:53 +08:00
胡宇飞 3b5a242f9f update: 更新构建 Android 版本的 API -> 34
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-29 11:48:07 +08:00
胡宇飞 561d351b73 fix: 优化网络状态打点
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 19:17:37 +08:00
胡宇飞 d1dba297a7 fix: 修复用户属性缓存问题
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 19:17:03 +08:00
胡宇飞 67abd081c8 update: 更新 Connectivity iOS 原生库为正式版本, 补全 meta 文件
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 15:07:48 +08:00
胡宇飞 400498af17 update:新增打点需求 review_creative_id 和 ad_placement
--story=1020787 --user=yufei.hu 【中台】【广告】新增打点需求 review_creative_id 和 ad_placement https://www.tapd.cn/33527076/s/1159788

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 14:39:32 +08:00
胡宇飞 50c5627ac2 fix: 修复 Notification 授权在 iOS 上自动触发的 BUG。
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 11:53:26 +08:00
胡宇飞 ef547caba9 fix: 优化 NetworkStatus代码
--story=1021014 --user=yufei.hu 【中台】【SDK】用户属性上报添加 Network 属性 https://www.tapd.cn/33527076/s/1159774

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 11:40:43 +08:00
胡宇飞 345b4ac971 update: 用户属性上报添加 Network 属性
--story=1021014 --user=yufei.hu 【中台】【SDK】用户属性上报添加 Network 属性 https://www.tapd.cn/33527076/s/1159710

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 11:08:18 +08:00
胡宇飞 ff5f2df4c4 update: 添加 Debug 模式打点保护
--story=1021118 --user=yufei.hu 【中台】【打点】打点初始化重构,添加日志缓存功能 https://www.tapd.cn/33527076/s/1159705

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-26 09:21:48 +08:00
胡宇飞 85c8058158 update: 打点初始化重构,添加日志缓存功能
--story=1021118 --user=yufei.hu 【中台】【打点】打点初始化重构,添加日志缓存功能 https://www.tapd.cn/33527076/s/1159704

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-25 22:59:47 +08:00
胡宇飞 6d5bc2c3a4 update: 优化Adjust 启动逻辑和点位赋值
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-25 12:39:38 +08:00
胡宇飞 edf6214cea update: 修复deeplink 合并冲突的问题
Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-25 11:49:32 +08:00
胡宇飞 c88de190a1 Merge branch 'deeplink' into dev
Signed-off-by: huyufei <yufei.hu@castbox.fm>

# Conflicts:
#	Runtime/GuruAdjust/AdjustService.cs
#	Runtime/GuruCore/Runtime/Firebase/FirebaseUtil.cs
2024-07-25 11:22:39 +08:00
胡宇飞 dc991efbf3 update: 打点事件优化, 优化打点缓存逻辑和初始化行为
--story=1021114 --user=yufei.hu 【中台】打点逻辑优化:初始化流程, 属性缓存 (QA 无需测试) https://www.tapd.cn/33527076/s/1159381

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-25 11:16:22 +08:00
胡宇飞 515c875ee8 修复 RemoteConfig 接口中立即获取线上更新配置不生效的 BUG
--story=1021111 --user=yufei.hu 【中台】【Fix】修复 RemoteConfig 接口中立即获取线上更新配置不生效的 BUG https://www.tapd.cn/33527076/s/1159321

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-25 08:51:49 +08:00
胡宇飞 2aad845378 update: 更新 SDK 版本号, 更新 IAP 插件版本为 4.12.2
--story=1020957 --user=yufei.hu 【中台】【IAP】Google Billing 升级 6.0.1 以上, In-app-purchase 插件升级 https://www.tapd.cn/33527076/s/1158446

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-22 14:06:32 +08:00
胡宇飞 c3b77622d9 update: 更新 Adjust 的 DeepLink 功能
--story=1020917 --user=yufei.hu 【中台】【SDK】新增 Adjust Deeplink 接口 https://www.tapd.cn/33527076/s/1156644

Signed-off-by: huyufei <yufei.hu@castbox.fm>
2024-07-12 10:29:39 +08:00
107 changed files with 3412 additions and 915 deletions

View File

@ -1,3 +1,5 @@
namespace Guru.Editor namespace Guru.Editor
{ {
using System.Linq; using System.Linq;
@ -14,17 +16,21 @@ namespace Guru.Editor
/// </summary> /// </summary>
public partial class AppBuilder public partial class AppBuilder
{ {
public static int AndroidTargetSdkVersion = 33; private const int DefaultAndroidTargetSdkVersion = 34;
public static string IOSTargetOSVersion = "13.0"; private const string IOSTargetOSVersion = "13.0";
public static string GuruIOSTeamId = "39253T242A"; private const string GuruIOSTeamId = "39253T242A";
public static string GuruKeystoreName => "guru_key.jks"; private const string GuruKeystoreName = "guru_key.jks";
public static string GuruKeystorePass => "guru0622"; private const string GuruKeystorePass = "guru0622";
public static string GuruAliasName => "guru"; private const string GuruAliasName = "guru";
public static string GuruAliasPass => "guru0622"; private const string GuruAliasPass = "guru0622";
public static string GuruKeystorePath => Application.dataPath + $"/Plugins/Android/{GuruKeystoreName}";
public static string ProguardName => "proguard-user.txt"; private const string UnityGradlePath_2021_3_41 =
public static string ProguardPath => Application.dataPath + $"/Plugins/Android/{ProguardName}"; "/Applications/Unity/Hub/Editor/2021.3.41f1/PlaybackEngines/AndroidPlayer/Tools/gradle";
public static string OutputDirName => "BuildOutput";
private static string GuruKeystorePath => Application.dataPath + $"/Plugins/Android/{GuruKeystoreName}";
private static string ProguardName => "proguard-user.txt";
private static string ProguardPath => Application.dataPath + $"/Plugins/Android/{ProguardName}";
private static string OutputDirName => "BuildOutput";
#region 构建接口 #region 构建接口
@ -70,11 +76,14 @@ namespace Guru.Editor
SwitchBuildPlatform(BuildTarget.Android); SwitchBuildPlatform(BuildTarget.Android);
// 打包通用设置 // 打包通用设置
ChangeBuildPlayerCommonSetting(buildParam, BuildTargetGroup.Android); ChangeBuildPlayerCommonSetting(buildParam, BuildTargetGroup.Android);
// Set GradlePath
SetGradlePath();
var isDebug = !buildParam.IsBuildRelease; var isDebug = !buildParam.IsBuildRelease;
var useMinify = buildParam.AndroidUseMinify; var useMinify = buildParam.AndroidUseMinify;
var buildNumber= GetBuildNumberString(BuildTarget.Android); var buildNumber= GetBuildNumberString(BuildTarget.Android);
if(buildParam.AutoSetBuildNumber) buildNumber = ChangeBuildNumber(BuildTarget.Android); var androidTargetVersion = buildParam.AndroidTargetVersion == 0 ? DefaultAndroidTargetSdkVersion : buildParam.AndroidTargetVersion;
if (buildParam.AutoSetBuildNumber) buildNumber = ChangeBuildNumber(BuildTarget.Android);
// 保存版本信息 // 保存版本信息
SaveBuildVersion(buildParam.BuildVersion, buildNumber); SaveBuildVersion(buildParam.BuildVersion, buildNumber);
@ -90,7 +99,6 @@ namespace Guru.Editor
PlayerSettings.muteOtherAudioSources = false; PlayerSettings.muteOtherAudioSources = false;
// ---- 开启 Minify 后需要配置 proguard-user.txt 文件 ---- // ---- 开启 Minify 后需要配置 proguard-user.txt 文件 ----
if (useMinify) DeployProguardTxt(); if (useMinify) DeployProguardTxt();
PlayerSettings.Android.minifyWithR8 = useMinify;
PlayerSettings.Android.minifyRelease = useMinify; PlayerSettings.Android.minifyRelease = useMinify;
PlayerSettings.Android.minifyDebug = useMinify; PlayerSettings.Android.minifyDebug = useMinify;
// ---- 部署 Guru 专用的 Keystore ---- // ---- 部署 Guru 专用的 Keystore ----
@ -113,10 +121,9 @@ namespace Guru.Editor
PlayerSettings.Android.keyaliasPass = buildParam.AndroidAliasPass; PlayerSettings.Android.keyaliasPass = buildParam.AndroidAliasPass;
} }
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARMv7 | AndroidArchitecture.ARM64; //只构建 armv7 和 arm64 PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARMv7 | AndroidArchitecture.ARM64; // 构建 armv7, arm64
PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel22; PlayerSettings.Android.minSdkVersion = AndroidSdkVersions.AndroidApiLevel22;
if (buildParam.AndroidTargetVersion > 0) AndroidTargetSdkVersion = buildParam.AndroidTargetVersion; PlayerSettings.Android.targetSdkVersion = (AndroidSdkVersions)androidTargetVersion; // 设置 API Version
PlayerSettings.Android.targetSdkVersion = (AndroidSdkVersions)AndroidTargetSdkVersion; // 默认设置API为33
//打包 //打包
string symbolDefine = buildParam.IsBuildRelease ? GameDefine.MACRO_RELEASE : GameDefine.MACRO_DEBUG; string symbolDefine = buildParam.IsBuildRelease ? GameDefine.MACRO_RELEASE : GameDefine.MACRO_DEBUG;
@ -142,7 +149,18 @@ namespace Guru.Editor
return apkPath; return apkPath;
} }
/// <summary> private static void SetGradlePath()
{
#if UNITY_ANDROID && UNITY_2021_3_41
if (Directory.Exists(UnityGradlePath_2021_3_41))
{
UnityEditor.Android.AndroidExternalToolsSettings.gradlePath = UnityGradlePath_2021_3_41;
}
#endif
}
/// <summary>
/// 部署 Guru 专用的 Keystore /// 部署 Guru 专用的 Keystore
/// </summary> /// </summary>
private static bool DeployAndroidKeystore() private static bool DeployAndroidKeystore()

View File

@ -1,3 +1,6 @@
using System.Collections.Generic;
using NUnit.Framework;
#if UNITY_ANDROID #if UNITY_ANDROID
namespace Guru namespace Guru
{ {
@ -13,7 +16,8 @@ namespace Guru
/// Android混淆器内容填充 /// Android混淆器内容填充
/// 于应用构建前执行 /// 于应用构建前执行
/// </summary> /// </summary>
public class UserProguardHelper: IPreprocessBuildWithReport // public class UserProguardHelper: IPreprocessBuildWithReport
public class UserProguardHelper
{ {
public int callbackOrder { get; } = 0; public int callbackOrder { get; } = 0;
public void OnPreprocessBuild(BuildReport report) public void OnPreprocessBuild(BuildReport report)
@ -27,7 +31,6 @@ namespace Guru
string proguardPath = $"{Application.dataPath}/Plugins/Android/proguard-user.txt"; string proguardPath = $"{Application.dataPath}/Plugins/Android/proguard-user.txt";
if (File.Exists(proguardPath)) if (File.Exists(proguardPath))
{ {
List<string> keeps = new List<string>();
DirectoryInfo dir = new DirectoryInfo(Application.dataPath); DirectoryInfo dir = new DirectoryInfo(Application.dataPath);
string raw = File.ReadAllText(proguardPath); string raw = File.ReadAllText(proguardPath);
@ -42,35 +45,39 @@ namespace Guru
// Debug.Log($"--- Proguard Files: {files.Length}"); // Debug.Log($"--- Proguard Files: {files.Length}");
string[] lens = null; ProguardItemBuilder builder = new ProguardItemBuilder();
string l = "";
var allItems = new List<ProguardItem>(30);
string[] lines = null;
for (int i = 0; i < files.Count; i++) for (int i = 0; i < files.Count; i++)
{ {
lens = File.ReadAllLines(files[i].FullName); lines = File.ReadAllLines(files[i].FullName);
foreach (var s in lens) var items = builder.BuildItemsFormLines(lines);
{ if(items != null && items.Count > 0) allItems.AddRange(items);
l = s.TrimStart();
if(string.IsNullOrEmpty(l)) continue;
if(raw.Contains(l)) continue;
keeps.Add(l);
Debug.Log($"--- ✏️ Apply: [ {l} ]");
}
} }
List<string> finalLines = new List<string>(50);
foreach (var item in allItems)
{
finalLines.AddRange(item.lines);
}
File.WriteAllLines(proguardPath, finalLines.ToArray());
Debug.Log($"--- Update proguard-user.txt done! ☀️ ---");
} }
if (keeps.Count == 0) return; // 无注入文件则退出
List<string> lines = File.ReadAllLines(proguardPath).ToList();
lines.Add("");
lines.AddRange(keeps);
File.WriteAllLines(proguardPath, lines.ToArray());
Debug.Log($"--- Update proguard-user.txt done! ☀️ ---");
} }
} }
[MenuItem("Tools/Android/Add proguard-user")] [MenuItem("Tools/Android/Add proguard-user")]
private static void EditorAddProguardUser() private static void EditorAddProguardUser()
{ {
@ -78,6 +85,67 @@ namespace Guru
} }
} }
internal class ProguardItemBuilder
{
public List<ProguardItem> BuildItemsFormLines(string[] lines)
{
List<ProguardItem> items = new List<ProguardItem>(30);
string line = "";
ProguardItem curItem = null;
for(int i =0; i < lines.Length; i++)
{
line = lines[i];
if(string.IsNullOrEmpty(line)) continue;
if (curItem == null)
{
curItem = new ProguardItem();
}
curItem.Append(line);
if(line.Contains("}"))
{
items.Add(curItem);
curItem = null;
}
}
return items;
}
}
internal class ProguardItem
{
public List<string> lines = new List<string>();
public string key = "";
public void Append(string line)
{
if (string.IsNullOrEmpty(key) &&
line.StartsWith("-"))
{
key = line;
}
if (lines == null) lines = new List<string>(5);
lines.Add(line);
}
}
} }
#endif #endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f0cef2fc19b2407381c7163d3a87ddec
timeCreated: 1722257668

View File

@ -0,0 +1,56 @@
#if UNITY_ANDROID
namespace Guru.BuildTool
{
using System.IO;
using UnityEditor.Android;
using UnityEngine;
public class AndroidSettingsGradleFixer: IPostGenerateGradleAndroidProject
{
private const string SettingsGradleName= "settings.gradle";
private const string K_LINE_UNITYPROJECT = "def unityProjectPath";
public int callbackOrder => 1;
public void OnPostGenerateGradleAndroidProject(string buildPath)
{
FixSettingsInAndroidProject(buildPath);
}
/// <summary>
/// 设置项目中的 Settings 文件
/// </summary>
/// <param name="buildPath"></param>
private void FixSettingsInAndroidProject(string buildPath)
{
var settingsPath = Path.GetFullPath($"{buildPath}/../{SettingsGradleName}");
if (File.Exists(settingsPath))
{
bool isDirty = false;
var lines = File.ReadAllLines(settingsPath);
string projectPath = Path.GetFullPath($"{Application.dataPath}/../").Replace("\\", "/"); // Unity project path
for (int i = 0; i < lines.Length; i++)
{
if (lines[i].Contains(K_LINE_UNITYPROJECT))
{
lines[i] = $" def unityProjectPath = $/file:////{projectPath}/$.replace(\"\\\\\", \"/\")";
isDirty = true;
break;
}
}
if (isDirty)
{
File.WriteAllLines(settingsPath, lines);
Debug.Log($"[SDK] --- Fix Unity Project Path at:{settingsPath}");
}
}
}
}
}
#endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 125df18a1af243018be105c54ab9bb5b
timeCreated: 1722257677

View File

@ -8,6 +8,8 @@ namespace Guru.Editor
using UnityEditor.iOS.Xcode; using UnityEditor.iOS.Xcode;
using UnityEngine; using UnityEngine;
// ----------- SKAdNetwork 更新版本日志: 2024-06-27 --------------------
/// <summary> /// <summary>
/// SKAdNetwork 注入逻辑 /// SKAdNetwork 注入逻辑
/// </summary> /// </summary>

View File

@ -596,6 +596,10 @@
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>k6y4y55b64.skadnetwork</string> <string>k6y4y55b64.skadnetwork</string>
</dict> </dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>6yxyv74ff7.skadnetwork</string>
</dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>t6d3zquu66.skadnetwork</string> <string>t6d3zquu66.skadnetwork</string>
@ -608,6 +612,10 @@
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>h65wbv5k3f.skadnetwork</string> <string>h65wbv5k3f.skadnetwork</string>
</dict> </dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>tvvz7th9br.skadnetwork</string>
</dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>bvpn9ufa9b.skadnetwork</string> <string>bvpn9ufa9b.skadnetwork</string>
@ -616,21 +624,13 @@
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>hjevpa356n.skadnetwork</string> <string>hjevpa356n.skadnetwork</string>
</dict> </dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>6yxyv74ff7.skadnetwork</string>
</dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>mqn7fxpca7.skadnetwork</string> <string>mqn7fxpca7.skadnetwork</string>
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>7953jerfzd.skadnetwork</string> <string>vhf287vqwu.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>qu637u8glc.skadnetwork</string>
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
@ -638,7 +638,11 @@
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>ln5gz23vtd.skadnetwork</string> <string>ce8ybjwass.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>jk2fsx2rgz.skadnetwork</string>
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
@ -646,19 +650,7 @@
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>nu4557a4je.skadnetwork</string> <string>dt3cjx1a9i.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>gvmwg8q7h5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>pu4na253f3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>yrqqpx2mcb.skadnetwork</string>
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
@ -666,7 +658,67 @@
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>bd757ywx3.skadnetwork</string> <string>ln5gz23vtd.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>pu4na253f3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>6rd35atwn8.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>gvmwg8q7h5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>fz2k2k5tej.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>7953jerfzd.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>577p5t736z.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>tmhh9296z4.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>7fbxrn65az.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>r8lj5b58b5.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>qu637u8glc.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>7bxrt786m8.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>xga6mpmplv.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>55644vm79v.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>nu4557a4je.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>mj797d8u6f.skadnetwork</string>
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
@ -678,11 +730,11 @@
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>633vhxswh4.skadnetwork</string> <string>qwpu75vrh2.skadnetwork</string>
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>tmhh9296z4.skadnetwork</string> <string>633vhxswh4.skadnetwork</string>
</dict> </dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
@ -732,10 +784,6 @@
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>899vrgt9g8.skadnetwork</string> <string>899vrgt9g8.skadnetwork</string>
</dict> </dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>mj797d8u6f.skadnetwork</string>
</dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>88k8774x49.skadnetwork</string> <string>88k8774x49.skadnetwork</string>
@ -768,10 +816,6 @@
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>t7ky8fmwkd.skadnetwork</string> <string>t7ky8fmwkd.skadnetwork</string>
</dict> </dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>fz2k2k5tej.skadnetwork</string>
</dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>w28pnjg2k4.skadnetwork</string> <string>w28pnjg2k4.skadnetwork</string>
@ -824,10 +868,6 @@
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>dmv22haz9p.skadnetwork</string> <string>dmv22haz9p.skadnetwork</string>
</dict> </dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>7fbxrn65az.skadnetwork</string>
</dict>
<dict> <dict>
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>b55w3d8y8z.skadnetwork</string> <string>b55w3d8y8z.skadnetwork</string>
@ -920,6 +960,18 @@
<key>SKAdNetworkIdentifier</key> <key>SKAdNetworkIdentifier</key>
<string>x2jnk7ly8j.skadnetwork</string> <string>x2jnk7ly8j.skadnetwork</string>
</dict> </dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>yrqqpx2mcb.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>bd757ywx3.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>w7jznl3r6g.skadnetwork</string>
</dict>
</array> </array>
</dict> </dict>
</plist> </plist>

View File

@ -72,7 +72,7 @@ namespace Guru
for (int i = 0; i < _params.Count; i++) for (int i = 0; i < _params.Count; i++)
{ {
// 上报实验AB属性 // 上报实验AB属性
GuruAnalytics.SetUserProperty(_params[i].id, _params[i].group); GuruAnalytics.Instance.SetUserProperty(_params[i].id, _params[i].group);
#if UNITY_EDITOR #if UNITY_EDITOR
Debug.Log($"[AB] --- Add AB Param <color=cyan>{_params[i].ToString()}</color>"); Debug.Log($"[AB] --- Add AB Param <color=cyan>{_params[i].ToString()}</color>");
#else #else

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> _onSessionSuccessCallback; private static Action<string> _onInitComplete;
private static string _adId = ""; private static string _adId = "";
@ -43,6 +43,9 @@ namespace Guru
} }
} }
private static bool _isReady = false;
public static bool IsReady => _isReady;
#region 启动服务 #region 启动服务
/// <summary> /// <summary>
@ -50,7 +53,9 @@ namespace Guru
/// </summary> /// </summary>
/// <param name="appToken"></param> /// <param name="appToken"></param>
/// <param name="fbAppId">MIR 追踪 AppID</param> /// <param name="fbAppId">MIR 追踪 AppID</param>
public static void StartService(string appToken, string fbAppId = "", Action<string> onSessionSuccess = null) /// <param name="onInitComplete"></param>
/// <param name="onDeeplinkCallback"></param>
public static void StartService(string appToken, string fbAppId = "", Action<string> onInitComplete = null, Action<string> onDeeplinkCallback = null)
{ {
if (string.IsNullOrEmpty(appToken)) if (string.IsNullOrEmpty(appToken))
{ {
@ -58,7 +63,7 @@ namespace Guru
return; return;
} }
_onSessionSuccessCallback = onSessionSuccess; _onInitComplete = onInitComplete;
InstallEvent(IPMConfig.FIREBASE_ID, IPMConfig.IPM_DEVICE_ID); // 注入启动参数 InstallEvent(IPMConfig.FIREBASE_ID, IPMConfig.IPM_DEVICE_ID); // 注入启动参数
@ -66,10 +71,13 @@ namespace Guru
AdjustConfig config = new AdjustConfig(appToken, environment); AdjustConfig config = new AdjustConfig(appToken, environment);
config.setLogLevel(GetAdjustLogLevel()); config.setLogLevel(GetAdjustLogLevel());
config.setDelayStart(DelayTime); config.setDelayStart(DelayTime);
config.setPreinstallTrackingEnabled(true); // Adjust Preinstall config.setPreinstallTrackingEnabled(true); // Adjust Preinstall
config.setSessionSuccessDelegate(OnSessionSuccessCallback); // SessionSuccess config.setSessionSuccessDelegate(OnSessionSuccessCallback); // SessionSuccess
if(onDeeplinkCallback != null)
config.setDeferredDeeplinkDelegate(onDeeplinkCallback);
#if UNITY_ANDROID #if UNITY_ANDROID
if (!string.IsNullOrEmpty(fbAppId)) config.setFbAppId(fbAppId); // 注入 MIR ID if (!string.IsNullOrEmpty(fbAppId)) config.setFbAppId(fbAppId); // 注入 MIR ID
#endif #endif
@ -79,7 +87,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.setSessionFailureDelegate(OnSessionFailureCallback);
config.setAttributionChangedDelegate(OnAttributionChangedCallback); config.setAttributionChangedDelegate(OnAttributionChangedCallback);
#endif #endif
@ -87,9 +94,6 @@ namespace Guru
SetupInstance(); SetupInstance();
Adjust.start(config); Adjust.start(config);
// 缓存标准属性
_adjustId = Adjust.getAdid(); // 获取AdjustID
// 异步加载AdId // 异步加载AdId
FetchGoogleAdId(); FetchGoogleAdId();
@ -161,6 +165,22 @@ namespace Guru
#region 事件回调函数 #region 事件回调函数
/// <summary>
/// Session 启动后回调
/// 回调中可以获取实际的 AdjustID
/// </summary>
/// <param name="sessionSuccessData"></param>
private static void OnSessionSuccessCallback(AdjustSessionSuccess sessionSuccessData)
{
LogI(LOG_TAG,$"{LOG_TAG} --- Session tracked successfully!");
var adid = sessionSuccessData.Adid;
_adjustId = adid;
_isReady = true;
_onInitComplete?.Invoke(adid);
}
private static void OnAttributionChangedCallback(AdjustAttribution attributionData) private static void OnAttributionChangedCallback(AdjustAttribution attributionData)
{ {
LogI(LOG_TAG, "Attribution changed!"); LogI(LOG_TAG, "Attribution changed!");
@ -278,14 +298,6 @@ namespace Guru
LogI(LOG_TAG, "WillRetry: " + eventFailureData.WillRetry.ToString()); LogI(LOG_TAG, "WillRetry: " + eventFailureData.WillRetry.ToString());
} }
private static void OnSessionSuccessCallback(AdjustSessionSuccess sessionSuccessData)
{
LogI(LOG_TAG,$"{LOG_TAG} --- Session tracked successfully!");
var adid = sessionSuccessData.Adid;
_onSessionSuccessCallback?.Invoke(adid);
}
private static void OnSessionFailureCallback(AdjustSessionFailure sessionFailureData) private static void OnSessionFailureCallback(AdjustSessionFailure sessionFailureData)
{ {
LogI(LOG_TAG,"Session tracking failed!"); LogI(LOG_TAG,"Session tracking failed!");
@ -358,24 +370,22 @@ namespace Guru
/// <summary> /// <summary>
/// 广告收入上报 (Adjust 特有的接口) /// 广告收入上报 (Adjust 特有的接口)
/// </summary> /// </summary>
/// <param name="adInfo"></param> /// <param name="value"></param>
public static void TrackADRevenue(MaxSdkBase.AdInfo adInfo) /// <param name="currency"></param>
/// <param name="adSource"></param>
/// <param name="adUnitId"></param>
/// <param name="adPlacement"></param>
public static void TrackADRevenue(double value, string currency, string adSource, string adUnitId, string adPlacement)
{ {
if (adInfo == null)
return;
var adRevenue = new AdjustAdRevenue(AdjustConfig.AdjustAdRevenueSourceAppLovinMAX); var adRevenue = new AdjustAdRevenue(AdjustConfig.AdjustAdRevenueSourceAppLovinMAX);
adRevenue.setRevenue(adInfo.Revenue, "USD"); if (string.IsNullOrEmpty(currency)) currency = "USD";
adRevenue.setAdRevenueNetwork(adInfo.NetworkName); adRevenue.setRevenue(value, currency);
adRevenue.setAdRevenueUnit(adInfo.AdUnitIdentifier); adRevenue.setAdRevenueNetwork(adSource);
adRevenue.setAdRevenuePlacement(adInfo.Placement); adRevenue.setAdRevenueUnit(adUnitId);
adRevenue.setAdRevenuePlacement(adPlacement);
Adjust.trackAdRevenue(adRevenue); Adjust.trackAdRevenue(adRevenue);
} }
#endregion #endregion
#region 关键属性上报 #region 关键属性上报

View File

@ -14,37 +14,60 @@ namespace Guru
public class GuruAnalytics public class GuruAnalytics
{ {
// Plugin Version // Plugin Version
public const string Version = "1.10.5"; public const string Version = "1.11.1";
public static readonly string Tag = "[ANU]"; public static readonly string Tag = "[ANU]";
private static readonly string ActionName = "logger_error"; private static readonly string ActionName = "logger_error";
internal const int EventPriorityDefault = 10; private const int EventPriorityDefault = 10;
private static IAnalyticsAgent _agent;
public static IAnalyticsAgent Agent private static GuruAnalytics _instance;
public static GuruAnalytics Instance
{
get
{
if (_instance == null)
{
throw new Exception("GuruAnalytics not initialized. Please call <Analytics.InitAnalytics()> first.");
}
return _instance;
}
}
private bool _isReady = false;
public bool IsReady => _isReady;
private IAnalyticsAgent _agent;
private IAnalyticsAgent Agent
{ {
get get
{ {
if (_agent == null) if (_agent == null)
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
_agent = new AnalyticsAgentStub(); _agent = new AnalyticsAgentMock();
#elif UNITY_ANDROID #elif UNITY_ANDROID
_agent = new AnalyticsAgentAndroid(); _agent = new AnalyticsAgentAndroid();
#elif UNITY_IOS #elif UNITY_IOS
_agent = new AnalyticsAgentIOS(); _agent = new AnalyticsAgentIOS();
#endif #endif
} }
if (_agent == null)
{
throw new NotImplementedException("You Should Implement IAnalyticsAgent on platform first.");
}
return _agent; return _agent;
} }
} }
private static Dictionary<string, string> _userProperties; private Dictionary<string, string> _userProperties;
/// <summary> /// <summary>
/// 用户属性缓存字典 /// 用户属性缓存字典
/// </summary> /// </summary>
public static Dictionary<string, string> UserProperties private Dictionary<string, string> UserProperties
{ {
get get
{ {
@ -59,15 +82,13 @@ namespace Guru
/// <summary> /// <summary>
/// 错误 code 表 /// 错误 code 表
/// </summary> /// </summary>
public static List<int> ErrorCodeList = new List<int>(); public List<int> ErrorCodeList = new List<int>();
private bool _enableErrorLog = false;
private static bool _autoSyncProperties = false;
private static bool _enableErrorLog = false;
/// <summary> /// <summary>
/// 启动日志错误上报 /// 启动日志错误上报
/// </summary> /// </summary>
public static bool EnableErrorLog public bool EnableErrorLog
{ {
get => _enableErrorLog; get => _enableErrorLog;
set set
@ -83,37 +104,40 @@ namespace Guru
/// <summary> /// <summary>
/// 初始化接口 /// 初始化接口
/// </summary> /// </summary>
public static void Init(string appId, string deviceInfo, bool isDebug = false, public static void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false,
bool enableErrorLog = false, bool syncProperties = false) bool enableErrorLog = false)
{ {
Debug.Log($"{Tag} --- Guru Analytics [{Version}] initialing..."); Debug.Log($"{Tag} --- Guru Analytics [{Version}] initialing...");
_autoSyncProperties = syncProperties; if (_instance == null)
_enableErrorLog = enableErrorLog; {
Agent?.Init(appId, deviceInfo, isDebug); _instance = new GuruAnalytics();
if(_enableErrorLog) InitCallbacks(); // 激活错误日志回调 _instance.Agent.Init(appId, deviceInfo, onInitComplete, isDebug);
_instance.EnableErrorLog = enableErrorLog;
_instance._isReady = true;
}
} }
/// <summary> /// <summary>
/// 设置视图名称 /// 设置视图名称
/// </summary> /// </summary>
/// <param name="screenName"></param> /// <param name="screenName"></param>
public static void SetScreen(string screenName) public void SetScreen(string screenName)
{ {
if (string.IsNullOrEmpty(screenName)) return; if (string.IsNullOrEmpty(screenName)) return;
CacheUserProperty($"screen_name", screenName); CacheUserProperty($"screen_name", screenName);
Agent?.SetScreen(screenName); Agent.SetScreen(screenName);
} }
/// <summary> /// <summary>
/// 设置广告ID /// 设置广告ID
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
public static void SetAdId(string id) public void SetAdId(string id)
{ {
if (string.IsNullOrEmpty(id)) return; if (string.IsNullOrEmpty(id)) return;
CacheUserProperty($"ad_id", id); CacheUserProperty($"ad_id", id);
Agent?.SetAdId(id); Agent.SetAdId(id);
} }
/// <summary> /// <summary>
@ -121,59 +145,59 @@ namespace Guru
/// </summary> /// </summary>
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
public static void SetUserProperty(string key, string value) public void SetUserProperty(string key, string value)
{ {
if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return; if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return;
CacheUserProperty(key, value); // 添加用户属性 CacheUserProperty(key, value); // 添加用户属性
Agent?.SetUserProperty(key, value); Agent.SetUserProperty(key, value);
} }
/// <summary> /// <summary>
/// 设置Firebase ID /// 设置Firebase ID
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
public static void SetFirebaseId(string id) public void SetFirebaseId(string id)
{ {
if (string.IsNullOrEmpty(id)) return; if (string.IsNullOrEmpty(id)) return;
CacheUserProperty($"firebase_id", id); CacheUserProperty($"firebase_id", id);
Agent?.SetFirebaseId(id); Agent.SetFirebaseId(id);
} }
/// <summary> /// <summary>
/// 设置Adjust ID /// 设置Adjust ID
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
public static void SetAdjustId(string id) public void SetAdjustId(string id)
{ {
if (string.IsNullOrEmpty(id)) return; if (string.IsNullOrEmpty(id)) return;
CacheUserProperty($"adjust_id", id); CacheUserProperty($"adjust_id", id);
Agent?.SetAdjustId(id); Agent.SetAdjustId(id);
} }
/// <summary> /// <summary>
/// 设置设备ID /// 设置设备ID
/// </summary> /// </summary>
/// <param name="deviceId"></param> /// <param name="deviceId"></param>
public static void SetDeviceId(string deviceId) public void SetDeviceId(string deviceId)
{ {
if (string.IsNullOrEmpty(deviceId)) return; if (string.IsNullOrEmpty(deviceId)) return;
CacheUserProperty($"device_id", deviceId); CacheUserProperty($"device_id", deviceId);
Agent?.SetDeviceId(deviceId); Agent.SetDeviceId(deviceId);
} }
public static void SetAndroidID(string androidId) public void SetAndroidID(string androidId)
{ {
if (string.IsNullOrEmpty(androidId)) return; if (string.IsNullOrEmpty(androidId)) return;
CacheUserProperty(Analytics.PropertyAndroidID, androidId); CacheUserProperty(Analytics.PropertyAndroidID, androidId);
} }
public static void SetIDFV(string idfv) public void SetIDFV(string idfv)
{ {
if (string.IsNullOrEmpty(idfv)) return; if (string.IsNullOrEmpty(idfv)) return;
CacheUserProperty(Analytics.PropertyIDFV, idfv); CacheUserProperty(Analytics.PropertyIDFV, idfv);
} }
public static void SetIDFA(string idfa) public void SetIDFA(string idfa)
{ {
if (string.IsNullOrEmpty(idfa)) return; if (string.IsNullOrEmpty(idfa)) return;
CacheUserProperty(Analytics.PropertyIDFA, idfa); CacheUserProperty(Analytics.PropertyIDFA, idfa);
@ -184,17 +208,17 @@ namespace Guru
/// 设置用户ID /// 设置用户ID
/// </summary> /// </summary>
/// <param name="uid"></param> /// <param name="uid"></param>
public static void SetUid(string uid) public void SetUid(string uid)
{ {
if (string.IsNullOrEmpty(uid)) return; if (string.IsNullOrEmpty(uid)) return;
CacheUserProperty($"uid", uid); CacheUserProperty($"uid", uid);
Agent?.SetUid(uid); Agent.SetUid(uid);
} }
/// <summary> /// <summary>
/// 上报事件成功率 /// 上报事件成功率
/// </summary> /// </summary>
public static void ReportEventSuccessRate() => Agent?.ReportEventSuccessRate(); public void ReportEventSuccessRate() => Agent.ReportEventSuccessRate();
/// <summary> /// <summary>
/// 上报打点事件 /// 上报打点事件
@ -202,21 +226,19 @@ namespace Guru
/// <param name="eventName">事件名称</param> /// <param name="eventName">事件名称</param>
/// <param name="data">INT类型的值</param> /// <param name="data">INT类型的值</param>
/// <param name="priority"></param> /// <param name="priority"></param>
public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null, int priority = -1) public void LogEvent(string eventName, Dictionary<string, dynamic> data = null, int priority = -1)
{ {
if(_autoSyncProperties)
UpdateAllUserProperties(); // 每次打点更新用户属性
string raw = ""; string raw = "";
if (data != null && data.Count > 0) if (data != null && data.Count > 0)
{ {
raw = BuildParamsJson(data); raw = BuildParamsJson(data);
} }
if (priority < 0) priority = EventPriorityDefault; if (priority < 0) priority = EventPriorityDefault;
Debug.Log($"{Tag} event:{eventName} | raw: {raw} | priority: {priority}"); Debug.Log($"{Tag} --- LogEvent GuruAnalytics:{eventName} | raw: {raw} | priority: {priority}");
Agent?.LogEvent(eventName, raw, priority); Agent.LogEvent(eventName, raw, priority);
} }
/*
private static string BuildParamsString(Dictionary<string, dynamic> data) private static string BuildParamsString(Dictionary<string, dynamic> data)
{ {
string raw = ""; string raw = "";
@ -228,8 +250,9 @@ namespace Guru
} }
return raw; return raw;
} }
*/
private static string BuildParamsJson(Dictionary<string, dynamic> data) private string BuildParamsJson(Dictionary<string, dynamic> data)
{ {
try try
{ {
@ -247,6 +270,7 @@ namespace Guru
return ""; return "";
} }
/*
/// <summary> /// <summary>
/// 构建带有类型格式的Str值 /// 构建带有类型格式的Str值
/// </summary> /// </summary>
@ -267,15 +291,16 @@ namespace Guru
return $"{kvp.Key}:s{kvp.Value}"; return $"{kvp.Key}:s{kvp.Value}";
} }
*/
/// <summary> /// <summary>
/// 设置太极02值 /// 设置太极02值
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
public static void SetTch02Value(double value) public void SetTch02Value(double value)
{ {
Debug.Log($"{Tag} set tch_02_value:{value}"); Debug.Log($"{Tag} set tch_02_value:{value}");
Agent?.SetTch02Value(value); Agent.SetTch02Value(value);
} }
#endregion #endregion
@ -296,37 +321,19 @@ namespace Guru
/// </summary> /// </summary>
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="value"></param> /// <param name="value"></param>
private static void CacheUserProperty(string key, string value) private void CacheUserProperty(string key, string value)
{ {
bool needUpdate = !UserProperties.ContainsKey(key) || UserProperties[key] != value; // bool needUpdate = !UserProperties.ContainsKey(key) || UserProperties[key] != value;
UserProperties[key] = value; UserProperties[key] = value;
// if (needUpdate) UpdateAllUserProperties(); // if (needUpdate) UpdateAllUserProperties();
} }
private static void UpdateAllUserProperties()
{
if (UserProperties != null && UserProperties.Count > 0)
{
var keys = UserProperties.Keys.ToArray();
int i = 0;
string key = "";
while (i < keys.Length)
{
key = keys[i];
if(!string.IsNullOrEmpty(key)) SetUserProperty(key, UserProperties[key]);
i++;
}
keys = null;
}
}
#endregion #endregion
#region 日志回调 #region 日志回调
private static void InitCallbacks() private void InitCallbacks()
{ {
try try
{ {
@ -346,8 +353,8 @@ namespace Guru
/// <summary> /// <summary>
/// 获取SDK回调 /// 获取SDK回调
/// </summary> /// </summary>
/// <param name="msg"></param> /// <param name="raw"></param>
private static void OnSDKCallback(string raw) private void OnSDKCallback(string raw)
{ {
if (string.IsNullOrEmpty(raw)) return; if (string.IsNullOrEmpty(raw)) return;
if (!raw.Contains($"\"{ActionName}\"")) return; // 不对其他行为的日志进行过滤 if (!raw.Contains($"\"{ActionName}\"")) return; // 不对其他行为的日志进行过滤
@ -359,7 +366,7 @@ namespace Guru
/// </summary> /// </summary>
/// <param name="code"></param> /// <param name="code"></param>
/// <param name="errorInfo"></param> /// <param name="errorInfo"></param>
private static void OnLoggerErrorEvent(int code, string errorInfo = "") private void OnLoggerErrorEvent(int code, string errorInfo = "")
{ {
// Debug.Log($"{Tag} --- OnLoggerErrorEvent: code:{code}\tinfo:{errorInfo}"); // Debug.Log($"{Tag} --- OnLoggerErrorEvent: code:{code}\tinfo:{errorInfo}");
@ -389,16 +396,12 @@ namespace Guru
Debug.Log($"{Tag} ------ ErrorLogInfo:: code:{codeString}\tinfo:{errorInfo}"); Debug.Log($"{Tag} ------ ErrorLogInfo:: code:{codeString}\tinfo:{errorInfo}");
#if !UNITY_EDITOR
// Only for firebase GA // Only for firebase GA
Analytics.LogEvent("dev_audit", parameters, Analytics.TrackEvent("dev_audit", parameters, new Analytics.EventSetting() { EnableFirebaseAnalytics = true });
new Analytics.EventSetting() { EnableFirebaseAnalytics = true });
#endif
} }
private static bool ParseWithJson(string json) private bool ParseWithJson(string json)
{ {
Debug.Log($"{Tag} ------ ParseWithJson: json:\n{json}"); Debug.Log($"{Tag} ------ ParseWithJson: json:\n{json}");
@ -435,7 +438,7 @@ namespace Guru
{ {
string p = "\"msg\":\""; string p = "\"msg\":\"";
string m = json; string m = json;
if (json.Contains(p)) m = json.Substring(json.IndexOf(p) + p.Length); if (json.Contains(p)) m = json.Substring(json.IndexOf(p, StringComparison.Ordinal) + p.Length);
info = $"JsonEX:{m}"; info = $"JsonEX:{m}";
// Debug.Log($"{Tag} --- {info}"); // Debug.Log($"{Tag} --- {info}");
Analytics.LogCrashlytics(json, false); Analytics.LogCrashlytics(json, false);
@ -445,22 +448,17 @@ namespace Guru
return false; return false;
} }
private static void ParseWithRaw(string raw) /**
private void ParseWithRaw(string raw)
{ {
int code = (int)AnalyticsCode.Unknown; var code = (int)AnalyticsCode.Unknown;
string info = raw; string info;
//------- message send to unity ---------- //------- message send to unity ----------
Debug.Log($"{Tag} get callback errorInfo:\n{raw}"); Debug.Log($"{Tag} get callback errorInfo:\n{raw}");
string patten = "";
string patten2 = "";
int idx = 0;
int idx2 = 0;
int len = 0;
var patten = "msg\":\"";
patten = "msg\":\"";
if (raw.Contains(patten)) if (raw.Contains(patten))
{ {
@ -483,16 +481,16 @@ namespace Guru
try try
{ {
idx = raw.IndexOf(patten, StringComparison.Ordinal) + patten.Length; var idx = raw.IndexOf(patten, StringComparison.Ordinal) + patten.Length;
string act = raw.Substring(idx, ActionName.Length); string act = raw.Substring(idx, ActionName.Length);
if (act == ActionName) if (act == ActionName)
{ {
patten = "code\":"; patten = "code\":";
patten2 = ",\"msg"; var patten2 = ",\"msg";
idx = raw.IndexOf(patten); idx = raw.IndexOf(patten, StringComparison.Ordinal);
idx2 = raw.IndexOf(patten2); var idx2 = raw.IndexOf(patten2, StringComparison.Ordinal);
len = idx2 - (idx + patten.Length); var len = idx2 - (idx + patten.Length);
if (len > 0) if (len > 0)
{ {
string c = raw.Substring(idx + patten.Length, len); string c = raw.Substring(idx + patten.Length, len);
@ -531,12 +529,12 @@ namespace Guru
{ {
Analytics.LogCrashlytics(raw, false); Analytics.LogCrashlytics(raw, false);
Analytics.LogCrashlytics($"{Tag} --- format error:{raw}"); Analytics.LogCrashlytics($"{Tag} --- format error:{raw}");
OnLoggerErrorEvent(code, raw.Substring(raw.IndexOf("msg\":" ) + 5)); OnLoggerErrorEvent(code, raw.Substring(raw.IndexOf("msg\":", StringComparison.Ordinal) + 5));
} }
} }
**/
private void ReportCodeInfo(int code, string info)
private static void ReportCodeInfo(int code, string info)
{ {
var ac = (AnalyticsCode)code; var ac = (AnalyticsCode)code;
Debug.Log($"{Tag} ------ Get Code And Info: code:{code}[{ac}] \tinfo:{info}"); Debug.Log($"{Tag} ------ Get Code And Info: code:{code}[{ac}] \tinfo:{info}");
@ -592,7 +590,7 @@ namespace Guru
public static void TestOnCallback(string msg) public static void TestOnCallback(string msg)
{ {
OnSDKCallback(msg); Instance.OnSDKCallback(msg);
} }
#endif #endif

View File

@ -1,11 +1,13 @@
namespace Guru namespace Guru
{ {
using System;
/// <summary> /// <summary>
/// 自打点代理接口 /// 自打点代理接口
/// </summary> /// </summary>
public interface IAnalyticsAgent public interface IAnalyticsAgent
{ {
void Init(string appId, string deviceInfo, bool isDebug = false); void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false);
void SetScreen(string screenName); void SetScreen(string screenName);
void SetAdId(string id); void SetAdId(string id);
void SetUserProperty(string key, string value); void SetUserProperty(string key, string value);

View File

@ -1,5 +1,7 @@
using System.Threading.Tasks;
namespace Guru namespace Guru
{ {
using System; using System;
@ -76,12 +78,16 @@ namespace Guru
#region 接口实现 #region 接口实现
public void Init(string appId, string deviceInfo, bool isDebug = false) public async void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false)
{ {
_isDebug = isDebug; _isDebug = isDebug;
string bundleId = Application.identifier; string bundleId = Application.identifier;
// public static void init(String appId, String deviceInfo, String bundleId, boolean isDebug, boolean useWorker, boolean useCronet, String baseUrl) // public static void init(String appId, String deviceInfo, String bundleId, boolean isDebug, boolean useWorker, boolean useCronet, String baseUrl)
// TODO: 将来把 CallStatic 转为异步实现
CallStatic("init", appId, deviceInfo, bundleId, isDebug, UseWorker, UseCronet, BaseUrl); // 调用接口 CallStatic("init", appId, deviceInfo, bundleId, isDebug, UseWorker, UseCronet, BaseUrl); // 调用接口
onInitComplete?.Invoke();
} }
public void SetScreen(string screenName) public void SetScreen(string screenName)

View File

@ -1,7 +1,9 @@
using System.Runtime.InteropServices;
namespace Guru namespace Guru
{ {
using System;
using System.Runtime.InteropServices;
public class AnalyticsAgentIOS: IAnalyticsAgent public class AnalyticsAgentIOS: IAnalyticsAgent
{ {
@ -55,13 +57,14 @@ namespace Guru
} }
public void Init(string appId, string deviceInfo, bool isDebug = false) public void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false)
{ {
_isDebug = isDebug; _isDebug = isDebug;
#if UNITY_IOS #if UNITY_IOS
unityInitAnalytics(appId, deviceInfo, isDebug); unityInitAnalytics(appId, deviceInfo, isDebug);
unityInitException(); // 初始化报错守护进程 unityInitException(); // 初始化报错守护进程
#endif #endif
onInitComplete?.Invoke();
} }
public void SetScreen(string screenName) public void SetScreen(string screenName)

View File

@ -1,9 +1,12 @@
using System.Text;
using UnityEngine;
namespace Guru namespace Guru
{ {
public class AnalyticsAgentStub: IAnalyticsAgent using System.Text;
using UnityEngine;
using System;
public class AnalyticsAgentMock: IAnalyticsAgent
{ {
public static readonly string TAG = "[EDT]"; public static readonly string TAG = "[EDT]";
@ -24,7 +27,7 @@ namespace Guru
} }
public void Init(string appId, string deviceInfo, bool isDebug = false) public void Init(string appId, string deviceInfo, Action onInitComplete, bool isDebug = false)
{ {
#if UNITY_EDITOR #if UNITY_EDITOR
_isShowLog = true; _isShowLog = true;
@ -32,6 +35,8 @@ namespace Guru
_isDebug = isDebug; _isDebug = isDebug;
if(_isShowLog) if(_isShowLog)
Debug.Log($"{TAG} init with Debug: <color=orange>{isDebug}</color> appId:{appId} deviceInfo:{deviceInfo}"); Debug.Log($"{TAG} init with Debug: <color=orange>{isDebug}</color> appId:{appId} deviceInfo:{deviceInfo}");
onInitComplete?.Invoke();
} }
@ -127,7 +132,7 @@ namespace Guru
} }
} }
Debug.Log($"{TAG} LogEvent: event:<color=orange>{eventName} ({priority})</color> Properties:\n{sb.ToString()}"); Debug.Log($"{TAG} LogEvent: GuruAnalytics:<color=orange>{eventName} ({priority})</color> Properties:\n{sb.ToString()}");
} }
} }
} }

View File

@ -5,7 +5,7 @@ using UnityEngine.UI;
namespace Guru namespace Guru
{ {
public class CuruAnalyticsDemo: MonoBehaviour public class GuruAnalyticsDemo: MonoBehaviour
{ {
[SerializeField] private bool _isDebug = true; [SerializeField] private bool _isDebug = true;
[SerializeField] private Button _btnInitSDK; [SerializeField] private Button _btnInitSDK;
@ -54,17 +54,22 @@ namespace Guru
private void OnClickInit() private void OnClickInit()
{ {
Debug.Log($"---- [DEMO] Call Analytics init"); Debug.Log($"---- [DEMO] Call Analytics init");
GuruAnalytics.Init(AppID, DeviceInfo, _isDebug); GuruAnalytics.Init(AppID, DeviceInfo, OnGuruAnalyticsInitComplete, _isDebug);
}
private void OnGuruAnalyticsInitComplete()
{
} }
private void OnClickStatus() private void OnClickStatus()
{ {
Debug.Log($"---- [DEMO] Report Stats IDs: UID:{UID} DeviceID:{DeviceID} FirebaseID:{FirebaseID} AdID:{AdID} AdjustID:{AdjustID}"); Debug.Log($"---- [DEMO] Report Stats IDs: UID:{UID} DeviceID:{DeviceID} FirebaseID:{FirebaseID} AdID:{AdID} AdjustID:{AdjustID}");
GuruAnalytics.SetUid(UID); GuruAnalytics.Instance.SetUid(UID);
GuruAnalytics.SetDeviceId(DeviceID); GuruAnalytics.Instance.SetDeviceId(DeviceID);
GuruAnalytics.SetFirebaseId(FirebaseID); GuruAnalytics.Instance.SetFirebaseId(FirebaseID);
GuruAnalytics.SetAdId(AdID); GuruAnalytics.Instance.SetAdId(AdID);
GuruAnalytics.SetAdjustId(AdjustID); GuruAnalytics.Instance.SetAdjustId(AdjustID);
} }
private void OnClickUserProperties() private void OnClickUserProperties()
@ -72,14 +77,14 @@ namespace Guru
string item_category = "main"; string item_category = "main";
int level = 7; int level = 7;
Debug.Log($"---- [DEMO] Call SetUserProperty: item_category:{item_category} level:{level}"); Debug.Log($"---- [DEMO] Call SetUserProperty: item_category:{item_category} level:{level}");
GuruAnalytics.SetUserProperty("item_category", item_category); GuruAnalytics.Instance.SetUserProperty("item_category", item_category);
GuruAnalytics.SetUserProperty("level", level.ToString()); GuruAnalytics.Instance.SetUserProperty("level", level.ToString());
} }
private void OnClickEvents() private void OnClickEvents()
{ {
Debug.Log($"---- [DEMO] Report Screen: {ScreenName}"); Debug.Log($"---- [DEMO] Report Screen: {ScreenName}");
GuruAnalytics.SetScreen(ScreenName); GuruAnalytics.Instance.SetScreen(ScreenName);
string eventName = "user_get_coin"; string eventName = "user_get_coin";
Dictionary<string, dynamic> data = new Dictionary<string, dynamic>() Dictionary<string, dynamic> data = new Dictionary<string, dynamic>()
@ -99,19 +104,19 @@ namespace Guru
Debug.Log(s); Debug.Log(s);
Debug.Log($"---- [DEMO] Call LogEvent"); Debug.Log($"---- [DEMO] Call LogEvent");
GuruAnalytics.LogEvent(eventName, data); GuruAnalytics.Instance.LogEvent(eventName, data);
} }
private void OnClickEvents2() private void OnClickEvents2()
{ {
string eventName = "user_data_loaded"; string eventName = "user_data_loaded";
GuruAnalytics.LogEvent(eventName); GuruAnalytics.Instance.LogEvent(eventName);
} }
private void OnClickReport() private void OnClickReport()
{ {
GuruAnalytics.ReportEventSuccessRate(); GuruAnalytics.Instance.ReportEventSuccessRate();
} }

View File

@ -140,7 +140,7 @@ namespace Guru
DmaResult = result; DmaResult = result;
//----------- Guru Analytics report --------------- //----------- Guru Analytics report ---------------
Analytics.LogEvent("dma_gg", new Dictionary<string, dynamic>() Analytics.TrackEvent("dma_gg", new Dictionary<string, dynamic>()
{ {
{ "purpose", purposeStr }, { "purpose", purposeStr },
{ "result", result } { "result", result }

View File

@ -1,5 +1,7 @@
using System.Threading.Tasks;
namespace Guru namespace Guru
{ {
using UnityEngine; using UnityEngine;
@ -30,6 +32,21 @@ namespace Guru
Debug.Log($"{Tag} Consent Request -> deviceid: {deviceId} debugGeography: {debugGeography}"); Debug.Log($"{Tag} Consent Request -> deviceid: {deviceId} debugGeography: {debugGeography}");
#if UNITY_EDITOR #if UNITY_EDITOR
SendEditorCallback();
#endif
}
#if UNITY_EDITOR
#endif
/// <summary>
/// 延迟触发 Consent
/// </summary>
private async void SendEditorCallback()
{
await Task.Delay(2000);
string msg = callbackMsgFmt.Replace("$0", $"{DebugStatusCode}").Replace("$1",DebugMessage); string msg = callbackMsgFmt.Replace("$0", $"{DebugStatusCode}").Replace("$1",DebugMessage);
var go = GameObject.Find(_objName); var go = GameObject.Find(_objName);
if (go != null) if (go != null)
@ -40,9 +57,10 @@ namespace Guru
{ {
Debug.LogError($"{Tag} Can't find callback object"); Debug.LogError($"{Tag} Can't find callback object");
} }
#endif
} }
/// <summary> /// <summary>
/// 获取 DMA 字段 /// 获取 DMA 字段
/// </summary> /// </summary>

View File

@ -1,4 +1,5 @@
using System;
using UnityEngine; using UnityEngine;
namespace Guru namespace Guru
@ -115,7 +116,7 @@ namespace Guru
private void OnLoadMaxBanner() private void OnLoadMaxBanner()
{ {
_badsloadStartTime = Time.realtimeSinceStartup; _badsloadStartTime = DateTime.UtcNow;
_chanelMax.LoadBannerAD(); _chanelMax.LoadBannerAD();
OnBannerStartLoad?.Invoke(_chanelMax.MaxBADSSlotID); OnBannerStartLoad?.Invoke(_chanelMax.MaxBADSSlotID);
} }
@ -147,7 +148,7 @@ namespace Guru
} }
private void OnLoadMaxIV() { private void OnLoadMaxIV() {
_iadsLoadStartTime = Time.realtimeSinceStartup; // 更新计时器 _iadsLoadStartTime = DateTime.UtcNow; // 更新计时器
_chanelMax.LoadInterstitialAD(); _chanelMax.LoadInterstitialAD();
OnInterstitialStartLoad?.Invoke(_chanelMax.MaxIADSSlotID); OnInterstitialStartLoad?.Invoke(_chanelMax.MaxIADSSlotID);
} }
@ -180,7 +181,7 @@ namespace Guru
private void OnLoadMaxRV() private void OnLoadMaxRV()
{ {
_radsLoadStartTime = Time.realtimeSinceStartup; // 更新计时器 _radsLoadStartTime = DateTime.UtcNow; // 更新计时器
_chanelMax.LoadRewardAD(); _chanelMax.LoadRewardAD();
OnRewardedStartLoad?.Invoke(_chanelMax.MaxRADSSlotID); OnRewardedStartLoad?.Invoke(_chanelMax.MaxRADSSlotID);
} }

View File

@ -1,8 +1,11 @@
using System.Linq;
namespace Guru namespace Guru
{ {
using System; using System;
using UnityEngine; using UnityEngine;
using System.Collections.Generic; using System.Collections.Generic;
using Guru.Ads;
public abstract class ADServiceBase<T> : IADService where T : new() public abstract class ADServiceBase<T> : IADService where T : new()
{ {
@ -18,7 +21,7 @@ namespace Guru
} }
} }
protected static readonly string Tag = "[Ads]"; protected static readonly string Tag = "[SDK][ADS]";
public bool IsInitialized => MaxSdk.IsInitialized() || _isServiceStarted; public bool IsInitialized => MaxSdk.IsInitialized() || _isServiceStarted;
protected bool IsNetworkEnabled => Application.internetReachability != NetworkReachability.NotReachable; protected bool IsNetworkEnabled => Application.internetReachability != NetworkReachability.NotReachable;
@ -41,9 +44,14 @@ namespace Guru
public static Action OnRewardFailed; public static Action OnRewardFailed;
public static Action OnRewardClosed; public static Action OnRewardClosed;
private Dictionary<string, string> _reviewCreativeIds = new Dictionary<string, string>(10); // Creative ID 缓存: Cid : RCid
private Dictionary<string, List<AdImpressionData>> _impressionCache = new Dictionary<string, List<AdImpressionData>>(10);
protected AdsModel _model; protected AdsModel _model;
protected AdsInitSpec _initSpec = null; protected AdsInitSpec _initSpec = null;
private AdImpressionDriver _impressionDriver;
public AdsModel Model public AdsModel Model
{ {
get get
@ -74,6 +82,9 @@ namespace Guru
if(_model == null) _model = AdsModel.Create(); if(_model == null) _model = AdsModel.Create();
this.Log("AD SDK Start Init"); this.Log("AD SDK Start Init");
_impressionDriver = new AdImpressionDriver();
_impressionDriver.Init(ReportAdsRevenue); // 初始化 Impression 驱动器
InitMaxCallbacks(); // 初始化 MAX 广告 InitMaxCallbacks(); // 初始化 MAX 广告
InitService(); // 内部继承接口 InitService(); // 内部继承接口
} }
@ -85,14 +96,16 @@ namespace Guru
{ {
//-------------- 初始化回调 ------------------ //-------------- 初始化回调 ------------------
MaxSdkCallbacks.OnSdkInitializedEvent += OnMaxSdkInitializedCallBack; MaxSdkCallbacks.OnSdkInitializedEvent += OnMaxSdkInitializedCallBack;
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent; //--------------- MRec 回调 -----------------
MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnBannerRevenuePaidEvent; // MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
//--------------- Banner 回调 ----------------- //--------------- Banner 回调 -----------------
MaxSdkCallbacks.Banner.OnAdLoadedEvent += OnBannerLoadedEvent; MaxSdkCallbacks.Banner.OnAdLoadedEvent += OnBannerLoadedEvent;
MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += OnBannerFailedEvent; MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += OnBannerFailedEvent;
MaxSdkCallbacks.Banner.OnAdClickedEvent += OnBannerClickedEvent; MaxSdkCallbacks.Banner.OnAdClickedEvent += OnBannerClickedEvent;
MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnBannerRevenuePaidEvent;
MaxSdkCallbacks.Banner.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent;
//--------------- IV 回调 ----------------- //--------------- IV 回调 -----------------
MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent; MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent;
MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += OnInterstitialFailedEvent; MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += OnInterstitialFailedEvent;
@ -100,6 +113,8 @@ namespace Guru
MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickEvent; MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickEvent;
MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayEvent; MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayEvent;
MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialDismissedEvent; MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialDismissedEvent;
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnInterstitialPaidEvent;
MaxSdkCallbacks.Interstitial.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent;
//--------------- RV 回调 ----------------- //--------------- RV 回调 -----------------
MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent; MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent;
MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += OnRewardedAdFailedEvent; MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += OnRewardedAdFailedEvent;
@ -108,11 +123,19 @@ namespace Guru
MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent; MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent;
MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdDismissedEvent; MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdDismissedEvent;
MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent; MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent;
MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnRewardedAdPaidEvent;
MaxSdkCallbacks.Rewarded.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent;
//--------------- Creative 回调 -----------------
//-------------- SDK 初始化 ------------------- //-------------- SDK 初始化 -------------------
MaxSdk.SetExtraParameter("enable_black_screen_fixes", "true"); // 修复黑屏 MaxSdk.SetExtraParameter("enable_black_screen_fixes", "true"); // 修复黑屏
} }
protected virtual void InitService() protected virtual void InitService()
{ {
} }
@ -174,7 +197,7 @@ namespace Guru
#endregion #endregion
#region ILRD #region 收益打点
private double TchAD001RevValue private double TchAD001RevValue
{ {
@ -188,49 +211,34 @@ namespace Guru
set => _model.TchAD02RevValue = value; set => _model.TchAD02RevValue = value;
} }
public void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
if (adInfo == null) return;
try
{
Log.I( $"[ADRevenue] - adUnitId:{adUnitId}, Revenue:{adInfo?.Revenue : 0}");
// #1 ad_impression
OnAdImpression(adInfo);
// #2 tch_001
double revenue = adInfo.Revenue;
CalcTaichi001Value(revenue);
CalcTaichi02Value(revenue);
// #3 adjust_ad_revenue
AdjustService.TrackADRevenue(adInfo);
}
catch (Exception ex)
{
Analytics.LogCrashlytics(ex);
}
}
/// <summary> /// <summary>
/// 广告ARO收益打点 /// 上报广告收益
/// </summary> /// </summary>
/// <param name="adInfo"></param> /// <param name="adInfo"></param>
/// <param name="platform"></param> /// <param name="reviewedCreativeId"></param>
private void OnAdImpression(MaxSdkBase.AdInfo adInfo, string platform = "") private void ReportAdsRevenue(AdImpressionData data)
{ {
Analytics.ADImpression(adInfo, platform); // #1 ad_impression
Analytics.ADImpression(data);
// #2 tch_001 和 tch_02
double revenue = data.value;
CalcTch001Value(revenue);
CalcTch02Value(revenue);
// #3 adjust_ad_revenue
AdjustService.TrackADRevenue(data.value, data.currency, data.ad_source, data.ad_unit_name, data.ad_placement);
} }
/// <summary> /// <summary>
/// 计算太极001收益 /// 计算太极001收益
/// </summary> /// </summary>
/// <param name="revenue"></param> /// <param name="revenue"></param>
private void CalcTaichi001Value(double revenue) private void CalcTch001Value(double revenue)
{ {
TchAD001RevValue += revenue; TchAD001RevValue += revenue;
double revenueValue = TchAD001RevValue; double revenueValue = TchAD001RevValue;
@ -247,7 +255,7 @@ namespace Guru
/// 计算太极02收益 /// 计算太极02收益
/// </summary> /// </summary>
/// <param name="revenue"></param> /// <param name="revenue"></param>
private void CalcTaichi02Value(double revenue) private void CalcTch02Value(double revenue)
{ {
if (!Analytics.EnableTch02Event) return; if (!Analytics.EnableTch02Event) return;
@ -269,21 +277,24 @@ namespace Guru
private string _backColorStr = "#50A436"; private string _backColorStr = "#50A436";
private Color _backColor = new Color(0, 0, 0, 0); private Color _backColor = new Color(0, 0, 0, 0);
private string _badsCategory; private string _badsCategory;
protected float _badsloadStartTime = 0; protected DateTime _badsloadStartTime;
private bool _bannerVisible = false; private bool _bannerVisible = false;
public bool IsBannerVisible => _bannerVisible; public bool IsBannerVisible => _bannerVisible;
private int _badsloadedNum = 0; private int _badsloadedNum = 0;
private int _badsLoadFailNum = 0; private int _badsLoadFailNum = 0;
/// <summary>
/// 获取动作间隔之间的毫秒数
private int GetAdsLoadDuration(ref float startTime) /// </summary>
/// <param name="startTime"></param>
/// <returns></returns>
private int GetActionDuration(DateTime startTime)
{ {
int duration = (int)((Time.realtimeSinceStartup - startTime) * 1000); var sp = DateTime.UtcNow.Subtract(startTime.ToUniversalTime()).Duration();
startTime = Time.realtimeSinceStartup; return (int) sp.TotalMilliseconds;
return duration;
} }
public virtual void RequestBannerAD() public virtual void RequestBannerAD()
{ {
_backColor = Color.clear; _backColor = Color.clear;
@ -314,12 +325,12 @@ namespace Guru
public void OnLoadBads() public void OnLoadBads()
{ {
_badsloadStartTime = Time.realtimeSinceStartup; _badsloadStartTime = DateTime.UtcNow;
} }
protected virtual void OnBadsLoaded() protected virtual void OnBadsLoaded()
{ {
_badsloadStartTime = Time.realtimeSinceStartup; _badsloadStartTime = DateTime.UtcNow;
OnBannerLoaded?.Invoke(); OnBannerLoaded?.Invoke();
} }
@ -386,6 +397,7 @@ namespace Guru
// --- fixed by Yufei 2024-5-29 为 don't report bads_loaded any more. --- // --- fixed by Yufei 2024-5-29 为 don't report bads_loaded any more. ---
// Analytics.ADBadsLoaded(AdParams.Build(adUnitId, adInfo, // Analytics.ADBadsLoaded(AdParams.Build(adUnitId, adInfo,
// duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory)); // duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory));
Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}");
OnBadsLoaded(); OnBadsLoaded();
} }
@ -394,7 +406,7 @@ namespace Guru
_badsLoadFailNum ++; _badsLoadFailNum ++;
// Analytics.ADBadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _badsloadStartTime), _badsCategory); // Analytics.ADBadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _badsloadStartTime), _badsCategory);
Analytics.ADBadsFailed(AdParams.Build(adUnitId, Analytics.ADBadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory, duration: GetActionDuration(_badsloadStartTime), category: _badsCategory,
errorCode: (int)errorInfo.Code, errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? "")); waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
} }
@ -426,7 +438,8 @@ namespace Guru
{ {
if (_bannerVisible) if (_bannerVisible)
{ {
OnAdRevenuePaidEvent(adUnitId, adInfo); // Banner 只有显示时才上报收益值 // Banner 只有显示时才上报收益值
AppendImpressionData(adInfo, eventName:Analytics.EventBadsPaid, itemCategory:_badsCategory);
} }
} }
@ -436,9 +449,12 @@ namespace Guru
private string _iadsCategory = "main"; private string _iadsCategory = "main";
private int _interstitialRetryAttempt; private int _interstitialRetryAttempt;
protected float _iadsLoadStartTime;
private Action _interCloseAction; private Action _interCloseAction;
protected bool _isIadsLoading = false; protected bool _isIadsLoading = false;
protected DateTime _iadsLoadStartTime;
private DateTime _iadsDisplayStartTime;
public bool IsIadsLoading => _isIadsLoading; public bool IsIadsLoading => _isIadsLoading;
public virtual void RequestInterstitialAD() public virtual void RequestInterstitialAD()
@ -462,7 +478,7 @@ namespace Guru
public void OnLoadIads() public void OnLoadIads()
{ {
_iadsLoadStartTime = Time.realtimeSinceStartup; _iadsLoadStartTime = DateTime.UtcNow;
} }
@ -496,6 +512,7 @@ namespace Guru
_interCloseAction = dismissAction; _interCloseAction = dismissAction;
MaxSdk.ShowInterstitial(GetInterstitialID()); MaxSdk.ShowInterstitial(GetInterstitialID());
_iadsDisplayStartTime = DateTime.UtcNow;
// RequestInterstitialAD(); // 直接加载下一个广告 // RequestInterstitialAD(); // 直接加载下一个广告
} }
@ -506,9 +523,11 @@ namespace Guru
// Reset retry attempt // Reset retry attempt
// Analytics.ADIadsLoaded(adUnitId, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory); // Analytics.ADIadsLoaded(adUnitId, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
Analytics.ADIadsLoaded(AdParams.Build(adUnitId, Analytics.ADIadsLoaded(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory)); duration: GetActionDuration(_iadsLoadStartTime), category: _iadsCategory));
_interstitialRetryAttempt = 0; _interstitialRetryAttempt = 0;
Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}");
OnInterstitialLoaded?.Invoke(); OnInterstitialLoaded?.Invoke();
} }
@ -523,8 +542,9 @@ namespace Guru
float retryDelay = GetRetryDelaySeconds(_interstitialRetryAttempt); float retryDelay = GetRetryDelaySeconds(_interstitialRetryAttempt);
DelayCall(retryDelay, RequestInterstitialAD); DelayCall(retryDelay, RequestInterstitialAD);
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory); // Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
if(string.IsNullOrEmpty(_iadsCategory)) _iadsCategory = "not_set";
Analytics.ADIadsFailed(AdParams.Build(adUnitId, Analytics.ADIadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory, duration: GetActionDuration(_iadsLoadStartTime), category: _iadsCategory,
errorCode: (int)errorInfo.Code, errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? "")); waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
@ -539,42 +559,61 @@ namespace Guru
$"InterstitialFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}"); $"InterstitialFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory); // Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
Analytics.ADIadsFailed(AdParams.Build(adUnitId, Analytics.ADIadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory, duration: GetActionDuration(_iadsDisplayStartTime), category: _iadsCategory,
errorCode: (int)errorInfo.Code, errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? "")); waterfallName: errorInfo.WaterfallInfo?.Name ?? ""));
DelayCall(2.0f, RequestInterstitialAD); DelayCall(2.0f, RequestInterstitialAD);
} }
// iads_imp
protected virtual void OnInterstitialDisplayEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) protected virtual void OnInterstitialDisplayEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{ {
// Analytics.ADIadsImp(adUnitId, _iadsCategory); // Analytics.ADIadsImp(adUnitId, _iadsCategory);
Analytics.ADIadsImp(AdParams.Build(adUnitId, category: _iadsCategory)); AppendImpressionData(adInfo, eventName:Analytics.EventIadsImp, itemCategory:_iadsCategory);
} }
protected virtual void OnInterstitialClickEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) protected virtual void OnInterstitialClickEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{ {
// Analytics.ADIadsClick(adUnitId, _iadsCategory); // Analytics.ADIadsClick(adUnitId, _iadsCategory);
Analytics.ADIadsClick(AdParams.Build(adUnitId, category: _iadsCategory)); if(string.IsNullOrEmpty(_iadsCategory)) _iadsCategory = "not_set";
AppendImpressionData(adInfo,
eventName:Analytics.EventIadsClick,
itemCategory:_iadsCategory);
} }
// Close
protected virtual void OnInterstitialDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) protected virtual void OnInterstitialDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{ {
// Interstitial ad is hidden. Pre-load the next ad // Interstitial ad is hidden. Pre-load the next ad
_interCloseAction?.Invoke(); _interCloseAction?.Invoke();
OnInterstitialClosed?.Invoke(); OnInterstitialClosed?.Invoke();
// Analytics.ADIadsClose(adUnitId, _iadsCategory); // Analytics.ADIadsClose(adUnitId, _iadsCategory);
Analytics.ADIadsClose(AdParams.Build(adUnitId, category: _iadsCategory)); Analytics.ADIadsClose(new Dictionary<string, object>()
{
[Analytics.ParameterItemCategory] = _iadsCategory,
[Analytics.ParameterDuration] = GetActionDuration(_iadsDisplayStartTime),
});
_impressionDriver.CleanCreativeId(adInfo.CreativeIdentifier);
//延时加载下一个广告 //延时加载下一个广告
DelayCall(2.0f, RequestInterstitialAD); DelayCall(2.0f, RequestInterstitialAD);
} }
private void OnInterstitialPaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
AppendImpressionData(adInfo, eventName:Analytics.EventIadsPaid, itemCategory: _iadsCategory);
}
#endregion #endregion
#region Rewarded Ads #region Rewarded Ads
private string _rewardCategory = "main"; private string _rewardCategory = "main";
private int _rewardRetryAttempt; private int _rewardRetryAttempt;
protected float _radsLoadStartTime; protected DateTime _radsLoadStartTime;
protected DateTime _radsShowStartTime;
private Action _rvRewardAction; private Action _rvRewardAction;
private Action<string> _rvFailAction; private Action<string> _rvFailAction;
private Action _rvDismissAction; private Action _rvDismissAction;
@ -607,7 +646,7 @@ namespace Guru
public void OnLoadRads() public void OnLoadRads()
{ {
_radsLoadStartTime = Time.realtimeSinceStartup; _radsLoadStartTime = DateTime.UtcNow;
} }
@ -646,6 +685,8 @@ namespace Guru
_rvDismissAction = dismissAction; _rvDismissAction = dismissAction;
MaxSdk.ShowRewardedAd(GetRewardedID()); MaxSdk.ShowRewardedAd(GetRewardedID());
_radsShowStartTime = DateTime.UtcNow;
// RequestRewardedAD(); // RequestRewardedAD();
} }
@ -658,9 +699,11 @@ namespace Guru
// this.Log("OnRewardedAdLoadedEvent"); // this.Log("OnRewardedAdLoadedEvent");
// Analytics.ADRadsLoaded(adUnitId, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory); // Analytics.ADRadsLoaded(adUnitId, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsLoaded(AdParams.Build(adUnitId, Analytics.ADRadsLoaded(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _iadsCategory)); duration: GetActionDuration(_radsLoadStartTime), category: _iadsCategory));
_rewardRetryAttempt = 0; _rewardRetryAttempt = 0;
Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}");
OnRewardLoaded?.Invoke(); OnRewardLoaded?.Invoke();
} }
@ -674,7 +717,7 @@ namespace Guru
$"OnRewardedAdFailedEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}"); $"OnRewardedAdFailedEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory); // Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsFailed(AdParams.Build(adUnitId, Analytics.ADRadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory, duration: GetActionDuration(_radsLoadStartTime), category: _rewardCategory,
errorCode: (int)errorInfo.Code, errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? "")); waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
_rewardRetryAttempt++; _rewardRetryAttempt++;
@ -692,7 +735,7 @@ namespace Guru
$"OnRewardedAdFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}"); $"OnRewardedAdFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory); // Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsFailed(AdParams.Build(adUnitId, Analytics.ADRadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory, duration: GetActionDuration(_radsShowStartTime), category: _rewardCategory,
errorCode: (int)errorInfo.Code, errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? "")); waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
_rvFailAction?.Invoke("OnRewardedAdFailedToDisplayEvent"); _rvFailAction?.Invoke("OnRewardedAdFailedToDisplayEvent");
@ -705,16 +748,17 @@ namespace Guru
{ {
this.Log("OnRewardedAdDisplayedEvent"); this.Log("OnRewardedAdDisplayedEvent");
// Analytics.ADRadsImp(adUnitId, _rewardCategory); // Analytics.ADRadsImp(adUnitId, _rewardCategory);
Analytics.ADRadsImp(AdParams.Build(adUnitId, category: _rewardCategory)); AppendImpressionData(adInfo, eventName:Analytics.EventRadsImp, itemCategory: _rewardCategory);
} }
protected virtual void OnRewardedAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) protected virtual void OnRewardedAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{ {
this.Log("OnRewardedAdClickedEvent"); this.Log("OnRewardedAdClickedEvent");
// Analytics.ADRadsClick(adUnitId, _rewardCategory); // Analytics.ADRadsClick(adUnitId, _rewardCategory);
Analytics.ADRadsClick(AdParams.Build(adUnitId, category: _rewardCategory)); AppendImpressionData(adInfo, eventName:Analytics.EventRadsClick, itemCategory: _rewardCategory);
} }
// rads_close
protected virtual void OnRewardedAdDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) protected virtual void OnRewardedAdDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{ {
this.Log("OnRewardedAdDismissedEvent"); this.Log("OnRewardedAdDismissedEvent");
@ -723,24 +767,36 @@ namespace Guru
OnRewardClosed?.Invoke(); OnRewardClosed?.Invoke();
// Analytics.ADRadsClose(adUnitId, _rewardCategory); // Analytics.ADRadsClose(adUnitId, _rewardCategory);
Analytics.ADRadsClose(AdParams.Build(adUnitId, category: _rewardCategory)); Analytics.ADRadsClose(new Dictionary<string, object>()
{
[Analytics.ParameterItemCategory] = _rewardCategory,
[Analytics.ParameterDuration] = GetActionDuration(_radsShowStartTime),
});
_impressionDriver.CleanCreativeId(adInfo.CreativeIdentifier);
//延时加载下一个广告 //延时加载下一个广告
DelayCall(2.0f, RequestRewardedAD); DelayCall(2.0f, RequestRewardedAD);
} }
// rads_rewarded
protected virtual void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward, protected virtual void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward,
MaxSdkBase.AdInfo arg3) MaxSdkBase.AdInfo adInfo)
{ {
this.Log("OnRewardedAdReceivedRewardEvent"); this.Log("OnRewardedAdReceivedRewardEvent");
// Analytics.ADRadsRewarded(adUnitId, _rewardCategory); // Analytics.ADRadsRewarded(adUnitId, _rewardCategory);
Analytics.ADRadsRewarded(AdParams.Build(adUnitId, category: _rewardCategory)); AppendImpressionData(adInfo, eventName:Analytics.EventRadsRewarded, itemCategory: _rewardCategory);
// Rewarded ad was displayed and user should receive the reward
_rvRewardAction?.Invoke(); _rvRewardAction?.Invoke();
} }
// rads_paid
private void OnRewardedAdPaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
this.Log("OnRewardedAdReceivedRewardEvent");
AppendImpressionData(adInfo, eventName:Analytics.EventRadsPaid, itemCategory: _rewardCategory);
}
#endregion #endregion
#region Ad Settings #region Ad Settings
@ -782,5 +838,87 @@ namespace Guru
} }
#endregion #endregion
#region ImpressionData
const int MAX_BADS_CID_NUMBER = 6;
private List<string> _badsCreativeIds = new List<string>(MAX_BADS_CID_NUMBER);
/// <summary>
/// 构建 Impression 数据
/// </summary>
/// <param name="adInfo"></param>
/// <param name="reviewCreativeId"></param>
/// <param name="platform"></param>
/// <param name="eventName"></param>
/// <param name="itemCategory"></param>
/// <param name="duration"></param>
/// <returns></returns>
private AdImpressionData CreateImpressionData(MaxSdkBase.AdInfo adInfo,
string reviewCreativeId = "", string platform = "",
string eventName = "", string itemCategory = "", int duration = 0)
{
var impression = AdImpressionDriver.Build(adInfo.Revenue, Analytics.USD, platform,
adInfo.NetworkName,
adInfo.AdFormat,
adInfo.AdUnitIdentifier,
adInfo.NetworkPlacement,
adInfo.CreativeIdentifier, reviewCreativeId,
eventName, itemCategory, duration);
return impression;
}
/// <summary>
/// 添加一条ImpressionData 数据
/// </summary>
/// <param name="adInfo"></param>
/// <param name="reviewCreativeId"></param>
/// <param name="platform"></param>
/// <param name="eventName"></param>
/// <param name="itemCategory"></param>
/// <param name="duration"></param>
/// <returns></returns>
private void AppendImpressionData(MaxSdkBase.AdInfo adInfo, string reviewCreativeId = "", string platform = "", string eventName = "", string itemCategory = "", int duration = 0)
{
var data = CreateImpressionData(adInfo, reviewCreativeId, platform, eventName, itemCategory, duration);
_impressionDriver.Append(data);
}
/// <summary>
/// 获取 AdReviewCreativeId 后的回调
/// </summary>
/// <param name="adUnitId"></param>
/// <param name="reviewCreativeId"></param>
/// <param name="adInfo"></param>
private void OnAdReviewCreativeIdGeneratedEvent(string adUnitId, string reviewCreativeId, MaxSdkBase.AdInfo adInfo)
{
Debug.Log($"{Tag} --- ReviewCreativeId:{reviewCreativeId} adUnitId: {adUnitId} Type:{adInfo?.AdFormat ?? "NULL"} CreativeId: {adInfo?.CreativeIdentifier ?? "NULL"} Revenue:{adInfo.Revenue}");
if (string.IsNullOrEmpty(adInfo.CreativeIdentifier))
{
Debug.LogError($"{Tag} --- Get ReviewCreativeId:{reviewCreativeId} but CreativeIdentifier is null");
return;
}
_impressionDriver.SetReviewCreativeId(adInfo.CreativeIdentifier, reviewCreativeId); // 缓存 ReviewCreateId
if (adUnitId == GetBannerID() || adInfo.AdFormat.ToUpper().Contains("BANNER"))
{
// 清理 BADS CID 缓存
_badsCreativeIds.Add(adInfo.CreativeIdentifier);
if (_badsCreativeIds.Count > MAX_BADS_CID_NUMBER)
{
var cid = _badsCreativeIds[0];
_badsCreativeIds.Remove(cid);
_impressionDriver.CleanCreativeId(cid);
}
}
}
#endregion
} }
} }

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1866d6a2a7d7447b867e491b9354a49b
timeCreated: 1722313457

View File

@ -0,0 +1,185 @@
namespace Guru.Ads
{
using System;
using System.Collections.Generic;
/// <summary>
/// AdImpression 对象
/// </summary>
public class AdImpressionData
{
private const int MAX_VALUE_LENGTH = 96;
public double value;
public string currency = "USD";
public string ad_platform = "MAX";
public string ad_source;
public string ad_format;
public string ad_unit_name;
public string ad_placement;
public string ad_creative_id;
public string review_creative_id;
public string event_name;
public DateTime createTime;
public string item_category;
public int duration;
public AdImpressionData()
{
createTime = DateTime.UtcNow;
}
public override string ToString()
{
return $"[AdImpressionData] ad_unit_name:{ad_unit_name} value:{value} currency:{currency} ad_platform:{ad_platform} ad_source:{ad_source} ad_format:{ad_format} ad_placement:{ad_placement} ad_creative_id:{ad_creative_id} review_creative_id:{review_creative_id} event_name:{event_name} duration:{duration} item_category:{item_category}";
}
public bool EqualsCreativeId(string cid)
{
if (string.IsNullOrEmpty(cid)) return false;
return ad_creative_id.Equals(cid);
}
public bool EqualsReviewCreativeId(string rcid)
{
if (string.IsNullOrEmpty(rcid)) return false;
return review_creative_id.Equals(rcid);
}
/// <summary>
/// 设置 CreativeId
/// </summary>
/// <param name="creativeId"></param>
public void SetCreativeId(string creativeId)
{
ad_creative_id = FixStringLength(creativeId);
}
/// <summary>
/// 设置 ReviewCreativeId
/// </summary>
/// <param name="reviewCreativeId"></param>
public void SetReviewCreativeId(string reviewCreativeId)
{
if (string.IsNullOrEmpty(reviewCreativeId)) return;
review_creative_id = FixStringLength(reviewCreativeId);
}
/// <summary>
/// 限制字符串长度为 96
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
private string FixStringLength(string source)
{
return source.Length <= MAX_VALUE_LENGTH ? source : source.Substring(0, MAX_VALUE_LENGTH);
}
/// <summary>
/// 获取自创建开始经过的秒数
/// </summary>
/// <returns></returns>
public double GetPassedSecond()
{
return (DateTime.UtcNow - createTime).TotalSeconds;
}
public Dictionary<string, object> BuildEventData()
{
var data = new Dictionary<string, object>()
{
{ "value", value },
{ "currency", currency },
{ "ad_platform", ad_platform },
{ "ad_format", ad_format },
{ "ad_source", ad_source },
{ "ad_unit_name", ad_unit_name },
{ "ad_placement", ad_placement },
{ "ad_creative_id", ad_creative_id },
{ "review_creative_id", review_creative_id },
};
return data;
}
public Dictionary<string, object> BuildEventAdImpData()
{
var data = new Dictionary<string, object>()
{
{ "ad_platform", ad_platform },
{ "ad_source", ad_source },
{ "ad_unit_name", ad_unit_name },
{ "ad_placement", ad_placement },
{ "ad_creative_id", ad_creative_id },
{ "review_creative_id", review_creative_id },
{ "item_category", item_category}
};
return data;
}
public Dictionary<string, object> BuildEventAdClickData()
{
var data = new Dictionary<string, object>()
{
{ "value", value },
{ "currency", currency },
{ "ad_platform", ad_platform },
{ "ad_source", ad_source },
{ "ad_unit_name", ad_unit_name },
{ "ad_placement", ad_placement },
{ "ad_creative_id", ad_creative_id },
{ "review_creative_id", review_creative_id },
{ "item_category", item_category}
};
return data;
}
public Dictionary<string, object> BuildEventAdPaidData()
{
var data = new Dictionary<string, object>()
{
{ "value", value },
{ "currency", currency },
{ "ad_platform", ad_platform },
{ "ad_source", ad_source },
{ "ad_unit_name", ad_unit_name },
{ "ad_placement", ad_placement },
{ "ad_creative_id", ad_creative_id },
{ "review_creative_id", review_creative_id },
{ "item_category", item_category}
};
return data;
}
public Dictionary<string, object> BuildEventAdRewardedData()
{
var data = new Dictionary<string, object>()
{
{ "value", value },
{ "currency", currency },
{ "ad_platform", ad_platform },
{ "ad_source", ad_source },
{ "ad_unit_name", ad_unit_name },
{ "ad_placement", ad_placement },
{ "ad_creative_id", ad_creative_id },
{ "review_creative_id", review_creative_id },
{ "item_category", item_category}
};
return data;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1aca2a4507b94dfe9f88040125708edb
timeCreated: 1721883318

View File

@ -0,0 +1,251 @@
namespace Guru.Ads
{
// using System.Collections.Concurrent;
using System;
using System.Collections.Generic;
using UnityEngine;
public class AdImpressionDriver
{
private const string Tag = "[SDK][ADS]";
private const double NEED_FLUSH_TIME = 40.0; // 单条 Impression data 存在的最大间隔时间(秒)
private List<AdImpressionData> _impressionData; // 所有缓存待上报的 impression data
private Dictionary<string, string> _savedReviewCreativeIds;
private Action<AdImpressionData> _onReportAdsRevenue;
public static AdImpressionData Build(double value, string currency,
string adPlatform, string adSource, string adFormat,
string adUnitName, string adPlacement, string adCreativeID, string reviewCreativeID,
string eventName = "", string itemCategory = "", int duration = 0)
{
if (string.IsNullOrEmpty(adPlatform)) adPlatform = Analytics.AdMAX;
if (string.IsNullOrEmpty(itemCategory)) itemCategory = "not_set";
if (string.IsNullOrEmpty(eventName)) eventName = Analytics.EventAdImpression;
var data = new AdImpressionData()
{
value = value,
currency = currency,
ad_platform = adPlatform,
ad_source = adSource,
ad_format = adFormat,
ad_unit_name = adUnitName,
ad_placement = adPlacement,
ad_creative_id = adCreativeID,
event_name = eventName,
item_category = itemCategory,
duration = duration,
};
data.SetCreativeId(adCreativeID);
data.SetReviewCreativeId(reviewCreativeID);
return data;
}
public void Init(Action<AdImpressionData> onReportRevenue)
{
_impressionData = new List<AdImpressionData>(20);
_savedReviewCreativeIds = new Dictionary<string, string>(100);
_onReportAdsRevenue = onReportRevenue;
}
public bool IsCreativeIdExists(string creativeId) => _savedReviewCreativeIds.ContainsKey(creativeId);
public void SetReviewCreativeId(string creativeId, string reviewCreativeId)
{
bool isCidExists = IsCreativeIdExists(creativeId);
_savedReviewCreativeIds[creativeId] = reviewCreativeId;
if (isCidExists && !string.IsNullOrEmpty(reviewCreativeId))
{
FlushAllImpressionData(creativeId, reviewCreativeId);
}
}
/// <summary>
/// 强制发送相关的数据
/// </summary>
/// <param name="creativeId"></param>
public void CleanCreativeId(string creativeId)
{
if (string.IsNullOrEmpty(creativeId)) return;
if (IsCreativeIdExists(creativeId))
{
FlushAllImpressionData(creativeId, "", true);
}
RemoveCreativeId(creativeId); //清理对应的 createId
}
private string GetReviewCreativeId(string creativeId)
{
if(string.IsNullOrEmpty(creativeId)) return "";
return _savedReviewCreativeIds.GetValueOrDefault(creativeId, "");
}
public void RemoveCreativeId(string creativeId)
{
if (IsCreativeIdExists(creativeId))
{
_savedReviewCreativeIds.Remove(creativeId);
}
}
/// <summary>
/// 添加一条Impression数据
/// </summary>
/// <param name="data"></param>
public void Append(AdImpressionData data)
{
if (CanFlushData(data))
{
// 立即触发数据
FlushImpressionData(data);
}
else
{
if (!IsCreativeIdExists(data.ad_creative_id))
{
SetReviewCreativeId(data.ad_creative_id, "");
}
// 缓存数据
PushImpressionData(data);
}
}
private void PushImpressionData(AdImpressionData data)
{
_impressionData.Add(data);
}
private bool CanFlushData(AdImpressionData data)
{
// #1 如果超时, 强制上报
if (data.GetPassedSecond() > NEED_FLUSH_TIME) return true;
// #2 如果 cid 和 rcid 都赋值了 则上报
if (!string.IsNullOrEmpty(data.review_creative_id)) return true;
// #3 如果 rcid 为空, 但是可以找到,也上报
var rcid = GetReviewCreativeId(data.ad_creative_id);
if (!string.IsNullOrEmpty(rcid))
{
data.SetReviewCreativeId(rcid);
return true;
}
return false;
}
/// <summary>
/// 触发所有相关的 cid 和 reviewCreateId
/// </summary>
/// <param name="creativeId"></param>
/// <param name="reviewCreativeId"></param>
/// <param name="force">强制触发</param>
private void FlushAllImpressionData(string creativeId, string reviewCreativeId = "", bool force = false)
{
List<AdImpressionData> tmp = new List<AdImpressionData>(_impressionData.Count);
if(string.IsNullOrEmpty(reviewCreativeId)) reviewCreativeId = GetReviewCreativeId(creativeId); //获取 reviewCreativeId
foreach(var data in _impressionData)
{
if (data.EqualsCreativeId(creativeId))
{
data.SetReviewCreativeId(reviewCreativeId);
if (CanFlushData(data) || force)
{
FlushImpressionData(data);
}
else
{
tmp.Add(data);
}
}
else if (CanFlushData(data))
{
FlushImpressionData(data);
}
else
{
tmp.Add(data);
}
}
_impressionData = tmp;
}
/// <summary>
/// 输出一个 Impression 事件
/// </summary>
/// <param name="data"></param>
private void FlushImpressionData(AdImpressionData data)
{
Debug.Log($"{Tag} --- FlushImpressionData: {data}");
switch (data.event_name)
{
case Analytics.EventBadsPaid:
// BADS 收入事件
// BADS 尚未统计 bads_paid 打点
_onReportAdsRevenue?.Invoke(data);
break;
case Analytics.EventIadsImp:
Analytics.ADIadsImp(data.BuildEventAdImpData());
break;
case Analytics.EventIadsClick:
Analytics.ADIadsClick(data.BuildEventAdClickData());
break;
case Analytics.EventIadsPaid:
// IADS 收入事件
Analytics.ADIadsPaid(data.BuildEventAdPaidData());
_onReportAdsRevenue?.Invoke(data);
break;
case Analytics.EventRadsImp:
Analytics.ADRadsImp(data.BuildEventAdImpData());
break;
case Analytics.EventRadsClick:
Analytics.ADRadsClick(data.BuildEventAdClickData());
break;
case Analytics.EventRadsRewarded:
Analytics.ADRadsRewarded(data.BuildEventAdRewardedData());
break;
case Analytics.EventRadsPaid:
// RADS 收入事件
Analytics.ADRadsPaid(data.BuildEventAdPaidData());
_onReportAdsRevenue?.Invoke(data);
break;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7194cdd8ed1447508011264371e2c23d
timeCreated: 1722313472

View File

@ -22,7 +22,7 @@ namespace Guru
} }
} }
private static AdjustEvent CreateAdjustEvent(string eventName) internal static AdjustEvent CreateAdjustEvent(string eventName)
{ {
string tokenID = GetAdjustEventToken(eventName); string tokenID = GetAdjustEventToken(eventName);
if (string.IsNullOrEmpty(tokenID)) if (string.IsNullOrEmpty(tokenID))

View File

@ -36,15 +36,37 @@ namespace Guru
if (adParams.duration > 0) if (adParams.duration > 0)
data[ParameterDuration] = adParams.duration; data[ParameterDuration] = adParams.duration;
if (adParams.errorCode != 0) if (adParams.errorCode != 0)
data[ParameterErrorCode] = adParams.errorCode; data[ParameterErrorCode] = adParams.errorCode;
if (!string.IsNullOrEmpty(adParams.networkName)) if (!string.IsNullOrEmpty(adParams.networkName))
data[ParameterNetworkName] = adParams.networkName; data[ParameterNetworkName] = adParams.networkName;
if (!string.IsNullOrEmpty(adParams.networkPlacement)) if (!string.IsNullOrEmpty(adParams.networkPlacement))
{
data[ParameterNetworkPlacement] = adParams.networkPlacement; data[ParameterNetworkPlacement] = adParams.networkPlacement;
data[ParameterAdPlacement] = adParams.networkPlacement;
}
if (!string.IsNullOrEmpty(adParams.waterfallName)) if (!string.IsNullOrEmpty(adParams.waterfallName))
data[ParameterWaterfall] = adParams.waterfallName; data[ParameterWaterfall] = adParams.waterfallName;
if (!string.IsNullOrEmpty(adParams.creativeId))
data[ParameterAdCreativeId] = adParams.creativeId;
if (!string.IsNullOrEmpty(adParams.reviewCreativeId))
data[ParameterReviewCreativeId] = adParams.reviewCreativeId;
if (!string.IsNullOrEmpty(adParams.adPlatform))
data[ParameterAdPlatform] = adParams.adPlatform;
if (!string.IsNullOrEmpty(adParams.adSource))
data[ParameterAdSource] = adParams.adSource;
if (!string.IsNullOrEmpty(adParams.adFormat))
data[ParameterAdFormat] = adParams.adFormat;
if (extra != null && extra.Count > 0) if (extra != null && extra.Count > 0)
{ {
foreach (var k in extra.Keys) foreach (var k in extra.Keys)
@ -59,26 +81,26 @@ namespace Guru
//---------------------- BANNER ------------------------- //---------------------- BANNER -------------------------
public static void ADBadsLoad(AdParams adParams) public static void ADBadsLoad(AdParams adParams)
{ {
LogEvent(EventBadsLoad, BuildAdEventData(adParams)); TrackEvent(EventBadsLoad, BuildAdEventData(adParams));
} }
public static void ADBadsLoaded(AdParams adParams) public static void ADBadsLoaded(AdParams adParams)
{ {
LogEvent(EventBadsLoaded, BuildAdEventData(adParams)); TrackEvent(EventBadsLoaded, BuildAdEventData(adParams));
} }
public static void ADBadsFailed(AdParams adParams) public static void ADBadsFailed(AdParams adParams)
{ {
LogEvent(EventBadsFailed, BuildAdEventData(adParams)); TrackEvent(EventBadsFailed, BuildAdEventData(adParams));
} }
/// <summary> /// <summary>
/// 广告点击 /// 广告点击
/// </summary> /// </summary>
public static void ADBadsClick(AdParams adParams) public static void ADBadsClick(AdParams adParams)
{ {
LogEvent(EventBadsClick, BuildAdEventData(adParams)); TrackEvent(EventBadsClick, BuildAdEventData(adParams));
} }
public static void ADBadsImp(AdParams adParams) public static void ADBadsImp(AdParams adParams)
{ {
LogEvent(EventBadsImp, BuildAdEventData(adParams)); TrackEvent(EventBadsImp, BuildAdEventData(adParams));
} }
public static void ADBadsHide( int loadedTimes, int failTimes) public static void ADBadsHide( int loadedTimes, int failTimes)
@ -88,7 +110,7 @@ namespace Guru
["loaded_times"] = loadedTimes, ["loaded_times"] = loadedTimes,
["fail_times"] = failTimes ["fail_times"] = failTimes
}; };
LogEvent(EventBadsHide, dict); TrackEvent(EventBadsHide, dict);
} }
//---------------------- INTERSTITIAL ------------------------- //---------------------- INTERSTITIAL -------------------------
/// <summary> /// <summary>
@ -96,7 +118,7 @@ namespace Guru
/// </summary> /// </summary>
public static void ADIadsLoad(AdParams adParams) public static void ADIadsLoad(AdParams adParams)
{ {
LogEvent(EventIadsLoad, BuildAdEventData(adParams)); TrackEvent(EventIadsLoad, BuildAdEventData(adParams));
} }
/// <summary> /// <summary>
@ -104,7 +126,7 @@ namespace Guru
/// </summary> /// </summary>
public static void ADIadsLoaded(AdParams adParams) public static void ADIadsLoaded(AdParams adParams)
{ {
LogEvent(EventIadsLoaded, BuildAdEventData(adParams)); TrackEvent(EventIadsLoaded, BuildAdEventData(adParams));
} }
/// <summary> /// <summary>
@ -112,7 +134,7 @@ namespace Guru
/// </summary> /// </summary>
public static void ADIadsFailed(AdParams adParams) public static void ADIadsFailed(AdParams adParams)
{ {
LogEvent(EventIadsFailed, BuildAdEventData(adParams)); TrackEvent(EventIadsFailed, BuildAdEventData(adParams));
} }
/// <summary> /// <summary>
@ -120,7 +142,12 @@ namespace Guru
/// </summary> /// </summary>
public static void ADIadsImp(AdParams adParams) public static void ADIadsImp(AdParams adParams)
{ {
LogEvent(EventIadsImp, BuildAdEventData(adParams)); ADIadsImp(BuildAdEventData(adParams));
}
public static void ADIadsImp(Dictionary<string, dynamic> data)
{
TrackEvent(EventIadsImp, data);
} }
/// <summary> /// <summary>
@ -128,7 +155,12 @@ namespace Guru
/// </summary> /// </summary>
public static void ADIadsClick(AdParams adParams) public static void ADIadsClick(AdParams adParams)
{ {
LogEvent(EventIadsClick, BuildAdEventData(adParams)); ADIadsClick(BuildAdEventData(adParams));
}
public static void ADIadsClick(Dictionary<string, object> data)
{
TrackEvent(EventIadsClick, data);
} }
/// <summary> /// <summary>
@ -136,7 +168,21 @@ namespace Guru
/// </summary> /// </summary>
public static void ADIadsClose(AdParams adParams) public static void ADIadsClose(AdParams adParams)
{ {
LogEvent(EventIadsClose, BuildAdEventData(adParams)); ADIadsClose(BuildAdEventData(adParams));
}
public static void ADIadsClose(Dictionary<string, object> data)
{
TrackEvent(EventIadsClose, data);
}
/// <summary>
/// 插屏广告收到奖励
/// </summary>
/// <param name="data"></param>
public static void ADIadsPaid(Dictionary<string, object> data)
{
TrackEvent(EventIadsPaid, data);
} }
//---------------------- REWARDS ------------------------- //---------------------- REWARDS -------------------------
@ -145,36 +191,48 @@ namespace Guru
/// </summary> /// </summary>
public static void ADRadsLoad(AdParams adParams) public static void ADRadsLoad(AdParams adParams)
{ {
LogEvent(EventRadsLoad, BuildAdEventData(adParams)); TrackEvent(EventRadsLoad, BuildAdEventData(adParams));
} }
/// <summary> /// <summary>
/// 广告拉取成功 /// 广告拉取成功
/// </summary> /// </summary>
public static void ADRadsLoaded(AdParams adParams) public static void ADRadsLoaded(AdParams adParams)
{ {
LogEvent(EventRadsLoaded, BuildAdEventData(adParams)); TrackEvent(EventRadsLoaded, BuildAdEventData(adParams));
} }
/// <summary> /// <summary>
/// 广告拉取失败 /// 广告拉取失败
/// </summary> /// </summary>
public static void ADRadsFailed(AdParams adParams) public static void ADRadsFailed(AdParams adParams)
{ {
LogEvent(EventRadsFailed, BuildAdEventData(adParams)); TrackEvent(EventRadsFailed, BuildAdEventData(adParams));
} }
/// <summary> /// <summary>
/// 广告展示 /// 广告展示
/// </summary> /// </summary>
public static void ADRadsImp(AdParams adParams) public static void ADRadsImp(AdParams adParams)
{ {
LogEvent(EventRadsImp, BuildAdEventData(adParams)); ADRadsImp(BuildAdEventData(adParams));
} }
public static void ADRadsImp(Dictionary<string, dynamic> data)
{
TrackEvent(EventRadsImp, data);
}
/// <summary> /// <summary>
/// 广告完成观看发奖励 /// 广告完成观看发奖励
/// </summary> /// </summary>
public static void ADRadsRewarded(AdParams adParams) public static void ADRadsRewarded(AdParams adParams)
{ {
var data = BuildAdEventData(adParams); ADRadsRewarded(BuildAdEventData(adParams));
LogEvent(EventRadsRewarded, data); }
public static void ADRadsRewarded(Dictionary<string, object> data)
{
TrackEvent(EventRadsRewarded, data);
if (RadsRewardCount == 0) if (RadsRewardCount == 0)
{ {
@ -183,6 +241,15 @@ namespace Guru
} }
} }
/// <summary>
/// 插屏广告收到奖励
/// </summary>
/// <param name="data"></param>
public static void ADRadsPaid(Dictionary<string, object> data)
{
TrackEvent(EventRadsPaid, data);
}
private static int RadsRewardCount private static int RadsRewardCount
{ {
@ -195,7 +262,7 @@ namespace Guru
/// </summary> /// </summary>
public static void ADRadsFirstRewarded(Dictionary<string, object> data) public static void ADRadsFirstRewarded(Dictionary<string, object> data)
{ {
LogEvent(EventFirstRadsRewarded, data); TrackEvent(EventFirstRadsRewarded, data);
} }
/// <summary> /// <summary>
@ -203,7 +270,12 @@ namespace Guru
/// </summary> /// </summary>
public static void ADRadsClick(AdParams adParams) public static void ADRadsClick(AdParams adParams)
{ {
LogEvent(EventRadsClick, BuildAdEventData(adParams)); ADRadsClick(BuildAdEventData(adParams));
}
public static void ADRadsClick(Dictionary<string, object> data)
{
TrackEvent(EventRadsClick, data);
} }
/// <summary> /// <summary>
@ -211,7 +283,12 @@ namespace Guru
/// </summary> /// </summary>
public static void ADRadsClose(AdParams adParams) public static void ADRadsClose(AdParams adParams)
{ {
LogEvent(EventRadsClose, BuildAdEventData(adParams)); ADRadsClose( BuildAdEventData(adParams));
}
public static void ADRadsClose(Dictionary<string, dynamic> data)
{
TrackEvent(EventRadsClose, data);
} }
#endregion #endregion
@ -235,7 +312,6 @@ namespace Guru
{ "type", type } { "type", type }
}; };
if(!string.IsNullOrEmpty(scene)) dict[ParameterItemName] = scene; if(!string.IsNullOrEmpty(scene)) dict[ParameterItemName] = scene;
LogEvent(EventATTResult, dict);
} }
/// <summary> /// <summary>
@ -261,10 +337,15 @@ namespace Guru
public string category; public string category;
public string networkName; public string networkName;
public string networkPlacement; public string networkPlacement;
public string adPlatform;
public string adSource;
public string adFormat;
public string waterfallName; public string waterfallName;
public string adUnitId; public string adUnitId;
public int errorCode = 0; public int errorCode = 0;
public int duration = 0; public int duration = 0;
public string creativeId;
public string reviewCreativeId;
/// <summary> /// <summary>
@ -276,31 +357,47 @@ namespace Guru
/// <param name="duration"></param> /// <param name="duration"></param>
/// <param name="errorCode"></param> /// <param name="errorCode"></param>
/// <param name="waterfallName"></param> /// <param name="waterfallName"></param>
/// <param name="reviewCreativeId"></param>
/// <param name="adPlatform"></param>
/// <returns></returns> /// <returns></returns>
public static AdParams Build(string adUnitId, MaxSdkBase.AdInfo adInfo = null, string category = "", public static AdParams Build(string adUnitId, MaxSdkBase.AdInfo adInfo = null, string category = "",
int duration = 0, int errorCode = 0, string waterfallName = "") int duration = 0, int errorCode = 0, string waterfallName = "", string reviewCreativeId = "", string adPlatform = "")
{ {
if (string.IsNullOrEmpty(adUnitId) && adInfo != null) adUnitId = adInfo.AdUnitIdentifier; if (string.IsNullOrEmpty(adUnitId) && adInfo != null) adUnitId = adInfo.AdUnitIdentifier;
var networkName = ""; var networkName = "";
var networkPlacement = ""; var networkPlacement = "";
var creativeId = "";
var adSource = "";
var adFormart = "";
if (string.IsNullOrEmpty(adPlatform)) adPlatform = Analytics.AdMAX;
if (adInfo != null) if (adInfo != null)
{ {
networkName = adInfo.NetworkName; networkName = adInfo.NetworkName;
networkPlacement = adInfo.NetworkPlacement; networkPlacement = adInfo.NetworkPlacement;
creativeId = adInfo.CreativeIdentifier;
adSource = adInfo.NetworkName;
adFormart = adInfo.AdFormat;
if (string.IsNullOrEmpty(waterfallName)) if (string.IsNullOrEmpty(waterfallName))
waterfallName = adInfo.WaterfallInfo?.Name ?? ""; waterfallName = adInfo.WaterfallInfo?.Name ?? "";
} }
var p = new AdParams() var p = new AdParams()
{ {
adUnitId = adUnitId, adUnitId = adUnitId,
adPlatform = adPlatform,
adSource = adSource,
adFormat = adFormart,
duration = duration, duration = duration,
networkName = networkName, networkName = networkName,
networkPlacement = networkPlacement, networkPlacement = networkPlacement,
waterfallName = waterfallName, waterfallName = waterfallName,
category = category, category = category,
errorCode = errorCode, errorCode = errorCode,
creativeId = creativeId,
reviewCreativeId = reviewCreativeId,
}; };
return p; return p;
} }

View File

@ -11,112 +11,119 @@ namespace Guru
//打点常量定义 //打点常量定义
public static partial class Analytics public static partial class Analytics
{ {
public static readonly string TAG = "Analytics"; public const string TAG = "Analytics";
// 美元符号 // 美元符号
public static readonly string USD = "USD"; public const string USD = "USD";
// 广告平台 // 广告平台
public static readonly string AdMAX = "MAX"; public const string AdMAX = "MAX";
public const string AdIronSource = "IronSource";
//IAP打点事件 //IAP打点事件
public static readonly string EventIAPFirst = "first_iap"; public const string EventIAPFirst = "first_iap";
public static readonly string EventIAPImp = "iap_imp"; public const string EventIAPImp = "iap_imp";
public static readonly string EventIAPClose = "iap_close"; public const string EventIAPClose = "iap_close";
public static readonly string EventIAPClick = "iap_clk"; public const string EventIAPClick = "iap_clk";
public static readonly string EventIAPReturnTrue = "iap_ret_true"; public const string EventIAPReturnTrue = "iap_ret_true";
public static readonly string EventIAPReturnFalse = "iap_ret_false"; public const string EventIAPReturnFalse = "iap_ret_false";
// 关卡打点 // 关卡打点
public static readonly string EventLevelFirstEnd = "level_first_end"; public const string EventLevelFirstEnd = "level_first_end";
//横幅广告打点事件 //横幅广告打点事件
public static readonly string EventBadsLoad = "bads_load"; public const string EventBadsLoad = "bads_load";
public static readonly string EventBadsLoaded = "bads_loaded"; public const string EventBadsLoaded = "bads_loaded";
public static readonly string EventBadsFailed = "bads_failed"; public const string EventBadsFailed = "bads_failed";
public static readonly string EventBadsClick = "bads_clk"; public const string EventBadsClick = "bads_clk";
public static readonly string EventBadsImp = "bads_imp"; public const string EventBadsImp = "bads_imp";
public static readonly string EventBadsHide = "bads_hide"; public const string EventBadsHide = "bads_hide";
public const string EventBadsPaid = "bads_paid";
//插屏广告打点事件 //插屏广告打点事件
public static readonly string EventIadsLoad = "iads_load"; public const string EventIadsLoad = "iads_load";
public static readonly string EventIadsLoaded = "iads_loaded"; public const string EventIadsLoaded = "iads_loaded";
public static readonly string EventIadsFailed = "iads_failed"; public const string EventIadsFailed = "iads_failed";
public static readonly string EventIadsImp = "iads_imp"; public const string EventIadsImp = "iads_imp";
public static readonly string EventIadsClick = "iads_clk"; public const string EventIadsClick = "iads_clk";
public static readonly string EventIadsClose = "iads_close"; public const string EventIadsClose = "iads_close";
public const string EventIadsPaid = "iads_paid";
//激励视频广告打点事件 //激励视频广告打点事件
public static readonly string EventRadsLoad = "rads_load"; public const string EventRadsLoad = "rads_load";
public static readonly string EventRadsLoaded = "rads_loaded"; public const string EventRadsLoaded = "rads_loaded";
public static readonly string EventRadsFailed = "rads_failed"; public const string EventRadsFailed = "rads_failed";
public static readonly string EventRadsImp = "rads_imp"; public const string EventRadsImp = "rads_imp";
public static readonly string EventRadsRewarded = "rads_rewarded"; public const string EventRadsRewarded = "rads_rewarded";
public static readonly string EventRadsClick = "rads_clk"; public const string EventRadsClick = "rads_clk";
public static readonly string EventRadsClose = "rads_close"; public const string EventRadsClose = "rads_close";
public static readonly string EventFirstRadsRewarded = "first_rads_rewarded"; public const string EventRadsPaid = "rads_paid";
public const string EventFirstRadsRewarded = "first_rads_rewarded";
//广告收益打点事件 //广告收益打点事件
public static readonly string EventTchAdRev001Impression = "tch_ad_rev_roas_001"; public const string EventTchAdRev001Impression = "tch_ad_rev_roas_001";
public static readonly string EventTchAdRev02Impression = "tch_ad_rev_roas_02"; public const string EventTchAdRev02Impression = "tch_ad_rev_roas_02";
public static readonly string EventTchAdRevAbnormal = "tch_ad_rev_value_abnormal"; public const string EventTchAdRevAbnormal = "tch_ad_rev_value_abnormal";
//内购成功事件上报 //内购成功事件上报
public static readonly string EventIAPPurchase = "iap_purchase"; public const string EventIAPPurchase = "iap_purchase";
public static readonly string EventSubPurchase = "sub_purchase"; public const string EventSubPurchase = "sub_purchase";
public static readonly string IAPStoreCategory = "Store"; public const string IAPStoreCategory = "Store";
public static readonly string IAPTypeProduct = "product"; public const string IAPTypeProduct = "product";
public static readonly string IAPTypeSubscription = "subscription"; public const string IAPTypeSubscription = "subscription";
//打点参数名 //打点参数名
public static readonly string ParameterResult = "result"; public const string ParameterResult = "result";
public static readonly string ParameterStep = "step"; public const string ParameterStep = "step";
public static readonly string ParameterDuration = "duration"; public const string ParameterDuration = "duration";
public static readonly string ParameterErrorCode = "error_code"; public const string ParameterErrorCode = "error_code";
public static readonly string ParameterProductId = "product_id"; public const string ParameterProductId = "product_id";
public static readonly string ParameterPlatform = "platform"; public const string ParameterPlatform = "platform";
public static readonly string ParameterStartType = "start_type"; // 游戏启动类型 public const string ParameterStartType = "start_type"; // 游戏启动类型
public static readonly string ParameterReplay = "replay"; // 游戏重玩 public const string ParameterReplay = "replay"; // 游戏重玩
public static readonly string ParameterContinue = "continue"; // 游戏继续 public const string ParameterContinue = "continue"; // 游戏继续
public static readonly string ParameterAdUnitName = "ad_unit_name"; public const string ParameterAdUnitName = "ad_unit_name";
public static readonly string ParameterAdCreativeId = "ad_creative_id"; public const string ParameterAdPlacement = "ad_placement";
public const string ParameterAdCreativeId = "ad_creative_id";
public const string ParameterReviewCreativeId = "review_creative_id";
// 评价参数 // 评价参数
public static readonly string EventRateImp = "rate_imp"; // 评价弹窗展示 public const string EventRateImp = "rate_imp"; // 评价弹窗展示
public static readonly string EventRateNow = "rate_now"; // 点击评分引导弹窗中的评分 public const string EventRateNow = "rate_now"; // 点击评分引导弹窗中的评分
//打点内部执行错误 //打点内部执行错误
public static string ParameterEventError => "event_error"; public static string ParameterEventError => "event_error";
//ios ATT打点 //ios ATT打点
public static readonly string ATTGuideShow = "att_guide_show"; public const string ATTGuideShow = "att_guide_show";
public static readonly string ATTGuideOK = "att_guide_ok"; public const string ATTGuideOK = "att_guide_ok";
public static readonly string ATTWindowShow = "att_window_show"; public const string ATTWindowShow = "att_window_show";
public static readonly string ATTOptIn = "att_opt_in"; public const string ATTOptIn = "att_opt_in";
public static readonly string ATTOpOut = "att_opt_out"; public const string ATTOpOut = "att_opt_out";
public static readonly string ParameterATTStatus = "att_status"; public const string ParameterATTStatus = "att_status";
public static readonly string EventATTResult = "att_result"; public const string EventATTResult = "att_result";
// 用户属性 // 用户属性
public static readonly string PropertyFirstOpenTime = "first_open_time"; //用户第一次first_open的时间 public const string PropertyFirstOpenTime = "first_open_time"; //用户第一次first_open的时间
public static readonly string PropertyDeviceID = "device_id"; //用户的设备ID public const string PropertyDeviceID = "device_id"; //用户的设备ID
public static readonly string PropertyUserID = "user_id"; public const string PropertyUserID = "user_id";
public static readonly string PropertyLevel = "b_level"; //"每次完成通关上升一次显示用户完成的最大关卡数。只针对主关卡和主玩法的局数做累加初始值为0。" public const string PropertyLevel = "b_level"; //"每次完成通关上升一次显示用户完成的最大关卡数。只针对主关卡和主玩法的局数做累加初始值为0。"
public static readonly string PropertyPlay = "b_play"; //每完成一局或者游戏触发, public const string PropertyPlay = "b_play"; //每完成一局或者游戏触发,
public static readonly string PropertyLastPlayedLevel = "last_played_level"; public const string PropertyLastPlayedLevel = "last_played_level";
public static readonly string PropertyGrade = "grade"; //当游戏玩家角色升级时触发 public const string PropertyGrade = "grade"; //当游戏玩家角色升级时触发
public static readonly string PropertyIsIAPUser = "is_iap_user"; //付费成功后设置属性参数为true如果没有发生付费可以不用设置该属性 public const string PropertyIsIAPUser = "is_iap_user"; //付费成功后设置属性参数为true如果没有发生付费可以不用设置该属性
public static readonly string PropertyIAPCoin = "iap_coin"; //付费所得的总金币数(iap获取累计值)\ public const string PropertyIAPCoin = "iap_coin"; //付费所得的总金币数(iap获取累计值)\
public static readonly string PropertyNonIAPCoin = "noniap_coin"; //非付费iap获取累计值 public const string PropertyNonIAPCoin = "noniap_coin"; //非付费iap获取累计值
public static readonly string PropertyCoin = "coin"; //当前金币数 public const string PropertyCoin = "coin"; //当前金币数
public static readonly string PropertyExp = "exp"; // 经验值 public const string PropertyExp = "exp"; // 经验值
public static readonly string PropertyHp = "hp"; // 生命值/体力 public const string PropertyHp = "hp"; // 生命值/体力
public static readonly string PropertyAndroidID = "android_id"; // Android 平台 AndroidID public const string PropertyAndroidID = "android_id"; // Android 平台 AndroidID
public static readonly string PropertyIDFV = "idfv"; // iOS 平台 IDFV public const string PropertyIDFV = "idfv"; // iOS 平台 IDFV
public static readonly string PropertyIDFA = "idfa"; // iOS 平台 IDFA public const string PropertyIDFA = "idfa"; // iOS 平台 IDFA
public static readonly string PropertyPicture = "picture"; // 玩家在主线的mapid public const string PropertyPicture = "picture"; // 玩家在主线的mapid
public static readonly string PropertyNoAds = "no_ads"; // 玩家是否去广告 public const string PropertyNoAds = "no_ads"; // 玩家是否去广告
public static readonly string PropertyATTStatus = "att_status"; // ATT 状态 public const string PropertyATTStatus = "att_status"; // ATT 状态
public static readonly string PropertyGDPR = "gdpr"; // GDPR状态 public const string PropertyGDPR = "gdpr"; // GDPR状态
// 经济相关 // 经济相关
public const string ParameterBalance = "balance"; // 用于余额 public const string ParameterBalance = "balance"; // 用于余额
@ -124,6 +131,6 @@ namespace Guru
public const string ParameterVirtualCurrencyName = "virtual_currency_name"; // 虚拟货币名称 public const string ParameterVirtualCurrencyName = "virtual_currency_name"; // 虚拟货币名称
// 中台 // 中台
public static readonly string EventDevAudit = "dev_audit"; // 中台事件异常 public const string EventDevAudit = "dev_audit"; // 中台事件异常
} }
} }

View File

@ -26,9 +26,7 @@ namespace Guru
public static bool IsDebug { get; set; } = false; public static bool IsDebug { get; set; } = false;
private static bool _hasInited = false; private static bool _isGuruAnalyticInitOnce = false;
public static bool IsReady => _hasInited;
/// <summary> /// <summary>
/// 初始化Guru自打点系统 (请优先于 Firebase 初始化调用) /// 初始化Guru自打点系统 (请优先于 Firebase 初始化调用)
@ -36,7 +34,7 @@ namespace Guru
public static void InstallGuruAnalytics(bool isDebug = false, bool enableErrorLog = false) public static void InstallGuruAnalytics(bool isDebug = false, bool enableErrorLog = false)
{ {
if (_hasInited) return; if (_isGuruAnalyticInitOnce) return;
try try
{ {
@ -47,7 +45,7 @@ namespace Guru
#endif #endif
string appId = IPMConfig.IPM_X_APP_ID; string appId = IPMConfig.IPM_X_APP_ID;
string deviceInfo = new DeviceInfoData().ToString(); string deviceInfo = new DeviceInfoData().ToString();
GuruAnalytics.Init(appId, deviceInfo, IsDebug, enableErrorLog); // 初始化(带Header) GuruAnalytics.Init(appId, deviceInfo, OnGuruAnalyticsInitComplete, IsDebug, enableErrorLog); // 初始化(带Header)
_hasGotFirebaseId = false; _hasGotFirebaseId = false;
_hasGotAdId = false; _hasGotAdId = false;
@ -59,7 +57,7 @@ namespace Guru
UpdateAllValues(); UpdateAllValues();
_hasInited = true; _isGuruAnalyticInitOnce = true;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -79,7 +77,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.IPM_UID)) if (!string.IsNullOrEmpty(IPMConfig.IPM_UID))
{ {
Debug.Log($"---[ANA] UID: {IPMConfig.IPM_UID}"); Debug.Log($"---[ANA] UID: {IPMConfig.IPM_UID}");
GuruAnalytics.SetUid(IPMConfig.IPM_UID); GuruAnalytics.Instance.SetUid(IPMConfig.IPM_UID);
FirebaseAnalytics.SetUserProperty(PropertyUserID, IPMConfig.IPM_UID); FirebaseAnalytics.SetUserProperty(PropertyUserID, IPMConfig.IPM_UID);
_hasGotUid = true; _hasGotUid = true;
} }
@ -95,7 +93,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.IPM_DEVICE_ID)) if (!string.IsNullOrEmpty(IPMConfig.IPM_DEVICE_ID))
{ {
GuruAnalytics.SetDeviceId(IPMConfig.IPM_DEVICE_ID); GuruAnalytics.Instance.SetDeviceId(IPMConfig.IPM_DEVICE_ID);
FirebaseAnalytics.SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID); FirebaseAnalytics.SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID);
_hasGotDeviceId = true; _hasGotDeviceId = true;
} }
@ -121,7 +119,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ID)) if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ID))
{ {
GuruAnalytics.SetAdjustId(IPMConfig.ADJUST_ID); GuruAnalytics.Instance.SetAdjustId(IPMConfig.ADJUST_ID);
_hasGotAdjustId = true; _hasGotAdjustId = true;
} }
else else
@ -152,7 +150,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ADID)) if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ADID))
{ {
GuruAnalytics.SetAdId(IPMConfig.ADJUST_ADID); GuruAnalytics.Instance.SetAdId(IPMConfig.ADJUST_ADID);
_hasGotAdId = true; _hasGotAdId = true;
} }
@ -171,7 +169,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.FIREBASE_ID)) if (!string.IsNullOrEmpty(IPMConfig.FIREBASE_ID))
{ {
GuruAnalytics.SetFirebaseId(IPMConfig.FIREBASE_ID); GuruAnalytics.Instance.SetFirebaseId(IPMConfig.FIREBASE_ID);
_hasGotFirebaseId = true; _hasGotFirebaseId = true;
} }
else else
@ -185,6 +183,8 @@ namespace Guru
/// </summary> /// </summary>
private static void FetchFirebaseId() private static void FetchFirebaseId()
{ {
if (!IsFirebaseReady) return;
FirebaseAnalytics.GetAnalyticsInstanceIdAsync() FirebaseAnalytics.GetAnalyticsInstanceIdAsync()
.ContinueWithOnMainThread(task => .ContinueWithOnMainThread(task =>
{ {
@ -207,12 +207,12 @@ namespace Guru
private static void SetATTStatus() private static void SetATTStatus()
{ {
string status = ATTManager.GetStatus(); string status = ATTManager.GetStatus();
GuruAnalytics.SetUserProperty(ParameterATTStatus, status); GuruAnalytics.Instance.SetUserProperty(ParameterATTStatus, status);
} }
private static void SetIDFV() private static void SetIDFV()
{ {
GuruAnalytics.SetIDFV(DeviceIDHelper.IDFV); GuruAnalytics.Instance.SetIDFV(DeviceIDHelper.IDFV);
} }
private static void SetIDFA() private static void SetIDFA()
@ -228,7 +228,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_IDFA)) if (!string.IsNullOrEmpty(IPMConfig.ADJUST_IDFA))
{ {
GuruAnalytics.SetIDFA(IPMConfig.ADJUST_IDFA); GuruAnalytics.Instance.SetIDFA(IPMConfig.ADJUST_IDFA);
_hasGotIDFA = true; _hasGotIDFA = true;
} }
} }
@ -241,7 +241,7 @@ namespace Guru
/// </summary> /// </summary>
private static void SetAndroidId() private static void SetAndroidId()
{ {
GuruAnalytics.SetAndroidID(DeviceIDHelper.AndroidID); GuruAnalytics.Instance.SetAndroidID(DeviceIDHelper.AndroidID);
} }
#endif #endif
@ -276,7 +276,7 @@ namespace Guru
var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds; var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds;
if (interval > _reportSuccessInterval) if (interval > _reportSuccessInterval)
{ {
GuruAnalytics.ReportEventSuccessRate(); GuruAnalytics.Instance.ReportEventSuccessRate();
_lastReportRateDate = DateTime.Now; _lastReportRateDate = DateTime.Now;
} }
} }
@ -294,7 +294,7 @@ namespace Guru
{ {
try try
{ {
GuruAnalytics.SetUserProperty(key, value); GuruAnalytics.Instance.SetUserProperty(key, value);
UpdateAllValues(); // 同步所有的ID UpdateAllValues(); // 同步所有的ID
} }
catch (Exception e) catch (Exception e)
@ -309,12 +309,12 @@ namespace Guru
/// </summary> /// </summary>
/// <param name="key"></param> /// <param name="key"></param>
/// <param name="data"></param> /// <param name="data"></param>
private static void CustomLogEvent(string key, Dictionary<string, dynamic> data = null, int priority = -1) private static void TrackEventGuru(string key, Dictionary<string, dynamic> data = null, int priority = -1)
{ {
try try
{ {
if (data == null) data = new Dictionary<string, dynamic>(); if (data == null) data = new Dictionary<string, dynamic>();
GuruAnalytics.LogEvent(key, data, priority); GuruAnalytics.Instance.LogEvent(key, data, priority);
UpdateAllValues(); // 同步所有的ID UpdateAllValues(); // 同步所有的ID
} }
catch (Exception e) catch (Exception e)
@ -337,7 +337,7 @@ namespace Guru
if (Math.Abs(_tch02TargetValue - value) > 0.001d) if (Math.Abs(_tch02TargetValue - value) > 0.001d)
{ {
_tch02TargetValue = value; _tch02TargetValue = value;
GuruAnalytics.SetTch02Value(value); GuruAnalytics.Instance.SetTch02Value(value);
} }
} }
} }

View File

@ -103,7 +103,7 @@ namespace Guru
if(!string.IsNullOrEmpty(scene)) data[ParameterScene] = scene; // 获取的虚拟货币或者道具的场景 if(!string.IsNullOrEmpty(scene)) data[ParameterScene] = scene; // 获取的虚拟货币或者道具的场景
if (extra != null) data.AddRange(extra, isOverride: true); if (extra != null) data.AddRange(extra, isOverride: true);
LogEvent(EventEarnVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true }); TrackEvent(EventEarnVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true });
// FB 上报收入点 // FB 上报收入点
FBService.LogEvent(EventEarnVirtualCurrency, value, data); FBService.LogEvent(EventEarnVirtualCurrency, value, data);
@ -131,7 +131,7 @@ namespace Guru
if(!string.IsNullOrEmpty(scene)) data[ParameterScene] = scene; // 获取的虚拟货币或者道具的场景 if(!string.IsNullOrEmpty(scene)) data[ParameterScene] = scene; // 获取的虚拟货币或者道具的场景
LogEvent(EventSpendVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true }); TrackEvent(EventSpendVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true });
// FB 上报消费点 // FB 上报消费点
FBService.LogEvent(EventSpendVirtualCurrency, value, data); FBService.LogEvent(EventSpendVirtualCurrency, value, data);

View File

@ -5,104 +5,104 @@ namespace Guru
//Firebase内置定义事件名称和参数名称 //Firebase内置定义事件名称和参数名称
public static partial class Analytics public static partial class Analytics
{ {
internal static readonly string EventAdImpression = "ad_impression"; internal const string EventAdImpression = "ad_impression";
internal static readonly string EventAddPaymentInfo = "add_payment_info"; internal const string EventAddPaymentInfo = "add_payment_info";
internal static readonly string EventAddShippingInfo = "add_shipping_info"; internal const string EventAddShippingInfo = "add_shipping_info";
internal static readonly string EventAddToCart = "add_to_cart"; internal const string EventAddToCart = "add_to_cart";
internal static readonly string EventAddToWishlist = "add_to_wishlist"; internal const string EventAddToWishlist = "add_to_wishlist";
internal static readonly string EventAppOpen = "app_open"; internal const string EventAppOpen = "app_open";
internal static readonly string EventBeginCheckout = "begin_checkout"; internal const string EventBeginCheckout = "begin_checkout";
internal static readonly string EventCampaignDetails = "campaign_details"; internal const string EventCampaignDetails = "campaign_details";
internal static readonly string EventEarnVirtualCurrency = "earn_virtual_currency"; internal const string EventEarnVirtualCurrency = "earn_virtual_currency";
internal static readonly string EventGenerateLead = "generate_lead"; internal const string EventGenerateLead = "generate_lead";
internal static readonly string EventJoinGroup = "join_group"; internal const string EventJoinGroup = "join_group";
internal static readonly string EventLevelEnd = "level_end"; internal const string EventLevelEnd = "level_end";
internal static readonly string EventLevelStart = "level_start"; internal const string EventLevelStart = "level_start";
internal static readonly string EventLevelUp = "level_up"; internal const string EventLevelUp = "level_up";
internal static readonly string EventLogin = "login"; internal const string EventLogin = "login";
internal static readonly string EventPostScore = "post_score"; internal const string EventPostScore = "post_score";
internal static readonly string EventPurchase = "purchase"; internal const string EventPurchase = "purchase";
internal static readonly string EventRefund = "refund"; internal const string EventRefund = "refund";
internal static readonly string EventRemoveFromCart = "remove_from_cart"; internal const string EventRemoveFromCart = "remove_from_cart";
internal static readonly string EventScreenView = "screen_view"; internal const string EventScreenView = "screen_view";
internal static readonly string EventSearch = "search"; internal const string EventSearch = "search";
internal static readonly string EventSelectContent = "select_content"; internal const string EventSelectContent = "select_content";
internal static readonly string EventSelectItem = "select_item"; internal const string EventSelectItem = "select_item";
internal static readonly string EventSelectPromotion = "select_promotion"; internal const string EventSelectPromotion = "select_promotion";
internal static readonly string EventShare = "share"; internal const string EventShare = "share";
internal static readonly string EventSignUp = "sign_up"; internal const string EventSignUp = "sign_up";
internal static readonly string EventSpendVirtualCurrency = "spend_virtual_currency"; internal const string EventSpendVirtualCurrency = "spend_virtual_currency";
internal static readonly string EventTutorialBegin = "tutorial_begin"; internal const string EventTutorialBegin = "tutorial_begin";
internal static readonly string EventTutorialComplete = "tutorial_complete"; internal const string EventTutorialComplete = "tutorial_complete";
internal static readonly string EventUnlockAchievement = "unlock_achievement"; internal const string EventUnlockAchievement = "unlock_achievement";
internal static readonly string EventViewCart = "view_cart"; internal const string EventViewCart = "view_cart";
internal static readonly string EventViewItem = "view_item"; internal const string EventViewItem = "view_item";
internal static readonly string EventViewItemList = "view_item_list"; internal const string EventViewItemList = "view_item_list";
internal static readonly string EventViewPromotion = "view_promotion"; internal const string EventViewPromotion = "view_promotion";
internal static readonly string EventViewSearchResults = "view_search_results"; internal const string EventViewSearchResults = "view_search_results";
internal static readonly string ParameterAchievementId = "achievement_id"; internal const string ParameterAchievementId = "achievement_id";
internal static readonly string ParameterAdFormat = "ad_format"; internal const string ParameterAdFormat = "ad_format";
internal static readonly string ParameterAdNetworkClickID = "aclid"; internal const string ParameterAdNetworkClickID = "aclid";
internal static readonly string ParameterAdPlatform = "ad_platform"; internal const string ParameterAdPlatform = "ad_platform";
internal static readonly string ParameterAdSource = "ad_source"; internal const string ParameterAdSource = "ad_source";
internal static readonly string ParameterAffiliation = "affiliation"; internal const string ParameterAffiliation = "affiliation";
internal static readonly string ParameterCP1 = "cp1"; internal const string ParameterCP1 = "cp1";
internal static readonly string ParameterCampaign = "campaign"; internal const string ParameterCampaign = "campaign";
internal static readonly string ParameterCharacter = "character"; internal const string ParameterCharacter = "character";
internal static readonly string ParameterContent = "content"; internal const string ParameterContent = "content";
internal static readonly string ParameterContentType = "content_type"; internal const string ParameterContentType = "content_type";
internal static readonly string ParameterCoupon = "coupon"; internal const string ParameterCoupon = "coupon";
internal static readonly string ParameterCreativeName = "creative_name"; internal const string ParameterCreativeName = "creative_name";
internal static readonly string ParameterCreativeSlot = "creative_slot"; internal const string ParameterCreativeSlot = "creative_slot";
internal static readonly string ParameterCurrency = "currency"; internal const string ParameterCurrency = "currency";
internal static readonly string ParameterDestination = "destination"; internal const string ParameterDestination = "destination";
internal static readonly string ParameterDiscount = "discount"; internal const string ParameterDiscount = "discount";
internal static readonly string ParameterEndDate = "end_date"; internal const string ParameterEndDate = "end_date";
internal static readonly string ParameterExtendSession = "extend_session"; internal const string ParameterExtendSession = "extend_session";
internal static readonly string ParameterFlightNumber = "flight_number"; internal const string ParameterFlightNumber = "flight_number";
internal static readonly string ParameterGroupId = "group_id"; internal const string ParameterGroupId = "group_id";
internal static readonly string ParameterIndex = "index"; internal const string ParameterIndex = "index";
internal static readonly string ParameterItemBrand = "item_brand"; internal const string ParameterItemBrand = "item_brand";
internal static readonly string ParameterItemCategory = "item_category"; internal const string ParameterItemCategory = "item_category";
internal static readonly string ParameterItemCategory2 = "item_category2"; internal const string ParameterItemCategory2 = "item_category2";
internal static readonly string ParameterItemCategory3 = "item_category3"; internal const string ParameterItemCategory3 = "item_category3";
internal static readonly string ParameterItemCategory4 = "item_category4"; internal const string ParameterItemCategory4 = "item_category4";
internal static readonly string ParameterItemCategory5 = "item_category5"; internal const string ParameterItemCategory5 = "item_category5";
internal static readonly string ParameterItemId = "item_id"; internal const string ParameterItemId = "item_id";
internal static readonly string ParameterItemList = "item_list"; internal const string ParameterItemList = "item_list";
internal static readonly string ParameterItemListID = "item_list_id"; internal const string ParameterItemListID = "item_list_id";
internal static readonly string ParameterItemListName = "item_list_name"; internal const string ParameterItemListName = "item_list_name";
internal static readonly string ParameterItemName = "item_name"; internal const string ParameterItemName = "item_name";
internal static readonly string ParameterLevel = "level"; internal const string ParameterLevel = "level";
internal static readonly string ParameterLevelName = "level_name"; internal const string ParameterLevelName = "level_name";
internal static readonly string ParameterLocation = "location"; internal const string ParameterLocation = "location";
internal static readonly string ParameterLocationID = "location_id"; internal const string ParameterLocationID = "location_id";
internal static readonly string ParameterMedium = "medium"; internal const string ParameterMedium = "medium";
internal static readonly string ParameterMethod = "method"; internal const string ParameterMethod = "method";
internal static readonly string ParameterNumberOfNights = "number_of_nights"; internal const string ParameterNumberOfNights = "number_of_nights";
internal static readonly string ParameterNumberOfPassengers = "number_of_passengers"; internal const string ParameterNumberOfPassengers = "number_of_passengers";
internal static readonly string ParameterNumberOfRooms = "number_of_rooms"; internal const string ParameterNumberOfRooms = "number_of_rooms";
internal static readonly string ParameterOrigin = "origin"; internal const string ParameterOrigin = "origin";
internal static readonly string ParameterPaymentType = "payment_type"; internal const string ParameterPaymentType = "payment_type";
internal static readonly string ParameterPrice = "price"; internal const string ParameterPrice = "price";
internal static readonly string ParameterPromotionID = "promotion_id"; internal const string ParameterPromotionID = "promotion_id";
internal static readonly string ParameterPromotionName = "promotion_name"; internal const string ParameterPromotionName = "promotion_name";
internal static readonly string ParameterQuantity = "quantity"; internal const string ParameterQuantity = "quantity";
internal static readonly string ParameterScore = "score"; internal const string ParameterScore = "score";
internal static readonly string ParameterScreenClass = "screen_class"; internal const string ParameterScreenClass = "screen_class";
internal static readonly string ParameterScreenName = "screen_name"; internal const string ParameterScreenName = "screen_name";
internal static readonly string ParameterSearchTerm = "search_term"; internal const string ParameterSearchTerm = "search_term";
internal static readonly string ParameterShipping = "shipping"; internal const string ParameterShipping = "shipping";
internal static readonly string ParameterShippingTier = "shipping_tier"; internal const string ParameterShippingTier = "shipping_tier";
internal static readonly string ParameterSignUpMethod = "sign_up_method"; internal const string ParameterSignUpMethod = "sign_up_method";
internal static readonly string ParameterSource = "source"; internal const string ParameterSource = "source";
internal static readonly string ParameterStartDate = "start_date"; internal const string ParameterStartDate = "start_date";
internal static readonly string ParameterSuccess = "success"; internal const string ParameterSuccess = "success";
internal static readonly string ParameterTax = "tax"; internal const string ParameterTax = "tax";
internal static readonly string ParameterTerm = "term"; internal const string ParameterTerm = "term";
internal static readonly string ParameterTransactionId = "transaction_id"; internal const string ParameterTransactionId = "transaction_id";
internal static readonly string ParameterTravelClass = "travel_class"; internal const string ParameterTravelClass = "travel_class";
internal static readonly string ParameterValue = "value"; internal const string ParameterValue = "value";
} }
} }

View File

@ -6,6 +6,7 @@ namespace Guru
using System.Collections.Generic; using System.Collections.Generic;
using Facebook.Unity; using Facebook.Unity;
using UnityEngine; using UnityEngine;
using Guru.Ads;
//游戏通用模版打点定义 //游戏通用模版打点定义
public static partial class Analytics public static partial class Analytics
@ -27,7 +28,7 @@ namespace Guru
}; };
if (extra != null) dict.AddRange(extra, isOverride:true); if (extra != null) dict.AddRange(extra, isOverride:true);
LogEvent(EventLevelUp, dict); TrackEvent(EventLevelUp, dict);
} }
/// <summary> /// <summary>
@ -42,7 +43,7 @@ namespace Guru
}; };
if (extra != null) dict.AddRange(extra, isOverride:true); if (extra != null) dict.AddRange(extra, isOverride:true);
LogEvent(EventUnlockAchievement, dict); TrackEvent(EventUnlockAchievement, dict);
} }
/// <summary> /// <summary>
@ -53,7 +54,7 @@ namespace Guru
[Obsolete("Obsolete method, please use <LogLevelStart> instead. will be discard in next version.")] [Obsolete("Obsolete method, please use <LogLevelStart> instead. will be discard in next version.")]
public static void LevelStart(int level) public static void LevelStart(int level)
{ {
LogEvent(EventLevelStart, new Dictionary<string, object>() TrackEvent(EventLevelStart, new Dictionary<string, object>()
{ {
{ ParameterLevel, level }, { ParameterLevel, level },
{ ParameterItemCategory, "main" }, { ParameterItemCategory, "main" },
@ -91,7 +92,7 @@ namespace Guru
dict.AddRange(extra, isOverride:true); dict.AddRange(extra, isOverride:true);
} }
LogEvent(EventLevelStart, dict); TrackEvent(EventLevelStart, dict);
} }
/// <summary> /// <summary>
@ -131,7 +132,7 @@ namespace Guru
if(extra != null) dict.AddRange(extra, isOverride:true); if(extra != null) dict.AddRange(extra, isOverride:true);
LogEvent(EventLevelEnd, dict); TrackEvent(EventLevelEnd, dict);
// if (isSuccess) // if (isSuccess)
// { // {
@ -160,7 +161,7 @@ namespace Guru
["level"] = level, ["level"] = level,
}; };
} }
LogEvent(eventName, extra, new EventSetting() TrackEvent(eventName, extra, new EventSetting()
{ {
EnableFirebaseAnalytics = true, EnableFirebaseAnalytics = true,
EnableFacebookAnalytics = true, EnableFacebookAnalytics = true,
@ -188,7 +189,7 @@ namespace Guru
if (extra != null) if (extra != null)
dict.AddRange(extra, isOverride: true); dict.AddRange(extra, isOverride: true);
LogEvent(EventLevelFirstEnd, dict); TrackEvent(EventLevelFirstEnd, dict);
} }
#endregion #endregion
@ -215,7 +216,7 @@ namespace Guru
}; };
if(extra != null) dict.AddRange(extra, isOverride: true); if(extra != null) dict.AddRange(extra, isOverride: true);
LogEvent(EventEarnVirtualCurrency, dict); TrackEvent(EventEarnVirtualCurrency, dict);
} }
/// <summary> /// <summary>
@ -237,7 +238,7 @@ namespace Guru
}; };
if(extra != null) dict.AddRange(extra, isOverride: true); if(extra != null) dict.AddRange(extra, isOverride: true);
LogEvent(EventSpendVirtualCurrency, dict); TrackEvent(EventSpendVirtualCurrency, dict);
} }
#endregion #endregion
@ -260,7 +261,7 @@ namespace Guru
}; };
if(extra != null) dict.AddRange(extra, isOverride: true); if(extra != null) dict.AddRange(extra, isOverride: true);
LogEvent("hit_points", dict); TrackEvent("hit_points", dict);
} }
#endregion #endregion
@ -387,7 +388,7 @@ namespace Guru
//--------- Extra data for IAP receipt --------------- //--------- Extra data for IAP receipt ---------------
LogEvent(evtName, data); TrackEvent(evtName, data);
} }
@ -416,7 +417,6 @@ namespace Guru
/// Google ARO买量点 /// Google ARO买量点
/// </summary> /// </summary>
/// <param name="impressionData">广告收入数据</param> /// <param name="impressionData">广告收入数据</param>
/// <param name="platform">广告平台</param>
/// <a href="https://docs.google.com/spreadsheets/d/1lFWLeOGJgq34QDBTfl6OpNh7MoI37ehGrhdbxlOrJgs/edit#gid=983654222"></a> /// <a href="https://docs.google.com/spreadsheets/d/1lFWLeOGJgq34QDBTfl6OpNh7MoI37ehGrhdbxlOrJgs/edit#gid=983654222"></a>
/// <li> /// <li>
/// value double eg0.002 /// value double eg0.002
@ -427,25 +427,25 @@ namespace Guru
/// ad_unit_name string 广告位名称 /// ad_unit_name string 广告位名称
/// ad_creative_id string 广告素材id /// ad_creative_id string 广告素材id
/// </li> /// </li>
public static void ADImpression(MaxSdkBase.AdInfo impressionData, string platform = "") public static void ADImpression(AdImpressionData impressionData)
{ {
if (string.IsNullOrEmpty(platform)) platform = AdMAX; TrackEvent(EventAdImpression, new Dictionary<string, dynamic>()
double revenue = impressionData.Revenue;
LogEvent(EventAdImpression, new Dictionary<string, dynamic>()
{ {
[ParameterValue] = revenue, [ParameterValue] = impressionData.value,
[ParameterCurrency] = USD, [ParameterCurrency] = impressionData.currency,
[ParameterAdPlatform] = platform, [ParameterAdPlatform] = impressionData.ad_platform,
[ParameterAdSource] = impressionData.NetworkName, [ParameterAdSource] = impressionData.ad_source,
[ParameterAdFormat] = impressionData.AdFormat, [ParameterAdFormat] = impressionData.ad_format,
[ParameterAdUnitName] = impressionData.AdUnitIdentifier, [ParameterAdUnitName] = impressionData.ad_unit_name,
[ParameterAdCreativeId] = impressionData.CreativeIdentifier, [ParameterAdPlacement] = impressionData.ad_placement,
[ParameterAdCreativeId] = impressionData.ad_creative_id,
[ParameterReviewCreativeId] = impressionData.review_creative_id,
}); });
} }
public static void TchAdAbnormalEvent(double value) public static void TchAdAbnormalEvent(double value)
{ {
LogEvent(EventTchAdRevAbnormal, new Dictionary<string, dynamic>() TrackEvent(EventTchAdRevAbnormal, new Dictionary<string, dynamic>()
{ {
{ ParameterAdPlatform, AdMAX }, { ParameterAdPlatform, AdMAX },
{ ParameterCurrency, USD }, { ParameterCurrency, USD },
@ -470,7 +470,7 @@ namespace Guru
}; };
if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra); if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
LogEvent(EventIAPImp, dict); TrackEvent(EventIAPImp, dict);
} }
/// <summary> /// <summary>
@ -486,7 +486,7 @@ namespace Guru
}; };
if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra); if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
LogEvent(EventIAPClose, dict); TrackEvent(EventIAPClose, dict);
} }
/// <summary> /// <summary>
@ -512,7 +512,7 @@ namespace Guru
}; };
if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra); if(extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
LogEvent(EventIAPClick, dict); TrackEvent(EventIAPClick, dict);
} }
/// <summary> /// <summary>
@ -543,7 +543,7 @@ namespace Guru
if(!string.IsNullOrEmpty(offerId)) if(!string.IsNullOrEmpty(offerId))
dict["basePlan"] = offerId; dict["basePlan"] = offerId;
LogEvent(EventIAPReturnTrue, dict, new EventSetting() TrackEvent(EventIAPReturnTrue, dict, new EventSetting()
{ {
EnableFirebaseAnalytics = true, EnableFirebaseAnalytics = true,
EnableAdjustAnalytics = true, EnableAdjustAnalytics = true,
@ -559,7 +559,7 @@ namespace Guru
/// <param name="failReason"></param> /// <param name="failReason"></param>
internal static void IAPRetFalse(string itemCategory, string productId, string failReason) internal static void IAPRetFalse(string itemCategory, string productId, string failReason)
{ {
LogEvent(EventIAPReturnFalse, new Dictionary<string, object>() TrackEvent(EventIAPReturnFalse, new Dictionary<string, object>()
{ {
{ ParameterItemCategory, itemCategory }, { ParameterItemCategory, itemCategory },
{ ParameterItemName, productId }, { ParameterItemName, productId },
@ -576,7 +576,7 @@ namespace Guru
/// <param name="currency">币种</param> /// <param name="currency">币种</param>
public static void FirstIAP(string itemName, double value, string currency) public static void FirstIAP(string itemName, double value, string currency)
{ {
LogEvent(EventIAPFirst, new Dictionary<string, object>() TrackEvent(EventIAPFirst, new Dictionary<string, object>()
{ {
{ ParameterItemName, itemName }, { ParameterItemName, itemName },
{ ParameterValue, value }, { ParameterValue, value },
@ -597,7 +597,7 @@ namespace Guru
if (productName.Contains(".")) productName = productName.Replace(".", "_"); if (productName.Contains(".")) productName = productName.Replace(".", "_");
string eventName = $"iap_{productName}"; string eventName = $"iap_{productName}";
LogEvent(eventName, new Dictionary<string, object>() TrackEvent(eventName, new Dictionary<string, object>()
{ {
{ ParameterItemName, itemName }, { ParameterItemName, itemName },
{ ParameterValue, value }, { ParameterValue, value },
@ -724,10 +724,8 @@ namespace Guru
["sandbox"] = isSandbox? "true": "false" ["sandbox"] = isSandbox? "true": "false"
}; };
// 上报Firebase + 自打点 // 上报Firebase + 自打点
LogEvent(eventName, dict, new EventSetting() { EnableFirebaseAnalytics = true }); TrackEvent(eventName, dict, new EventSetting() { EnableFirebaseAnalytics = true });
// 上报 Adjust 支付事件 // 上报 Adjust 支付事件
LogAdjustRevenueEvent(eventName, value, productId, orderId, purchaseToken, receipt, dict); LogAdjustRevenueEvent(eventName, value, productId, orderId, purchaseToken, receipt, dict);
@ -746,7 +744,7 @@ namespace Guru
if (data == null) return; if (data == null) return;
data["country"] = IPMConfig.IPM_COUNTRY_CODE; data["country"] = IPMConfig.IPM_COUNTRY_CODE;
data["network"] = Application.internetReachability.ToString(); data["network"] = Application.internetReachability.ToString();
LogEvent(EventDevAudit, data, new EventSetting() { EnableFirebaseAnalytics = true }); TrackEvent(EventDevAudit, data, new EventSetting() { EnableFirebaseAnalytics = true });
} }
#endregion #endregion

View File

@ -1,5 +1,7 @@
using System.Threading;
namespace Guru namespace Guru
{ {
using System; using System;
@ -16,97 +18,131 @@ namespace Guru
{ {
public class EventSetting public class EventSetting
{ {
public bool EnableFirebaseAnalytics = false; public bool EnableFirebaseAnalytics;
public bool EnableAdjustAnalytics = false; public bool EnableAdjustAnalytics;
public bool EnableFacebookAnalytics = false; public bool EnableFacebookAnalytics;
public bool EnableGuruAnalytics;
public override string ToString()
{
return $"EvenSetting: firebase:{EnableFirebaseAnalytics}, adjust:{EnableAdjustAnalytics}, facebook:{EnableFacebookAnalytics}, guru:{EnableGuruAnalytics}";
}
public static EventSetting GetDefaultSetting()
{
return new EventSetting()
{
EnableFirebaseAnalytics = true,
EnableFacebookAnalytics = true,
EnableAdjustAnalytics = true,
EnableGuruAnalytics = true
};
}
} }
private static EventSetting _defaultEventSetting; private static EventSetting DefaultEventSetting => EventSetting.GetDefaultSetting();
private static bool _isInited; //Analytics是否初始化完成 private static bool _isInitOnce; //Analytics是否初始化完成
public static bool EnableDebugAnalytics; //允许Debug包上报打点 public static bool EnableDebugAnalytics; //允许Debug包上报打点
public static bool IsDebugMode => PlatformUtil.IsDebug(); public static bool IsDebugMode => PlatformUtil.IsDebug();
private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized;
private static bool IsEnable private static bool IsReady
{ {
get get
{ {
//Firebase服务没有初始化完成不上报打点
if (!FirebaseUtil.IsFirebaseInitialized)
return false;
//Analytics没有初始化不上报打点 //Analytics没有初始化不上报打点
if (!_isInited) if (!_isInitOnce) return false;
return false;
//Firebase服务没有初始化完成不上报打点
if (!IsFirebaseReady) return false;
#if !UNITY_EDITOR
//开发环境打点不上报 //开发环境打点不上报
if (IsDebugMode && !EnableDebugAnalytics) if (IsDebugMode && !EnableDebugAnalytics)
return false; return false;
#endif
return true; return true;
} }
} }
private static AdjustEventDriver _adjustEventDriver;
private static FBEventDriver _fbEventDriver;
private static FirebaseEventDriver _firebaseEventDriver;
private static GuruEventDriver _guruEventDriver;
#region 初始化 #region 初始化
public static void InitAnalytics() public static void InitAnalytics()
{ {
if (_isInited) return; if (_isInitOnce) return;
_isInited = true; _isInitOnce = true;
// -------- 初始化 Exception ---------- _adjustEventDriver = new AdjustEventDriver();
CrashlyticsAgent.Install(); _fbEventDriver = new FBEventDriver();
_firebaseEventDriver = new FirebaseEventDriver();
_guruEventDriver = new GuruEventDriver();
// ------- 初始化自打点 ---------- // ------- 初始化自打点 ----------
InstallGuruAnalytics(IsDebug); InstallGuruAnalytics(IsDebug);
if (_defaultEventSetting == null)
{
var analyticsSetting = GuruSettings.Instance.AnalyticsSetting;
_defaultEventSetting = new EventSetting
{
EnableFirebaseAnalytics = analyticsSetting.EnalbeFirebaseAnalytics,
EnableFacebookAnalytics = analyticsSetting.EnalbeFacebookAnalytics,
EnableAdjustAnalytics = analyticsSetting.EnalbeAdjustAnalytics
};
}
FirebaseUtil.onInitComplete += OnFirebaseCompleted;
} }
private static void OnFirebaseCompleted(bool success)
public static void OnFirebaseInitCompleted()
{ {
FirebaseUtil.onInitComplete -= OnFirebaseCompleted; Debug.Log($"[SDK] --- Analytics Init After FirebaseReady:{IsFirebaseReady}");
if (success) // -------- 初始化 Crashlytics ----------
{ CrashlyticsAgent.Init();
Crashlytics.IsCrashlyticsCollectionEnabled = true; FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
if (_defaultEventSetting.EnableFirebaseAnalytics) FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0));
{ SetUserProperty(FirebaseAnalytics.UserPropertySignUpMethod, "Google");
FirebaseAnalytics.SetAnalyticsCollectionEnabled(true); SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID);
FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0)); // SetUserProperty(PropertyFirstOpenTime, FirstOpenTime);
SetUserProperty(FirebaseAnalytics.UserPropertySignUpMethod, "Google");
SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID); _firebaseEventDriver.TriggerFlush();
// SetUserProperty(PropertyFirstOpenTime, FirstOpenTime);
}
}
} }
public static void OnFBInitComplete()
{
_fbEventDriver.TriggerFlush();
}
public static void OnAdjustInitComplete()
{
_adjustEventDriver.TriggerFlush();
}
private static void OnGuruAnalyticsInitComplete()
{
_guruEventDriver.TriggerFlush();
}
#endregion #endregion
#region 屏幕(场景)名称 #region 屏幕(场景)名称
public static void SetCurrentScreen(string screenName, string className) public static void SetCurrentScreen(string screenName, string className)
{ {
Log.I(TAG,$"SetCurrentScreen -> screenName:{screenName}, className:{className}"); if (!_isInitOnce)
GuruAnalytics.SetScreen(screenName); {
return;
}
if (!IsEnable) return; Log.I(TAG,$"SetCurrentScreen -> screenName:{screenName}, className:{className}");
FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventScreenView, GuruAnalytics.Instance.SetScreen(screenName);
new Parameter(FirebaseAnalytics.ParameterScreenClass, className),
new Parameter(FirebaseAnalytics.ParameterScreenName, screenName) TrackEvent(EventScreenView, new Dictionary<string, dynamic>()
); {
[ParameterScreenName] = screenName,
[ParameterScreenClass] = className,
});
} }
#endregion #endregion
@ -120,7 +156,7 @@ namespace Guru
public static void SetUserIDProperty(string userID) public static void SetUserIDProperty(string userID)
{ {
Log.I(TAG,$"SetUserIDProperty -> userID:{userID}"); Log.I(TAG,$"SetUserIDProperty -> userID:{userID}");
if (!IsEnable) return; if (!IsReady) return;
FirebaseAnalytics.SetUserId(userID); FirebaseAnalytics.SetUserId(userID);
} }
@ -128,127 +164,108 @@ namespace Guru
/// <summary> /// <summary>
/// Firebase上报用户属性 /// Firebase上报用户属性
/// </summary> /// </summary>
public static void SetUserProperty(string propertyName, string propertyValue) public static void SetUserProperty(string key, string value)
{ {
Log.I(TAG,$"SetUserProperty -> propertyName:{propertyName}, propertyValue:{propertyValue}"); if (!_isInitOnce)
{
throw new Exception($"[{TAG}][SDK] Analytics did not initialized, Call <Analytics.{nameof(InitAnalytics)}()> first!");
}
if (!IsEnable) if (IsDebug && !EnableDebugAnalytics)
{
Debug.LogWarning($"[{TAG}][SDK] --- SetProperty {key}:{value} can not send int Debug mode. Set <InitConfig.EnableDebugAnalytics> with `true`");
return; return;
}
try
{
// 填充相关的追踪事件
_guruEventDriver.AddProperty(key, value);
_firebaseEventDriver.AddProperty(key, value);
Debug.Log($"{TAG} --- SetUserProperty -> propertyName:{key}, propertyValue:{value}");
}
catch (Exception ex)
{
if (FirebaseUtil.IsReady)
{
Crashlytics.LogException(ex);
}
else
{
Debug.Log($"Catch Error: {ex}");
}
}
FirebaseAnalytics.SetUserProperty(propertyName, propertyValue);
CustomSetUserProperty(propertyName, propertyValue);
} }
#endregion #endregion
#region 打点上报 #region 打点上报
/// <summary>
/// 打点上报
/// </summary>
/// <param name="eventName"></param>
/// <param name="eventSetting"></param>
internal static void LogEvent(string eventName, EventSetting eventSetting = null, int priority = -1)
{
Log.I(TAG, $"eventName:{eventName}");
CustomLogEvent(eventName, null, priority); // 自定义打点上报
CheckLogCache(eventName, null, eventSetting); // log缓存和消费
if (!IsEnable) return;
eventSetting ??= _defaultEventSetting;
if (eventSetting.EnableFirebaseAnalytics)
{
FirebaseAnalytics.LogEvent(eventName);
}
if (eventSetting.EnableAdjustAnalytics)
{
Adjust.trackEvent(CreateAdjustEvent(eventName));
}
if (eventSetting.EnableFacebookAnalytics)
{
FBService.LogEvent(eventName);
}
}
/// <summary> /// <summary>
/// 打点上报 (带参数) /// 打点上报 (带参数)
/// </summary> /// </summary>
/// <param name="eventName"></param> /// <param name="eventName"></param>
/// <param name="extras"></param> /// <param name="data"></param>
/// <param name="eventSetting"></param> /// <param name="eventSetting"></param>
/// <param name="priority"></param> /// <param name="priority"></param>
internal static void LogEvent(string eventName, Dictionary<string, dynamic> extras, EventSetting eventSetting = null, int priority = -1) internal static void TrackEvent(string eventName, Dictionary<string, dynamic> data,
EventSetting eventSetting = null, int priority = -1)
{ {
CustomLogEvent(eventName, extras, priority); // 自定义打点上报 if (!_isInitOnce)
CheckLogCache(eventName, extras, eventSetting); // log缓存和消费
if (!IsEnable) return;
if (extras == null)
{ {
LogEvent(eventName, eventSetting, priority); // 防空判定 throw new Exception($"[{TAG}][SDK] Analytics did not initialized, Call <Analytics.{nameof(InitAnalytics)}()> first!");
}
if (IsDebug && !EnableDebugAnalytics)
{
Debug.LogWarning($"[{TAG}][SDK] --- LogEvent [{eventName}] can not send int Debug mode. Set <InitConfig.EnableDebugAnalytics> with `true`");
return; return;
} }
string paramStr = string.Join(",", extras); if (eventSetting == null) eventSetting = DefaultEventSetting;
Log.I(TAG, $"eventName:{eventName}, params:{paramStr}");
if (eventSetting == null) eventSetting = _defaultEventSetting; var dataStr = "";
if (eventSetting.EnableFirebaseAnalytics) if (data != null) dataStr = JsonParser.ToJson(data);
Debug.Log($"[{TAG}] --- [SDK] TrackEvent: {eventName} | priority: {priority} | data:{dataStr} | eventSetting: {eventSetting}");
try
{ {
List<Parameter> parameters = new List<Parameter>(); // 填充相关的追踪事件
foreach (var kv in extras) if (eventSetting.EnableGuruAnalytics)
{ {
if(kv.Value is string strValue) _guruEventDriver.AddEvent(eventName, data, eventSetting, priority);
parameters.Add(new Parameter(kv.Key, strValue));
else if (kv.Value is bool boolValue)
parameters.Add(new Parameter(kv.Key, boolValue ? "true" : "false"));
else if (kv.Value is int intValue)
parameters.Add(new Parameter(kv.Key, intValue));
else if (kv.Value is long longValue)
parameters.Add(new Parameter(kv.Key, longValue));
else if (kv.Value is float floatValue)
parameters.Add(new Parameter(kv.Key, floatValue));
else if (kv.Value is double doubleValue)
parameters.Add(new Parameter(kv.Key, doubleValue));
else if (kv.Value is decimal decimalValue)
parameters.Add(new Parameter(kv.Key, decimal.ToDouble(decimalValue)));
else
parameters.Add(new Parameter(kv.Key, kv.Value.ToString()));
} }
if (eventSetting.EnableFirebaseAnalytics)
FirebaseAnalytics.LogEvent(eventName, parameters.ToArray());
}
Dictionary<string, object> dict = new Dictionary<string, object>();
GuruSDKUtils.MergeDictionary(dict, extras);
if (eventSetting.EnableAdjustAnalytics)
{
AdjustEvent adjustEvent = Analytics.CreateAdjustEvent(eventName);
if (adjustEvent != null)
{ {
if (dict.Count > 0) _firebaseEventDriver.AddEvent(eventName, data, eventSetting, priority);
{ }
foreach (var kv in dict) if (eventSetting.EnableAdjustAnalytics)
{ {
adjustEvent.AddEventParameter(kv.Key, kv.Value.ToString()); _adjustEventDriver.AddEvent(eventName, data, eventSetting, priority);
} }
} if (eventSetting.EnableFacebookAnalytics)
Adjust.trackEvent(adjustEvent); {
_fbEventDriver.AddEvent(eventName, data, eventSetting, priority);
} }
} }
catch (Exception ex)
if (eventSetting.EnableFacebookAnalytics)
{ {
FBService.LogEvent(eventName, null, dict); if (FirebaseUtil.IsReady)
{
Crashlytics.LogException(ex);
}
else
{
Debug.Log($"Catch Error: {ex}");
}
} }
} }
/// <summary> /// <summary>
/// 上报 Adjust 事件 /// 上报 Adjust 事件
/// </summary> /// </summary>
@ -300,14 +317,7 @@ namespace Guru
/// <param name="priority"></param> /// <param name="priority"></param>
public static void Track(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null, int priority = -1) public static void Track(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null, int priority = -1)
{ {
if (null != data) TrackEvent(key, data, setting, priority);
{
LogEvent(key, data, setting, priority);
}
else
{
LogEvent(key, setting, priority);
}
} }
@ -318,7 +328,7 @@ namespace Guru
/// <param name="isException"></param> /// <param name="isException"></param>
public static void LogCrashlytics(string msg, bool isException = true) public static void LogCrashlytics(string msg, bool isException = true)
{ {
if (!_isInited) return; if (!_isInitOnce) return;
if (isException) if (isException)
{ {
LogCrashlytics(new Exception(msg)); LogCrashlytics(new Exception(msg));
@ -332,84 +342,15 @@ namespace Guru
public static void LogCrashlytics(Exception exp) public static void LogCrashlytics(Exception exp)
{ {
if (!_isInited) return; if (!_isInitOnce) return;
CrashlyticsAgent.LogException(exp); CrashlyticsAgent.LogException(exp);
} }
#endregion #endregion
#region 打点缓存
private static Queue<SavedLog> _savedLogs;
internal static Queue<SavedLog> SavedLogs
{
get
{
if (_savedLogs == null) _savedLogs = new Queue<SavedLog>(20);
return _savedLogs;
}
}
private static void CheckLogCache(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null, int priority = -1)
{
try
{
if (!_isInited)
{
if (data == null) data = new Dictionary<string, dynamic>();
data["log_stamp"] = TimeUtil.GetCurrentTimeStamp().ToString();
SavedLogs.Enqueue(new SavedLog(key, data, setting, priority));
}
else
{
int len = SavedLogs.Count;
if (len > 0)
{
while (SavedLogs.Count > 0)
{
var log = SavedLogs.Dequeue();
LogEvent(log.key, log.data, log.setting, log.priority);
}
}
}
}
catch (Exception ex)
{
Crashlytics.LogException(ex);
}
}
#endregion
} }
internal class SavedLog
{
public string key;
public int priority;
public Dictionary<string, dynamic> data;
public Analytics.EventSetting setting;
public SavedLog()
{
}
/// <summary>
/// 保存打点信息
/// </summary>
/// <param name="_key"></param>
/// <param name="_data"></param>
/// <param name="_setting"></param>
/// <param name="_priority"></param>
public SavedLog(string _key, Dictionary<string, dynamic> _data = null, Analytics.EventSetting _setting = null, int _priority = -1)
{
key = _key;
data = _data;
setting = _setting;
priority = _priority;
}
}
} }

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d13f245a2ea24c8ebdb957ad4ba79ca4
timeCreated: 1721908201

View File

@ -0,0 +1,106 @@
using System.Collections.Generic;
namespace Guru
{
public interface IEventDriver
{
void TriggerFlush();
void AddEvent(TrackingEvent trackingEvent);
}
public interface IPropertyCollecter
{
void AddProperty(string key, string value);
}
public abstract class AbstractEventDriver: IEventDriver, IPropertyCollecter
{
private GuruEventBuffer<TrackingEvent> _eventBuffer = new GuruEventBuffer<TrackingEvent>();
private GuruEventBuffer<TrackingProperty> _propertyBuffer = new GuruEventBuffer<TrackingProperty>();
// Firebase 是否可用
private bool _isDriverReady = false;
public void TriggerFlush()
{
_isDriverReady = true;
FlushAll();
}
public void AddEvent(string eventName, Dictionary<string, dynamic> data = null,
Analytics.EventSetting setting = null, int priority = -1)
{
var trackingEvent= new TrackingEvent(eventName, data, setting, priority);
AddEvent(trackingEvent);
}
/// <summary>
/// 添加事件
/// </summary>
/// <param name="trackingEvent"></param>
public void AddEvent(TrackingEvent trackingEvent)
{
if (_isDriverReady)
{
FlushTrackingEvent(trackingEvent);
}
else
{
_eventBuffer.Push(trackingEvent);
}
}
/// <summary>
/// 添加属性
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void AddProperty(string key, string value)
{
var property = new TrackingProperty(key, value);
if (_isDriverReady)
{
FlushProperty(property);
}
else
{
_propertyBuffer.Push(property);
}
}
/// <summary>
/// 写入所有
/// </summary>
private void FlushAll()
{
while(_eventBuffer.Pop(out var trackingEvent))
{
FlushTrackingEvent(trackingEvent);
}
while (_propertyBuffer.Pop(out var property))
{
FlushProperty(property);
}
}
/// <summary>
/// 发送事件
/// </summary>
/// <param name="trackEvent"></param>
protected abstract void FlushTrackingEvent(TrackingEvent trackEvent);
protected abstract void FlushProperty(TrackingProperty property);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fe02e66845f64aafa94654814822930a
timeCreated: 1721916181

View File

@ -0,0 +1,39 @@
using System.Collections.Generic;
namespace Guru
{
using com.adjust.sdk;
public class AdjustEventDriver : AbstractEventDriver
{
/// <summary>
/// 发送事件
/// </summary>
/// <param name="trackingEvent"></param>
protected override void FlushTrackingEvent(TrackingEvent trackingEvent)
{
var eventName = trackingEvent.eventName;
var data = trackingEvent.data;
AdjustEvent adjustEvent = Analytics.CreateAdjustEvent(eventName);
if (adjustEvent != null)
{
UnityEngine.Debug.Log($"[SDK] --- Adjust logEvent: {trackingEvent}");
if (data != null && data.Count > 0)
{
foreach (var kv in data)
{
adjustEvent.AddEventParameter(kv.Key, ((object)kv.Value).ToString());
}
}
Adjust.trackEvent(adjustEvent);
}
}
protected override void FlushProperty(TrackingProperty property)
{
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f064544085c8401d988b9eae91bd79b1
timeCreated: 1721910840

View File

@ -0,0 +1,26 @@
using System;
using UnityEngine;
namespace Guru
{
public class FBEventDriver: AbstractEventDriver
{
/// <summary>
/// 发送事件
/// </summary>
/// <param name="trackingEvent"></param>
protected override void FlushTrackingEvent(TrackingEvent trackingEvent)
{
var eventName = trackingEvent.eventName;
var data = trackingEvent.data;
Debug.Log($"[SDK] --- FB logEvent: {trackingEvent}");
FBService.LogEvent(eventName, null, data);
}
protected override void FlushProperty(TrackingProperty property)
{
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 305a62f1c0fe4a16b7c9101264be523b
timeCreated: 1721910530

View File

@ -0,0 +1,64 @@
namespace Guru
{
using Firebase.Analytics;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Firebase 专用
/// </summary>
internal class FirebaseEventDriver : AbstractEventDriver
{
protected override void FlushTrackingEvent(TrackingEvent trackingEvent)
{
var eventName = trackingEvent.eventName;
var data = trackingEvent.data;
Debug.Log($"[SDK] --- Firebase logEvent: {trackingEvent}");
if (data != null)
{
List<Parameter> parameters = new List<Parameter>();
foreach (var kv in data)
{
if(kv.Value is string strValue)
parameters.Add(new Parameter(kv.Key, strValue));
else if (kv.Value is bool boolValue)
parameters.Add(new Parameter(kv.Key, boolValue ? "true" : "false"));
else if (kv.Value is int intValue)
parameters.Add(new Parameter(kv.Key, intValue));
else if (kv.Value is long longValue)
parameters.Add(new Parameter(kv.Key, longValue));
else if (kv.Value is float floatValue)
parameters.Add(new Parameter(kv.Key, floatValue));
else if (kv.Value is double doubleValue)
parameters.Add(new Parameter(kv.Key, doubleValue));
else if (kv.Value is decimal decimalValue)
parameters.Add(new Parameter(kv.Key, decimal.ToDouble(decimalValue)));
else
parameters.Add(new Parameter(kv.Key, kv.Value.ToString()));
}
FirebaseAnalytics.LogEvent(eventName, parameters.ToArray());
}
else
{
FirebaseAnalytics.LogEvent(eventName);
}
}
/// <summary>
/// 输出属性
/// </summary>
/// <param name="property"></param>
protected override void FlushProperty(TrackingProperty property)
{
FirebaseAnalytics.SetUserProperty(property.key, property.value);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7a4c2262ab86431ba6d5961e7453d60f
timeCreated: 1721905429

View File

@ -0,0 +1,44 @@
namespace Guru
{
using System.Collections.Concurrent;
public class GuruEventBuffer<T>
{
private ConcurrentQueue<T> _buffer;
/// <summary>
/// 构造函数
/// </summary>
public GuruEventBuffer()
{
_buffer = new ConcurrentQueue<T>();
}
/// <summary>
/// 入栈
/// </summary>
/// <param name="item"></param>
public void Push(T item)
{
_buffer.Enqueue(item);
}
/// <summary>
/// 出栈
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool Pop(out T item)
{
return _buffer.TryDequeue(out item);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f6dd65ae849944c59be2182eb64db34a
timeCreated: 1721899117

View File

@ -0,0 +1,20 @@
namespace Guru
{
public class GuruEventDriver: AbstractEventDriver
{
protected override void FlushTrackingEvent(TrackingEvent trackingEvent)
{
GuruAnalytics.Instance.LogEvent(trackingEvent.eventName, trackingEvent.data, trackingEvent.priority);
}
/// <summary>
/// 输出属性
/// </summary>
/// <param name="property"></param>
protected override void FlushProperty(TrackingProperty property)
{
GuruAnalytics.Instance.SetUserProperty(property.key, property.value);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d3fee5c262ca43c387ce76d52fb149c8
timeCreated: 1721908696

View File

@ -0,0 +1,12 @@
namespace Guru
{
using System.Collections.Concurrent;
public class GuruPropertyBuffer
{
private ConcurrentQueue<TrackingEvent> _propertyQueue;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 38faf6b8af864e829144d9de91c4b0a5
timeCreated: 1721983424

View File

@ -0,0 +1,65 @@
namespace Guru
{
using System.Collections.Generic;
/// <summary>
/// 追踪事件
/// </summary>
public class TrackingEvent
{
public string eventName;
public int priority;
public Dictionary<string, dynamic> data;
public Analytics.EventSetting setting;
public TrackingEvent()
{
}
/// <summary>
/// 保存打点信息
/// </summary>
/// <param name="eventName"></param>
/// <param name="_data"></param>
/// <param name="_setting"></param>
/// <param name="_priority"></param>
public TrackingEvent(string eventName, Dictionary<string, dynamic> data = null, Analytics.EventSetting setting = null, int priority = -1)
{
this.eventName = eventName;
this.data = data;
this.setting = setting;
this.priority = priority;
}
public override string ToString()
{
return $"eventName: {eventName}, data: {data}, setting: {setting}, priority: {priority}";
}
}
/// <summary>
/// 追踪用户属性
/// </summary>
public class TrackingProperty
{
public string key;
public string value;
public TrackingProperty(string key, string value)
{
this.key = key;
this.value = value;
}
public override string ToString()
{
return $"property: {key}{value}";
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6b9532ec20444115a888ffc89276172a
timeCreated: 1721983520

View File

@ -58,7 +58,7 @@ namespace Guru
if (!string.IsNullOrEmpty(value)) if (!string.IsNullOrEmpty(value))
{ {
PlayerPrefs.SetString(nameof(FirebaseId), value); PlayerPrefs.SetString(nameof(FirebaseId), value);
GuruAnalytics.SetFirebaseId(value); GuruAnalytics.Instance.SetFirebaseId(value);
} }
} }
} }
@ -73,7 +73,7 @@ namespace Guru
if (!string.IsNullOrEmpty(value)) if (!string.IsNullOrEmpty(value))
{ {
PlayerPrefs.SetString(nameof(AdjustId), value); PlayerPrefs.SetString(nameof(AdjustId), value);
GuruAnalytics.SetAdjustId(value); GuruAnalytics.Instance.SetAdjustId(value);
} }
} }
} }
@ -88,7 +88,7 @@ namespace Guru
if (!string.IsNullOrEmpty(value)) if (!string.IsNullOrEmpty(value))
{ {
PlayerPrefs.SetString(nameof(GoogleAdId), value); PlayerPrefs.SetString(nameof(GoogleAdId), value);
GuruAnalytics.SetAdId(value); GuruAnalytics.Instance.SetAdId(value);
} }
} }
} }

View File

@ -1,44 +1,38 @@
using System.Collections.Generic;
using Facebook.Unity;
using UnityEngine;
namespace Guru namespace Guru
{ {
using System;
using System.Collections.Generic;
using Facebook.Unity;
using UnityEngine;
[MonoSingleton(EMonoSingletonType.CreateOnNewGameObject, false)] [MonoSingleton(EMonoSingletonType.CreateOnNewGameObject, false)]
public class FBService : MonoSingleton<FBService> public class FBService : MonoSingleton<FBService>
{ {
public static readonly string LOG_TAG = "FB"; private const string Tag = "[FB]";
private bool _isInitOnce;
private Action _onInitComplete;
public void StartService() public void StartService(Action onInitComplete = null)
{ {
if (!FB.IsInitialized) if(_isInitOnce) return;
{ _isInitOnce = true;
// Initialize the Facebook SDK
FB.Init(InitCallback, OnHideUnity); _onInitComplete = onInitComplete;
} // Initialize the Facebook SDK
else FB.Init(InitCallback, OnHideUnity);
{
// Already initialized, signal an app activation App Event
FB.ActivateApp();
}
} }
private void InitCallback() private void InitCallback()
{ {
if (FB.IsInitialized)
{ // Signal an app activation App Event
// Signal an app activation App Event FB.ActivateApp();
FB.ActivateApp(); FB.Mobile.SetAdvertiserIDCollectionEnabled(true);
FB.Mobile.SetAdvertiserIDCollectionEnabled(true); FB.Mobile.SetAutoLogAppEventsEnabled(false); // 关闭自动打点上报
FB.Mobile.SetAutoLogAppEventsEnabled(false); // 关闭自动打点上报
#if UNITY_IOS #if UNITY_IOS
FB.Mobile.SetAdvertiserTrackingEnabled(true); FB.Mobile.SetAdvertiserTrackingEnabled(true);
#endif #endif
} _onInitComplete?.Invoke();
else
{
Log.E(LOG_TAG, "Failed to Initialize the Facebook SDK");
}
} }
private void OnHideUnity(bool isGameShown) private void OnHideUnity(bool isGameShown)
@ -81,13 +75,13 @@ namespace Guru
} }
private static bool IsAvailable public static bool IsAvailable
{ {
get get
{ {
if (!FB.IsInitialized) if (!FB.IsInitialized)
{ {
Debug.LogError("[FB] FB is not initialized, please call <FBService.StartService> first."); Debug.LogError($"{Tag} FB is not initialized, please call <FBService.StartService> first.");
return false; return false;
} }
return true; return true;

View File

@ -8,14 +8,31 @@ namespace Guru
public static partial class FirebaseUtil public static partial class FirebaseUtil
{ {
private static int _messageRetry = 5; private static int _messageRetry = 5;
public static bool? IsInitMessage; // public static bool? IsInitMessage;
private static bool _isAutoFetchFcmToken = true;
private static bool _isFetchOnce = false;
public static void SetAutoFetchFcmToken(bool value)
{
_isAutoFetchFcmToken = value;
}
public static void InitializeMessage() public static void InitializeMessage()
{ {
if (_isAutoFetchFcmToken)
{
StartFetchFcmToken();
}
}
public static void StartFetchFcmToken()
{
if (_isFetchOnce) return;
_isFetchOnce = true;
FirebaseMessaging.TokenReceived += OnTokenReceived; FirebaseMessaging.TokenReceived += OnTokenReceived;
FirebaseMessaging.MessageReceived += OnMessageReceived; FirebaseMessaging.MessageReceived += OnMessageReceived;
GetFCMToken(); GetFCMToken();
IsInitMessage = true;
} }
private static void GetFCMToken() private static void GetFCMToken()

View File

@ -9,7 +9,6 @@ namespace Guru
public static partial class FirebaseUtil public static partial class FirebaseUtil
{ {
private static readonly string LOG_TAG = "Firebase"; private static readonly string LOG_TAG = "Firebase";
private static bool _isDebug = false;
private static bool _isReady = false; private static bool _isReady = false;
public static bool IsReady => _isReady; public static bool IsReady => _isReady;
@ -19,14 +18,13 @@ namespace Guru
public static Action<bool> OnFirebaseAuthResult; public static Action<bool> OnFirebaseAuthResult;
public static Action<bool> OnUserAuthResult; public static Action<bool> OnUserAuthResult;
public static Action<string> OnAdjustDeeplinkCallback = null;
public static void InitFirebase(Action callback)
public static void InitFirebase(Action callback, bool isDebug = false)
{ {
_isReady = false; _isReady = false;
_isDebug = isDebug; // Analytics.InitAnalytics(); // 打点提前初始化
Analytics.InitAnalytics(); // 打点提前初始化
// Loom.StartUp(); // 确保主线程开启 // Loom.StartUp(); // 确保主线程开启
@ -103,6 +101,7 @@ namespace Guru
FirebaseAnalytics.GetAnalyticsInstanceIdAsync() FirebaseAnalytics.GetAnalyticsInstanceIdAsync()
.ContinueWithOnMainThread(task => .ContinueWithOnMainThread(task =>
{ {
if (task.IsCompleted && !string.IsNullOrEmpty(task.Result)) if (task.IsCompleted && !string.IsNullOrEmpty(task.Result))
{ {
// 保存本地ID备份 // 保存本地ID备份
@ -119,27 +118,29 @@ namespace Guru
string fbAppId = GuruSettings.Instance.IPMSetting.FacebookAppId; string fbAppId = GuruSettings.Instance.IPMSetting.FacebookAppId;
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ID)) if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ID))
{
ReportAdjustId(IPMConfig.ADJUST_ID); // 二次启动后,若有值则立即上报属性 ReportAdjustId(IPMConfig.ADJUST_ID); // 二次启动后,若有值则立即上报属性
}
AdjustService.StartService(appToken, fbAppId, adjustId => AdjustService.StartService(appToken, fbAppId, OnGetAdjustId, OnAdjustDeeplinkCallback);
{
// 获取 ADID
if (string.IsNullOrEmpty(adjustId))
{
adjustId = "not_set";
}
else
{
IPMConfig.ADJUST_ID = adjustId;
}
ReportAdjustId(adjustId);
});
}); });
} }
private static void OnGetAdjustId(string adjustId)
{
// 获取 ADID
if (string.IsNullOrEmpty(adjustId))
{
adjustId = "not_set";
}
else
{
IPMConfig.ADJUST_ID = adjustId;
}
ReportAdjustId(adjustId);
Analytics.OnAdjustInitComplete();
}
private static void ReportAdjustId(string adjustId) private static void ReportAdjustId(string adjustId)
{ {

View File

@ -9,9 +9,8 @@ namespace Guru
public static class CrashlyticsAgent public static class CrashlyticsAgent
{ {
private static bool _initOnce; private static bool _initOnce;
private static bool _isReady; private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized;
private static Queue<Exception> _expCache;
private static bool _hasSetUser = false; private static bool _hasSetUser = false;
/// <summary> /// <summary>
@ -32,45 +31,18 @@ namespace Guru
LogType.Assert, LogType.Assert,
}; };
public static void Install() public static void Init()
{ {
if (_initOnce) return; if (_initOnce) return;
_initOnce = true; _initOnce = true;
_expCache = new Queue<Exception>(20);
Application.logMessageReceived -= OnReceivedMessage; Application.logMessageReceived -= OnReceivedMessage;
Application.logMessageReceived += OnReceivedMessage; Application.logMessageReceived += OnReceivedMessage;
// Application.logMessageReceivedThreaded -= OnReceivedMessage; Crashlytics.IsCrashlyticsCollectionEnabled = true;
// Application.logMessageReceivedThreaded += OnReceivedMessage;
if (FirebaseUtil.IsReady)
{
OnFirebaseComplete(true);
return;
}
FirebaseUtil.onInitComplete -= OnFirebaseComplete;
FirebaseUtil.onInitComplete += OnFirebaseComplete;
} }
private static void OnFirebaseComplete(bool success)
{
FirebaseUtil.onInitComplete -= OnFirebaseComplete;
if (success)
{
_isReady = true;
Crashlytics.IsCrashlyticsCollectionEnabled = true;
if (_expCache != null && _expCache.Count > 0)
{
while (_expCache.Count > 0)
{
LogException(_expCache.Dequeue());
}
_expCache.Clear();
}
}
}
private static string ToLogTypeString(LogType type) private static string ToLogTypeString(LogType type)
{ {
@ -101,14 +73,8 @@ namespace Guru
public static void LogException(Exception ex) public static void LogException(Exception ex)
{ {
if (!_isReady) if (!IsFirebaseReady) return;
{
Install();
_expCache.Enqueue(ex);
return;
}
Crashlytics.LogException(ex); Crashlytics.LogException(ex);
// CheckSetUser();
} }
public static void LogException(string msg) public static void LogException(string msg)
@ -118,15 +84,14 @@ namespace Guru
public static void Log(string msg) public static void Log(string msg)
{ {
if (!_isReady) return; if (!IsFirebaseReady) return;
Crashlytics.Log(msg); Crashlytics.Log(msg);
// CheckSetUser();
} }
public static void SetCustomKey(string key, string value) public static void SetCustomKey(string key, string value)
{ {
if (!_isReady) return; if (!IsFirebaseReady) return;
Crashlytics.SetCustomKey(key, value); Crashlytics.SetCustomKey(key, value);
} }

View File

@ -140,9 +140,13 @@ namespace Guru
public class AnalyticsSetting public class AnalyticsSetting
{ {
[SerializeField] private int levelEndSuccessNum = 50; [SerializeField] private int levelEndSuccessNum = 50;
[Obsolete("Will not use in next version", false)]
[SerializeField] private bool enalbeFirebaseAnalytics = true; [SerializeField] private bool enalbeFirebaseAnalytics = true;
[Obsolete("Will not use in next version", false)]
[SerializeField] private bool enalbeFacebookAnalytics = true; [SerializeField] private bool enalbeFacebookAnalytics = true;
[Obsolete("Will not use in next version", false)]
[SerializeField] private bool enalbeAdjustAnalytics = true; [SerializeField] private bool enalbeAdjustAnalytics = true;
[SerializeField] internal List<AdjustEvent> adjustEventList; [SerializeField] internal List<AdjustEvent> adjustEventList;
public int LevelEndSuccessNum => levelEndSuccessNum; public int LevelEndSuccessNum => levelEndSuccessNum;

View File

@ -65,6 +65,7 @@ namespace Guru
private void OnStatueChanged(AdStatusInfo info) private void OnStatueChanged(AdStatusInfo info)
{ {
if (_model == null) return;
_model.monitorInfo = CreateMonitorInfo(); _model.monitorInfo = CreateMonitorInfo();
if (info != null) if (info != null)
@ -106,7 +107,7 @@ namespace Guru
string msg = ""; string msg = "";
bool loaded = false; bool loaded = false;
if (!ADService.Instance.IsInitialized) if (ADService.Instance == null || !ADService.Instance.IsInitialized)
{ {
msg = ColoredText("AdService not initialized...", Consts.ColorRed); msg = ColoredText("AdService not initialized...", Consts.ColorRed);
return msg; return msg;

View File

@ -1132,7 +1132,7 @@ namespace Guru
private void ReportGoogleOrderLost(GoogleOrderData data) private void ReportGoogleOrderLost(GoogleOrderData data)
{ {
Analytics.LogEvent("google_order_lost", new Dictionary<string, dynamic>() Analytics.TrackEvent("google_order_lost", new Dictionary<string, dynamic>()
{ {
["data"] = data.ToString(), ["data"] = data.ToString(),
}, new Analytics.EventSetting() }, new Analytics.EventSetting()
@ -1144,7 +1144,7 @@ namespace Guru
private void ReportAppleOrderLost(AppleOrderData data) private void ReportAppleOrderLost(AppleOrderData data)
{ {
Analytics.LogEvent("apple_order_lost", new Dictionary<string, dynamic>() Analytics.TrackEvent("apple_order_lost", new Dictionary<string, dynamic>()
{ {
["data"] = data.ToString(), ["data"] = data.ToString(),
}, new Analytics.EventSetting() }, new Analytics.EventSetting()

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 10f8491dbf6264bc393cb7578397ec7f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bc0062a7d36f144beabfdea9e3a8e2c7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4725a71a48aec4a5083c37f5ff09a550
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
fileFormatVersion: 2
guid: 05a3c5d94488c454ea77722fc8f0a80c
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

@ -0,0 +1,3 @@
-keep class com.facebook.unity.* { *; }
-keepattributes Signature
-keep class com.guru.unity.monitor.** { *; }

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d0ac28ef06c604f789bb32b31225c157
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e5d09fde296334b46844a972d0289dcc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,80 @@
fileFormatVersion: 2
guid: 18c322abb3a1e4d9eaea5e395dab1377
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux64: 1
Exclude OSXUniversal: 1
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: None
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: true
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ec7317011341a40a1a0ee7ae5f38f270
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a4ccb52ed7f6b4dff8731e9e93293ccb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,337 @@
#if 0
#elif defined(__arm64__) && __arm64__
// Generated by Apple Swift version 5.9.2 effective-4.1.50 (swiftlang-5.9.2.2.56 clang-1500.1.0.2.5)
#ifndef CONNECTIVITY_SWIFT_H
#define CONNECTIVITY_SWIFT_H
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgcc-compat"
#if !defined(__has_include)
# define __has_include(x) 0
#endif
#if !defined(__has_attribute)
# define __has_attribute(x) 0
#endif
#if !defined(__has_feature)
# define __has_feature(x) 0
#endif
#if !defined(__has_warning)
# define __has_warning(x) 0
#endif
#if __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif
#pragma clang diagnostic ignored "-Wauto-import"
#if defined(__OBJC__)
#include <Foundation/Foundation.h>
#endif
#if defined(__cplusplus)
#include <cstdint>
#include <cstddef>
#include <cstdbool>
#include <cstring>
#include <stdlib.h>
#include <new>
#include <type_traits>
#else
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#endif
#if defined(__cplusplus)
#if defined(__arm64e__) && __has_include(<ptrauth.h>)
# include <ptrauth.h>
#else
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreserved-macro-identifier"
# ifndef __ptrauth_swift_value_witness_function_pointer
# define __ptrauth_swift_value_witness_function_pointer(x)
# endif
# ifndef __ptrauth_swift_class_method_pointer
# define __ptrauth_swift_class_method_pointer(x)
# endif
#pragma clang diagnostic pop
#endif
#endif
#if !defined(SWIFT_TYPEDEFS)
# define SWIFT_TYPEDEFS 1
# if __has_include(<uchar.h>)
# include <uchar.h>
# elif !defined(__cplusplus)
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
# endif
typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2)));
typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3)));
typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4)));
#endif
#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif
#if !defined(SWIFT_CLASS_PROPERTY)
# if __has_feature(objc_class_property)
# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
# else
# define SWIFT_CLASS_PROPERTY(...)
# endif
#endif
#if !defined(SWIFT_RUNTIME_NAME)
# if __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
# else
# define SWIFT_RUNTIME_NAME(X)
# endif
#endif
#if !defined(SWIFT_COMPILE_NAME)
# if __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
# else
# define SWIFT_COMPILE_NAME(X)
# endif
#endif
#if !defined(SWIFT_METHOD_FAMILY)
# if __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
# else
# define SWIFT_METHOD_FAMILY(X)
# endif
#endif
#if !defined(SWIFT_NOESCAPE)
# if __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
# else
# define SWIFT_NOESCAPE
# endif
#endif
#if !defined(SWIFT_RELEASES_ARGUMENT)
# if __has_attribute(ns_consumed)
# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed))
# else
# define SWIFT_RELEASES_ARGUMENT
# endif
#endif
#if !defined(SWIFT_WARN_UNUSED_RESULT)
# if __has_attribute(warn_unused_result)
# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
# else
# define SWIFT_WARN_UNUSED_RESULT
# endif
#endif
#if !defined(SWIFT_NORETURN)
# if __has_attribute(noreturn)
# define SWIFT_NORETURN __attribute__((noreturn))
# else
# define SWIFT_NORETURN
# endif
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_ENUM_EXTRA)
# define SWIFT_ENUM_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if __has_attribute(objc_subclassing_restricted)
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# else
# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif
#if !defined(SWIFT_RESILIENT_CLASS)
# if __has_attribute(objc_class_stub)
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub))
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME)
# else
# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME)
# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME)
# endif
#endif
#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif
#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if __has_attribute(objc_designated_initializer)
# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
# define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if !defined(SWIFT_ENUM_ATTR)
# if __has_attribute(enum_extensibility)
# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility)))
# else
# define SWIFT_ENUM_ATTR(_extensibility)
# endif
#endif
#if !defined(SWIFT_ENUM)
# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# if __has_feature(generalized_swift_name)
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type
# else
# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility)
# endif
#endif
#if !defined(SWIFT_UNAVAILABLE)
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
#endif
#if !defined(SWIFT_UNAVAILABLE_MSG)
# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg)))
#endif
#if !defined(SWIFT_AVAILABILITY)
# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__)))
#endif
#if !defined(SWIFT_WEAK_IMPORT)
# define SWIFT_WEAK_IMPORT __attribute__((weak_import))
#endif
#if !defined(SWIFT_DEPRECATED)
# define SWIFT_DEPRECATED __attribute__((deprecated))
#endif
#if !defined(SWIFT_DEPRECATED_MSG)
# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__)))
#endif
#if !defined(SWIFT_DEPRECATED_OBJC)
# if __has_feature(attribute_diagnose_if_objc)
# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning")))
# else
# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg)
# endif
#endif
#if defined(__OBJC__)
#if !defined(IBSegueAction)
# define IBSegueAction
#endif
#endif
#if !defined(SWIFT_EXTERN)
# if defined(__cplusplus)
# define SWIFT_EXTERN extern "C"
# else
# define SWIFT_EXTERN extern
# endif
#endif
#if !defined(SWIFT_CALL)
# define SWIFT_CALL __attribute__((swiftcall))
#endif
#if !defined(SWIFT_INDIRECT_RESULT)
# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result))
#endif
#if !defined(SWIFT_CONTEXT)
# define SWIFT_CONTEXT __attribute__((swift_context))
#endif
#if !defined(SWIFT_ERROR_RESULT)
# define SWIFT_ERROR_RESULT __attribute__((swift_error_result))
#endif
#if defined(__cplusplus)
# define SWIFT_NOEXCEPT noexcept
#else
# define SWIFT_NOEXCEPT
#endif
#if !defined(SWIFT_C_INLINE_THUNK)
# if __has_attribute(always_inline)
# if __has_attribute(nodebug)
# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) __attribute__((nodebug))
# else
# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline))
# endif
# else
# define SWIFT_C_INLINE_THUNK inline
# endif
#endif
#if defined(_WIN32)
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport)
#endif
#else
#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL)
# define SWIFT_IMPORT_STDLIB_SYMBOL
#endif
#endif
#if defined(__OBJC__)
#if __has_feature(objc_modules)
#if __has_warning("-Watimport-in-framework-header")
#pragma clang diagnostic ignored "-Watimport-in-framework-header"
#endif
@import Foundation;
@import ObjectiveC;
#endif
#endif
#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
#if __has_warning("-Wpragma-clang-attribute")
# pragma clang diagnostic ignored "-Wpragma-clang-attribute"
#endif
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wnullability"
#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension"
#if __has_attribute(external_source_symbol)
# pragma push_macro("any")
# undef any
# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="Connectivity",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol))
# pragma pop_macro("any")
#endif
#if defined(__OBJC__)
@class NSString;
SWIFT_CLASS("_TtC12Connectivity12Connectivity")
@interface Connectivity : NSObject
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong) Connectivity * _Nonnull shared;)
+ (Connectivity * _Nonnull)shared SWIFT_WARN_UNUSED_RESULT;
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull CONNECTIVITY_NONE;)
+ (NSString * _Nonnull)CONNECTIVITY_NONE SWIFT_WARN_UNUSED_RESULT;
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull CONNECTIVITY_WIFI;)
+ (NSString * _Nonnull)CONNECTIVITY_WIFI SWIFT_WARN_UNUSED_RESULT;
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull CONNECTIVITY_MOBILE;)
+ (NSString * _Nonnull)CONNECTIVITY_MOBILE SWIFT_WARN_UNUSED_RESULT;
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull CONNECTIVITY_ETHERNET;)
+ (NSString * _Nonnull)CONNECTIVITY_ETHERNET SWIFT_WARN_UNUSED_RESULT;
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull CONNECTIVITY_VPN;)
+ (NSString * _Nonnull)CONNECTIVITY_VPN SWIFT_WARN_UNUSED_RESULT;
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull CONNECTIVITY_OTHER;)
+ (NSString * _Nonnull)CONNECTIVITY_OTHER SWIFT_WARN_UNUSED_RESULT;
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_DEPRECATED_MSG("-init is unavailable");
- (void)initializeWithCompletion:(void (^ _Nonnull)(BOOL))completion;
- (NSArray<NSString *> * _Nonnull)checkConnectionType SWIFT_WARN_UNUSED_RESULT;
@end
#endif
#if __has_attribute(external_source_symbol)
# pragma clang attribute pop
#endif
#if defined(__cplusplus)
#endif
#pragma clang diagnostic pop
#endif
#else
#error unsupported Swift architecture
#endif

View File

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

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b3be6515c98fc4516b74799d2232851a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 009197294dbfe4bd5b64f833fce7277e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: db929fad7809a40a6af254c5262adb3a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d014052e45f6948db82f9fbecdb02a96
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5a2b967c5b7f944adb348971a0e13c79
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
{
"ABIRoot": {
"kind": "Root",
"name": "TopLevel",
"printedName": "TopLevel",
"json_format_version": 8
},
"ConstValues": []
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b8637a4450c6b4ca895cd05427db6ffc
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2b7b377a06cfe4472ace76077b0d1e24
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: be5b523ba98e649d9938fc7df1e7b55a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,4 @@
framework module Connectivity {
header "Connectivity-Swift.h"
requires objc
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 97a465fd6df3b4f72a477ef19bf727a9
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1a90376b0826241cf8ed25c4ba2b91fc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/Connectivity-Swift.h</key>
<data>
2jZWRNZEB9lWoT02/WI0gpx8bUY=
</data>
<key>Info.plist</key>
<data>
lVs8E6FtUHvDAsoK7zwpgZ+1m84=
</data>
<key>Modules/Connectivity.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo</key>
<data>
3vRjRUNrw8fWaShfTaH+cBfxfLE=
</data>
<key>Modules/Connectivity.swiftmodule/arm64-apple-ios.abi.json</key>
<data>
FSPnLbho3G+LL9smI3XgVOqBIQ4=
</data>
<key>Modules/Connectivity.swiftmodule/arm64-apple-ios.swiftdoc</key>
<data>
HgPMAkcK2+NGvcVfwyFJ9u/nd0k=
</data>
<key>Modules/Connectivity.swiftmodule/arm64-apple-ios.swiftmodule</key>
<data>
nK9APrK3atZTGuid35+A6Dde02M=
</data>
<key>Modules/module.modulemap</key>
<data>
JQ0IhYrWi46ysbcXxnNfARgJPro=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/Connectivity-Swift.h</key>
<dict>
<key>hash2</key>
<data>
xwPPIVygOJDaH/CCrDO25Y2645Q/IQYSiJrV3eJJy+M=
</data>
</dict>
<key>Modules/Connectivity.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo</key>
<dict>
<key>hash2</key>
<data>
Qgk/xiutw35xy8VeU5niELPbBEi5gVVuXYai3rhRrbI=
</data>
</dict>
<key>Modules/Connectivity.swiftmodule/arm64-apple-ios.abi.json</key>
<dict>
<key>hash2</key>
<data>
KnRdWE4y6t4QM5zi5JDptPdHFgJy1Tku+7GLkZS2aNM=
</data>
</dict>
<key>Modules/Connectivity.swiftmodule/arm64-apple-ios.swiftdoc</key>
<dict>
<key>hash2</key>
<data>
ZNpy4/pGL15IFXpHTav2UvUYM7kQPN/0eTjxtfLqYq8=
</data>
</dict>
<key>Modules/Connectivity.swiftmodule/arm64-apple-ios.swiftmodule</key>
<dict>
<key>hash2</key>
<data>
Et4EI2nA28WHGnFW0ki2IUjCTs703CjwdRvol0loQGo=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash2</key>
<data>
07XGBKw7w58ugYy09lbnsq9IhqStrsOHCKCfwm/MrpU=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 158f1aee738db4ad8a07a36e89614060
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a0a25c648675a494eb50f2dd3159ff81
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d1121778023d64cafad6d7eb947140d0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,116 @@
namespace Guru.Network
{
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class NetworkStatusMonitor
{
private const string Tag = "[NET]";
private const string NETWORK_STATUS_NONE = "none";
private const string NETWORK_STATUS_MOBILE = "mobile";
private const string NETWORK_STATUS_WIFI = "wifi";
private const string NETWORK_STATUS_ETHERNET = "ethernet";
private const string NETWORK_STATUS_VPN = "vpn";
private const string NETWORK_STATUS_TETHER = "tether";
private const string NETWORK_STATUS_BLUETOOTH = "bluetooth";
private const string NETWORK_STATUS_OTHER = "other";
private bool _isReady = false;
private INetworkStatusProxy _proxy;
private INetworkStatusProxy Proxy
{
get
{
if (_proxy == null)
{
#if UNITY_EDITOR
_proxy = new NetworkStatusEditor();
#elif UNITY_ANDROID
_proxy = new NetworkStatusAndroid();
#elif UNITY_IOS
_proxy = new NetworkStatusIOS();
#endif
}
if (_proxy == null)
{
// 如果未实现则报异常
throw new NotImplementedException("Can't find NetworkStatusProxy instance!!");
}
return _proxy;
}
}
/// <summary>
/// 网络状态列表
/// </summary>
private List<string> _statusNameList = new List<string>()
{
NETWORK_STATUS_VPN,
NETWORK_STATUS_TETHER,
NETWORK_STATUS_MOBILE,
NETWORK_STATUS_WIFI,
NETWORK_STATUS_ETHERNET,
NETWORK_STATUS_BLUETOOTH,
NETWORK_STATUS_OTHER,
NETWORK_STATUS_NONE,
};
public void Init(Action<bool> onInitComplete = null)
{
Proxy.Init(success =>
{
_isReady = success;
onInitComplete?.Invoke(success);
});
}
/// <summary>
/// 获取网络状态
/// </summary>
/// <returns></returns>
public string GetNetworkStatus()
{
if (_isReady)
{
var status = Proxy.GetNetworkStatus();
if (status != null && status.Length > 0)
{
string statusName = "";
for (int i = 0; i < _statusNameList.Count; i++)
{
// 根据名称优先级, 先获取到的优先上报
statusName = _statusNameList[i];
if (status.Contains(statusName))
{
Debug.Log($"{Tag} --- GetNetworkStatus: [{string.Join(",", status)}]");
return statusName;
}
}
}
}
Debug.LogWarning($"{Tag} --- Network Monitor is not ready!");
return NETWORK_STATUS_NONE;
}
// private void OnProxyInitComplete(bool success)
// {
// if (success)
// {
// Debug.Log($"{Tag} --- NetworkStatusMonitor init success");
// }
// else
// {
// Debug.LogError($"{Tag} --- NetworkStatusMonitor init failed");
// }
// }
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 89389dfafc844651bb8f6a23865edca6
timeCreated: 1721958852

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1981d1e0510af48ff81cbd4db201318f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,16 @@
namespace Guru.Network
{
using System;
/// <summary>
/// 网络状态代理
/// </summary>
public interface INetworkStatusProxy
{
void Init(Action<bool> onInitComplete);
string[] GetNetworkStatus();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: aeba66b9f9e4413a8475bf5cc363fae1
timeCreated: 1721957685

View File

@ -0,0 +1,55 @@
namespace Guru.Network
{
using System;
using UnityEngine;
public class NetworkStatusAndroid: INetworkStatusProxy
{
private const string Tag = "[NET][AND]";
#if UNITY_ANDROID
private const string CONNECTIVITY_ANDROID_CLASS_NAME = "com.guru.unity.monitor.Connectivity";
private AndroidJavaObject _connectivity;
private bool _isReady = false;
#endif
/// <summary>
/// 初始化
/// </summary>
/// <param name="onInitComplete"></param>
public void Init(Action<bool> onInitComplete)
{
#if UNITY_ANDROID
AndroidJavaObject currentActivity = new AndroidJavaObject("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
_connectivity = new AndroidJavaObject(CONNECTIVITY_ANDROID_CLASS_NAME).CallStatic<AndroidJavaObject>("getInstance");
_isReady = _connectivity.Call<bool>("initialize", currentActivity);
// Debug.LogWarning($"{Tag} --- Network status init result:{_isReady}");
// Debug.LogWarning($"{Tag} --- _connectivity:{_connectivity}");
onInitComplete?.Invoke(_isReady); // 调用初始化回调
#endif
}
/// <summary>
/// 获取网络状态
/// </summary>
/// <returns></returns>
public string[] GetNetworkStatus()
{
#if UNITY_ANDROID
if (!_isReady)
{
Debug.LogError($"{Tag} --- GetNetworkStatus :: initialized failed.");
}
else if(_connectivity != null)
{
return _connectivity.Call<string[]>("checkConnectionType");
}
#endif
return new string[] {"none"};
}
}
}

Some files were not shown because too many files have changed in this diff Show More