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
{
using System.Linq;
@ -14,17 +16,21 @@ namespace Guru.Editor
/// </summary>
public partial class AppBuilder
{
public static int AndroidTargetSdkVersion = 33;
public static string IOSTargetOSVersion = "13.0";
public static string GuruIOSTeamId = "39253T242A";
public static string GuruKeystoreName => "guru_key.jks";
public static string GuruKeystorePass => "guru0622";
public static string GuruAliasName => "guru";
public static string GuruAliasPass => "guru0622";
public static string GuruKeystorePath => Application.dataPath + $"/Plugins/Android/{GuruKeystoreName}";
public static string ProguardName => "proguard-user.txt";
public static string ProguardPath => Application.dataPath + $"/Plugins/Android/{ProguardName}";
public static string OutputDirName => "BuildOutput";
private const int DefaultAndroidTargetSdkVersion = 34;
private const string IOSTargetOSVersion = "13.0";
private const string GuruIOSTeamId = "39253T242A";
private const string GuruKeystoreName = "guru_key.jks";
private const string GuruKeystorePass = "guru0622";
private const string GuruAliasName = "guru";
private const string GuruAliasPass = "guru0622";
private const string UnityGradlePath_2021_3_41 =
"/Applications/Unity/Hub/Editor/2021.3.41f1/PlaybackEngines/AndroidPlayer/Tools/gradle";
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 构建接口
@ -70,11 +76,14 @@ namespace Guru.Editor
SwitchBuildPlatform(BuildTarget.Android);
// 打包通用设置
ChangeBuildPlayerCommonSetting(buildParam, BuildTargetGroup.Android);
// Set GradlePath
SetGradlePath();
var isDebug = !buildParam.IsBuildRelease;
var useMinify = buildParam.AndroidUseMinify;
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);
@ -90,7 +99,6 @@ namespace Guru.Editor
PlayerSettings.muteOtherAudioSources = false;
// ---- 开启 Minify 后需要配置 proguard-user.txt 文件 ----
if (useMinify) DeployProguardTxt();
PlayerSettings.Android.minifyWithR8 = useMinify;
PlayerSettings.Android.minifyRelease = useMinify;
PlayerSettings.Android.minifyDebug = useMinify;
// ---- 部署 Guru 专用的 Keystore ----
@ -113,10 +121,9 @@ namespace Guru.Editor
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;
if (buildParam.AndroidTargetVersion > 0) AndroidTargetSdkVersion = buildParam.AndroidTargetVersion;
PlayerSettings.Android.targetSdkVersion = (AndroidSdkVersions)AndroidTargetSdkVersion; // 默认设置API为33
PlayerSettings.Android.targetSdkVersion = (AndroidSdkVersions)androidTargetVersion; // 设置 API Version
//打包
string symbolDefine = buildParam.IsBuildRelease ? GameDefine.MACRO_RELEASE : GameDefine.MACRO_DEBUG;
@ -142,7 +149,18 @@ namespace Guru.Editor
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
/// </summary>
private static bool DeployAndroidKeystore()

View File

@ -1,3 +1,6 @@
using System.Collections.Generic;
using NUnit.Framework;
#if UNITY_ANDROID
namespace Guru
{
@ -13,7 +16,8 @@ namespace Guru
/// Android混淆器内容填充
/// 于应用构建前执行
/// </summary>
public class UserProguardHelper: IPreprocessBuildWithReport
// public class UserProguardHelper: IPreprocessBuildWithReport
public class UserProguardHelper
{
public int callbackOrder { get; } = 0;
public void OnPreprocessBuild(BuildReport report)
@ -27,7 +31,6 @@ namespace Guru
string proguardPath = $"{Application.dataPath}/Plugins/Android/proguard-user.txt";
if (File.Exists(proguardPath))
{
List<string> keeps = new List<string>();
DirectoryInfo dir = new DirectoryInfo(Application.dataPath);
string raw = File.ReadAllText(proguardPath);
@ -41,36 +44,40 @@ namespace Guru
}
// Debug.Log($"--- Proguard Files: {files.Length}");
ProguardItemBuilder builder = new ProguardItemBuilder();
string[] lens = null;
string l = "";
var allItems = new List<ProguardItem>(30);
string[] lines = null;
for (int i = 0; i < files.Count; i++)
{
lens = File.ReadAllLines(files[i].FullName);
foreach (var s in lens)
{
l = s.TrimStart();
if(string.IsNullOrEmpty(l)) continue;
if(raw.Contains(l)) continue;
keeps.Add(l);
Debug.Log($"--- ✏️ Apply: [ {l} ]");
}
lines = File.ReadAllLines(files[i].FullName);
var items = builder.BuildItemsFormLines(lines);
if(items != null && items.Count > 0) allItems.AddRange(items);
}
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")]
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

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

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

View File

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

View File

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

View File

@ -18,7 +18,7 @@ namespace Guru
public const string K_IAP_PURCHASE = "iap_purchase"; // 固定点位事件
public const string K_SUB_PURCHASE = "sub_purchase"; // 固定点位事件
private static Action<string> _onSessionSuccessCallback;
private static Action<string> _onInitComplete;
private static string _adId = "";
@ -42,6 +42,9 @@ namespace Guru
return _adjustId; // Adjust AdId;
}
}
private static bool _isReady = false;
public static bool IsReady => _isReady;
#region 启动服务
@ -50,7 +53,9 @@ namespace Guru
/// </summary>
/// <param name="appToken"></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))
{
@ -58,7 +63,7 @@ namespace Guru
return;
}
_onSessionSuccessCallback = onSessionSuccess;
_onInitComplete = onInitComplete;
InstallEvent(IPMConfig.FIREBASE_ID, IPMConfig.IPM_DEVICE_ID); // 注入启动参数
@ -66,9 +71,12 @@ namespace Guru
AdjustConfig config = new AdjustConfig(appToken, environment);
config.setLogLevel(GetAdjustLogLevel());
config.setDelayStart(DelayTime);
config.setPreinstallTrackingEnabled(true); // Adjust Preinstall
config.setSessionSuccessDelegate(OnSessionSuccessCallback); // SessionSuccess
if(onDeeplinkCallback != null)
config.setDeferredDeeplinkDelegate(onDeeplinkCallback);
#if UNITY_ANDROID
if (!string.IsNullOrEmpty(fbAppId)) config.setFbAppId(fbAppId); // 注入 MIR ID
@ -79,7 +87,6 @@ namespace Guru
config.setLogDelegate(log => LogI(LOG_TAG, log));
config.setEventSuccessDelegate(OnEventSuccessCallback);
config.setEventFailureDelegate(OnEventFailureCallback);
config.setSessionFailureDelegate(OnSessionFailureCallback);
config.setAttributionChangedDelegate(OnAttributionChangedCallback);
#endif
@ -87,9 +94,6 @@ namespace Guru
SetupInstance();
Adjust.start(config);
// 缓存标准属性
_adjustId = Adjust.getAdid(); // 获取AdjustID
// 异步加载AdId
FetchGoogleAdId();
@ -160,6 +164,22 @@ namespace Guru
#endregion
#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)
{
@ -278,14 +298,6 @@ namespace Guru
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)
{
LogI(LOG_TAG,"Session tracking failed!");
@ -358,24 +370,22 @@ namespace Guru
/// <summary>
/// 广告收入上报 (Adjust 特有的接口)
/// </summary>
/// <param name="adInfo"></param>
public static void TrackADRevenue(MaxSdkBase.AdInfo adInfo)
/// <param name="value"></param>
/// <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);
adRevenue.setRevenue(adInfo.Revenue, "USD");
adRevenue.setAdRevenueNetwork(adInfo.NetworkName);
adRevenue.setAdRevenueUnit(adInfo.AdUnitIdentifier);
adRevenue.setAdRevenuePlacement(adInfo.Placement);
if (string.IsNullOrEmpty(currency)) currency = "USD";
adRevenue.setRevenue(value, currency);
adRevenue.setAdRevenueNetwork(adSource);
adRevenue.setAdRevenueUnit(adUnitId);
adRevenue.setAdRevenuePlacement(adPlacement);
Adjust.trackAdRevenue(adRevenue);
}
#endregion
#region 关键属性上报

View File

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

View File

@ -1,11 +1,13 @@
namespace Guru
{
using System;
/// <summary>
/// 自打点代理接口
/// </summary>
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 SetAdId(string id);
void SetUserProperty(string key, string value);

View File

@ -1,5 +1,7 @@
using System.Threading.Tasks;
namespace Guru
{
using System;
@ -76,12 +78,16 @@ namespace Guru
#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;
string bundleId = Application.identifier;
// 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); // 调用接口
onInitComplete?.Invoke();
}
public void SetScreen(string screenName)

View File

@ -1,7 +1,9 @@
using System.Runtime.InteropServices;
namespace Guru
{
using System;
using System.Runtime.InteropServices;
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;
#if UNITY_IOS
unityInitAnalytics(appId, deviceInfo, isDebug);
unityInitException(); // 初始化报错守护进程
#endif
onInitComplete?.Invoke();
}
public void SetScreen(string screenName)

View File

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

View File

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

View File

@ -1,5 +1,7 @@
using System.Threading.Tasks;
namespace Guru
{
using UnityEngine;
@ -30,6 +32,21 @@ namespace Guru
Debug.Log($"{Tag} Consent Request -> deviceid: {deviceId} debugGeography: {debugGeography}");
#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);
var go = GameObject.Find(_objName);
if (go != null)
@ -40,9 +57,10 @@ namespace Guru
{
Debug.LogError($"{Tag} Can't find callback object");
}
#endif
}
/// <summary>
/// 获取 DMA 字段
/// </summary>

View File

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

View File

@ -1,8 +1,11 @@
using System.Linq;
namespace Guru
{
using System;
using UnityEngine;
using System.Collections.Generic;
using Guru.Ads;
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;
protected bool IsNetworkEnabled => Application.internetReachability != NetworkReachability.NotReachable;
@ -40,10 +43,15 @@ namespace Guru
public static Action OnRewardLoaded;
public static Action OnRewardFailed;
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 AdsInitSpec _initSpec = null;
private AdImpressionDriver _impressionDriver;
public AdsModel Model
{
get
@ -74,6 +82,9 @@ namespace Guru
if(_model == null) _model = AdsModel.Create();
this.Log("AD SDK Start Init");
_impressionDriver = new AdImpressionDriver();
_impressionDriver.Init(ReportAdsRevenue); // 初始化 Impression 驱动器
InitMaxCallbacks(); // 初始化 MAX 广告
InitService(); // 内部继承接口
}
@ -85,14 +96,16 @@ namespace Guru
{
//-------------- 初始化回调 ------------------
MaxSdkCallbacks.OnSdkInitializedEvent += OnMaxSdkInitializedCallBack;
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnBannerRevenuePaidEvent;
MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
//--------------- MRec 回调 -----------------
// MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
//--------------- Banner 回调 -----------------
MaxSdkCallbacks.Banner.OnAdLoadedEvent += OnBannerLoadedEvent;
MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += OnBannerFailedEvent;
MaxSdkCallbacks.Banner.OnAdClickedEvent += OnBannerClickedEvent;
MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnBannerRevenuePaidEvent;
MaxSdkCallbacks.Banner.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent;
//--------------- IV 回调 -----------------
MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent;
MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += OnInterstitialFailedEvent;
@ -100,6 +113,8 @@ namespace Guru
MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickEvent;
MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayEvent;
MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialDismissedEvent;
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnInterstitialPaidEvent;
MaxSdkCallbacks.Interstitial.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent;
//--------------- RV 回调 -----------------
MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent;
MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += OnRewardedAdFailedEvent;
@ -108,11 +123,19 @@ namespace Guru
MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent;
MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdDismissedEvent;
MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent;
MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnRewardedAdPaidEvent;
MaxSdkCallbacks.Rewarded.OnAdReviewCreativeIdGeneratedEvent += OnAdReviewCreativeIdGeneratedEvent;
//--------------- Creative 回调 -----------------
//-------------- SDK 初始化 -------------------
MaxSdk.SetExtraParameter("enable_black_screen_fixes", "true"); // 修复黑屏
}
protected virtual void InitService()
{
}
@ -174,7 +197,7 @@ namespace Guru
#endregion
#region ILRD
#region 收益打点
private double TchAD001RevValue
{
@ -188,49 +211,34 @@ namespace Guru
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>
/// 广告ARO收益打点
/// 上报广告收益
/// </summary>
/// <param name="adInfo"></param>
/// <param name="platform"></param>
private void OnAdImpression(MaxSdkBase.AdInfo adInfo, string platform = "")
/// <param name="reviewedCreativeId"></param>
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>
/// 计算太极001收益
/// </summary>
/// <param name="revenue"></param>
private void CalcTaichi001Value(double revenue)
private void CalcTch001Value(double revenue)
{
TchAD001RevValue += revenue;
double revenueValue = TchAD001RevValue;
@ -247,7 +255,7 @@ namespace Guru
/// 计算太极02收益
/// </summary>
/// <param name="revenue"></param>
private void CalcTaichi02Value(double revenue)
private void CalcTch02Value(double revenue)
{
if (!Analytics.EnableTch02Event) return;
@ -269,21 +277,24 @@ namespace Guru
private string _backColorStr = "#50A436";
private Color _backColor = new Color(0, 0, 0, 0);
private string _badsCategory;
protected float _badsloadStartTime = 0;
protected DateTime _badsloadStartTime;
private bool _bannerVisible = false;
public bool IsBannerVisible => _bannerVisible;
private int _badsloadedNum = 0;
private int _badsLoadFailNum = 0;
private int GetAdsLoadDuration(ref float startTime)
/// <summary>
/// 获取动作间隔之间的毫秒数
/// </summary>
/// <param name="startTime"></param>
/// <returns></returns>
private int GetActionDuration(DateTime startTime)
{
int duration = (int)((Time.realtimeSinceStartup - startTime) * 1000);
startTime = Time.realtimeSinceStartup;
return duration;
var sp = DateTime.UtcNow.Subtract(startTime.ToUniversalTime()).Duration();
return (int) sp.TotalMilliseconds;
}
public virtual void RequestBannerAD()
{
_backColor = Color.clear;
@ -314,12 +325,12 @@ namespace Guru
public void OnLoadBads()
{
_badsloadStartTime = Time.realtimeSinceStartup;
_badsloadStartTime = DateTime.UtcNow;
}
protected virtual void OnBadsLoaded()
{
_badsloadStartTime = Time.realtimeSinceStartup;
_badsloadStartTime = DateTime.UtcNow;
OnBannerLoaded?.Invoke();
}
@ -386,6 +397,7 @@ namespace Guru
// --- fixed by Yufei 2024-5-29 为 don't report bads_loaded any more. ---
// Analytics.ADBadsLoaded(AdParams.Build(adUnitId, adInfo,
// duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory));
Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}");
OnBadsLoaded();
}
@ -394,7 +406,7 @@ namespace Guru
_badsLoadFailNum ++;
// Analytics.ADBadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _badsloadStartTime), _badsCategory);
Analytics.ADBadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory,
duration: GetActionDuration(_badsloadStartTime), category: _badsCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
}
@ -426,7 +438,8 @@ namespace Guru
{
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 int _interstitialRetryAttempt;
protected float _iadsLoadStartTime;
private Action _interCloseAction;
protected bool _isIadsLoading = false;
protected DateTime _iadsLoadStartTime;
private DateTime _iadsDisplayStartTime;
public bool IsIadsLoading => _isIadsLoading;
public virtual void RequestInterstitialAD()
@ -462,7 +478,7 @@ namespace Guru
public void OnLoadIads()
{
_iadsLoadStartTime = Time.realtimeSinceStartup;
_iadsLoadStartTime = DateTime.UtcNow;
}
@ -496,6 +512,7 @@ namespace Guru
_interCloseAction = dismissAction;
MaxSdk.ShowInterstitial(GetInterstitialID());
_iadsDisplayStartTime = DateTime.UtcNow;
// RequestInterstitialAD(); // 直接加载下一个广告
}
@ -506,9 +523,11 @@ namespace Guru
// Reset retry attempt
// Analytics.ADIadsLoaded(adUnitId, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
Analytics.ADIadsLoaded(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory));
duration: GetActionDuration(_iadsLoadStartTime), category: _iadsCategory));
_interstitialRetryAttempt = 0;
Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}");
OnInterstitialLoaded?.Invoke();
}
@ -523,8 +542,9 @@ namespace Guru
float retryDelay = GetRetryDelaySeconds(_interstitialRetryAttempt);
DelayCall(retryDelay, RequestInterstitialAD);
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
if(string.IsNullOrEmpty(_iadsCategory)) _iadsCategory = "not_set";
Analytics.ADIadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory,
duration: GetActionDuration(_iadsLoadStartTime), category: _iadsCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
@ -539,42 +559,61 @@ namespace Guru
$"InterstitialFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
Analytics.ADIadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory,
duration: GetActionDuration(_iadsDisplayStartTime), category: _iadsCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
waterfallName: errorInfo.WaterfallInfo?.Name ?? ""));
DelayCall(2.0f, RequestInterstitialAD);
}
// iads_imp
protected virtual void OnInterstitialDisplayEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// 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)
{
// 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)
{
// Interstitial ad is hidden. Pre-load the next ad
_interCloseAction?.Invoke();
OnInterstitialClosed?.Invoke();
// 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);
}
private void OnInterstitialPaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
AppendImpressionData(adInfo, eventName:Analytics.EventIadsPaid, itemCategory: _iadsCategory);
}
#endregion
#region Rewarded Ads
private string _rewardCategory = "main";
private int _rewardRetryAttempt;
protected float _radsLoadStartTime;
protected DateTime _radsLoadStartTime;
protected DateTime _radsShowStartTime;
private Action _rvRewardAction;
private Action<string> _rvFailAction;
private Action _rvDismissAction;
@ -607,7 +646,7 @@ namespace Guru
public void OnLoadRads()
{
_radsLoadStartTime = Time.realtimeSinceStartup;
_radsLoadStartTime = DateTime.UtcNow;
}
@ -646,6 +685,8 @@ namespace Guru
_rvDismissAction = dismissAction;
MaxSdk.ShowRewardedAd(GetRewardedID());
_radsShowStartTime = DateTime.UtcNow;
// RequestRewardedAD();
}
@ -658,8 +699,10 @@ namespace Guru
// this.Log("OnRewardedAdLoadedEvent");
// Analytics.ADRadsLoaded(adUnitId, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsLoaded(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _iadsCategory));
duration: GetActionDuration(_radsLoadStartTime), category: _iadsCategory));
_rewardRetryAttempt = 0;
Debug.Log( $"[SDK][Ads][Loaded] --- adUnitId:{adUnitId} Revenue:{adInfo.Revenue} Type:{adInfo.AdFormat} CreativeId:{adInfo.CreativeIdentifier}");
OnRewardLoaded?.Invoke();
}
@ -674,7 +717,7 @@ namespace Guru
$"OnRewardedAdFailedEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory,
duration: GetActionDuration(_radsLoadStartTime), category: _rewardCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
_rewardRetryAttempt++;
@ -692,7 +735,7 @@ namespace Guru
$"OnRewardedAdFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory,
duration: GetActionDuration(_radsShowStartTime), category: _rewardCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
_rvFailAction?.Invoke("OnRewardedAdFailedToDisplayEvent");
@ -705,16 +748,17 @@ namespace Guru
{
this.Log("OnRewardedAdDisplayedEvent");
// 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)
{
this.Log("OnRewardedAdClickedEvent");
// 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)
{
this.Log("OnRewardedAdDismissedEvent");
@ -723,24 +767,36 @@ namespace Guru
OnRewardClosed?.Invoke();
// 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);
}
// rads_rewarded
protected virtual void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward,
MaxSdkBase.AdInfo arg3)
MaxSdkBase.AdInfo adInfo)
{
this.Log("OnRewardedAdReceivedRewardEvent");
// Analytics.ADRadsRewarded(adUnitId, _rewardCategory);
Analytics.ADRadsRewarded(AdParams.Build(adUnitId, category: _rewardCategory));
// Rewarded ad was displayed and user should receive the reward
AppendImpressionData(adInfo, eventName:Analytics.EventRadsRewarded, itemCategory: _rewardCategory);
_rvRewardAction?.Invoke();
}
// rads_paid
private void OnRewardedAdPaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
this.Log("OnRewardedAdReceivedRewardEvent");
AppendImpressionData(adInfo, eventName:Analytics.EventRadsPaid, itemCategory: _rewardCategory);
}
#endregion
#region Ad Settings
@ -782,5 +838,87 @@ namespace Guru
}
#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);
if (string.IsNullOrEmpty(tokenID))

View File

@ -36,15 +36,37 @@ namespace Guru
if (adParams.duration > 0)
data[ParameterDuration] = adParams.duration;
if (adParams.errorCode != 0)
data[ParameterErrorCode] = adParams.errorCode;
if (!string.IsNullOrEmpty(adParams.networkName))
data[ParameterNetworkName] = adParams.networkName;
if (!string.IsNullOrEmpty(adParams.networkPlacement))
if (!string.IsNullOrEmpty(adParams.networkPlacement))
{
data[ParameterNetworkPlacement] = adParams.networkPlacement;
data[ParameterAdPlacement] = adParams.networkPlacement;
}
if (!string.IsNullOrEmpty(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)
{
foreach (var k in extra.Keys)
@ -59,26 +81,26 @@ namespace Guru
//---------------------- BANNER -------------------------
public static void ADBadsLoad(AdParams adParams)
{
LogEvent(EventBadsLoad, BuildAdEventData(adParams));
TrackEvent(EventBadsLoad, BuildAdEventData(adParams));
}
public static void ADBadsLoaded(AdParams adParams)
{
LogEvent(EventBadsLoaded, BuildAdEventData(adParams));
TrackEvent(EventBadsLoaded, BuildAdEventData(adParams));
}
public static void ADBadsFailed(AdParams adParams)
{
LogEvent(EventBadsFailed, BuildAdEventData(adParams));
TrackEvent(EventBadsFailed, BuildAdEventData(adParams));
}
/// <summary>
/// 广告点击
/// </summary>
public static void ADBadsClick(AdParams adParams)
{
LogEvent(EventBadsClick, BuildAdEventData(adParams));
TrackEvent(EventBadsClick, BuildAdEventData(adParams));
}
public static void ADBadsImp(AdParams adParams)
{
LogEvent(EventBadsImp, BuildAdEventData(adParams));
TrackEvent(EventBadsImp, BuildAdEventData(adParams));
}
public static void ADBadsHide( int loadedTimes, int failTimes)
@ -88,7 +110,7 @@ namespace Guru
["loaded_times"] = loadedTimes,
["fail_times"] = failTimes
};
LogEvent(EventBadsHide, dict);
TrackEvent(EventBadsHide, dict);
}
//---------------------- INTERSTITIAL -------------------------
/// <summary>
@ -96,7 +118,7 @@ namespace Guru
/// </summary>
public static void ADIadsLoad(AdParams adParams)
{
LogEvent(EventIadsLoad, BuildAdEventData(adParams));
TrackEvent(EventIadsLoad, BuildAdEventData(adParams));
}
/// <summary>
@ -104,7 +126,7 @@ namespace Guru
/// </summary>
public static void ADIadsLoaded(AdParams adParams)
{
LogEvent(EventIadsLoaded, BuildAdEventData(adParams));
TrackEvent(EventIadsLoaded, BuildAdEventData(adParams));
}
/// <summary>
@ -112,7 +134,7 @@ namespace Guru
/// </summary>
public static void ADIadsFailed(AdParams adParams)
{
LogEvent(EventIadsFailed, BuildAdEventData(adParams));
TrackEvent(EventIadsFailed, BuildAdEventData(adParams));
}
/// <summary>
@ -120,7 +142,12 @@ namespace Guru
/// </summary>
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>
@ -128,7 +155,12 @@ namespace Guru
/// </summary>
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>
@ -136,7 +168,21 @@ namespace Guru
/// </summary>
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 -------------------------
@ -145,36 +191,48 @@ namespace Guru
/// </summary>
public static void ADRadsLoad(AdParams adParams)
{
LogEvent(EventRadsLoad, BuildAdEventData(adParams));
TrackEvent(EventRadsLoad, BuildAdEventData(adParams));
}
/// <summary>
/// 广告拉取成功
/// </summary>
public static void ADRadsLoaded(AdParams adParams)
{
LogEvent(EventRadsLoaded, BuildAdEventData(adParams));
TrackEvent(EventRadsLoaded, BuildAdEventData(adParams));
}
/// <summary>
/// 广告拉取失败
/// </summary>
public static void ADRadsFailed(AdParams adParams)
{
LogEvent(EventRadsFailed, BuildAdEventData(adParams));
TrackEvent(EventRadsFailed, BuildAdEventData(adParams));
}
/// <summary>
/// 广告展示
/// </summary>
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>
public static void ADRadsRewarded(AdParams adParams)
{
var data = BuildAdEventData(adParams);
LogEvent(EventRadsRewarded, data);
ADRadsRewarded(BuildAdEventData(adParams));
}
public static void ADRadsRewarded(Dictionary<string, object> data)
{
TrackEvent(EventRadsRewarded, data);
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
{
@ -195,7 +262,7 @@ namespace Guru
/// </summary>
public static void ADRadsFirstRewarded(Dictionary<string, object> data)
{
LogEvent(EventFirstRadsRewarded, data);
TrackEvent(EventFirstRadsRewarded, data);
}
/// <summary>
@ -203,7 +270,12 @@ namespace Guru
/// </summary>
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>
@ -211,7 +283,12 @@ namespace Guru
/// </summary>
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
@ -235,7 +312,6 @@ namespace Guru
{ "type", type }
};
if(!string.IsNullOrEmpty(scene)) dict[ParameterItemName] = scene;
LogEvent(EventATTResult, dict);
}
/// <summary>
@ -261,10 +337,15 @@ namespace Guru
public string category;
public string networkName;
public string networkPlacement;
public string adPlatform;
public string adSource;
public string adFormat;
public string waterfallName;
public string adUnitId;
public int errorCode = 0;
public int duration = 0;
public string creativeId;
public string reviewCreativeId;
/// <summary>
@ -276,31 +357,47 @@ namespace Guru
/// <param name="duration"></param>
/// <param name="errorCode"></param>
/// <param name="waterfallName"></param>
/// <param name="reviewCreativeId"></param>
/// <param name="adPlatform"></param>
/// <returns></returns>
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;
var networkName = "";
var networkPlacement = "";
var creativeId = "";
var adSource = "";
var adFormart = "";
if (string.IsNullOrEmpty(adPlatform)) adPlatform = Analytics.AdMAX;
if (adInfo != null)
{
networkName = adInfo.NetworkName;
networkPlacement = adInfo.NetworkPlacement;
creativeId = adInfo.CreativeIdentifier;
adSource = adInfo.NetworkName;
adFormart = adInfo.AdFormat;
if (string.IsNullOrEmpty(waterfallName))
waterfallName = adInfo.WaterfallInfo?.Name ?? "";
}
var p = new AdParams()
{
adUnitId = adUnitId,
adPlatform = adPlatform,
adSource = adSource,
adFormat = adFormart,
duration = duration,
networkName = networkName,
networkPlacement = networkPlacement,
waterfallName = waterfallName,
category = category,
errorCode = errorCode,
creativeId = creativeId,
reviewCreativeId = reviewCreativeId,
};
return p;
}

View File

@ -11,112 +11,119 @@ namespace Guru
//打点常量定义
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打点事件
public static readonly string EventIAPFirst = "first_iap";
public static readonly string EventIAPImp = "iap_imp";
public static readonly string EventIAPClose = "iap_close";
public static readonly string EventIAPClick = "iap_clk";
public static readonly string EventIAPReturnTrue = "iap_ret_true";
public static readonly string EventIAPReturnFalse = "iap_ret_false";
public const string EventIAPFirst = "first_iap";
public const string EventIAPImp = "iap_imp";
public const string EventIAPClose = "iap_close";
public const string EventIAPClick = "iap_clk";
public const string EventIAPReturnTrue = "iap_ret_true";
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 static readonly string EventBadsLoaded = "bads_loaded";
public static readonly string EventBadsFailed = "bads_failed";
public static readonly string EventBadsClick = "bads_clk";
public static readonly string EventBadsImp = "bads_imp";
public static readonly string EventBadsHide = "bads_hide";
public const string EventBadsLoad = "bads_load";
public const string EventBadsLoaded = "bads_loaded";
public const string EventBadsFailed = "bads_failed";
public const string EventBadsClick = "bads_clk";
public const string EventBadsImp = "bads_imp";
public const string EventBadsHide = "bads_hide";
public const string EventBadsPaid = "bads_paid";
//插屏广告打点事件
public static readonly string EventIadsLoad = "iads_load";
public static readonly string EventIadsLoaded = "iads_loaded";
public static readonly string EventIadsFailed = "iads_failed";
public static readonly string EventIadsImp = "iads_imp";
public static readonly string EventIadsClick = "iads_clk";
public static readonly string EventIadsClose = "iads_close";
public const string EventIadsLoad = "iads_load";
public const string EventIadsLoaded = "iads_loaded";
public const string EventIadsFailed = "iads_failed";
public const string EventIadsImp = "iads_imp";
public const string EventIadsClick = "iads_clk";
public const string EventIadsClose = "iads_close";
public const string EventIadsPaid = "iads_paid";
//激励视频广告打点事件
public static readonly string EventRadsLoad = "rads_load";
public static readonly string EventRadsLoaded = "rads_loaded";
public static readonly string EventRadsFailed = "rads_failed";
public static readonly string EventRadsImp = "rads_imp";
public static readonly string EventRadsRewarded = "rads_rewarded";
public static readonly string EventRadsClick = "rads_clk";
public static readonly string EventRadsClose = "rads_close";
public static readonly string EventFirstRadsRewarded = "first_rads_rewarded";
public const string EventRadsLoad = "rads_load";
public const string EventRadsLoaded = "rads_loaded";
public const string EventRadsFailed = "rads_failed";
public const string EventRadsImp = "rads_imp";
public const string EventRadsRewarded = "rads_rewarded";
public const string EventRadsClick = "rads_clk";
public const string EventRadsClose = "rads_close";
public const string EventRadsPaid = "rads_paid";
public const string EventFirstRadsRewarded = "first_rads_rewarded";
//广告收益打点事件
public static readonly string EventTchAdRev001Impression = "tch_ad_rev_roas_001";
public static readonly string EventTchAdRev02Impression = "tch_ad_rev_roas_02";
public static readonly string EventTchAdRevAbnormal = "tch_ad_rev_value_abnormal";
public const string EventTchAdRev001Impression = "tch_ad_rev_roas_001";
public const string EventTchAdRev02Impression = "tch_ad_rev_roas_02";
public const string EventTchAdRevAbnormal = "tch_ad_rev_value_abnormal";
//内购成功事件上报
public static readonly string EventIAPPurchase = "iap_purchase";
public static readonly string EventSubPurchase = "sub_purchase";
public static readonly string IAPStoreCategory = "Store";
public static readonly string IAPTypeProduct = "product";
public static readonly string IAPTypeSubscription = "subscription";
public const string EventIAPPurchase = "iap_purchase";
public const string EventSubPurchase = "sub_purchase";
public const string IAPStoreCategory = "Store";
public const string IAPTypeProduct = "product";
public const string IAPTypeSubscription = "subscription";
//打点参数名
public static readonly string ParameterResult = "result";
public static readonly string ParameterStep = "step";
public static readonly string ParameterDuration = "duration";
public static readonly string ParameterErrorCode = "error_code";
public static readonly string ParameterProductId = "product_id";
public static readonly string ParameterPlatform = "platform";
public static readonly string ParameterStartType = "start_type"; // 游戏启动类型
public static readonly string ParameterReplay = "replay"; // 游戏重玩
public static readonly string ParameterContinue = "continue"; // 游戏继续
public static readonly string ParameterAdUnitName = "ad_unit_name";
public static readonly string ParameterAdCreativeId = "ad_creative_id";
public const string ParameterResult = "result";
public const string ParameterStep = "step";
public const string ParameterDuration = "duration";
public const string ParameterErrorCode = "error_code";
public const string ParameterProductId = "product_id";
public const string ParameterPlatform = "platform";
public const string ParameterStartType = "start_type"; // 游戏启动类型
public const string ParameterReplay = "replay"; // 游戏重玩
public const string ParameterContinue = "continue"; // 游戏继续
public const string ParameterAdUnitName = "ad_unit_name";
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 static readonly string EventRateNow = "rate_now"; // 点击评分引导弹窗中的评分
public const string EventRateImp = "rate_imp"; // 评价弹窗展示
public const string EventRateNow = "rate_now"; // 点击评分引导弹窗中的评分
//打点内部执行错误
public static string ParameterEventError => "event_error";
//ios ATT打点
public static readonly string ATTGuideShow = "att_guide_show";
public static readonly string ATTGuideOK = "att_guide_ok";
public static readonly string ATTWindowShow = "att_window_show";
public static readonly string ATTOptIn = "att_opt_in";
public static readonly string ATTOpOut = "att_opt_out";
public static readonly string ParameterATTStatus = "att_status";
public static readonly string EventATTResult = "att_result";
public const string ATTGuideShow = "att_guide_show";
public const string ATTGuideOK = "att_guide_ok";
public const string ATTWindowShow = "att_window_show";
public const string ATTOptIn = "att_opt_in";
public const string ATTOpOut = "att_opt_out";
public const string ParameterATTStatus = "att_status";
public const string EventATTResult = "att_result";
// 用户属性
public static readonly string PropertyFirstOpenTime = "first_open_time"; //用户第一次first_open的时间
public static readonly string PropertyDeviceID = "device_id"; //用户的设备ID
public static readonly string PropertyUserID = "user_id";
public static readonly string PropertyLevel = "b_level"; //"每次完成通关上升一次显示用户完成的最大关卡数。只针对主关卡和主玩法的局数做累加初始值为0。"
public static readonly string PropertyPlay = "b_play"; //每完成一局或者游戏触发,
public static readonly string PropertyLastPlayedLevel = "last_played_level";
public static readonly string PropertyGrade = "grade"; //当游戏玩家角色升级时触发
public static readonly string PropertyIsIAPUser = "is_iap_user"; //付费成功后设置属性参数为true如果没有发生付费可以不用设置该属性
public static readonly string PropertyIAPCoin = "iap_coin"; //付费所得的总金币数(iap获取累计值)\
public static readonly string PropertyNonIAPCoin = "noniap_coin"; //非付费iap获取累计值
public static readonly string PropertyCoin = "coin"; //当前金币数
public static readonly string PropertyExp = "exp"; // 经验值
public static readonly string PropertyHp = "hp"; // 生命值/体力
public static readonly string PropertyAndroidID = "android_id"; // Android 平台 AndroidID
public static readonly string PropertyIDFV = "idfv"; // iOS 平台 IDFV
public static readonly string PropertyIDFA = "idfa"; // iOS 平台 IDFA
public static readonly string PropertyPicture = "picture"; // 玩家在主线的mapid
public static readonly string PropertyNoAds = "no_ads"; // 玩家是否去广告
public static readonly string PropertyATTStatus = "att_status"; // ATT 状态
public static readonly string PropertyGDPR = "gdpr"; // GDPR状态
public const string PropertyFirstOpenTime = "first_open_time"; //用户第一次first_open的时间
public const string PropertyDeviceID = "device_id"; //用户的设备ID
public const string PropertyUserID = "user_id";
public const string PropertyLevel = "b_level"; //"每次完成通关上升一次显示用户完成的最大关卡数。只针对主关卡和主玩法的局数做累加初始值为0。"
public const string PropertyPlay = "b_play"; //每完成一局或者游戏触发,
public const string PropertyLastPlayedLevel = "last_played_level";
public const string PropertyGrade = "grade"; //当游戏玩家角色升级时触发
public const string PropertyIsIAPUser = "is_iap_user"; //付费成功后设置属性参数为true如果没有发生付费可以不用设置该属性
public const string PropertyIAPCoin = "iap_coin"; //付费所得的总金币数(iap获取累计值)\
public const string PropertyNonIAPCoin = "noniap_coin"; //非付费iap获取累计值
public const string PropertyCoin = "coin"; //当前金币数
public const string PropertyExp = "exp"; // 经验值
public const string PropertyHp = "hp"; // 生命值/体力
public const string PropertyAndroidID = "android_id"; // Android 平台 AndroidID
public const string PropertyIDFV = "idfv"; // iOS 平台 IDFV
public const string PropertyIDFA = "idfa"; // iOS 平台 IDFA
public const string PropertyPicture = "picture"; // 玩家在主线的mapid
public const string PropertyNoAds = "no_ads"; // 玩家是否去广告
public const string PropertyATTStatus = "att_status"; // ATT 状态
public const string PropertyGDPR = "gdpr"; // GDPR状态
// 经济相关
public const string ParameterBalance = "balance"; // 用于余额
@ -124,6 +131,6 @@ namespace Guru
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;
private static bool _hasInited = false;
public static bool IsReady => _hasInited;
private static bool _isGuruAnalyticInitOnce = false;
/// <summary>
/// 初始化Guru自打点系统 (请优先于 Firebase 初始化调用)
@ -36,7 +34,7 @@ namespace Guru
public static void InstallGuruAnalytics(bool isDebug = false, bool enableErrorLog = false)
{
if (_hasInited) return;
if (_isGuruAnalyticInitOnce) return;
try
{
@ -47,7 +45,7 @@ namespace Guru
#endif
string appId = IPMConfig.IPM_X_APP_ID;
string deviceInfo = new DeviceInfoData().ToString();
GuruAnalytics.Init(appId, deviceInfo, IsDebug, enableErrorLog); // 初始化(带Header)
GuruAnalytics.Init(appId, deviceInfo, OnGuruAnalyticsInitComplete, IsDebug, enableErrorLog); // 初始化(带Header)
_hasGotFirebaseId = false;
_hasGotAdId = false;
@ -59,7 +57,7 @@ namespace Guru
UpdateAllValues();
_hasInited = true;
_isGuruAnalyticInitOnce = true;
}
catch (Exception ex)
{
@ -79,7 +77,7 @@ namespace Guru
if (!string.IsNullOrEmpty(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);
_hasGotUid = true;
}
@ -95,7 +93,7 @@ namespace Guru
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);
_hasGotDeviceId = true;
}
@ -121,7 +119,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ID))
{
GuruAnalytics.SetAdjustId(IPMConfig.ADJUST_ID);
GuruAnalytics.Instance.SetAdjustId(IPMConfig.ADJUST_ID);
_hasGotAdjustId = true;
}
else
@ -152,7 +150,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ADID))
{
GuruAnalytics.SetAdId(IPMConfig.ADJUST_ADID);
GuruAnalytics.Instance.SetAdId(IPMConfig.ADJUST_ADID);
_hasGotAdId = true;
}
@ -171,7 +169,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.FIREBASE_ID))
{
GuruAnalytics.SetFirebaseId(IPMConfig.FIREBASE_ID);
GuruAnalytics.Instance.SetFirebaseId(IPMConfig.FIREBASE_ID);
_hasGotFirebaseId = true;
}
else
@ -185,6 +183,8 @@ namespace Guru
/// </summary>
private static void FetchFirebaseId()
{
if (!IsFirebaseReady) return;
FirebaseAnalytics.GetAnalyticsInstanceIdAsync()
.ContinueWithOnMainThread(task =>
{
@ -207,12 +207,12 @@ namespace Guru
private static void SetATTStatus()
{
string status = ATTManager.GetStatus();
GuruAnalytics.SetUserProperty(ParameterATTStatus, status);
GuruAnalytics.Instance.SetUserProperty(ParameterATTStatus, status);
}
private static void SetIDFV()
{
GuruAnalytics.SetIDFV(DeviceIDHelper.IDFV);
GuruAnalytics.Instance.SetIDFV(DeviceIDHelper.IDFV);
}
private static void SetIDFA()
@ -228,7 +228,7 @@ namespace Guru
if (!string.IsNullOrEmpty(IPMConfig.ADJUST_IDFA))
{
GuruAnalytics.SetIDFA(IPMConfig.ADJUST_IDFA);
GuruAnalytics.Instance.SetIDFA(IPMConfig.ADJUST_IDFA);
_hasGotIDFA = true;
}
}
@ -241,7 +241,7 @@ namespace Guru
/// </summary>
private static void SetAndroidId()
{
GuruAnalytics.SetAndroidID(DeviceIDHelper.AndroidID);
GuruAnalytics.Instance.SetAndroidID(DeviceIDHelper.AndroidID);
}
#endif
@ -276,7 +276,7 @@ namespace Guru
var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds;
if (interval > _reportSuccessInterval)
{
GuruAnalytics.ReportEventSuccessRate();
GuruAnalytics.Instance.ReportEventSuccessRate();
_lastReportRateDate = DateTime.Now;
}
}
@ -294,7 +294,7 @@ namespace Guru
{
try
{
GuruAnalytics.SetUserProperty(key, value);
GuruAnalytics.Instance.SetUserProperty(key, value);
UpdateAllValues(); // 同步所有的ID
}
catch (Exception e)
@ -309,12 +309,12 @@ namespace Guru
/// </summary>
/// <param name="key"></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
{
if (data == null) data = new Dictionary<string, dynamic>();
GuruAnalytics.LogEvent(key, data, priority);
GuruAnalytics.Instance.LogEvent(key, data, priority);
UpdateAllValues(); // 同步所有的ID
}
catch (Exception e)
@ -337,7 +337,7 @@ namespace Guru
if (Math.Abs(_tch02TargetValue - value) > 0.001d)
{
_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 (extra != null) data.AddRange(extra, isOverride: true);
LogEvent(EventEarnVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true });
TrackEvent(EventEarnVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true });
// FB 上报收入点
FBService.LogEvent(EventEarnVirtualCurrency, value, data);
@ -131,7 +131,7 @@ namespace Guru
if(!string.IsNullOrEmpty(scene)) data[ParameterScene] = scene; // 获取的虚拟货币或者道具的场景
LogEvent(EventSpendVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true });
TrackEvent(EventSpendVirtualCurrency, data, new EventSetting() { EnableFirebaseAnalytics = true });
// FB 上报消费点
FBService.LogEvent(EventSpendVirtualCurrency, value, data);

View File

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

View File

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

View File

@ -1,5 +1,7 @@
using System.Threading;
namespace Guru
{
using System;
@ -16,82 +18,111 @@ namespace Guru
{
public class EventSetting
{
public bool EnableFirebaseAnalytics = false;
public bool EnableAdjustAnalytics = false;
public bool EnableFacebookAnalytics = false;
public bool EnableFirebaseAnalytics;
public bool EnableAdjustAnalytics;
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 bool _isInited; //Analytics是否初始化完成
private static EventSetting DefaultEventSetting => EventSetting.GetDefaultSetting();
private static bool _isInitOnce; //Analytics是否初始化完成
public static bool EnableDebugAnalytics; //允许Debug包上报打点
public static bool IsDebugMode => PlatformUtil.IsDebug();
private static bool IsFirebaseReady => FirebaseUtil.IsFirebaseInitialized;
private static bool IsEnable
private static bool IsReady
{
get
{
//Firebase服务没有初始化完成不上报打点
if (!FirebaseUtil.IsFirebaseInitialized)
return false;
//Analytics没有初始化不上报打点
if (!_isInited)
return false;
if (!_isInitOnce) return false;
//Firebase服务没有初始化完成不上报打点
if (!IsFirebaseReady) return false;
#if !UNITY_EDITOR
//开发环境打点不上报
if (IsDebugMode && !EnableDebugAnalytics)
return false;
#endif
return true;
}
}
private static AdjustEventDriver _adjustEventDriver;
private static FBEventDriver _fbEventDriver;
private static FirebaseEventDriver _firebaseEventDriver;
private static GuruEventDriver _guruEventDriver;
#region 初始化
public static void InitAnalytics()
{
if (_isInited) return;
_isInited = true;
if (_isInitOnce) return;
_isInitOnce = true;
// -------- 初始化 Exception ----------
CrashlyticsAgent.Install();
_adjustEventDriver = new AdjustEventDriver();
_fbEventDriver = new FBEventDriver();
_firebaseEventDriver = new FirebaseEventDriver();
_guruEventDriver = new GuruEventDriver();
// ------- 初始化自打点 ----------
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;
if (success)
{
Crashlytics.IsCrashlyticsCollectionEnabled = true;
if (_defaultEventSetting.EnableFirebaseAnalytics)
{
FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0));
SetUserProperty(FirebaseAnalytics.UserPropertySignUpMethod, "Google");
SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID);
// SetUserProperty(PropertyFirstOpenTime, FirstOpenTime);
}
}
Debug.Log($"[SDK] --- Analytics Init After FirebaseReady:{IsFirebaseReady}");
// -------- 初始化 Crashlytics ----------
CrashlyticsAgent.Init();
FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);
FirebaseAnalytics.SetSessionTimeoutDuration(new TimeSpan(0, 30, 0));
SetUserProperty(FirebaseAnalytics.UserPropertySignUpMethod, "Google");
SetUserProperty(PropertyDeviceID, IPMConfig.IPM_DEVICE_ID);
// SetUserProperty(PropertyFirstOpenTime, FirstOpenTime);
_firebaseEventDriver.TriggerFlush();
}
public static void OnFBInitComplete()
{
_fbEventDriver.TriggerFlush();
}
public static void OnAdjustInitComplete()
{
_adjustEventDriver.TriggerFlush();
}
private static void OnGuruAnalyticsInitComplete()
{
_guruEventDriver.TriggerFlush();
}
#endregion
@ -99,14 +130,19 @@ namespace Guru
public static void SetCurrentScreen(string screenName, string className)
{
if (!_isInitOnce)
{
return;
}
Log.I(TAG,$"SetCurrentScreen -> screenName:{screenName}, className:{className}");
GuruAnalytics.SetScreen(screenName);
if (!IsEnable) return;
FirebaseAnalytics.LogEvent(FirebaseAnalytics.EventScreenView,
new Parameter(FirebaseAnalytics.ParameterScreenClass, className),
new Parameter(FirebaseAnalytics.ParameterScreenName, screenName)
);
GuruAnalytics.Instance.SetScreen(screenName);
TrackEvent(EventScreenView, new Dictionary<string, dynamic>()
{
[ParameterScreenName] = screenName,
[ParameterScreenClass] = className,
});
}
#endregion
@ -120,7 +156,7 @@ namespace Guru
public static void SetUserIDProperty(string userID)
{
Log.I(TAG,$"SetUserIDProperty -> userID:{userID}");
if (!IsEnable) return;
if (!IsReady) return;
FirebaseAnalytics.SetUserId(userID);
}
@ -128,126 +164,107 @@ namespace Guru
/// <summary>
/// Firebase上报用户属性
/// </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 (!IsEnable)
return;
if (!_isInitOnce)
{
throw new Exception($"[{TAG}][SDK] Analytics did not initialized, Call <Analytics.{nameof(InitAnalytics)}()> first!");
}
if (IsDebug && !EnableDebugAnalytics)
{
Debug.LogWarning($"[{TAG}][SDK] --- SetProperty {key}:{value} can not send int Debug mode. Set <InitConfig.EnableDebugAnalytics> with `true`");
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
#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>
/// <param name="eventName"></param>
/// <param name="extras"></param>
/// <param name="data"></param>
/// <param name="eventSetting"></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); // 自定义打点上报
CheckLogCache(eventName, extras, eventSetting); // log缓存和消费
if (!IsEnable) return;
if (extras == null)
if (!_isInitOnce)
{
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;
}
string paramStr = string.Join(",", extras);
Log.I(TAG, $"eventName:{eventName}, params:{paramStr}");
if (eventSetting == null) eventSetting = DefaultEventSetting;
if (eventSetting == null) eventSetting = _defaultEventSetting;
if (eventSetting.EnableFirebaseAnalytics)
{
List<Parameter> parameters = new List<Parameter>();
foreach (var kv in extras)
{
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());
}
Dictionary<string, object> dict = new Dictionary<string, object>();
GuruSDKUtils.MergeDictionary(dict, extras);
var dataStr = "";
if (data != null) dataStr = JsonParser.ToJson(data);
Debug.Log($"[{TAG}] --- [SDK] TrackEvent: {eventName} | priority: {priority} | data:{dataStr} | eventSetting: {eventSetting}");
if (eventSetting.EnableAdjustAnalytics)
try
{
AdjustEvent adjustEvent = Analytics.CreateAdjustEvent(eventName);
if (adjustEvent != null)
// 填充相关的追踪事件
if (eventSetting.EnableGuruAnalytics)
{
if (dict.Count > 0)
{
foreach (var kv in dict)
{
adjustEvent.AddEventParameter(kv.Key, kv.Value.ToString());
}
}
Adjust.trackEvent(adjustEvent);
_guruEventDriver.AddEvent(eventName, data, eventSetting, priority);
}
if (eventSetting.EnableFirebaseAnalytics)
{
_firebaseEventDriver.AddEvent(eventName, data, eventSetting, priority);
}
if (eventSetting.EnableAdjustAnalytics)
{
_adjustEventDriver.AddEvent(eventName, data, eventSetting, priority);
}
if (eventSetting.EnableFacebookAnalytics)
{
_fbEventDriver.AddEvent(eventName, data, eventSetting, priority);
}
}
if (eventSetting.EnableFacebookAnalytics)
catch (Exception ex)
{
FBService.LogEvent(eventName, null, dict);
if (FirebaseUtil.IsReady)
{
Crashlytics.LogException(ex);
}
else
{
Debug.Log($"Catch Error: {ex}");
}
}
}
/// <summary>
/// 上报 Adjust 事件
@ -300,14 +317,7 @@ namespace Guru
/// <param name="priority"></param>
public static void Track(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null, int priority = -1)
{
if (null != data)
{
LogEvent(key, data, setting, priority);
}
else
{
LogEvent(key, setting, priority);
}
TrackEvent(key, data, setting, priority);
}
@ -318,7 +328,7 @@ namespace Guru
/// <param name="isException"></param>
public static void LogCrashlytics(string msg, bool isException = true)
{
if (!_isInited) return;
if (!_isInitOnce) return;
if (isException)
{
LogCrashlytics(new Exception(msg));
@ -332,84 +342,15 @@ namespace Guru
public static void LogCrashlytics(Exception exp)
{
if (!_isInited) return;
if (!_isInitOnce) return;
CrashlyticsAgent.LogException(exp);
}
#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))
{
PlayerPrefs.SetString(nameof(FirebaseId), value);
GuruAnalytics.SetFirebaseId(value);
GuruAnalytics.Instance.SetFirebaseId(value);
}
}
}
@ -73,7 +73,7 @@ namespace Guru
if (!string.IsNullOrEmpty(value))
{
PlayerPrefs.SetString(nameof(AdjustId), value);
GuruAnalytics.SetAdjustId(value);
GuruAnalytics.Instance.SetAdjustId(value);
}
}
}
@ -88,7 +88,7 @@ namespace Guru
if (!string.IsNullOrEmpty(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
{
using System;
using System.Collections.Generic;
using Facebook.Unity;
using UnityEngine;
[MonoSingleton(EMonoSingletonType.CreateOnNewGameObject, false)]
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)
{
// Initialize the Facebook SDK
FB.Init(InitCallback, OnHideUnity);
}
else
{
// Already initialized, signal an app activation App Event
FB.ActivateApp();
}
if(_isInitOnce) return;
_isInitOnce = true;
_onInitComplete = onInitComplete;
// Initialize the Facebook SDK
FB.Init(InitCallback, OnHideUnity);
}
private void InitCallback()
{
if (FB.IsInitialized)
{
// Signal an app activation App Event
FB.ActivateApp();
FB.Mobile.SetAdvertiserIDCollectionEnabled(true);
FB.Mobile.SetAutoLogAppEventsEnabled(false); // 关闭自动打点上报
// Signal an app activation App Event
FB.ActivateApp();
FB.Mobile.SetAdvertiserIDCollectionEnabled(true);
FB.Mobile.SetAutoLogAppEventsEnabled(false); // 关闭自动打点上报
#if UNITY_IOS
FB.Mobile.SetAdvertiserTrackingEnabled(true);
FB.Mobile.SetAdvertiserTrackingEnabled(true);
#endif
}
else
{
Log.E(LOG_TAG, "Failed to Initialize the Facebook SDK");
}
_onInitComplete?.Invoke();
}
private void OnHideUnity(bool isGameShown)
@ -81,13 +75,13 @@ namespace Guru
}
private static bool IsAvailable
public static bool IsAvailable
{
get
{
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 true;

View File

@ -8,14 +8,31 @@ namespace Guru
public static partial class FirebaseUtil
{
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()
{
if (_isAutoFetchFcmToken)
{
StartFetchFcmToken();
}
}
public static void StartFetchFcmToken()
{
if (_isFetchOnce) return;
_isFetchOnce = true;
FirebaseMessaging.TokenReceived += OnTokenReceived;
FirebaseMessaging.MessageReceived += OnMessageReceived;
GetFCMToken();
IsInitMessage = true;
}
private static void GetFCMToken()

View File

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

View File

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

View File

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

View File

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

View File

@ -1132,7 +1132,7 @@ namespace Guru
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(),
}, new Analytics.EventSetting()
@ -1144,7 +1144,7 @@ namespace Guru
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(),
}, 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