411 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			411 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
| namespace Guru
 | |
| {
 | |
|     using UnityEngine;
 | |
|     using System;
 | |
|     using System.Collections;
 | |
|     using System.Collections.Generic;
 | |
|     using System.IO;
 | |
|     
 | |
|     public partial class GuruSDK: MonoBehaviour
 | |
|     {
 | |
|         public const string Version = "1.0.6";
 | |
|         public const string Tag = "[Guru]";
 | |
|         public const string ServicesConfigKey = "guru_services";
 | |
|         
 | |
|         private static GuruSDK _instance;
 | |
|         /// <summary>
 | |
|         /// 单利引用
 | |
|         /// </summary>
 | |
|         public static GuruSDK Instance
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if(null == _instance)
 | |
|                 {
 | |
|                     _instance = CreateInstance();
 | |
|                 }
 | |
|                 return _instance;
 | |
|             }
 | |
|             
 | |
|         }
 | |
| 
 | |
|         private GuruSDKInitConfig _initConfig;
 | |
|         private Action<bool> _onCompleteCallback;
 | |
| 
 | |
|         private static GuruSDKModel _model;
 | |
| 
 | |
|         internal static GuruSDKInitConfig InitConfig => Instance._initConfig;
 | |
|         internal static GuruSDKModel Model => GuruSDKModel.Instance;
 | |
|         private static GuruServicesConfig _appServicesConfig;
 | |
| 
 | |
|         private static GuruSettings _guruSettings;
 | |
| 
 | |
|         private static GuruSettings GuruSettings
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (_guruSettings == null) _guruSettings = GuruSettings.Instance;
 | |
|                 return _guruSettings;
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|         private static bool _isDebugEnabled = false;
 | |
|         /// <summary>
 | |
|         /// Debug Mode
 | |
|         /// </summary>
 | |
|         public static bool IsDebugMode
 | |
|         {
 | |
|             get
 | |
|             {
 | |
| #if UNITY_EDITOR || DEBUG
 | |
|                 return true;
 | |
| #endif
 | |
|                 return _isDebugEnabled;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 初始化成功标志位
 | |
|         /// </summary>
 | |
|         public static bool IsInitialSuccess { get; private set; } = false;
 | |
| 
 | |
|         #region 初始化
 | |
|         
 | |
|         private static GuruSDK CreateInstance()
 | |
|         {
 | |
|             var go = new GameObject(nameof(GuruSDK));
 | |
|             DontDestroyOnLoad(go);
 | |
|             _instance = go.AddComponent<GuruSDK>();
 | |
|             return _instance;
 | |
|         }
 | |
| 
 | |
|         public static GuruSDKInitConfig BuildConfig(
 | |
|             bool useCustomConsent = false, 
 | |
|             bool autoLoadAds = true, 
 | |
|             bool iapEnabled = true, 
 | |
|             bool autoRecordFinishedLevels = true, 
 | |
|             bool debugMode = false,
 | |
|             Dictionary<string, object> defaultRemoteData = null,
 | |
|             byte[] googleKeys = null,
 | |
|             byte[] appleRootCerts = null)
 | |
|         {
 | |
|             var config = GuruSDKInitConfig.Build(useCustomConsent, autoLoadAds, iapEnabled, 
 | |
|                 autoRecordFinishedLevels, debugMode, defaultRemoteData, googleKeys, appleRootCerts);
 | |
|             return config;
 | |
|         }
 | |
| 
 | |
|         public static void Init(Action<bool> onComplete)
 | |
|         {
 | |
|             Init(GuruSDKInitConfig.Build(), onComplete);
 | |
|         }
 | |
|         
 | |
|         public static void Init(GuruSDKInitConfig config, Action<bool> onComplete)
 | |
|         {
 | |
|             LogI($"---- Guru SDK init ----\n{config.ToString()}");
 | |
|             Instance.StartWithConfig(config, onComplete);
 | |
|         }
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 启动SDK
 | |
|         /// </summary>
 | |
|         /// <param name="config"></param>
 | |
|         /// <param name="onComplete"></param>
 | |
|         private void StartWithConfig(GuruSDKInitConfig config, Action<bool> onComplete)
 | |
|         {
 | |
|             Model.PropBLevel.OnValueChanged += OnBLevelChanged;
 | |
|             Model.PropBPlay.OnValueChanged += OnBPlayChanged;
 | |
|             
 | |
|             IsInitialSuccess = false;
 | |
|             _initConfig = config;
 | |
|             _onCompleteCallback = onComplete;
 | |
|             _isDebugEnabled = config.DebugMode;
 | |
| 
 | |
|             //--- 之后的逻辑放在 Start 方法内 ---
 | |
|         }
 | |
| 
 | |
|         void Start()
 | |
|         {
 | |
|             //---- Init All tools ----
 | |
| 
 | |
|             //---------- Start Firebase ------------
 | |
|             FirebaseUtil.InitFirebase(OnFirebaseReady);
 | |
|             // FirebaseUtil.OnFetchRemoteSuccess+= OnFetchRemoteCallback;
 | |
|             //---------- Start Facebook ------------
 | |
|             FBService.Instance.StartService();
 | |
|         }
 | |
|         
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 开始各种组件初始化
 | |
|         /// </summary>
 | |
|         private void OnFirebaseReady()
 | |
|         {
 | |
|             IsInitialSuccess = true;
 | |
|    
 | |
|             if (!InitConfig.UseCustomConsent)
 | |
|             {
 | |
|                 // LogI($"--- #3 Start Consent Flow ---");
 | |
|                 StartConsentFlow();
 | |
|             }
 | |
|             
 | |
|             if(!string.IsNullOrEmpty(IPMConfig.IPM_UID)) SetUID(IPMConfig.IPM_UID);
 | |
| 
 | |
|             // 开始Remote Manager初始化 
 | |
|             RemoteConfigManager.Init(BuildDefaultRemoteData(_initConfig.DefaultRemoteData));
 | |
|             RemoteConfigManager.OnFetchCompleted += OnFetchRemoteCallback;
 | |
|             
 | |
|             // 根据上次的云控配置来初始化参数
 | |
|             SetupServicesConfig();
 | |
|             
 | |
|             _onCompleteCallback?.Invoke(true);
 | |
|         }
 | |
|         
 | |
|         /// <summary>
 | |
|         /// 注入云控参数基础数据
 | |
|         /// </summary>
 | |
|         /// <param name="dict"></param>
 | |
|         /// <returns></returns>
 | |
|         private Dictionary<string, object> BuildDefaultRemoteData(Dictionary<string, object> dict)
 | |
|         {
 | |
|             if (dict == null) dict = new Dictionary<string, object>(3);
 | |
|             
 | |
|             // 注入默认的 Services 配置值
 | |
|             string json = Model.LoadDefaltServicesConfigJson(); 
 | |
|             if (!string.IsNullOrEmpty(json)) dict[ServicesConfigKey] = json;
 | |
|        
 | |
|             return dict;
 | |
|         }
 | |
|         
 | |
|         /// <summary>
 | |
|         /// 拉取云控参数完成
 | |
|         /// </summary>
 | |
|         /// <param name="success"></param>
 | |
|         private void OnFetchRemoteCallback(bool success)
 | |
|         {
 | |
|             LogI($"--- Remote fetch complete: {success} ---");
 | |
|             ABTestManager.Init(); // 启动AB测试解析器
 | |
|             Callbacks.Remote._onRemoteFetchComplete?.Invoke(success);
 | |
|         }
 | |
|         
 | |
|         #endregion
 | |
| 
 | |
|         #region App Remote Update
 | |
| 
 | |
|         private void SetupServicesConfig()
 | |
|         {
 | |
|             bool useKeywords = true;
 | |
|             bool useIAP = true;
 | |
|             
 | |
|             var services = GetRemoteServicesConfig();
 | |
|             if (services != null)
 | |
|             {
 | |
|                 _appServicesConfig = services;
 | |
|                 useKeywords = _appServicesConfig.IsKeywordsEnabled();
 | |
|                 
 | |
|                 if (null != GuruSettings)
 | |
|                 {
 | |
|                     if(_appServicesConfig.adjust_settings != null)
 | |
|                     {    
 | |
|                         // 更新 Adjust Tokens
 | |
|                         GuruSettings.UpdateAdjustTokens(_appServicesConfig.adjust_settings.AndroidToken
 | |
|                             ,_appServicesConfig.adjust_settings.iOSToken);
 | |
|                         // 更新 Adjust Events
 | |
|                         GuruSettings.UpdateAdjustEvents(_appServicesConfig.adjust_settings.events);
 | |
|                     }
 | |
|                 }
 | |
|                 useIAP = _appServicesConfig.IsIAPEnabled();
 | |
| 
 | |
|                 if (_appServicesConfig.app_settings != null)
 | |
|                 {
 | |
|                     if (_appServicesConfig.app_settings.tch020_val > 0)
 | |
|                     {
 | |
|                         Analytics.EnableTch02Event = true;
 | |
|                         Analytics.SetTch02TargetValue(_appServicesConfig.app_settings.tch020_val);
 | |
|                     }
 | |
|                     
 | |
|                     // 更新和升级 GuruSettings 对应的值
 | |
|                     GuruSettings.UpdateAppSettings(
 | |
|                         _appServicesConfig.app_settings.bundle_id, 
 | |
|                         _appServicesConfig.fb_settings.fb_app_id,
 | |
|                         _appServicesConfig.app_settings.support_email,
 | |
|                         _appServicesConfig.app_settings.privacy_url,
 | |
|                         _appServicesConfig.app_settings.terms_url,
 | |
|                         _appServicesConfig.app_settings.android_store,
 | |
|                         _appServicesConfig.app_settings.ios_store);
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             if(useIAP) {
 | |
|                 InitIAP(_initConfig.GoogleKeys, _initConfig.AppleRootCerts); // 初始化IAP
 | |
|             }
 | |
|             
 | |
|             if(useKeywords) {
 | |
|                 KeywordsManager.Install(Model.IsIAPUser, Model.SuccessLevelCount); // 启动Keyword管理器
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private GuruServicesConfig GetRemoteServicesConfig()
 | |
|         {
 | |
|             var json = GetRemoteString(ServicesConfigKey);
 | |
|             if (!string.IsNullOrEmpty(json))
 | |
|             {
 | |
|                 return JsonParser.ToObject<GuruServicesConfig>(json);
 | |
|             }
 | |
|             return null;
 | |
|         }
 | |
|         #endregion
 | |
| 
 | |
|         #region 数据
 | |
| 
 | |
|         private void OnBLevelChanged(int blevel)
 | |
|         {
 | |
|             SetUserBLevel(blevel);
 | |
|         }
 | |
| 
 | |
|         private void OnBPlayChanged(int bplay)
 | |
|         {
 | |
|             SetUserBPlay(bplay);
 | |
|         }
 | |
| 
 | |
|         public static string UID => _model?.UserId ?? "";
 | |
| 
 | |
|         public static string SupportEmail => GuruSettings.SupportEmail ?? "";
 | |
| 
 | |
|         public static string StoreUrl
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 string url = "";
 | |
| #if UNITY_EDITOR
 | |
|                 url = "https://test@com.guru.ai";
 | |
| #elif UNITY_ANDROID
 | |
|                 url = GuruSettings?.AndroidStoreUrl ?? "";
 | |
| #elif UNITY_IOS
 | |
|                 url = GuruSettings?.IOSStoreUrl ?? "";
 | |
| #endif
 | |
|                 return url;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         #endregion
 | |
|         
 | |
|         #region Misc
 | |
|         
 | |
|         /// <summary>
 | |
|         /// 打开页面
 | |
|         /// </summary>
 | |
|         /// <param name="url"></param>
 | |
|         public static void OpenURL(string url)
 | |
|         {
 | |
|             GuruWebview.OpenPage(url);
 | |
|         }
 | |
|         
 | |
|         #endregion
 | |
| 
 | |
|         #region Logging
 | |
|         
 | |
|         internal static void LogI(object message)
 | |
|         {
 | |
|             Debug.Log($"{Tag} {message}");
 | |
|         }
 | |
|         
 | |
|         internal static void LogW(object message)
 | |
|         {
 | |
|             Debug.LogWarning($"{Tag} {message}");
 | |
|         }
 | |
|         
 | |
|         internal static void LogE(object message)
 | |
|         {
 | |
|             Debug.LogError($"{Tag} {message}");
 | |
|         }
 | |
| 
 | |
|         
 | |
|         internal static void LogException(string message)
 | |
|         {
 | |
|             LogException( new Exception($"{Tag} {message}"));
 | |
|         }
 | |
|         
 | |
|         internal static void LogException(Exception e)
 | |
|         {
 | |
|             Debug.LogException(e);
 | |
|         }
 | |
|         
 | |
|         #endregion
 | |
| 
 | |
|         #region 生命周期
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 暂停时处理
 | |
|         /// </summary>
 | |
|         /// <param name="paused"></param>
 | |
|         private void OnAppPauseHandler(bool paused)
 | |
|         {
 | |
|             if(paused) Model.Save(true); // 强制保存数据
 | |
|             Callbacks.App._onAppPaused?.Invoke(paused);
 | |
|         }
 | |
|         
 | |
|         private void OnApplicationPause(bool paused)
 | |
|         {
 | |
|             OnAppPauseHandler(paused);
 | |
|         }
 | |
| 
 | |
|         private void OnApplicationFocus(bool hasFocus)
 | |
|         {
 | |
|             OnAppPauseHandler(!hasFocus);
 | |
|         }
 | |
| 
 | |
|         private void OnApplicationQuit()
 | |
|         {
 | |
|             Model.Save(true);
 | |
|             Callbacks.App._onAppQuit?.Invoke();
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region 延迟处理
 | |
| 
 | |
|         /// <summary>
 | |
|         /// 启动协程
 | |
|         /// </summary>
 | |
|         /// <param name="enumerator"></param>
 | |
|         /// <returns></returns>
 | |
|         public static Coroutine DoCoroutine(IEnumerator enumerator)
 | |
|         {
 | |
|             return Instance != null ? Instance.StartCoroutine(enumerator) : null;
 | |
|         }
 | |
| 
 | |
|         public static void KillCoroutine(Coroutine coroutine)
 | |
|         {
 | |
|             if(coroutine != null)
 | |
|                 Instance.StopCoroutine(coroutine);
 | |
|         }
 | |
|         
 | |
|         /// <summary>
 | |
|         /// 延时执行
 | |
|         /// </summary>
 | |
|         /// <param name="seconds"></param>
 | |
|         /// <param name="callback"></param>
 | |
|         public static void Delay(float seconds, Action callback)
 | |
|         {
 | |
|             DoCoroutine(Instance.OnDelayCall(seconds, callback));
 | |
|         }
 | |
| 
 | |
|         private IEnumerator OnDelayCall(float delay, Action callback)
 | |
|         {
 | |
|             if (delay > 0)
 | |
|             {
 | |
|                 yield return new WaitForSeconds(delay);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 yield return null;
 | |
|             }
 | |
|             callback?.Invoke();
 | |
|         }
 | |
|         
 | |
|         #endregion
 | |
|         
 | |
|     }
 | |
| } |