com.guru.unity.sdk/Runtime/Code/SDK/GuruSDK.cs

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.5";
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
}
}