Compare commits
45 Commits
hotfix/v1.
...
main
| Author | SHA1 | Date |
|---|---|---|
|
|
5c1f73fc18 | |
|
|
8a81ed78b4 | |
|
|
76fc4f5c26 | |
|
|
72bf076537 | |
|
|
19a46fff1e | |
|
|
4989926a47 | |
|
|
fe691235d6 | |
|
|
dc47cec8bd | |
|
|
2075f676b9 | |
|
|
660303e45d | |
|
|
2a895b370e | |
|
|
c0c557b34e | |
|
|
1256880b22 | |
|
|
e77994d811 | |
|
|
85dc4a7ddc | |
|
|
b7aacb61e4 | |
|
|
8cc083410d | |
|
|
81f37625c1 | |
|
|
1a9481b094 | |
|
|
2174bcf1a3 | |
|
|
602662881c | |
|
|
e36f7483a3 | |
|
|
7cbc5ac148 | |
|
|
e8c17f4cf4 | |
|
|
e8b3112cc5 | |
|
|
e0e78da9a3 | |
|
|
9e7e94ef36 | |
|
|
80e38bf85d | |
|
|
cfe81b5583 | |
|
|
34ae9e3f0b | |
|
|
eba48e4a75 | |
|
|
a53c153338 | |
|
|
ffcb846a64 | |
|
|
dbb56e5a32 | |
|
|
b6e038a027 | |
|
|
4e24169b25 | |
|
|
9024b8171c | |
|
|
f5747977ec | |
|
|
d3028d9e3b | |
|
|
a9a438b288 | |
|
|
523115bdb9 | |
|
|
f360529552 | |
|
|
f96e506a19 | |
|
|
c59f76aead | |
|
|
ba90a32195 |
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "Guru.Editor",
|
"name": "Guru.Editor",
|
||||||
"rootNamespace": "",
|
|
||||||
"references": [
|
"references": [
|
||||||
"Guru.Runtime"
|
"Guru.Runtime",
|
||||||
|
"Guru.Notification"
|
||||||
],
|
],
|
||||||
"includePlatforms": [
|
"includePlatforms": [
|
||||||
"Editor"
|
"Editor"
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ namespace Guru.Editor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Firebase 10.20.0 fixed to 10.22.0. BUT higher version do not open this ATTRIBUTE !!
|
||||||
[PostProcessBuild(47)] // MAX POD Process Order
|
// [PostProcessBuild(47)] // MAX POD Process Order
|
||||||
public static void PostBuildFixPodDeps(BuildTarget target, string projPath)
|
public static void PostBuildFixPodDeps(BuildTarget target, string projPath)
|
||||||
{
|
{
|
||||||
if (target != BuildTarget.iOS) return;
|
if (target != BuildTarget.iOS) return;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Guru
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class IOSPostBuildSwift
|
public class IOSPostBuildSwift
|
||||||
{
|
{
|
||||||
[PostProcessBuild(40)]
|
[PostProcessBuild(2000)]
|
||||||
public static void OnPostProcessBuild(BuildTarget target, string buildPath)
|
public static void OnPostProcessBuild(BuildTarget target, string buildPath)
|
||||||
{
|
{
|
||||||
if (target != BuildTarget.iOS) return;
|
if (target != BuildTarget.iOS) return;
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Guru
|
||||||
|
|
||||||
// 设置主项目的SWIFT构建支持
|
// 设置主项目的SWIFT构建支持
|
||||||
project.SetBuildProperty(mainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES");
|
project.SetBuildProperty(mainTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "YES");
|
||||||
|
project.SetBuildProperty(frameworkTargetGuid, "ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES", "NO");
|
||||||
|
|
||||||
project.WriteToFile(projectPath);
|
project.WriteToFile(projectPath);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
"MaxSdk",
|
"MaxSdk",
|
||||||
"MaxSdk.Scripts",
|
"MaxSdk.Scripts",
|
||||||
"Amazon",
|
"Amazon",
|
||||||
|
"Amazon.Scripts",
|
||||||
"OpenWrapSDK",
|
"OpenWrapSDK",
|
||||||
"UniWebView-CSharp",
|
"UniWebView-CSharp",
|
||||||
"UnityEngine.Purchasing",
|
"UnityEngine.Purchasing",
|
||||||
|
|
@ -17,7 +18,9 @@
|
||||||
"Google.Play.Review",
|
"Google.Play.Review",
|
||||||
"Google.Play.Common",
|
"Google.Play.Common",
|
||||||
"Guru.LitJson",
|
"Guru.LitJson",
|
||||||
"Unity.Advertisement.IosSupport"
|
"Unity.Advertisement.IosSupport",
|
||||||
|
"Unity.Notifications.Android",
|
||||||
|
"Unity.Notifications.iOS"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Guru
|
namespace Guru
|
||||||
{
|
{
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using com.adjust.sdk;
|
using com.adjust.sdk;
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
public static class AdjustService
|
public class AdjustService
|
||||||
{
|
{
|
||||||
public const string Version = "1.6.1";
|
public const string Version = "1.6.1";
|
||||||
public const string AdjustVersion = "4.38.0"; // Adjust SDK Version
|
public const string AdjustVersion = "4.38.0"; // Adjust SDK Version
|
||||||
|
|
@ -14,6 +17,8 @@ namespace Guru
|
||||||
|
|
||||||
public const string K_IAP_PURCHASE = "iap_purchase"; // 固定点位事件
|
public const string K_IAP_PURCHASE = "iap_purchase"; // 固定点位事件
|
||||||
public const string K_SUB_PURCHASE = "sub_purchase"; // 固定点位事件
|
public const string K_SUB_PURCHASE = "sub_purchase"; // 固定点位事件
|
||||||
|
|
||||||
|
private static Action<string> _onSessionSuccessCallback;
|
||||||
|
|
||||||
|
|
||||||
private static string _adId = "";
|
private static string _adId = "";
|
||||||
|
|
@ -45,7 +50,7 @@ namespace Guru
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="appToken"></param>
|
/// <param name="appToken"></param>
|
||||||
/// <param name="fbAppId">MIR 追踪 AppID</param>
|
/// <param name="fbAppId">MIR 追踪 AppID</param>
|
||||||
public static void StartService(string appToken, string fbAppId = "")
|
public static void StartService(string appToken, string fbAppId = "", Action<string> onSessionSuccess = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(appToken))
|
if (string.IsNullOrEmpty(appToken))
|
||||||
{
|
{
|
||||||
|
|
@ -53,6 +58,8 @@ namespace Guru
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onSessionSuccessCallback = onSessionSuccess;
|
||||||
|
|
||||||
InstallEvent(IPMConfig.FIREBASE_ID, IPMConfig.IPM_DEVICE_ID); // 注入启动参数
|
InstallEvent(IPMConfig.FIREBASE_ID, IPMConfig.IPM_DEVICE_ID); // 注入启动参数
|
||||||
|
|
||||||
AdjustEnvironment environment = GetAdjustEnvironment();
|
AdjustEnvironment environment = GetAdjustEnvironment();
|
||||||
|
|
@ -61,6 +68,7 @@ namespace Guru
|
||||||
config.setDelayStart(DelayTime);
|
config.setDelayStart(DelayTime);
|
||||||
|
|
||||||
config.setPreinstallTrackingEnabled(true); // Adjust Preinstall
|
config.setPreinstallTrackingEnabled(true); // Adjust Preinstall
|
||||||
|
config.setSessionSuccessDelegate(OnSessionSuccessCallback); // SessionSuccess
|
||||||
|
|
||||||
#if UNITY_ANDROID
|
#if UNITY_ANDROID
|
||||||
if (!string.IsNullOrEmpty(fbAppId)) config.setFbAppId(fbAppId); // 注入 MIR ID
|
if (!string.IsNullOrEmpty(fbAppId)) config.setFbAppId(fbAppId); // 注入 MIR ID
|
||||||
|
|
@ -71,7 +79,7 @@ namespace Guru
|
||||||
config.setLogDelegate(log => LogI(LOG_TAG, log));
|
config.setLogDelegate(log => LogI(LOG_TAG, log));
|
||||||
config.setEventSuccessDelegate(OnEventSuccessCallback);
|
config.setEventSuccessDelegate(OnEventSuccessCallback);
|
||||||
config.setEventFailureDelegate(OnEventFailureCallback);
|
config.setEventFailureDelegate(OnEventFailureCallback);
|
||||||
config.setSessionSuccessDelegate(OnSessionSuccessCallback);
|
|
||||||
config.setSessionFailureDelegate(OnSessionFailureCallback);
|
config.setSessionFailureDelegate(OnSessionFailureCallback);
|
||||||
config.setAttributionChangedDelegate(OnAttributionChangedCallback);
|
config.setAttributionChangedDelegate(OnAttributionChangedCallback);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -272,27 +280,10 @@ namespace Guru
|
||||||
|
|
||||||
private static void OnSessionSuccessCallback(AdjustSessionSuccess sessionSuccessData)
|
private static void OnSessionSuccessCallback(AdjustSessionSuccess sessionSuccessData)
|
||||||
{
|
{
|
||||||
LogI(LOG_TAG,"Session tracked successfully!");
|
LogI(LOG_TAG,$"{LOG_TAG} --- Session tracked successfully!");
|
||||||
|
|
||||||
if (sessionSuccessData.Message != null)
|
var adid = sessionSuccessData.Adid;
|
||||||
{
|
_onSessionSuccessCallback?.Invoke(adid);
|
||||||
LogI(LOG_TAG,"Message: " + sessionSuccessData.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sessionSuccessData.Timestamp != null)
|
|
||||||
{
|
|
||||||
LogI(LOG_TAG,"Timestamp: " + sessionSuccessData.Timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sessionSuccessData.Adid != null)
|
|
||||||
{
|
|
||||||
LogI(LOG_TAG, "Adid: " + sessionSuccessData.Adid);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sessionSuccessData.JsonResponse != null)
|
|
||||||
{
|
|
||||||
LogI(LOG_TAG, "JsonResponse: " + sessionSuccessData.GetJsonResponse());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnSessionFailureCallback(AdjustSessionFailure sessionFailureData)
|
private static void OnSessionFailureCallback(AdjustSessionFailure sessionFailureData)
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ namespace Guru
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化平台
|
/// 初始化平台
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Initialize()
|
public void Initialize(bool isDebug = false)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
Debug.Log($"<color=orange>=== Amazon will not init on Editor ===</color>");
|
Debug.Log($"<color=orange>=== Amazon will not init on Editor ===</color>");
|
||||||
|
|
@ -93,11 +93,9 @@ namespace Guru
|
||||||
// 初始化Amazon
|
// 初始化Amazon
|
||||||
Amazon.Initialize (AmazonAppID);
|
Amazon.Initialize (AmazonAppID);
|
||||||
Amazon.SetAdNetworkInfo(new AdNetworkInfo(DTBAdNetwork.MAX));
|
Amazon.SetAdNetworkInfo(new AdNetworkInfo(DTBAdNetwork.MAX));
|
||||||
#if UNITY_EDITOR || DEBUG
|
Debug.Log($"[Ads] --- Amazon init start isDebug:{isDebug}, AmazonID:{AmazonAppID}");
|
||||||
Amazon.EnableTesting (true); // Make sure to take this off when going live.
|
Amazon.EnableTesting (isDebug); // Make sure to take this off when going live.
|
||||||
#else
|
Amazon.EnableLogging (isDebug);
|
||||||
Amazon.EnableLogging (false);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if UNITY_IOS
|
#if UNITY_IOS
|
||||||
Amazon.SetAPSPublisherExtendedIdFeatureEnabled(true);
|
Amazon.SetAPSPublisherExtendedIdFeatureEnabled(true);
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ namespace Guru
|
||||||
* before it can request an ad using OpenWrap SDK.
|
* before it can request an ad using OpenWrap SDK.
|
||||||
* The storeURL is the URL where users can download your app from the App Store/Google Play Store.
|
* The storeURL is the URL where users can download your app from the App Store/Google Play Store.
|
||||||
*/
|
*/
|
||||||
public void Initialize()
|
public void Initialize(bool isDebug = false)
|
||||||
{
|
{
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
Debug.Log($"<color=orange>=== PubMatic will not init on Editor ===</color>");
|
Debug.Log($"<color=orange>=== PubMatic will not init on Editor ===</color>");
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,5 +1,5 @@
|
||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 07cf2335bd298401b8015718fca55265
|
guid: 32eda01e213614348899eefe856392d3
|
||||||
PluginImporter:
|
PluginImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
Binary file not shown.
|
|
@ -1,3 +0,0 @@
|
||||||
fileFormatVersion: 2
|
|
||||||
guid: caf6ff09835a4a75bff1b4b068f664ef
|
|
||||||
timeCreated: 1717117895
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,32 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 66c5f430ab9654ef4a2376e71aa04bca
|
||||||
|
PluginImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
iconMap: {}
|
||||||
|
executionOrder: {}
|
||||||
|
defineConstraints: []
|
||||||
|
isPreloaded: 0
|
||||||
|
isOverridable: 0
|
||||||
|
isExplicitlyReferenced: 0
|
||||||
|
validateReferences: 1
|
||||||
|
platformData:
|
||||||
|
- first:
|
||||||
|
Android: Android
|
||||||
|
second:
|
||||||
|
enabled: 1
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Any:
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings: {}
|
||||||
|
- first:
|
||||||
|
Editor: Editor
|
||||||
|
second:
|
||||||
|
enabled: 0
|
||||||
|
settings:
|
||||||
|
DefaultValueInitialized: true
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -7,15 +7,29 @@ GuruAnalyticsLib 的 Unity 插件库
|
||||||
- 插件库内的 .aar 通过 [guru_analytics](https://github.com/castbox/guru_analytics) 项目直接构建 ( 命令 `gradle publishToMavenLocal` )
|
- 插件库内的 .aar 通过 [guru_analytics](https://github.com/castbox/guru_analytics) 项目直接构建 ( 命令 `gradle publishToMavenLocal` )
|
||||||
- 构建后请改名为 `guru-analytics-{version}.aar`
|
- 构建后请改名为 `guru-analytics-{version}.aar`
|
||||||
- 请将 .aar 文件放置于 `./Runtime/GuruAnalytics/Plugins/Android` 目录下
|
- 请将 .aar 文件放置于 `./Runtime/GuruAnalytics/Plugins/Android` 目录下
|
||||||
- **iOS**
|
- **iOS**
|
||||||
- 插件库内的文件 通过 [GuruAnalytics_iOS](https://github.com/castbox/GuruAnalytics_iOS) 项目
|
- 插件库内的文件 通过 [GuruAnalytics_iOS](https://github.com/castbox/GuruAnalytics_iOS) 项目
|
||||||
- (1) 请将 repo 内的两个文件夹 `Assets` 和 `Classses` 拷贝至 `./Runtime/GuruAnalytics/Plugins/iOS/GuruAnalytics` 目录下:
|
- (1) 请将 repo 内的两个文件夹 `Assets` 和 `Classses` 拷贝至 `./Runtime/GuruAnalytics/Plugins/iOS/GuruAnalytics` 目录下:
|
||||||
- (2) 请将部署到 Unity 内所有的 `.swift` 文件的 meta 属性内, 取消 iOS 文件属性. (因为打包时会按照 POD 导入)
|
- (2) 请将部署到 Unity 内所有的 `.swift` 文件的 meta 属性内, 取消 iOS 文件属性. (因为打包时会按照 POD 导入)
|
||||||
- 注意及时更新 `GuruAnalyticsLib.podspec`文件内的更新内容
|
- 注意及时更新 `GuruAnalyticsLib.podspec`文件内的更新内容
|
||||||
|
```ruby
|
||||||
|
# 将 source 内的 git 属性删除, 只保留 tag 属性
|
||||||
|
# s.source = { :git => 'git@github.com:castbox/GuruAnalytics_iOS.git', :tag => s.version.to_s }
|
||||||
|
s.source = { :tag => s.version.to_s }
|
||||||
|
```
|
||||||
---
|
---
|
||||||
|
|
||||||
## Change Logs
|
## Change Logs
|
||||||
|
|
||||||
|
### 1.12.0
|
||||||
|
- Android 端对齐 `1.1.1`
|
||||||
|
> Hash: bdb41ae118dcf438e8efe4f27d0ec856bc3147b0
|
||||||
|
- iOS 端对齐 `0.3.6`
|
||||||
|
> Hash: 0cd5ce7aa64e12caa7413c938a3164687b973843
|
||||||
|
- Pod 库改为 本地文件引用 (配合外部发行项目)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 1.11.0
|
### 1.11.0
|
||||||
- Android 端对齐 `1.0.3`
|
- Android 端对齐 `1.0.3`
|
||||||
> Hash: 1978686dbcba38b7b0421d8b6b2bef111356366b
|
> Hash: 1978686dbcba38b7b0421d8b6b2bef111356366b
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,11 @@ namespace Guru
|
||||||
public class GuruAnalytics
|
public class GuruAnalytics
|
||||||
{
|
{
|
||||||
// Plugin Version
|
// Plugin Version
|
||||||
public const string Version = "1.11.0";
|
public const string Version = "1.10.5";
|
||||||
|
|
||||||
public static readonly string Tag = "[ANU]";
|
public static readonly string Tag = "[ANU]";
|
||||||
private static readonly string ActionName = "logger_error";
|
private static readonly string ActionName = "logger_error";
|
||||||
|
internal const int EventPriorityDefault = 10;
|
||||||
|
|
||||||
private static IAnalyticsAgent _agent;
|
private static IAnalyticsAgent _agent;
|
||||||
|
|
||||||
|
|
@ -200,7 +201,8 @@ namespace Guru
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="eventName">事件名称</param>
|
/// <param name="eventName">事件名称</param>
|
||||||
/// <param name="data">INT类型的值</param>
|
/// <param name="data">INT类型的值</param>
|
||||||
public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null)
|
/// <param name="priority"></param>
|
||||||
|
public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null, int priority = -1)
|
||||||
{
|
{
|
||||||
if(_autoSyncProperties)
|
if(_autoSyncProperties)
|
||||||
UpdateAllUserProperties(); // 每次打点更新用户属性
|
UpdateAllUserProperties(); // 每次打点更新用户属性
|
||||||
|
|
@ -210,8 +212,9 @@ namespace Guru
|
||||||
{
|
{
|
||||||
raw = BuildParamsJson(data);
|
raw = BuildParamsJson(data);
|
||||||
}
|
}
|
||||||
Debug.Log($"{Tag} event:{eventName} | raw: {raw}");
|
if (priority < 0) priority = EventPriorityDefault;
|
||||||
Agent?.LogEvent(eventName, raw);
|
Debug.Log($"{Tag} event:{eventName} | raw: {raw} | priority: {priority}");
|
||||||
|
Agent?.LogEvent(eventName, raw, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildParamsString(Dictionary<string, dynamic> data)
|
private static string BuildParamsString(Dictionary<string, dynamic> data)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Guru
|
||||||
void SetUid(string uid);
|
void SetUid(string uid);
|
||||||
bool IsDebug { get; }
|
bool IsDebug { get; }
|
||||||
bool EnableErrorLog { get; set; }
|
bool EnableErrorLog { get; set; }
|
||||||
void LogEvent(string eventName, string parameters);
|
void LogEvent(string eventName, string parameters, int priority = -1);
|
||||||
void ReportEventSuccessRate(); // 上报任务成功率
|
void ReportEventSuccessRate(); // 上报任务成功率
|
||||||
void SetTch02Value(double value); // 设置太极02数值
|
void SetTch02Value(double value); // 设置太极02数值
|
||||||
void InitCallback(string objName, string method); // 设置回调对象参数
|
void InitCallback(string objName, string method); // 设置回调对象参数
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,8 @@ namespace Guru
|
||||||
{
|
{
|
||||||
_isDebug = isDebug;
|
_isDebug = isDebug;
|
||||||
string bundleId = Application.identifier;
|
string bundleId = Application.identifier;
|
||||||
CallStatic("init", appId, deviceInfo, bundleId, UseWorker, isDebug, UseCronet, BaseUrl); // 调用接口
|
// public static void init(String appId, String deviceInfo, String bundleId, boolean isDebug, boolean useWorker, boolean useCronet, String baseUrl)
|
||||||
|
CallStatic("init", appId, deviceInfo, bundleId, isDebug, UseWorker, UseCronet, BaseUrl); // 调用接口
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetScreen(string screenName)
|
public void SetScreen(string screenName)
|
||||||
|
|
@ -124,7 +125,10 @@ namespace Guru
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsDebug => CallStatic<bool>("isDebug");
|
public bool IsDebug => CallStatic<bool>("isDebug");
|
||||||
public void LogEvent(string eventName, string parameters) => CallStatic("logEvent", eventName, parameters);
|
public void LogEvent(string eventName, string parameters, int priority = -1)
|
||||||
|
{
|
||||||
|
CallStatic("logEvent", eventName, parameters, priority);
|
||||||
|
}
|
||||||
public void ReportEventSuccessRate() => CallStatic("reportEventRate");
|
public void ReportEventSuccessRate() => CallStatic("reportEventRate");
|
||||||
public void SetTch02Value(double value) => CallStatic("setTch02Value", value);
|
public void SetTch02Value(double value) => CallStatic("setTch02Value", value);
|
||||||
public void InitCallback(string objName, string method) => CallStatic("initCallback", objName, method);
|
public void InitCallback(string objName, string method) => CallStatic("initCallback", objName, method);
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ namespace Guru
|
||||||
|
|
||||||
public bool IsDebug => _isDebug;
|
public bool IsDebug => _isDebug;
|
||||||
|
|
||||||
public void LogEvent(string eventName, string data)
|
public void LogEvent(string eventName, string data, int priority = -1)
|
||||||
{
|
{
|
||||||
#if UNITY_IOS
|
#if UNITY_IOS
|
||||||
unityLogEvent(eventName, data);
|
unityLogEvent(eventName, data);
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ namespace Guru
|
||||||
public bool IsDebug => _isDebug;
|
public bool IsDebug => _isDebug;
|
||||||
|
|
||||||
|
|
||||||
public void LogEvent(string eventName, string parameters)
|
public void LogEvent(string eventName, string parameters, int priority = -1)
|
||||||
{
|
{
|
||||||
if (_isShowLog)
|
if (_isShowLog)
|
||||||
{
|
{
|
||||||
|
|
@ -127,7 +127,7 @@ namespace Guru
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Log($"{TAG} LogEvent: event:<color=orange>{eventName}</color> Properties:\n{sb.ToString()}");
|
Debug.Log($"{TAG} LogEvent: event:<color=orange>{eventName} ({priority})</color> Properties:\n{sb.ToString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Guru
|
||||||
protected override void InitService()
|
protected override void InitService()
|
||||||
{
|
{
|
||||||
base.InitService();
|
base.InitService();
|
||||||
InitChannels(); // 启动各广告渠道代理
|
InitChannels(_isDebug); // 启动各广告渠道代理
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
@ -37,14 +37,14 @@ namespace Guru
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 各渠道初始化
|
/// 各渠道初始化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitChannels()
|
private void InitChannels(bool isDebug)
|
||||||
{
|
{
|
||||||
_adChannels = new HashSet<IAdChannel>();
|
_adChannels = new HashSet<IAdChannel>();
|
||||||
IAdChannel channel = null;
|
IAdChannel channel = null;
|
||||||
_asyncLoader = null;
|
_asyncLoader = null;
|
||||||
|
|
||||||
_chanelMax = new AdChanelMax(); // 默认持有MAXChannel
|
_chanelMax = new AdChanelMax(); // 默认持有MAXChannel
|
||||||
_chanelMax.Initialize();
|
_chanelMax.Initialize(isDebug);
|
||||||
if(_initSpec != null) _chanelMax.SetBannerBackColor(_initSpec.bannerColorHex);
|
if(_initSpec != null) _chanelMax.SetBannerBackColor(_initSpec.bannerColorHex);
|
||||||
|
|
||||||
//------------ 以下为扩展的广告渠道 ------------------
|
//------------ 以下为扩展的广告渠道 ------------------
|
||||||
|
|
@ -52,7 +52,7 @@ namespace Guru
|
||||||
// 开启渠道需要添加对应的宏
|
// 开启渠道需要添加对应的宏
|
||||||
|
|
||||||
channel = new AdChanelAmazon();
|
channel = new AdChanelAmazon();
|
||||||
channel.Initialize();
|
channel.Initialize(isDebug);
|
||||||
_adChannels.Add(channel); // Amazon
|
_adChannels.Add(channel); // Amazon
|
||||||
_asyncLoader = channel as IAsyncRequestChannel;
|
_asyncLoader = channel as IAsyncRequestChannel;
|
||||||
if (_asyncLoader != null)
|
if (_asyncLoader != null)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Guru;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Guru
|
namespace Guru
|
||||||
{
|
{
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public abstract class ADServiceBase<T> : IADService where T : new()
|
public abstract class ADServiceBase<T> : IADService where T : new()
|
||||||
{
|
{
|
||||||
// 单利定义
|
// 单利定义
|
||||||
|
|
@ -23,6 +22,8 @@ namespace Guru
|
||||||
public bool IsInitialized => MaxSdk.IsInitialized() || _isServiceStarted;
|
public bool IsInitialized => MaxSdk.IsInitialized() || _isServiceStarted;
|
||||||
protected bool IsNetworkEnabled => Application.internetReachability != NetworkReachability.NotReachable;
|
protected bool IsNetworkEnabled => Application.internetReachability != NetworkReachability.NotReachable;
|
||||||
|
|
||||||
|
private const int MAX_ADS_RELOAD_INTERVAL = 6; // 广告加载最高时间为 2 的 6 次方 = 64秒
|
||||||
|
|
||||||
private bool _isServiceStarted;
|
private bool _isServiceStarted;
|
||||||
|
|
||||||
protected Action _onSdkInitReady;
|
protected Action _onSdkInitReady;
|
||||||
|
|
@ -33,10 +34,12 @@ namespace Guru
|
||||||
public static Action<string> OnInterstitialStartLoad;
|
public static Action<string> OnInterstitialStartLoad;
|
||||||
public static Action OnInterstitialLoaded;
|
public static Action OnInterstitialLoaded;
|
||||||
public static Action OnInterstitialFailed;
|
public static Action OnInterstitialFailed;
|
||||||
|
public static Action OnInterstitialClosed;
|
||||||
|
|
||||||
public static Action<string> OnRewardedStartLoad;
|
public static Action<string> OnRewardedStartLoad;
|
||||||
public static Action OnRewardLoaded;
|
public static Action OnRewardLoaded;
|
||||||
public static Action OnRewardFailed;
|
public static Action OnRewardFailed;
|
||||||
|
public static Action OnRewardClosed;
|
||||||
|
|
||||||
protected AdsModel _model;
|
protected AdsModel _model;
|
||||||
protected AdsInitSpec _initSpec = null;
|
protected AdsInitSpec _initSpec = null;
|
||||||
|
|
@ -50,6 +53,7 @@ namespace Guru
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool _isDebug = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启动广告服务
|
/// 启动广告服务
|
||||||
|
|
@ -62,11 +66,23 @@ namespace Guru
|
||||||
if (IsInitialized) return; // 已经初始化后, 无需再次初始化
|
if (IsInitialized) return; // 已经初始化后, 无需再次初始化
|
||||||
|
|
||||||
_initSpec = initSpec;
|
_initSpec = initSpec;
|
||||||
|
if (_initSpec == null) _initSpec = AdsInitSpec.BuildDefault();
|
||||||
|
|
||||||
|
_isDebug = _initSpec.isDebug;
|
||||||
_isServiceStarted = true;
|
_isServiceStarted = true;
|
||||||
_onSdkInitReady = callback;
|
_onSdkInitReady = callback;
|
||||||
if(_model == null) _model = AdsModel.Create();
|
if(_model == null) _model = AdsModel.Create();
|
||||||
this.Log("AD SDK Start Init");
|
this.Log("AD SDK Start Init");
|
||||||
|
|
||||||
|
InitMaxCallbacks(); // 初始化 MAX 广告
|
||||||
|
InitService(); // 内部继承接口
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化 MAX 广告组件
|
||||||
|
/// </summary>
|
||||||
|
private void InitMaxCallbacks()
|
||||||
|
{
|
||||||
//-------------- 初始化回调 ------------------
|
//-------------- 初始化回调 ------------------
|
||||||
MaxSdkCallbacks.OnSdkInitializedEvent += OnMaxSdkInitializedCallBack;
|
MaxSdkCallbacks.OnSdkInitializedEvent += OnMaxSdkInitializedCallBack;
|
||||||
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
|
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
|
||||||
|
|
@ -94,10 +110,7 @@ namespace Guru
|
||||||
MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent;
|
MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent;
|
||||||
|
|
||||||
//-------------- SDK 初始化 -------------------
|
//-------------- SDK 初始化 -------------------
|
||||||
if (_initSpec == null) _initSpec = AdsInitSpec.BuildDefault();
|
MaxSdk.SetExtraParameter("enable_black_screen_fixes", "true"); // 修复黑屏
|
||||||
MaxSdk.SetVerboseLogging(_initSpec.isDebug);
|
|
||||||
|
|
||||||
InitService(); // 内部继承接口
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void InitService()
|
protected virtual void InitService()
|
||||||
|
|
@ -138,6 +151,13 @@ namespace Guru
|
||||||
set => Model.BuyNoAds = value;
|
set => Model.BuyNoAds = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private float GetRetryDelaySeconds(int retryCount)
|
||||||
|
{
|
||||||
|
// 最低 2^retryCount 秒
|
||||||
|
// 最高 2^6 = 64 秒
|
||||||
|
return (float)Math.Pow(2, Math.Min(MAX_ADS_RELOAD_INTERVAL, retryCount));
|
||||||
|
}
|
||||||
|
|
||||||
#region Lifecycele
|
#region Lifecycele
|
||||||
|
|
||||||
public void OnAppPaused(bool paused)
|
public void OnAppPaused(bool paused)
|
||||||
|
|
@ -417,7 +437,7 @@ namespace Guru
|
||||||
private string _iadsCategory = "main";
|
private string _iadsCategory = "main";
|
||||||
private int _interstitialRetryAttempt;
|
private int _interstitialRetryAttempt;
|
||||||
protected float _iadsLoadStartTime;
|
protected float _iadsLoadStartTime;
|
||||||
private Action _interstitialDismissAction;
|
private Action _interCloseAction;
|
||||||
protected bool _isIadsLoading = false;
|
protected bool _isIadsLoading = false;
|
||||||
public bool IsIadsLoading => _isIadsLoading;
|
public bool IsIadsLoading => _isIadsLoading;
|
||||||
|
|
||||||
|
|
@ -473,7 +493,7 @@ namespace Guru
|
||||||
}
|
}
|
||||||
|
|
||||||
_iadsCategory = category;
|
_iadsCategory = category;
|
||||||
_interstitialDismissAction = dismissAction;
|
_interCloseAction = dismissAction;
|
||||||
MaxSdk.ShowInterstitial(GetInterstitialID());
|
MaxSdk.ShowInterstitial(GetInterstitialID());
|
||||||
|
|
||||||
// RequestInterstitialAD(); // 直接加载下一个广告
|
// RequestInterstitialAD(); // 直接加载下一个广告
|
||||||
|
|
@ -500,8 +520,8 @@ namespace Guru
|
||||||
this.LogError(
|
this.LogError(
|
||||||
$"OnInterstitialFailedEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
|
$"OnInterstitialFailedEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
|
||||||
_interstitialRetryAttempt++;
|
_interstitialRetryAttempt++;
|
||||||
double retryDelay = Math.Pow(2, Math.Min(3, _interstitialRetryAttempt));
|
float retryDelay = GetRetryDelaySeconds(_interstitialRetryAttempt);
|
||||||
DelayCall((float)retryDelay, RequestInterstitialAD);
|
DelayCall(retryDelay, RequestInterstitialAD);
|
||||||
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
|
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
|
||||||
Analytics.ADIadsFailed(AdParams.Build(adUnitId,
|
Analytics.ADIadsFailed(AdParams.Build(adUnitId,
|
||||||
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory,
|
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory,
|
||||||
|
|
@ -540,7 +560,8 @@ namespace Guru
|
||||||
protected virtual void OnInterstitialDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
protected virtual void OnInterstitialDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||||
{
|
{
|
||||||
// Interstitial ad is hidden. Pre-load the next ad
|
// Interstitial ad is hidden. Pre-load the next ad
|
||||||
_interstitialDismissAction?.Invoke();
|
_interCloseAction?.Invoke();
|
||||||
|
OnInterstitialClosed?.Invoke();
|
||||||
// Analytics.ADIadsClose(adUnitId, _iadsCategory);
|
// Analytics.ADIadsClose(adUnitId, _iadsCategory);
|
||||||
Analytics.ADIadsClose(AdParams.Build(adUnitId, category: _iadsCategory));
|
Analytics.ADIadsClose(AdParams.Build(adUnitId, category: _iadsCategory));
|
||||||
//延时加载下一个广告
|
//延时加载下一个广告
|
||||||
|
|
@ -554,9 +575,9 @@ namespace Guru
|
||||||
private string _rewardCategory = "main";
|
private string _rewardCategory = "main";
|
||||||
private int _rewardRetryAttempt;
|
private int _rewardRetryAttempt;
|
||||||
protected float _radsLoadStartTime;
|
protected float _radsLoadStartTime;
|
||||||
private Action _rewardAction;
|
private Action _rvRewardAction;
|
||||||
private Action<string> _failAction;
|
private Action<string> _rvFailAction;
|
||||||
private Action _dismissAction;
|
private Action _rvDismissAction;
|
||||||
protected bool _isRadsLoading = false;
|
protected bool _isRadsLoading = false;
|
||||||
public bool IsRadsLoading => _isRadsLoading;
|
public bool IsRadsLoading => _isRadsLoading;
|
||||||
|
|
||||||
|
|
@ -620,9 +641,9 @@ namespace Guru
|
||||||
}
|
}
|
||||||
|
|
||||||
_rewardCategory = category;
|
_rewardCategory = category;
|
||||||
_rewardAction = rewardAction;
|
_rvRewardAction = rewardAction;
|
||||||
_failAction = failAction;
|
_rvFailAction = failAction;
|
||||||
_dismissAction = dismissAction;
|
_rvDismissAction = dismissAction;
|
||||||
MaxSdk.ShowRewardedAd(GetRewardedID());
|
MaxSdk.ShowRewardedAd(GetRewardedID());
|
||||||
|
|
||||||
// RequestRewardedAD();
|
// RequestRewardedAD();
|
||||||
|
|
@ -657,8 +678,8 @@ namespace Guru
|
||||||
errorCode: (int)errorInfo.Code,
|
errorCode: (int)errorInfo.Code,
|
||||||
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
|
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
|
||||||
_rewardRetryAttempt++;
|
_rewardRetryAttempt++;
|
||||||
double retryDelay = Math.Pow(2, Math.Min(3, _rewardRetryAttempt));
|
float retryDelay = GetRetryDelaySeconds(_rewardRetryAttempt);
|
||||||
DelayCall((float)retryDelay, RequestRewardedAD);
|
DelayCall(retryDelay, RequestRewardedAD);
|
||||||
|
|
||||||
OnRewardFailed?.Invoke();
|
OnRewardFailed?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
@ -674,7 +695,7 @@ namespace Guru
|
||||||
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory,
|
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory,
|
||||||
errorCode: (int)errorInfo.Code,
|
errorCode: (int)errorInfo.Code,
|
||||||
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
|
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
|
||||||
_failAction?.Invoke("OnRewardedAdFailedToDisplayEvent");
|
_rvFailAction?.Invoke("OnRewardedAdFailedToDisplayEvent");
|
||||||
DelayCall(2.0f, RequestRewardedAD);
|
DelayCall(2.0f, RequestRewardedAD);
|
||||||
|
|
||||||
OnRewardFailed?.Invoke();
|
OnRewardFailed?.Invoke();
|
||||||
|
|
@ -697,11 +718,17 @@ namespace Guru
|
||||||
protected virtual void OnRewardedAdDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
protected virtual void OnRewardedAdDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
|
||||||
{
|
{
|
||||||
this.Log("OnRewardedAdDismissedEvent");
|
this.Log("OnRewardedAdDismissedEvent");
|
||||||
|
|
||||||
|
_rvDismissAction?.Invoke();
|
||||||
|
OnRewardClosed?.Invoke();
|
||||||
|
|
||||||
// Analytics.ADRadsClose(adUnitId, _rewardCategory);
|
// Analytics.ADRadsClose(adUnitId, _rewardCategory);
|
||||||
Analytics.ADRadsClose(AdParams.Build(adUnitId, category: _rewardCategory));
|
Analytics.ADRadsClose(AdParams.Build(adUnitId, category: _rewardCategory));
|
||||||
_dismissAction?.Invoke();
|
|
||||||
//延时加载下一个广告
|
//延时加载下一个广告
|
||||||
DelayCall(2.0f, RequestRewardedAD);
|
DelayCall(2.0f, RequestRewardedAD);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward,
|
protected virtual void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward,
|
||||||
|
|
@ -711,7 +738,7 @@ namespace Guru
|
||||||
// Analytics.ADRadsRewarded(adUnitId, _rewardCategory);
|
// Analytics.ADRadsRewarded(adUnitId, _rewardCategory);
|
||||||
Analytics.ADRadsRewarded(AdParams.Build(adUnitId, category: _rewardCategory));
|
Analytics.ADRadsRewarded(AdParams.Build(adUnitId, category: _rewardCategory));
|
||||||
// Rewarded ad was displayed and user should receive the reward
|
// Rewarded ad was displayed and user should receive the reward
|
||||||
_rewardAction?.Invoke();
|
_rvRewardAction?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,11 @@ namespace Guru
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MAX 渠道初始化, 启动服务
|
/// MAX 渠道初始化, 启动服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Initialize()
|
public void Initialize(bool isDebug = false)
|
||||||
{
|
{
|
||||||
MaxSdk.SetSdkKey(GuruSettings.Instance.ADSetting.SDK_KEY);
|
MaxSdk.SetSdkKey(GuruSettings.Instance.ADSetting.SDK_KEY);
|
||||||
MaxSdk.SetUserId(IPMConfig.IPM_UID); // 上报用户ID
|
MaxSdk.SetUserId(IPMConfig.IPM_UID); // 上报用户ID
|
||||||
|
MaxSdk.SetVerboseLogging(isDebug); // 设置调试数据
|
||||||
MaxSdk.InitializeSdk();
|
MaxSdk.InitializeSdk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Guru
|
||||||
{
|
{
|
||||||
// Action<string> OnRequestOver { get; set; }
|
// Action<string> OnRequestOver { get; set; }
|
||||||
|
|
||||||
void Initialize();
|
void Initialize(bool isDebug = false);
|
||||||
|
|
||||||
string Name { get;}
|
string Name { get;}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Guru
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
UnityEngine.Debug.Log($"{TAG} --- Send Adjust Event: {eventName}({tokenID})");
|
||||||
return new AdjustEvent(tokenID);
|
return new AdjustEvent(tokenID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -224,17 +224,17 @@ namespace Guru
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="status"></param>
|
/// <param name="status"></param>
|
||||||
/// <param name="channel"></param>
|
/// <param name="channel"></param>
|
||||||
/// <param name="others"></param>
|
/// <param name="scene"></param>
|
||||||
public static void AttResult(string status, string type = "custom", string others = "")
|
public static void AttResult(string status, string type = "custom", string scene = "")
|
||||||
{
|
{
|
||||||
SetAttProperty(status);
|
SetAttProperty(status);
|
||||||
Debug.Log($"{TAG} AttResult: {status} type:{type} others:{others}");
|
Debug.Log($"{TAG} AttResult: {status} type:{type} others:{scene}");
|
||||||
var dict = new Dictionary<string, dynamic>()
|
var dict = new Dictionary<string, dynamic>()
|
||||||
{
|
{
|
||||||
{ ParameterItemCategory, status },
|
{ ParameterItemCategory, status },
|
||||||
{ "type", type }
|
{ "type", type }
|
||||||
};
|
};
|
||||||
if(!string.IsNullOrEmpty(others)) dict[ParameterItemName] = others;
|
if(!string.IsNullOrEmpty(scene)) dict[ParameterItemName] = scene;
|
||||||
LogEvent(EventATTResult, dict);
|
LogEvent(EventATTResult, dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Guru
|
||||||
// 美元符号
|
// 美元符号
|
||||||
public static readonly string USD = "USD";
|
public static readonly string USD = "USD";
|
||||||
// 广告平台
|
// 广告平台
|
||||||
public static readonly string AdMAX = "MAX";
|
public static readonly string AdMAX = "MAX";
|
||||||
|
|
||||||
//IAP打点事件
|
//IAP打点事件
|
||||||
public static readonly string EventIAPFirst = "first_iap";
|
public static readonly string EventIAPFirst = "first_iap";
|
||||||
|
|
|
||||||
|
|
@ -309,12 +309,12 @@ namespace Guru
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
private static void CustomLogEvent(string key, Dictionary<string, dynamic> data = null)
|
private static void CustomLogEvent(string key, Dictionary<string, dynamic> data = null, int priority = -1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (data == null) data = new Dictionary<string, dynamic>();
|
if (data == null) data = new Dictionary<string, dynamic>();
|
||||||
GuruAnalytics.LogEvent(key, data);
|
GuruAnalytics.LogEvent(key, data, priority);
|
||||||
UpdateAllValues(); // 同步所有的ID
|
UpdateAllValues(); // 同步所有的ID
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
||||||
|
|
@ -295,9 +295,11 @@ namespace Guru
|
||||||
/// <param name="orderId"></param>
|
/// <param name="orderId"></param>
|
||||||
/// <param name="orderType"></param>
|
/// <param name="orderType"></param>
|
||||||
/// <param name="timestamp"></param>
|
/// <param name="timestamp"></param>
|
||||||
public static void Tch001IAPRev(double value, string productId, string orderId, string orderType, string timestamp)
|
/// <param name="isTest"></param>
|
||||||
|
public static void Tch001IAPRev(double value, string productId, string orderId, string orderType, string timestamp, bool isTest = false)
|
||||||
{
|
{
|
||||||
TchRevEvent(EventTchAdRev001Impression, IAPPlatform, value, orderType, productId, orderId, timestamp);
|
string sandbox = isTest ? "true" : "false";
|
||||||
|
TchRevEvent(EventTchAdRev001Impression, IAPPlatform, value, orderType, productId, orderId, timestamp, sandbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -309,11 +311,13 @@ namespace Guru
|
||||||
/// <param name="orderId"></param>
|
/// <param name="orderId"></param>
|
||||||
/// <param name="orderType"></param>
|
/// <param name="orderType"></param>
|
||||||
/// <param name="timestamp"></param>
|
/// <param name="timestamp"></param>
|
||||||
|
/// <param name="isTest"></param>
|
||||||
// public static void Tch02IAPRev(double value, string productId, string orderId, string orderType, string timestamp)
|
// public static void Tch02IAPRev(double value, string productId, string orderId, string orderType, string timestamp)
|
||||||
public static void Tch02IAPRev(double value, string productId, string orderId, string orderType, string timestamp)
|
public static void Tch02IAPRev(double value, string productId, string orderId, string orderType, string timestamp, bool isTest = false)
|
||||||
{
|
{
|
||||||
if (!EnableTch02Event) return;
|
if (!EnableTch02Event) return;
|
||||||
TchRevEvent(EventTchAdRev02Impression, IAPPlatform, value, orderType, productId, orderId, timestamp);
|
string sandbox = isTest ? "true" : "false";
|
||||||
|
TchRevEvent(EventTchAdRev02Impression, IAPPlatform, value, orderType, productId, orderId, timestamp, sandbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -362,8 +366,9 @@ namespace Guru
|
||||||
/// <param name="productId"></param>
|
/// <param name="productId"></param>
|
||||||
/// <param name="orderId"></param>
|
/// <param name="orderId"></param>
|
||||||
/// <param name="timestamp"></param>
|
/// <param name="timestamp"></param>
|
||||||
|
/// <param name="sandbox"></param>
|
||||||
private static void TchRevEvent(string evtName, string platform, double value,
|
private static void TchRevEvent(string evtName, string platform, double value,
|
||||||
string orderType = "", string productId = "", string orderId = "", string timestamp = "")
|
string orderType = "", string productId = "", string orderId = "", string timestamp = "", string sandbox = "")
|
||||||
{
|
{
|
||||||
var data = new Dictionary<string, dynamic>()
|
var data = new Dictionary<string, dynamic>()
|
||||||
{
|
{
|
||||||
|
|
@ -373,10 +378,13 @@ namespace Guru
|
||||||
};
|
};
|
||||||
|
|
||||||
//--------- Extra data for IAP receipt ---------------
|
//--------- Extra data for IAP receipt ---------------
|
||||||
|
|
||||||
if(!string.IsNullOrEmpty(orderType)) data["order_type"] = orderType;
|
if(!string.IsNullOrEmpty(orderType)) data["order_type"] = orderType;
|
||||||
if(!string.IsNullOrEmpty(productId)) data["product_id"] = productId;
|
if(!string.IsNullOrEmpty(productId)) data["product_id"] = productId;
|
||||||
if(!string.IsNullOrEmpty(orderId)) data["order_id"] = orderId;
|
if(!string.IsNullOrEmpty(orderId)) data["order_id"] = orderId;
|
||||||
if(!string.IsNullOrEmpty(timestamp)) data["trans_ts"] = timestamp;
|
if(!string.IsNullOrEmpty(timestamp)) data["trans_ts"] = timestamp;
|
||||||
|
if(!string.IsNullOrEmpty(sandbox)) data["sandbox"] = sandbox;
|
||||||
|
|
||||||
//--------- Extra data for IAP receipt ---------------
|
//--------- Extra data for IAP receipt ---------------
|
||||||
|
|
||||||
LogEvent(evtName, data);
|
LogEvent(evtName, data);
|
||||||
|
|
@ -603,15 +611,19 @@ namespace Guru
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="productId"></param>
|
/// <param name="productId"></param>
|
||||||
/// <param name="usdPrice"></param>
|
/// <param name="usdPrice"></param>
|
||||||
/// <param name="userCurrency"></param>
|
/// <param name="orderData"></param>
|
||||||
/// <param name="payPrice"></param>
|
/// <param name="isTest"></param>
|
||||||
/// <param name="orderId"></param>
|
public static void ReportIAPSuccessEvent(BaseOrderData orderData, double usdPrice, bool isTest = false)
|
||||||
/// <param name="orderType"></param>
|
|
||||||
/// <param name="orderDate"></param>
|
|
||||||
/// <param name="scene"></param>
|
|
||||||
/// <param name="isFree"></param>
|
|
||||||
public static void ReportIAPSuccessEvent(double usdPrice, string productId, BaseOrderData orderData)
|
|
||||||
{
|
{
|
||||||
|
if (orderData == null) return;
|
||||||
|
|
||||||
|
if (!isTest && usdPrice == 0)
|
||||||
|
{
|
||||||
|
Debug.Log($"[SDK] --- Pruchase value is 0, skip report orders");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string productId = orderData.productId;
|
||||||
string userCurrency = orderData.userCurrency;
|
string userCurrency = orderData.userCurrency;
|
||||||
double payPrice = orderData.payPrice;
|
double payPrice = orderData.payPrice;
|
||||||
string orderType = orderData.OrderType();
|
string orderType = orderData.OrderType();
|
||||||
|
|
@ -621,7 +633,7 @@ namespace Guru
|
||||||
string scene = orderData.scene;
|
string scene = orderData.scene;
|
||||||
bool isFree = orderData.isFree;
|
bool isFree = orderData.isFree;
|
||||||
string offerId = orderData.offerId;
|
string offerId = orderData.offerId;
|
||||||
|
|
||||||
string transactionId = "";
|
string transactionId = "";
|
||||||
string productToken = "";
|
string productToken = "";
|
||||||
string receipt = "";
|
string receipt = "";
|
||||||
|
|
@ -636,21 +648,23 @@ namespace Guru
|
||||||
}
|
}
|
||||||
|
|
||||||
// TCH 001
|
// TCH 001
|
||||||
Tch001IAPRev(usdPrice, productId, orderId, orderType, orderDate);
|
Tch001IAPRev(usdPrice, productId, orderId, orderType, orderDate, isTest);
|
||||||
|
|
||||||
// TCH 020
|
// TCH 020
|
||||||
Tch02IAPRev(usdPrice, productId, orderId, orderType, orderDate);
|
Tch02IAPRev(usdPrice, productId, orderId, orderType, orderDate, isTest);
|
||||||
|
|
||||||
// Facebook Track IAP Purchase
|
// Facebook Track IAP Purchase
|
||||||
FBPurchase(usdPrice, USD, "iap", IAPPlatform);
|
FBPurchase(usdPrice, USD, "iap", IAPPlatform);
|
||||||
|
|
||||||
if (orderData.orderType == 1)
|
if (orderData.orderType == 1)
|
||||||
{
|
{
|
||||||
// sub_pruchase : Firebase + Guru + Adjust
|
// sub_pruchase : Firebase + Guru + Adjust
|
||||||
SubPurchase(usdPrice, productId, orderId, orderDate, productToken, receipt);
|
SubPurchase(usdPrice, productId, orderId, orderDate, productToken, receipt, isTest);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// iap_purchase : Firebase + Guru + Adjust
|
// iap_purchase : Firebase + Guru + Adjust
|
||||||
IAPPurchase(usdPrice, productId, orderId, orderDate, productToken, receipt);
|
IAPPurchase(usdPrice, productId, orderId, orderDate, productToken, receipt, isTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IAP Ret true : Firebase + Guru + Adjust
|
// IAP Ret true : Firebase + Guru + Adjust
|
||||||
|
|
@ -669,21 +683,33 @@ namespace Guru
|
||||||
/// <param name="productId"></param>
|
/// <param name="productId"></param>
|
||||||
/// <param name="orderId"></param>
|
/// <param name="orderId"></param>
|
||||||
/// <param name="orderDate"></param>
|
/// <param name="orderDate"></param>
|
||||||
public static void IAPPurchase(double value, string productId, string orderId, string orderDate,
|
/// <param name="purchaseToken"></param>
|
||||||
string purchaseToken = "", string receipt = "")
|
/// <param name="receipt"></param>
|
||||||
|
/// <param name="isSandbox"></param>
|
||||||
|
public static void IAPPurchase(double value, string productId, string orderId, string orderDate,
|
||||||
|
string purchaseToken = "", string receipt = "", bool isSandbox = false)
|
||||||
{
|
{
|
||||||
IAPPurchaseReport(EventIAPPurchase, value, productId, orderId, "IAP", orderDate, purchaseToken, receipt);
|
IAPPurchaseReport(EventIAPPurchase, value, productId, orderId, "IAP", orderDate, purchaseToken, receipt, isSandbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SubPurchase(double value, string productId, string orderId, string orderDate,
|
|
||||||
string purchaseToken = "", string receipt = "")
|
|
||||||
{
|
|
||||||
IAPPurchaseReport(EventSubPurchase, value, productId, orderId, "SUB", orderDate, purchaseToken, receipt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static void IAPPurchaseReport(string eventName, double value, string productId, string orderId, string orderType, string orderDate,
|
/// <summary>
|
||||||
string purchaseToken = "", string receipt = "")
|
/// SUB 订阅上报
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="productId"></param>
|
||||||
|
/// <param name="orderId"></param>
|
||||||
|
/// <param name="orderDate"></param>
|
||||||
|
/// <param name="purchaseToken"></param>
|
||||||
|
/// <param name="receipt"></param>
|
||||||
|
/// <param name="isSandbox"></param>
|
||||||
|
public static void SubPurchase(double value, string productId, string orderId, string orderDate,
|
||||||
|
string purchaseToken = "", string receipt = "", bool isSandbox = false)
|
||||||
|
{
|
||||||
|
IAPPurchaseReport(EventSubPurchase, value, productId, orderId, "SUB", orderDate, purchaseToken, receipt, isSandbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IAPPurchaseReport(string eventName, double value, string productId,
|
||||||
|
string orderId, string orderType, string orderDate, string purchaseToken = "", string receipt = "", bool isSandbox = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
var dict = new Dictionary<string, dynamic>()
|
var dict = new Dictionary<string, dynamic>()
|
||||||
|
|
@ -694,20 +720,17 @@ namespace Guru
|
||||||
[ParameterProductId] = productId,
|
[ParameterProductId] = productId,
|
||||||
["order_id"] = orderId,
|
["order_id"] = orderId,
|
||||||
["order_type"] = orderType,
|
["order_type"] = orderType,
|
||||||
["trans_ts"] = orderDate
|
["trans_ts"] = orderDate,
|
||||||
|
["sandbox"] = isSandbox? "true": "false"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 上报Firebase + 自打点
|
// 上报Firebase + 自打点
|
||||||
LogEvent(eventName, dict, new EventSetting() { EnableFirebaseAnalytics = true, });
|
LogEvent(eventName, dict, new EventSetting() { EnableFirebaseAnalytics = true });
|
||||||
|
|
||||||
|
|
||||||
// 上报 Adjust 支付事件
|
// 上报 Adjust 支付事件
|
||||||
// if (value > 0)
|
|
||||||
// {
|
|
||||||
// 根据事件名称来获取对应的事件Token(iap_purchase/sub_purchase)
|
|
||||||
LogAdjustRevenueEvent(eventName, value, productId, orderId, purchaseToken, receipt, dict);
|
LogAdjustRevenueEvent(eventName, value, productId, orderId, purchaseToken, receipt, dict);
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
|
|
||||||
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
namespace Guru
|
namespace Guru
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using com.adjust.sdk;
|
using com.adjust.sdk;
|
||||||
using Facebook.Unity;
|
using Facebook.Unity;
|
||||||
|
using UnityEngine;
|
||||||
using Firebase.Analytics;
|
using Firebase.Analytics;
|
||||||
using Firebase.Crashlytics;
|
using Firebase.Crashlytics;
|
||||||
|
|
||||||
|
|
@ -148,10 +148,10 @@ namespace Guru
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="eventName"></param>
|
/// <param name="eventName"></param>
|
||||||
/// <param name="eventSetting"></param>
|
/// <param name="eventSetting"></param>
|
||||||
internal static void LogEvent(string eventName, EventSetting eventSetting = null)
|
internal static void LogEvent(string eventName, EventSetting eventSetting = null, int priority = -1)
|
||||||
{
|
{
|
||||||
Log.I(TAG, $"eventName:{eventName}");
|
Log.I(TAG, $"eventName:{eventName}");
|
||||||
CustomLogEvent(eventName); // 自定义打点上报
|
CustomLogEvent(eventName, null, priority); // 自定义打点上报
|
||||||
CheckLogCache(eventName, null, eventSetting); // log缓存和消费
|
CheckLogCache(eventName, null, eventSetting); // log缓存和消费
|
||||||
|
|
||||||
if (!IsEnable) return;
|
if (!IsEnable) return;
|
||||||
|
|
@ -180,22 +180,24 @@ namespace Guru
|
||||||
/// <param name="eventName"></param>
|
/// <param name="eventName"></param>
|
||||||
/// <param name="extras"></param>
|
/// <param name="extras"></param>
|
||||||
/// <param name="eventSetting"></param>
|
/// <param name="eventSetting"></param>
|
||||||
internal static void LogEvent(string eventName, Dictionary<string, dynamic> extras, EventSetting eventSetting = null)
|
/// <param name="priority"></param>
|
||||||
|
internal static void LogEvent(string eventName, Dictionary<string, dynamic> extras, EventSetting eventSetting = null, int priority = -1)
|
||||||
{
|
{
|
||||||
Log.I(TAG, $"eventName:{eventName}, params:{string.Join(",", extras)}");
|
CustomLogEvent(eventName, extras, priority); // 自定义打点上报
|
||||||
CustomLogEvent(eventName, extras); // 自定义打点上报
|
|
||||||
|
|
||||||
CheckLogCache(eventName, extras, eventSetting); // log缓存和消费
|
CheckLogCache(eventName, extras, eventSetting); // log缓存和消费
|
||||||
|
|
||||||
if (!IsEnable) return;
|
if (!IsEnable) return;
|
||||||
|
|
||||||
if (extras == null)
|
if (extras == null)
|
||||||
{
|
{
|
||||||
LogEvent(eventName, eventSetting); // 防空判定
|
LogEvent(eventName, eventSetting, priority); // 防空判定
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string paramStr = string.Join(",", extras);
|
||||||
|
Log.I(TAG, $"eventName:{eventName}, params:{paramStr}");
|
||||||
|
|
||||||
eventSetting ??= _defaultEventSetting;
|
if (eventSetting == null) eventSetting = _defaultEventSetting;
|
||||||
if (eventSetting.EnableFirebaseAnalytics)
|
if (eventSetting.EnableFirebaseAnalytics)
|
||||||
{
|
{
|
||||||
List<Parameter> parameters = new List<Parameter>();
|
List<Parameter> parameters = new List<Parameter>();
|
||||||
|
|
@ -217,7 +219,6 @@ namespace Guru
|
||||||
parameters.Add(new Parameter(kv.Key, decimal.ToDouble(decimalValue)));
|
parameters.Add(new Parameter(kv.Key, decimal.ToDouble(decimalValue)));
|
||||||
else
|
else
|
||||||
parameters.Add(new Parameter(kv.Key, kv.Value.ToString()));
|
parameters.Add(new Parameter(kv.Key, kv.Value.ToString()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FirebaseAnalytics.LogEvent(eventName, parameters.ToArray());
|
FirebaseAnalytics.LogEvent(eventName, parameters.ToArray());
|
||||||
|
|
@ -296,15 +297,16 @@ namespace Guru
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="data"></param>
|
/// <param name="data"></param>
|
||||||
/// <param name="setting"></param>
|
/// <param name="setting"></param>
|
||||||
public static void Track(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null)
|
/// <param name="priority"></param>
|
||||||
|
public static void Track(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null, int priority = -1)
|
||||||
{
|
{
|
||||||
if (null != data)
|
if (null != data)
|
||||||
{
|
{
|
||||||
LogEvent(key, data, setting);
|
LogEvent(key, data, setting, priority);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogEvent(key, setting);
|
LogEvent(key, setting, priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -350,7 +352,7 @@ namespace Guru
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void CheckLogCache(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null)
|
private static void CheckLogCache(string key, Dictionary<string, dynamic> data = null, EventSetting setting = null, int priority = -1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -358,7 +360,7 @@ namespace Guru
|
||||||
{
|
{
|
||||||
if (data == null) data = new Dictionary<string, dynamic>();
|
if (data == null) data = new Dictionary<string, dynamic>();
|
||||||
data["log_stamp"] = TimeUtil.GetCurrentTimeStamp().ToString();
|
data["log_stamp"] = TimeUtil.GetCurrentTimeStamp().ToString();
|
||||||
SavedLogs.Enqueue(new SavedLog(key, data, setting));
|
SavedLogs.Enqueue(new SavedLog(key, data, setting, priority));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -368,7 +370,7 @@ namespace Guru
|
||||||
while (SavedLogs.Count > 0)
|
while (SavedLogs.Count > 0)
|
||||||
{
|
{
|
||||||
var log = SavedLogs.Dequeue();
|
var log = SavedLogs.Dequeue();
|
||||||
LogEvent(log.key, log.data, log.setting);
|
LogEvent(log.key, log.data, log.setting, log.priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -387,18 +389,27 @@ namespace Guru
|
||||||
internal class SavedLog
|
internal class SavedLog
|
||||||
{
|
{
|
||||||
public string key;
|
public string key;
|
||||||
|
public int priority;
|
||||||
public Dictionary<string, dynamic> data;
|
public Dictionary<string, dynamic> data;
|
||||||
public Analytics.EventSetting setting;
|
public Analytics.EventSetting setting;
|
||||||
|
|
||||||
public SavedLog()
|
public SavedLog()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public SavedLog(string _key, Dictionary<string, dynamic> _data = null, Analytics.EventSetting _setting = null)
|
/// <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;
|
key = _key;
|
||||||
data = _data;
|
data = _data;
|
||||||
setting = _setting;
|
setting = _setting;
|
||||||
|
priority = _priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,7 +52,10 @@ namespace Guru
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// return JsonMapper.ToObject<T>(jsonStr);
|
// return JsonMapper.ToObject<T>(jsonStr);
|
||||||
return JsonConvert.DeserializeObject<T>(jsonStr);
|
return JsonConvert.DeserializeObject<T>(jsonStr, new JsonSerializerSettings()
|
||||||
|
{
|
||||||
|
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Firebase;
|
using Firebase;
|
||||||
using Firebase.Analytics;
|
using Firebase.Analytics;
|
||||||
using Firebase.Extensions;
|
using Firebase.Extensions;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Guru
|
namespace Guru
|
||||||
{
|
{
|
||||||
|
|
@ -117,12 +117,36 @@ namespace Guru
|
||||||
// 启动 AdjustService
|
// 启动 AdjustService
|
||||||
string appToken = GuruSettings.Instance.AdjustSetting?.GetAppToken() ?? "";
|
string appToken = GuruSettings.Instance.AdjustSetting?.GetAppToken() ?? "";
|
||||||
string fbAppId = GuruSettings.Instance.IPMSetting.FacebookAppId;
|
string fbAppId = GuruSettings.Instance.IPMSetting.FacebookAppId;
|
||||||
AdjustService.StartService(appToken, fbAppId);
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void ReportAdjustId(string adjustId)
|
||||||
|
{
|
||||||
|
FirebaseAnalytics.SetUserProperty("adjust_id", adjustId); // 仅上报 Firebase 用户属性
|
||||||
|
Debug.Log($"[SDK] --- Firebase + Adjust ID: {adjustId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ namespace Guru
|
||||||
{
|
{
|
||||||
GenDeviceId();
|
GenDeviceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
return SavedDeviceId; // 优先使用缓存的 DeviceID
|
return SavedDeviceId; // 优先使用缓存的 DeviceID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ namespace Guru
|
||||||
$"{nameof(language)}: {language}, {nameof(locale)}: {locale}, {nameof(deviceToken)}: {deviceToken}, {nameof(deviceType)}: {deviceType}, " +
|
$"{nameof(language)}: {language}, {nameof(locale)}: {locale}, {nameof(deviceToken)}: {deviceToken}, {nameof(deviceType)}: {deviceType}, " +
|
||||||
$"{nameof(pushType)}: {pushType}, {nameof(appIdentifier)}: {appIdentifier}, {nameof(appVersion)}: {appVersion}, {nameof(brand)}: {brand}, " +
|
$"{nameof(pushType)}: {pushType}, {nameof(appIdentifier)}: {appIdentifier}, {nameof(appVersion)}: {appVersion}, {nameof(brand)}: {brand}, " +
|
||||||
$"{nameof(model)}: {model}, {nameof(timezone)}: {timezone}, {nameof(pushNotificationEnable)}: {pushNotificationEnable}, " +
|
$"{nameof(model)}: {model}, {nameof(timezone)}: {timezone}, {nameof(pushNotificationEnable)}: {pushNotificationEnable}, " +
|
||||||
$"{nameof(firebaseAppInstanceId)}: {firebaseAppInstanceId}, {nameof(idfa)}: {idfa}, {nameof(adid)}: {adid}, {nameof(gpsAdid)}: {gpsAdid}";
|
$"{nameof(firebaseAppInstanceId)}: {firebaseAppInstanceId}, {nameof(idfa)}: {idfa}, {nameof(adid)}: {adid}, {nameof(gpsAdid)}: {gpsAdid}, {nameof(userUuid)}: {userUuid}";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,19 +34,14 @@ namespace Guru
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Debug.Log($"[IAP] --- Apple Order Response: {response}");
|
||||||
ResponseData<OrderResponse> responseData = JsonUtility.FromJson<ResponseData<OrderResponse>>(response);
|
ResponseData<OrderResponse> responseData = JsonUtility.FromJson<ResponseData<OrderResponse>>(response);
|
||||||
if (responseData != null && responseData.data != null)
|
if (responseData != null && responseData.data != null)
|
||||||
{
|
{
|
||||||
double usdPrice = responseData.data.usdPrice;
|
double usdPrice = responseData.data.usdPrice;
|
||||||
string productId = orderData.productId;
|
bool isTest = responseData.data.test;
|
||||||
|
|
||||||
// Analytics.Tch001IAPRev(usdPrice, productId, orderData.orderId, orderData.OrderType(), orderData.payedDate);
|
Analytics.ReportIAPSuccessEvent(orderData, usdPrice, isTest);
|
||||||
// Analytics.Tch02IAPRev(usdPrice);
|
|
||||||
//
|
|
||||||
// AdjustService.TrackSubPurchase(usdPrice, productId);
|
|
||||||
// Analytics.SubPurchase(usdPrice, productId);
|
|
||||||
|
|
||||||
Analytics.ReportIAPSuccessEvent(usdPrice, productId, orderData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Guru
|
||||||
{
|
{
|
||||||
DeviceData deviceData = new DeviceData();
|
DeviceData deviceData = new DeviceData();
|
||||||
deviceData.pushNotificationEnable = _isPushEnabled;
|
deviceData.pushNotificationEnable = _isPushEnabled;
|
||||||
this.Log($"send deviceData:{deviceData}");
|
UnityEngine.Debug.Log($"[SDK] --- Send DeviceData:{deviceData}");
|
||||||
var request = new UnityWebRequest(RequestURL, "POST");
|
var request = new UnityWebRequest(RequestURL, "POST");
|
||||||
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonUtility.ToJson(deviceData)));
|
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(JsonUtility.ToJson(deviceData)));
|
||||||
request.downloadHandler = new DownloadHandlerBuffer();
|
request.downloadHandler = new DownloadHandlerBuffer();
|
||||||
|
|
@ -31,10 +31,10 @@ namespace Guru
|
||||||
|
|
||||||
protected override void RequestSuccessCallBack(string response)
|
protected override void RequestSuccessCallBack(string response)
|
||||||
{
|
{
|
||||||
this.Log("@@@ Send OK!");
|
UnityEngine.Debug.Log("[SDK] --- Send DeviceData Success");
|
||||||
IPMConfig.IS_UPLOAD_DEVICE_SUCCESS = true;
|
IPMConfig.IS_UPLOAD_DEVICE_SUCCESS = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置是否打开推送
|
/// 设置是否打开推送
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -31,21 +31,14 @@ namespace Guru
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Debug.Log($"[IAP] --- Google Order Response: {response}");
|
||||||
ResponseData<OrderResponse> responseData = JsonUtility.FromJson<ResponseData<OrderResponse>>(response);
|
ResponseData<OrderResponse> responseData = JsonUtility.FromJson<ResponseData<OrderResponse>>(response);
|
||||||
if (responseData != null && responseData.data != null)
|
if (responseData != null && responseData.data != null)
|
||||||
{
|
{
|
||||||
double usdPrice = responseData.data.usdPrice;
|
double usdPrice = responseData.data.usdPrice;
|
||||||
string productId = orderData.RealProductId;
|
bool isTest = responseData.data.test;
|
||||||
|
|
||||||
// Analytics.Tch001IAPRev(usdPrice, productId, orderId, orderType, orderDate); // TCH 001
|
Analytics.ReportIAPSuccessEvent(orderData, usdPrice, isTest);
|
||||||
// // Analytics.Tch02IAPRev(usdPrice, productId, orderId, orderTypeString, timestamp);
|
|
||||||
// Analytics.Tch02IAPRev(usdPrice); // TCH 020
|
|
||||||
//
|
|
||||||
// // Adjust Track IAP Purchase
|
|
||||||
// AdjustService.TrackIAPPurchase(usdPrice, productId); // 上报 IAP 支付事件
|
|
||||||
// Analytics.IAPPurchase(usdPrice, productId);
|
|
||||||
|
|
||||||
Analytics.ReportIAPSuccessEvent(usdPrice, productId, orderData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,12 @@ namespace Guru
|
||||||
public class OrderResponse
|
public class OrderResponse
|
||||||
{
|
{
|
||||||
public double usdPrice;
|
public double usdPrice;
|
||||||
|
public bool test;
|
||||||
|
public string state;
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{nameof(usdPrice)}: {usdPrice}";
|
return $"{nameof(usdPrice)}: {usdPrice} {nameof(test)}: {test} {nameof(state)}: {state}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -99,22 +99,22 @@ namespace Guru
|
||||||
UpdateView(); // 刷新视图
|
UpdateView(); // 刷新视图
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 字段缓冲
|
||||||
|
private StringBuilder _infoBuff;
|
||||||
private string CreateMonitorInfo()
|
private string CreateMonitorInfo()
|
||||||
{
|
{
|
||||||
string msg = "";
|
string msg = "";
|
||||||
bool loaded = false;
|
bool loaded = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
if (!ADService.Instance.IsInitialized)
|
if (!ADService.Instance.IsInitialized)
|
||||||
{
|
{
|
||||||
msg = ColoredText("AdService not initialized...", Consts.ColorRed);
|
msg = ColoredText("AdService not initialized...", Consts.ColorRed);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_infoBuff == null) _infoBuff = new StringBuilder();
|
||||||
|
_infoBuff.Clear();
|
||||||
|
|
||||||
if (_curBadsInfo == null)
|
if (_curBadsInfo == null)
|
||||||
{
|
{
|
||||||
msg = $"BADS: {ColoredText("not ready", Consts.ColorRed)}\n";
|
msg = $"BADS: {ColoredText("not ready", Consts.ColorRed)}\n";
|
||||||
|
|
@ -137,7 +137,7 @@ namespace Guru
|
||||||
msg = $"BADS: {ColoredText("loading...", Consts.ColorYellow)}\n\tformat: {_curBadsInfo.format}\n";
|
msg = $"BADS: {ColoredText("loading...", Consts.ColorYellow)}\n\tformat: {_curBadsInfo.format}\n";
|
||||||
break;
|
break;
|
||||||
case AdStatusType.Paid:
|
case AdStatusType.Paid:
|
||||||
msg = $"BADS: {ColoredText("display", Consts.ColorGreen)}\n\tnetwork: {_curIadsInfo.network}\n\trevenue: {_curBadsInfo.revenue}\n";
|
msg = $"BADS: {ColoredText("display", Consts.ColorGreen)}\n\tnetwork: {_curBadsInfo.network}\n\trevenue: {_curBadsInfo.revenue}\n";
|
||||||
break;
|
break;
|
||||||
case AdStatusType.NotReady:
|
case AdStatusType.NotReady:
|
||||||
msg = $"BADS: {ColoredText("not ready", Consts.ColorGray)}\n\t{ColoredText("---", Consts.ColorGray)}\n";
|
msg = $"BADS: {ColoredText("not ready", Consts.ColorGray)}\n\t{ColoredText("---", Consts.ColorGray)}\n";
|
||||||
|
|
@ -147,7 +147,7 @@ namespace Guru
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.Append(msg);
|
_infoBuff.Append(msg);
|
||||||
|
|
||||||
|
|
||||||
if (_curIadsInfo == null)
|
if (_curIadsInfo == null)
|
||||||
|
|
@ -159,7 +159,7 @@ namespace Guru
|
||||||
switch (_curIadsInfo.status)
|
switch (_curIadsInfo.status)
|
||||||
{
|
{
|
||||||
case AdStatusType.Loaded:
|
case AdStatusType.Loaded:
|
||||||
msg = $"IADS: {ColoredText("loaded", Consts.ColorGreen)}\n\tnetwork: {_curIadsInfo.network}\n\twaterfall: {_curBadsInfo.waterfall}\n";
|
msg = $"IADS: {ColoredText("loaded", Consts.ColorGreen)}\n\tnetwork: {_curIadsInfo.network}\n\twaterfall: {_curIadsInfo.waterfall}\n";
|
||||||
break;
|
break;
|
||||||
case AdStatusType.LoadFailed:
|
case AdStatusType.LoadFailed:
|
||||||
msg = $"IADS: {ColoredText("loading failed", Consts.ColorRed)}\n\tmessage: {_curIadsInfo.info}\n";
|
msg = $"IADS: {ColoredText("loading failed", Consts.ColorRed)}\n\tmessage: {_curIadsInfo.info}\n";
|
||||||
|
|
@ -181,7 +181,7 @@ namespace Guru
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.Append(msg);
|
_infoBuff.Append(msg);
|
||||||
|
|
||||||
|
|
||||||
if (_curRadsInfo == null)
|
if (_curRadsInfo == null)
|
||||||
|
|
@ -215,10 +215,11 @@ namespace Guru
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.Append(msg);
|
_infoBuff.Append(msg);
|
||||||
|
|
||||||
|
|
||||||
return sb.ToString();
|
return _infoBuff.ToString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1fef034d48ac449fb99531b40139954e
|
||||||
|
timeCreated: 1718844748
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8c0dd2d4b63445c2828e05c10274d672
|
||||||
|
timeCreated: 1718845536
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
|
||||||
|
|
||||||
|
#if UNITY_ANDROID
|
||||||
|
|
||||||
|
namespace Guru.Notification
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEditor.Android;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
public class PostCustomActivity: IPostGenerateGradleAndroidProject
|
||||||
|
{
|
||||||
|
private const int POST_ORDER = 10;
|
||||||
|
private const string K_PREMISSION_POST_NOTIFICATIONS = "android.permission.POST_NOTIFICATIONS";
|
||||||
|
private const string K_CUSTOM_NOTIFICATION_ACTIVITY = "custom_notification_android_activity";
|
||||||
|
private const string V_DEFAULT_GURU_ACTIVITY = "com.google.firebase.messaging.MessageForwardingService";
|
||||||
|
const string K_ANDROID_NAMESPACE_URI = "http://schemas.android.com/apk/res/android";
|
||||||
|
|
||||||
|
public int callbackOrder => POST_ORDER;
|
||||||
|
|
||||||
|
public void OnPostGenerateGradleAndroidProject(string path)
|
||||||
|
{
|
||||||
|
SetupAndroidManifest(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置 Android Manifest
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="projectPath"></param>
|
||||||
|
/// <exception cref="FileNotFoundException"></exception>
|
||||||
|
private void SetupAndroidManifest(string projectPath)
|
||||||
|
{
|
||||||
|
var manifestPath = $"{projectPath}/src/main/AndroidManifest.xml";
|
||||||
|
if (!File.Exists(manifestPath))
|
||||||
|
throw new FileNotFoundException($"'{manifestPath}' doesn't exist.");
|
||||||
|
|
||||||
|
XmlDocument manifestDoc = new XmlDocument();
|
||||||
|
manifestDoc.Load(manifestPath);
|
||||||
|
|
||||||
|
InjectAndroidManifest(manifestPath, manifestDoc);
|
||||||
|
|
||||||
|
manifestDoc.Save(manifestPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void InjectAndroidManifest(string manifestPath, XmlDocument manifestDoc)
|
||||||
|
{
|
||||||
|
string mainActivity = GetLauncherActivity(manifestDoc);
|
||||||
|
|
||||||
|
AppendAndroidMetadataField(manifestPath, manifestDoc, K_CUSTOM_NOTIFICATION_ACTIVITY, mainActivity);
|
||||||
|
AppendAndroidPermissionField(manifestPath, manifestDoc, K_PREMISSION_POST_NOTIFICATIONS);
|
||||||
|
|
||||||
|
UnityEngine.Debug.Log($"<color=#88ff00>Add custom notification activity: {mainActivity} success!!</color>");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AppendAndroidPermissionField(string manifestPath, XmlDocument xmlDoc, string name, string maxSdk = null)
|
||||||
|
{
|
||||||
|
AppendAndroidPermissionField(manifestPath, xmlDoc, "uses-permission", name, maxSdk);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AppendAndroidPermissionField(string manifestPath, XmlDocument xmlDoc, string tagName, string name, string maxSdk)
|
||||||
|
{
|
||||||
|
var manifestNode = xmlDoc.SelectSingleNode("manifest");
|
||||||
|
if (manifestNode == null)
|
||||||
|
throw new ArgumentException(string.Format("Missing 'manifest' node in '{0}'.", manifestPath));
|
||||||
|
|
||||||
|
XmlElement metaDataNode = null;
|
||||||
|
foreach (XmlNode node in manifestNode.ChildNodes)
|
||||||
|
{
|
||||||
|
if (!(node is XmlElement) || node.Name != tagName)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var element = (XmlElement)node;
|
||||||
|
var elementName = element.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||||||
|
if (elementName == name)
|
||||||
|
{
|
||||||
|
if (maxSdk == null)
|
||||||
|
return;
|
||||||
|
var maxSdkAttr = element.GetAttribute("maxSdkVersion", K_ANDROID_NAMESPACE_URI);
|
||||||
|
if (!string.IsNullOrEmpty(maxSdkAttr))
|
||||||
|
return;
|
||||||
|
metaDataNode = element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metaDataNode == null)
|
||||||
|
{
|
||||||
|
metaDataNode = xmlDoc.CreateElement(tagName);
|
||||||
|
metaDataNode.SetAttribute("name", K_ANDROID_NAMESPACE_URI, name);
|
||||||
|
}
|
||||||
|
if (maxSdk != null)
|
||||||
|
metaDataNode.SetAttribute("maxSdkVersion", K_ANDROID_NAMESPACE_URI, maxSdk);
|
||||||
|
|
||||||
|
manifestNode.AppendChild(metaDataNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void AppendAndroidMetadataField(string manifestPath, XmlDocument xmlDoc, string name, string value)
|
||||||
|
{
|
||||||
|
var applicationNode = xmlDoc.SelectSingleNode("manifest/application");
|
||||||
|
if (applicationNode == null)
|
||||||
|
throw new ArgumentException(string.Format("Missing 'application' node in '{0}'.", manifestPath));
|
||||||
|
|
||||||
|
var nodes = xmlDoc.SelectNodes("manifest/application/meta-data");
|
||||||
|
if (nodes != null)
|
||||||
|
{
|
||||||
|
// Check if there is a 'meta-data' with the same name.
|
||||||
|
foreach (XmlNode node in nodes)
|
||||||
|
{
|
||||||
|
var element = node as XmlElement;
|
||||||
|
if (element == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var elementName = element.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||||||
|
if (elementName == name)
|
||||||
|
{
|
||||||
|
element.SetAttribute("value", K_ANDROID_NAMESPACE_URI, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XmlElement metaDataNode = xmlDoc.CreateElement("meta-data");
|
||||||
|
metaDataNode.SetAttribute("name", K_ANDROID_NAMESPACE_URI, name);
|
||||||
|
metaDataNode.SetAttribute("value", K_ANDROID_NAMESPACE_URI, value);
|
||||||
|
|
||||||
|
applicationNode.AppendChild(metaDataNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string GetLauncherActivity(XmlDocument xmlDoc)
|
||||||
|
{
|
||||||
|
var applicationNode = xmlDoc.SelectSingleNode("manifest/application");
|
||||||
|
if (applicationNode == null)
|
||||||
|
throw new ArgumentException($"Missing 'application' node in doc.");
|
||||||
|
|
||||||
|
var nodes = xmlDoc.SelectNodes("manifest/application/activity");
|
||||||
|
if (nodes != null)
|
||||||
|
{
|
||||||
|
foreach (XmlNode node in nodes)
|
||||||
|
{
|
||||||
|
var activityNode = node as XmlElement;
|
||||||
|
if (activityNode == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (activityNode.HasChildNodes)
|
||||||
|
{
|
||||||
|
var intentFilterNode = activityNode.SelectSingleNode("intent-filter");
|
||||||
|
|
||||||
|
if(intentFilterNode == null || !intentFilterNode.HasChildNodes)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (XmlElement childNode in intentFilterNode)
|
||||||
|
{
|
||||||
|
if(childNode == null) continue;
|
||||||
|
|
||||||
|
// 判断 action/category 二者取其一
|
||||||
|
if (childNode.Name == "action" && childNode.InnerXml.Contains("android.intent.action.MAIN"))
|
||||||
|
{
|
||||||
|
var activityName = activityNode.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||||||
|
return activityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childNode.Name == "category" && childNode.InnerXml.Contains("android.intent.category.LAUNCHER"))
|
||||||
|
{
|
||||||
|
var activityName = activityNode.GetAttribute("name", K_ANDROID_NAMESPACE_URI);
|
||||||
|
return activityName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return V_DEFAULT_GURU_ACTIVITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2e6de94961cc47abbabbc7e872085a98
|
||||||
|
timeCreated: 1718934648
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "GuruNotification.Editor",
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e75025463d0c436482bf4c3dab674315
|
||||||
|
timeCreated: 1718845553
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d6dd827f370441718ca2e49f3f603e4e
|
||||||
|
timeCreated: 1718845525
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace Guru.Notification
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
public interface INotificationAgent
|
||||||
|
{
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
string GetStatus();
|
||||||
|
|
||||||
|
bool IsAllowed();
|
||||||
|
|
||||||
|
void RequestPermission(Action<string> callback = null);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 43e051a65e9b469b8b9e8a9f6b4be944
|
||||||
|
timeCreated: 1718844775
|
||||||
|
|
@ -0,0 +1,252 @@
|
||||||
|
namespace Guru.Notification
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
#if UNITY_ANDROID
|
||||||
|
using UnityEngine.Android;
|
||||||
|
using Unity.Notifications.Android;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public class NotificationAgentAndroid : INotificationAgent
|
||||||
|
{
|
||||||
|
public const string FCM_DEFAULT_CHANNEL_ID = "fcm_default_channel";
|
||||||
|
private const string STATUS_GRANTED = "granted";
|
||||||
|
private const string STATUS_DENIDED = "denied";
|
||||||
|
// private const string STATUS_NOT_DETERMINED = "not_determined";
|
||||||
|
private const int REQUEST_PERMISSION_SDK_VERSION = 33;
|
||||||
|
private const string PERMISSION_POST_NOTIFICATION = "android.permission.POST_NOTIFICATIONS";
|
||||||
|
|
||||||
|
private bool _initOnce = false;
|
||||||
|
private string _notiStatus;
|
||||||
|
|
||||||
|
private string SavedNotiPermStatus
|
||||||
|
{
|
||||||
|
get => PlayerPrefs.GetString(nameof(SavedNotiPermStatus), "");
|
||||||
|
set => PlayerPrefs.SetString(nameof(SavedNotiPermStatus), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化
|
||||||
|
/// </summary>
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
if (!_initOnce) return;
|
||||||
|
_initOnce = true;
|
||||||
|
|
||||||
|
_notiStatus = STATUS_DENIDED;
|
||||||
|
if (!string.IsNullOrEmpty(SavedNotiPermStatus))
|
||||||
|
{
|
||||||
|
_notiStatus = SavedNotiPermStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_ANDROID
|
||||||
|
InitPlugins();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取状态
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string GetStatus()
|
||||||
|
{
|
||||||
|
if (!_initOnce) Init();
|
||||||
|
#if UNITY_ANDROID
|
||||||
|
UpdateNotiStatus();
|
||||||
|
#endif
|
||||||
|
return _notiStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置授权状态
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="status">授权状态</param>
|
||||||
|
private void SetGrantStatus(string status)
|
||||||
|
{
|
||||||
|
_notiStatus = status;
|
||||||
|
SavedNotiPermStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsAllowed()
|
||||||
|
{
|
||||||
|
return _notiStatus == STATUS_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestPermission(Action<string> callback = null)
|
||||||
|
{
|
||||||
|
#if UNITY_ANDROID
|
||||||
|
RequestAndroidPermission(callback);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------- Android 获取状态逻辑 --------------------
|
||||||
|
|
||||||
|
#if UNITY_ANDROID
|
||||||
|
|
||||||
|
private PermissionStatus _permissionStatus;
|
||||||
|
|
||||||
|
private void TryExecute(Action handler)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
handler?.Invoke();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.LogError(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化插件
|
||||||
|
/// </summary>
|
||||||
|
private void InitPlugins()
|
||||||
|
{
|
||||||
|
AndroidNotificationCenter.Initialize();
|
||||||
|
Debug.Log($"[Noti][AND] --- Notification Service InitPlugins");
|
||||||
|
|
||||||
|
UpdateNotiStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新 Notification 状态码
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateNotiStatus()
|
||||||
|
{
|
||||||
|
|
||||||
|
TryExecute(() =>
|
||||||
|
{
|
||||||
|
_permissionStatus = AndroidNotificationCenter.UserPermissionToPost;
|
||||||
|
var status = "";
|
||||||
|
switch (_permissionStatus)
|
||||||
|
{
|
||||||
|
// case PermissionStatus.NotRequested:
|
||||||
|
// _notiStatus = STATUS_NOT_DETERMINED;
|
||||||
|
// break;
|
||||||
|
case PermissionStatus.Allowed:
|
||||||
|
status = STATUS_GRANTED;;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = STATUS_DENIDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetGrantStatus(status);
|
||||||
|
Debug.LogWarning($"[SDK][AND] --- UpdateNotiStatus:{_notiStatus} | UserPermissionToPost:{_permissionStatus}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Action<string> _onPermissionCallback;
|
||||||
|
private PermissionCallbacks _permissionCallbacks;
|
||||||
|
private void RequestAndroidPermission(Action<string> callback = null)
|
||||||
|
{
|
||||||
|
UpdateNotiStatus();
|
||||||
|
|
||||||
|
if (_notiStatus == STATUS_GRANTED)
|
||||||
|
{
|
||||||
|
callback?.Invoke(_notiStatus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_onPermissionCallback = callback;
|
||||||
|
TryExecute(() =>
|
||||||
|
{
|
||||||
|
var sdkInt = GetAndroidSDKVersion();
|
||||||
|
if (sdkInt < REQUEST_PERMISSION_SDK_VERSION)
|
||||||
|
{
|
||||||
|
// 低版本处理方式
|
||||||
|
Debug.Log($"[SDK][Noti] --- #2 SDK {sdkInt} not requested -> open channel");
|
||||||
|
AndroidNotificationCenter.RegisterNotificationChannel(new AndroidNotificationChannel(FCM_DEFAULT_CHANNEL_ID,
|
||||||
|
FCM_DEFAULT_CHANNEL_ID, "", Importance.Default)); // 打开ChannelID
|
||||||
|
SetGrantStatus(STATUS_GRANTED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// SDK 33 以上,请求弹窗
|
||||||
|
bool hasPermission = Permission.HasUserAuthorizedPermission(PERMISSION_POST_NOTIFICATION);
|
||||||
|
if (hasPermission)
|
||||||
|
{
|
||||||
|
SetGrantStatus(STATUS_GRANTED);
|
||||||
|
callback?.Invoke(STATUS_GRANTED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Debug.Log($"[SDK][Noti] --- #3 SDK {sdkInt} :: Ask Post Permission");
|
||||||
|
Permission.RequestUserPermission(PERMISSION_POST_NOTIFICATION, SetupPermissionCallbacks());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private PermissionCallbacks SetupPermissionCallbacks()
|
||||||
|
{
|
||||||
|
if(_permissionCallbacks != null) DisposePermissionCallbacks();
|
||||||
|
_permissionCallbacks = new PermissionCallbacks();
|
||||||
|
_permissionCallbacks.PermissionGranted += OnPermissionGranted;
|
||||||
|
_permissionCallbacks.PermissionDenied += OnPermissionDenied;
|
||||||
|
_permissionCallbacks.PermissionDeniedAndDontAskAgain += OnPermissionDenied;
|
||||||
|
return _permissionCallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposePermissionCallbacks()
|
||||||
|
{
|
||||||
|
if (_permissionCallbacks != null)
|
||||||
|
{
|
||||||
|
_permissionCallbacks.PermissionGranted -= OnPermissionGranted;
|
||||||
|
_permissionCallbacks.PermissionDenied -= OnPermissionDenied;
|
||||||
|
_permissionCallbacks.PermissionDeniedAndDontAskAgain -= OnPermissionDenied;
|
||||||
|
_permissionCallbacks = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求通过
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="permissionName"></param>
|
||||||
|
private void OnPermissionGranted(string permissionName)
|
||||||
|
{
|
||||||
|
if (permissionName == PERMISSION_POST_NOTIFICATION)
|
||||||
|
{
|
||||||
|
_notiStatus = STATUS_GRANTED;
|
||||||
|
_onPermissionCallback?.Invoke(_notiStatus);
|
||||||
|
}
|
||||||
|
SetGrantStatus(STATUS_GRANTED);
|
||||||
|
DisposePermissionCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求拒绝
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="permissionName"></param>
|
||||||
|
private void OnPermissionDenied(string permissionName)
|
||||||
|
{
|
||||||
|
if (permissionName == PERMISSION_POST_NOTIFICATION)
|
||||||
|
{
|
||||||
|
_notiStatus = STATUS_DENIDED;
|
||||||
|
_onPermissionCallback?.Invoke(_notiStatus);
|
||||||
|
}
|
||||||
|
SetGrantStatus(STATUS_DENIDED);
|
||||||
|
DisposePermissionCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetAndroidSDKVersion()
|
||||||
|
{
|
||||||
|
int sdkInt = 999;
|
||||||
|
TryExecute(() =>
|
||||||
|
{
|
||||||
|
using (AndroidJavaClass jc = new AndroidJavaClass("android.os.Build$VERSION"))
|
||||||
|
{
|
||||||
|
sdkInt = jc.GetStatic<int>("SDK_INT");
|
||||||
|
Debug.LogWarning($"[SDK] --- Android SDK Version:{sdkInt}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return sdkInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 554fcea56ce74a80a2424e5c037ce6c0
|
||||||
|
timeCreated: 1718844764
|
||||||
|
|
@ -0,0 +1,151 @@
|
||||||
|
|
||||||
|
|
||||||
|
namespace Guru.Notification
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
#if UNITY_IOS
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Unity.Notifications.iOS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public class NotificationAgentIOS : INotificationAgent
|
||||||
|
{
|
||||||
|
|
||||||
|
private const string STATUS_GRANTED = "granted";
|
||||||
|
private const string STATUS_DENIDED = "denied";
|
||||||
|
private const string STATUS_PROVISIONAL = "provisional";
|
||||||
|
private const string STATUS_NOT_DETERMINED = "not_determined";
|
||||||
|
|
||||||
|
private static bool _initOnce;
|
||||||
|
private static int _waitSeconds = 30;
|
||||||
|
private string SavedNotiPermStatus
|
||||||
|
{
|
||||||
|
get => PlayerPrefs.GetString(nameof(SavedNotiPermStatus), "");
|
||||||
|
set => PlayerPrefs.SetString(nameof(SavedNotiPermStatus), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private string _notiStatus;
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
if (_initOnce) return;
|
||||||
|
_initOnce = true;
|
||||||
|
|
||||||
|
_notiStatus = SavedNotiPermStatus;
|
||||||
|
if (string.IsNullOrEmpty(_notiStatus))
|
||||||
|
_notiStatus = STATUS_NOT_DETERMINED;
|
||||||
|
|
||||||
|
#if UNITY_IOS
|
||||||
|
InitPlugins();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStatus()
|
||||||
|
{
|
||||||
|
if (!_initOnce) Init();
|
||||||
|
#if UNITY_IOS
|
||||||
|
UpdateStatus();
|
||||||
|
#endif
|
||||||
|
return _notiStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAllowed()
|
||||||
|
{
|
||||||
|
return _notiStatus == STATUS_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestPermission(Action<string> callback = null)
|
||||||
|
{
|
||||||
|
if (!_initOnce) Init();
|
||||||
|
|
||||||
|
if (_notiStatus == STATUS_GRANTED || _notiStatus == STATUS_DENIDED)
|
||||||
|
{
|
||||||
|
Debug.Log($"[SDK][Noti][iOS] --- Already has Status: {_notiStatus}");
|
||||||
|
callback?.Invoke(_notiStatus); // 已获得授权, 直接返回结果
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_IOS
|
||||||
|
RequestIOSPermission(callback);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if UNITY_IOS
|
||||||
|
|
||||||
|
private void InitPlugins()
|
||||||
|
{
|
||||||
|
UpdateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新状态
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateStatus()
|
||||||
|
{
|
||||||
|
string status = STATUS_NOT_DETERMINED;
|
||||||
|
var authorizationStatus = iOSNotificationCenter.GetNotificationSettings().AuthorizationStatus;
|
||||||
|
switch (authorizationStatus)
|
||||||
|
{
|
||||||
|
case AuthorizationStatus.Authorized:
|
||||||
|
status = STATUS_GRANTED;
|
||||||
|
break;
|
||||||
|
case AuthorizationStatus.Denied:
|
||||||
|
status = STATUS_DENIDED;
|
||||||
|
break;
|
||||||
|
case AuthorizationStatus.NotDetermined:
|
||||||
|
status = STATUS_NOT_DETERMINED;
|
||||||
|
break;
|
||||||
|
case AuthorizationStatus.Provisional:
|
||||||
|
status = STATUS_PROVISIONAL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug.Log($"[SDK][Noti][iOS] --- Unmarked AuthorizationStatus: {status}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetGrantStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetGrantStatus(string status)
|
||||||
|
{
|
||||||
|
_notiStatus = status;
|
||||||
|
SavedNotiPermStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 请求 IOS 的推送
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
private async void RequestIOSPermission(Action<string> callback = null)
|
||||||
|
{
|
||||||
|
Debug.Log($"[SDK][Noti][iOS] --- RequestIOSPermission start");
|
||||||
|
int timePassed = 0;
|
||||||
|
using (var req = new AuthorizationRequest(AuthorizationOption.Alert | AuthorizationOption.Badge, true))
|
||||||
|
{
|
||||||
|
while (!req.IsFinished && timePassed < _waitSeconds)
|
||||||
|
{
|
||||||
|
timePassed++;
|
||||||
|
await Task.Delay(1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (timePassed >= _waitSeconds)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"[SDK][Noti][iOS] --- RequestIOSPermission timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateStatus();
|
||||||
|
callback?.Invoke(_notiStatus);
|
||||||
|
Debug.Log($"[SDK][Noti][iOS] --- User Selected: {_notiStatus}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5068c6e238e74251955320761c96182b
|
||||||
|
timeCreated: 1718871877
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
|
||||||
|
namespace Guru.Notification
|
||||||
|
{
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For Editor to use Notifications
|
||||||
|
/// </summary>
|
||||||
|
public class NotificationAgentStub: INotificationAgent
|
||||||
|
{
|
||||||
|
private const string STATUS_GRANTED = "granted";
|
||||||
|
private const string STATUS_DENIDED = "denied";
|
||||||
|
private const string STATUS_NOT_DETERMINED = "not_determined";
|
||||||
|
|
||||||
|
private Action<string> _onPermissionCallback;
|
||||||
|
private float _delaySeconds = 1.0f;
|
||||||
|
|
||||||
|
private string EditorGrantedStatus
|
||||||
|
{
|
||||||
|
get => PlayerPrefs.GetString(nameof(EditorGrantedStatus), STATUS_NOT_DETERMINED);
|
||||||
|
set => PlayerPrefs.SetString(nameof(EditorGrantedStatus), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
Debug.Log($"[SDK][Noti][EDT] --- NotificationAgentStub Init: {EditorGrantedStatus}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStatus() => EditorGrantedStatus;
|
||||||
|
|
||||||
|
public bool IsAllowed()
|
||||||
|
{
|
||||||
|
return EditorGrantedStatus == STATUS_GRANTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RequestPermission(Action<string> callback = null)
|
||||||
|
{
|
||||||
|
Debug.Log($"[SDK][Noti][EDT] --- RequestPermission ---");
|
||||||
|
_onPermissionCallback = callback;
|
||||||
|
DelayCallPermissionHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 延迟模拟回调
|
||||||
|
/// </summary>
|
||||||
|
private async void DelayCallPermissionHandle()
|
||||||
|
{
|
||||||
|
await Task.Delay((int)(1000 * _delaySeconds));
|
||||||
|
EditorGrantedStatus = STATUS_GRANTED;
|
||||||
|
_onPermissionCallback?.Invoke(EditorGrantedStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6550e85d25634c46b7a57c490dcea173
|
||||||
|
timeCreated: 1718850440
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
namespace Guru.Notification
|
||||||
|
{
|
||||||
|
using UnityEngine;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息管理器
|
||||||
|
/// </summary>
|
||||||
|
public class NotificationService
|
||||||
|
{
|
||||||
|
// 服务版本号
|
||||||
|
public const string Version = "0.0.1";
|
||||||
|
|
||||||
|
|
||||||
|
// 初始化标志位
|
||||||
|
private static bool _initOnce;
|
||||||
|
|
||||||
|
private static string DefaultPermissionStatus
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#if UNITY_IOS
|
||||||
|
return "not_determined";
|
||||||
|
#endif
|
||||||
|
return "denied";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 初始化
|
||||||
|
|
||||||
|
private static INotificationAgent _agent;
|
||||||
|
|
||||||
|
internal static INotificationAgent Agent
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_agent == null)
|
||||||
|
{
|
||||||
|
_agent = GetAgent();
|
||||||
|
}
|
||||||
|
return _agent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static INotificationAgent GetAgent()
|
||||||
|
{
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
return new NotificationAgentStub();
|
||||||
|
#elif UNITY_ANDROID
|
||||||
|
return new NotificationAgentAndroid();
|
||||||
|
#elif UNITY_IOS
|
||||||
|
return new NotificationAgentIOS();
|
||||||
|
#endif
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化
|
||||||
|
/// </summary>
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
if (_initOnce) return;
|
||||||
|
_initOnce = true;
|
||||||
|
Agent?.Init(); // 初始化代理
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region 接口
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 拉起 Noti 请求
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
public static void RequestPermission(Action<string> callback = null)
|
||||||
|
{
|
||||||
|
if (Agent != null)
|
||||||
|
{
|
||||||
|
Agent.RequestPermission(callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Debug.LogError($"[SDK][Noti] --- Agent is missing, return default status: {DefaultPermissionStatus}");
|
||||||
|
callback?.Invoke(DefaultPermissionStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsPermissionGranted()
|
||||||
|
{
|
||||||
|
return Agent?.IsAllowed() ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetStatus()
|
||||||
|
{
|
||||||
|
if(!_initOnce) Initialize();
|
||||||
|
|
||||||
|
if(Agent != null) return Agent.GetStatus();
|
||||||
|
|
||||||
|
Debug.LogError($"[SDK][Noti] --- Agent is missing, return default status: {DefaultPermissionStatus}");
|
||||||
|
return DefaultPermissionStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e0f31750e8bc48a6a5e4f56ee2d5e1cc
|
||||||
|
timeCreated: 1718846076
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
namespace Guru
|
namespace Guru
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
public abstract class RemoteConfigBase<T>: IRemoteConfig<T> where T : IRemoteConfig<T>
|
public abstract class RemoteConfigBase<T>: IRemoteConfig<T> where T : IRemoteConfig<T>
|
||||||
{
|
{
|
||||||
|
|
@ -8,6 +10,8 @@ namespace Guru
|
||||||
/// 配置是否可用
|
/// 配置是否可用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool enable { get; set; } = true;
|
public bool enable { get; set; } = true;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public Action<T> OnValueChanged { get; set; }
|
public Action<T> OnValueChanged { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转为Json
|
/// 转为Json
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.ads.ios-support": "1.2.0",
|
"com.unity.ads.ios-support": "1.2.0",
|
||||||
"com.unity.editorcoroutines": "1.0.0",
|
"com.unity.editorcoroutines": "1.0.0",
|
||||||
|
"com.unity.mobile.notifications": "2.2.2",
|
||||||
"com.unity.mobile.android-logcat": "1.3.2",
|
"com.unity.mobile.android-logcat": "1.3.2",
|
||||||
"com.unity.purchasing": "4.10.0"
|
"com.unity.purchasing": "4.10.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue