update: 自打点库升级到 1.9.0, 双端: a:0.3.2 i:0.3.3
parent
9c3795227c
commit
be1c9cc327
|
|
@ -25,7 +25,7 @@ Sample Dependencies.xml:
|
|||
<!-- <androidPackage spec="com.squareup.retrofit2:retrofit:2.7.1" />-->
|
||||
</androidPackages>
|
||||
<iosPods>
|
||||
<iosPod name="GuruAnalyticsLib" version="0.3.2" bitcodeEnabled="false">
|
||||
<iosPod name="GuruAnalyticsLib" version="0.3.3" bitcodeEnabled="false">
|
||||
<sources>
|
||||
<source>git@github.com:castbox/GuruSpecs.git</source>
|
||||
</sources>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,32 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a336b814594434b4092d38e5ce76577a
|
||||
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:
|
||||
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 979b8da6b92542e990e6038f43f1835d
|
||||
timeCreated: 1710317078
|
||||
Binary file not shown.
|
|
@ -1,32 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c5a9f9e11213b4bb78856debe4c967ca
|
||||
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:
|
||||
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7d0a7721c57840829fad465c4c33e846
|
||||
timeCreated: 1710317052
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
source 'git@github.com:castbox/GuruSpecs.git'
|
||||
|
||||
platform :ios, '11.0'
|
||||
|
||||
target 'UnityFramework' do
|
||||
|
||||
pod 'GuruAnalyticsLib', '~>0.2.2'
|
||||
# pod 'GuruAnalyticsLib', :git => 'git@github.com:castbox/GuruAnalytics_iOS.git', :branch => 'dev'
|
||||
end
|
||||
target 'Unity-iPhone' do
|
||||
end
|
||||
use_frameworks!
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 10035163694574b63b74cd99c7ee5c68
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
@end
|
||||
|
||||
static NSString *gameobjectName;
|
||||
static NSString *callbackName;
|
||||
static NSString *gameobjectName = @"GuruCallback";
|
||||
static NSString *callbackName =@"OnCallback";
|
||||
|
||||
static GuruAnalytics *_analytics;
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ static GuruAnalytics *_analytics;
|
|||
@implementation U3DAnalytics
|
||||
|
||||
// Const value define
|
||||
NSString * const Version = @"1.8.1";
|
||||
NSString * const Version = @"1.9.0";
|
||||
|
||||
static const double kUploadPeriodInSecond = 60.0;
|
||||
static const int kBatchLimit = 15;
|
||||
|
|
@ -35,6 +35,8 @@ static const double kInitializeTimeout = 5.0;
|
|||
|
||||
static double tch001MaxValue = 0.01;
|
||||
static double tch02MaxValue = 0.2;
|
||||
static bool enableErrorLog = false;
|
||||
|
||||
NSString * const TchAdRevRoas001 = @"tch_ad_rev_roas_001";
|
||||
NSString * const TchAdRevRoas02 = @"tch_ad_rev_roas_02";
|
||||
NSString * const TchError = @"tch_error";
|
||||
|
|
@ -78,12 +80,29 @@ NSString * const TchError = @"tch_error";
|
|||
tch02MaxValue = value;
|
||||
}
|
||||
|
||||
// 设置是否启用日志错误上报
|
||||
+(void) setEnableErrorLog: (bool) value{
|
||||
if(enableErrorLog == false && value){
|
||||
|
||||
enableErrorLog = value;
|
||||
|
||||
[GuruAnalytics registerInternalEventObserverWithReportCallback:^(NSInteger code, NSString * info){
|
||||
[U3DAnalytics onEventCallback:code andInfo:info];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
// 事件上报回调
|
||||
+(void) onEventCallback: (NSInteger)code andInfo:(NSString *) info{
|
||||
[U3DAnalytics sendMessage: [U3DAnalytics buildLogEventString: code andMessage:info]];
|
||||
}
|
||||
|
||||
|
||||
// 构建数据
|
||||
//+(NSString *) buildDataString: (int)status andMessage: (NSString *)msg{
|
||||
//
|
||||
// NSString *jsonString = [NSString stringWithFormat: @"{\"action\":\"gdpr\",\"data\":{\"status\":%d,\"msg\":\"%@\"}}", status, msg];
|
||||
// return jsonString;
|
||||
//}
|
||||
+(NSString *) buildLogEventString: (NSInteger)status andMessage: (NSString *)msg{
|
||||
NSString *jsonString = [NSString stringWithFormat: @"{\"action\":\"logger_error\",\"data\":{\"code\":%d,\"msg\":\"%@\"}}", (int)status, msg];
|
||||
return jsonString;
|
||||
}
|
||||
|
||||
// 构建数据字典
|
||||
+(NSDictionary<NSString*, id> *) buildDataDict: (NSString *) str{
|
||||
|
|
@ -179,6 +198,19 @@ NSString * const TchError = @"tch_error";
|
|||
}
|
||||
}
|
||||
|
||||
// 向Unity发送数据
|
||||
+(void) sendMessage: (NSString *)msg
|
||||
{
|
||||
// NSLog(@"--- unityInitSDK222: %@:%@", gameobjectName, callbackName);
|
||||
if(gameobjectName != nil && callbackName != nil){
|
||||
char *t1 = [U3DAnalytics finalChar: gameobjectName];
|
||||
char *t2 = [U3DAnalytics finalChar: callbackName];
|
||||
char *t3 = [U3DAnalytics finalChar: msg];
|
||||
|
||||
UnitySendMessage(t1, t2, t3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 上报 tch_error 事件
|
||||
|
|
@ -206,6 +238,10 @@ NSString * const TchError = @"tch_error";
|
|||
return NO;
|
||||
}
|
||||
|
||||
//---------------------------
|
||||
|
||||
|
||||
|
||||
@end
|
||||
|
||||
//============================ UNITY PUBLIC API ============================
|
||||
|
|
@ -225,6 +261,12 @@ extern "C" {
|
|||
loggerDebug:isDebug];
|
||||
}
|
||||
|
||||
void unityInitCallback(const char *gameobject, const char *method){
|
||||
// NSLog(@"--- unityInitSDK111: %s:%s", gameobject, method);
|
||||
gameobjectName = [NSString stringWithUTF8String:gameobject];
|
||||
callbackName = [NSString stringWithUTF8String:method];
|
||||
}
|
||||
|
||||
// 设置用户ID
|
||||
void unitySetUserID(const char *uid){
|
||||
[GuruAnalytics setUserID:[U3DAnalytics charToString:uid]];
|
||||
|
|
@ -288,6 +330,11 @@ extern "C" {
|
|||
}];
|
||||
}
|
||||
|
||||
// 注册内部日志 Error 监听
|
||||
void unitySetEnableErrorLog(bool value){
|
||||
[U3DAnalytics setEnableErrorLog:value];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -6,6 +6,15 @@ GuruAnalyticsLib 的 Unity 插件库
|
|||
|
||||
## Change Logs
|
||||
|
||||
### 1.9.0
|
||||
- Android 端对齐 0.3.1+.
|
||||
> Hash: 0457eba963a9049fb6a16708b921573ef36c99b1
|
||||
- iOS 端对齐 0.3.3
|
||||
> Hash: c86d19fb38c8260f468e38d756aca84e89d58c8b
|
||||
- 新增自打点的错误上报功能, 但需要项目内接入 GuruSDKCallbacks 对象才能完成日志回发的功能
|
||||
- 错误上报开在 Plugin 外部应关依赖云控开启, 默认关闭.
|
||||
|
||||
|
||||
### 1.8.4
|
||||
- 优化Android 端 Worker 调用逻辑, 重启 Worker 有助于让打点数据更准确
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ namespace Guru
|
|||
public class GuruAnalytics
|
||||
{
|
||||
// Plugin Version
|
||||
public const string Version = "1.8.4";
|
||||
public const string Version = "1.9.0";
|
||||
|
||||
public static readonly string Tag = "[ANA]";
|
||||
private static readonly string ActionName = "logger_error";
|
||||
|
||||
private static IAnalyticsAgent _agent;
|
||||
|
||||
public static IAnalyticsAgent Agent
|
||||
|
|
@ -54,16 +56,34 @@ namespace Guru
|
|||
}
|
||||
|
||||
private static bool _autoSyncProperties = false;
|
||||
private static bool _enableErrorLog = false;
|
||||
|
||||
/// <summary>
|
||||
/// 启动日志错误上报
|
||||
/// </summary>
|
||||
public static bool EnableErrorLog
|
||||
{
|
||||
get => _enableErrorLog;
|
||||
set
|
||||
{
|
||||
_enableErrorLog = value;
|
||||
if (_enableErrorLog) InitCallbacks(); // 激活错误日志回调
|
||||
if (Agent != null) Agent.EnableErrorLog = _enableErrorLog;
|
||||
}
|
||||
}
|
||||
|
||||
#region 公用接口
|
||||
|
||||
/// <summary>
|
||||
/// 初始化接口
|
||||
/// </summary>
|
||||
public static void Init(string appId, string deviceInfo, bool isDebug = false, bool syncProperties = false)
|
||||
public static void Init(string appId, string deviceInfo, bool isDebug = false,
|
||||
bool enableErrorLog = false, bool syncProperties = false)
|
||||
{
|
||||
_autoSyncProperties = syncProperties;
|
||||
_enableErrorLog = enableErrorLog;
|
||||
Agent?.Init(appId, deviceInfo, isDebug);
|
||||
if(_enableErrorLog) InitCallbacks(); // 激活错误日志回调
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -255,7 +275,6 @@ namespace Guru
|
|||
{
|
||||
bool needUpdate = !UserProperties.ContainsKey(key) || UserProperties[key] != value;
|
||||
UserProperties[key] = value;
|
||||
|
||||
// if (needUpdate) UpdateAllUserProperties();
|
||||
}
|
||||
|
||||
|
|
@ -279,6 +298,115 @@ namespace Guru
|
|||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 日志回调
|
||||
|
||||
private static void InitCallbacks()
|
||||
{
|
||||
try
|
||||
{
|
||||
GuruSDKCallback.RemoveCallback(OnSDKCallback);
|
||||
GuruSDKCallback.AddCallback(OnSDKCallback);
|
||||
if (Agent != null)
|
||||
Agent.InitCallback(GuruSDKCallback.ObjectName, GuruSDKCallback.MethodName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Analytics.LogCrashlytics(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取SDK回调
|
||||
/// </summary>
|
||||
/// <param name="msg"></param>
|
||||
private static void OnSDKCallback(string msg)
|
||||
{
|
||||
//------- message send to unity ----------
|
||||
Debug.Log($"{Tag} get callback errorInfo:\n{msg}");
|
||||
|
||||
var result = JsonConvert.DeserializeObject<GuruLoggerCallback>(msg);
|
||||
try
|
||||
{
|
||||
if (result != null && result.action == ActionName)
|
||||
{
|
||||
if (result.data != null)
|
||||
{
|
||||
OnLoggerErrorEvent(result.data.code, result.data.msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogError($"{Tag} Parse callback Error");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Analytics.LogCrashlytics(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上报错误信息
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <param name="errorInfo"></param>
|
||||
private static void OnLoggerErrorEvent(int code, string errorInfo = "")
|
||||
{
|
||||
Dictionary<string, dynamic> parameters = new Dictionary<string, dynamic>()
|
||||
{
|
||||
{"item_category", "error_event"},
|
||||
{"item_name", ((AnalyticsCode)code).ToString()},
|
||||
{"country", IPMConfig.IPM_COUNTRY_CODE},
|
||||
{"network", Application.internetReachability.ToString()},
|
||||
};
|
||||
if (!string.IsNullOrEmpty(errorInfo))
|
||||
{
|
||||
int len = 32;
|
||||
if (errorInfo.Length > len) errorInfo = errorInfo.TrimStart().Substring(0, len);
|
||||
parameters["err"] = errorInfo;
|
||||
}
|
||||
|
||||
Debug.Log($"{Tag} --- ErrorLogInfo:: code:{code}\tinfo:{errorInfo}");
|
||||
|
||||
// Only for firebase GA
|
||||
Analytics.LogEvent("dev_audit", parameters,
|
||||
new Analytics.EventSetting() { EnableFirebaseAnalytics = true });
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class GuruLoggerCallback
|
||||
{
|
||||
public string action = "";
|
||||
public GuruLoggerErrorBody data;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class GuruLoggerErrorBody
|
||||
{
|
||||
public int code;
|
||||
public string msg;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 网络状态枚举
|
||||
/// </summary>
|
||||
public enum AnalyticsCode
|
||||
{
|
||||
Network_Lost = 22,
|
||||
|
||||
ERROR_API = 101,
|
||||
ERROR_RESPONSE = 102,
|
||||
ERROR_CACHE_CONTROL = 103,
|
||||
ERROR_DELETE_EXPIRED = 104,
|
||||
ERROR_LOAD_MARK = 105,
|
||||
ERROR_DNS = 106,
|
||||
ERROR_ZIP = 107,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ namespace Guru
|
|||
void SetDeviceId(string deviceId);
|
||||
void SetUid(string uid);
|
||||
bool IsDebug { get; }
|
||||
bool EnableErrorLog { get; set; }
|
||||
void LogEvent(string eventName, string parameters);
|
||||
void ReportEventSuccessRate(); // 上报任务成功率
|
||||
void SetTch02Value(double value); // 设置太极02数值
|
||||
void InitCallback(string objName, string method); // 设置回调对象参数
|
||||
}
|
||||
}
|
||||
|
|
@ -89,6 +89,18 @@ namespace Guru
|
|||
public void LogEvent(string eventName, string parameters) => CallStatic("logEvent", eventName, parameters);
|
||||
public void ReportEventSuccessRate() => CallStatic("reportEventRate");
|
||||
public void SetTch02Value(double value) => CallStatic("setTch02Value", value);
|
||||
public void InitCallback(string objName, string method) => CallStatic("initCallback", objName, method);
|
||||
|
||||
private bool _enableErrorLog;
|
||||
public bool EnableErrorLog
|
||||
{
|
||||
get => _enableErrorLog;
|
||||
set
|
||||
{
|
||||
_enableErrorLog = value;
|
||||
CallStatic("setEnableErrorLog", _enableErrorLog);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ namespace Guru
|
|||
[DllImport(K_INTERNAL)] private static extern void unityInitException();
|
||||
[DllImport(K_INTERNAL)] private static extern void unityTestUnrecognizedSelectorCrash();
|
||||
[DllImport(K_INTERNAL)] private static extern void unitySetTch02Value(double value);
|
||||
[DllImport(K_INTERNAL)] private static extern void unitySetEnableErrorLog(bool value);
|
||||
[DllImport(K_INTERNAL)] private static extern void unityInitCallback(string objName, string method);
|
||||
#endif
|
||||
|
||||
private static bool _isDebug = false;
|
||||
|
|
@ -32,6 +34,27 @@ namespace Guru
|
|||
|
||||
#region 接口实现
|
||||
|
||||
private bool _enableErrorLog;
|
||||
public bool EnableErrorLog
|
||||
{
|
||||
get => _enableErrorLog;
|
||||
set
|
||||
{
|
||||
_enableErrorLog = value;
|
||||
#if UNITY_IOS
|
||||
unitySetEnableErrorLog(_enableErrorLog);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public void InitCallback(string objName, string method)
|
||||
{
|
||||
#if UNITY_IOS
|
||||
unityInitCallback(objName, method);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
public void Init(string appId, string deviceInfo, bool isDebug = false)
|
||||
{
|
||||
_isDebug = isDebug;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,18 @@ namespace Guru
|
|||
private bool _isShowLog = false;
|
||||
private bool _isDebug = false;
|
||||
|
||||
private bool _enableErrorLog;
|
||||
|
||||
public bool EnableErrorLog
|
||||
{
|
||||
get => _enableErrorLog;
|
||||
set
|
||||
{
|
||||
Debug.Log($"{TAG} EnableErrorLog:<color=orange>{value}</color>");
|
||||
_enableErrorLog = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Init(string appId, string deviceInfo, bool isDebug = false)
|
||||
{
|
||||
|
|
@ -22,6 +34,14 @@ namespace Guru
|
|||
Debug.Log($"{TAG} init with Debug: <color=orange>{isDebug}</color> appId:{appId} deviceInfo:{deviceInfo}");
|
||||
}
|
||||
|
||||
|
||||
public void InitCallback(string objName, string method)
|
||||
{
|
||||
if(_isShowLog)
|
||||
Debug.Log($"{TAG} InitCallback: <color=orange>object:{objName} method:{method}</color>");
|
||||
}
|
||||
|
||||
|
||||
public void SetScreen(string screenName)
|
||||
{
|
||||
if(_isShowLog)
|
||||
|
|
@ -118,5 +138,14 @@ namespace Guru
|
|||
{
|
||||
Debug.Log($"{TAG} Tch02MaxValue: {value}");
|
||||
}
|
||||
|
||||
|
||||
#region Editor Test API
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -115,5 +115,8 @@ namespace Guru
|
|||
public static readonly string ParameterBalance = "balance"; // 用于余额
|
||||
public static readonly string ParameterSku = "sku"; // sku
|
||||
public static readonly string ParameterVirtualCurrencyName = "virtual_currency_name"; // 虚拟货币名称
|
||||
|
||||
// 中台
|
||||
public static readonly string EventDevAudit = "dev_audit"; // 中台事件异常
|
||||
}
|
||||
}
|
||||
|
|
@ -31,8 +31,9 @@ namespace Guru
|
|||
/// <summary>
|
||||
/// 初始化Guru自打点系统 (请优先于 Firebase 初始化调用)
|
||||
/// </summary>
|
||||
public static void InstallGuruAnalytics(bool isDebug = false)
|
||||
public static void InstallGuruAnalytics(bool isDebug = false, bool enableErrorLog = false)
|
||||
{
|
||||
|
||||
if (_hasInited) return;
|
||||
|
||||
try
|
||||
|
|
@ -44,7 +45,7 @@ namespace Guru
|
|||
#endif
|
||||
string appId = IPMConfig.IPM_X_APP_ID;
|
||||
string deviceInfo = new DeviceInfoData().ToString();
|
||||
GuruAnalytics.Init(appId, deviceInfo, IsDebug); // 初始化(带Header)
|
||||
GuruAnalytics.Init(appId, deviceInfo, IsDebug, enableErrorLog); // 初始化(带Header)
|
||||
|
||||
_hasGotFirebaseId = false;
|
||||
_hasGotAdId = false;
|
||||
|
|
|
|||
|
|
@ -596,6 +596,21 @@ namespace Guru
|
|||
|
||||
#endregion
|
||||
|
||||
#region 中台异常打点
|
||||
|
||||
/// <summary>
|
||||
/// 中台异常打点
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public static void LogDevAudit(Dictionary<string, dynamic> data)
|
||||
{
|
||||
if (data == null) return;
|
||||
data["country"] = IPMConfig.IPM_COUNTRY_CODE;
|
||||
data["network"] = Application.internetReachability.ToString();
|
||||
LogEvent(EventDevAudit, data, new EventSetting() { EnableFirebaseAnalytics = true });
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,11 +40,6 @@ namespace Guru
|
|||
return ins;
|
||||
}
|
||||
|
||||
private void SetCallback(Action<string> callback)
|
||||
{
|
||||
msgCallback += callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// External 回调参数
|
||||
/// </summary>
|
||||
|
|
@ -60,7 +55,16 @@ namespace Guru
|
|||
/// <param name="callback"></param>
|
||||
public static void AddCallback(Action<string> callback)
|
||||
{
|
||||
Instance.SetCallback(callback);
|
||||
Instance.msgCallback += callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加回调
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
public static void RemoveCallback(Action<string> callback)
|
||||
{
|
||||
Instance.msgCallback -= callback;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue