Compare commits
	
		
			No commits in common. "main" and "dev" have entirely different histories. 
		
	
	
		| 
						 | 
				
			
			@ -5,8 +5,7 @@ dependencies {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
android {
 | 
			
		||||
    namespace "**NAMESPACE**"
 | 
			
		||||
    compileSdkVersion **TARGETSDKVERSION**
 | 
			
		||||
    compileSdkVersion **APIVERSION**
 | 
			
		||||
    buildToolsVersion '**BUILDTOOLS**'
 | 
			
		||||
 | 
			
		||||
    compileOptions {
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +22,6 @@ android {
 | 
			
		|||
        }
 | 
			
		||||
        versionCode **VERSIONCODE**
 | 
			
		||||
        versionName '**VERSIONNAME**'
 | 
			
		||||
        multiDexEnabled true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    aaptOptions {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,28 +11,28 @@ namespace Guru.Editor
 | 
			
		|||
    public class AndroidProjectMod
 | 
			
		||||
    {
 | 
			
		||||
        private const int TargetSDKVersion = 34;
 | 
			
		||||
        private const string K_ANDROID_PLUGINS_NAME = "Plugins/Android";
 | 
			
		||||
        private const string K_ANRDROID_PLUGINS_NAME = "Plugins/Android";
 | 
			
		||||
        
 | 
			
		||||
        private const string LauncherName = "launcherTemplate";
 | 
			
		||||
        private static readonly string LauncherFullPath = Path.Combine(Application.dataPath, $"{K_ANDROID_PLUGINS_NAME}/{LauncherName}.gradle");
 | 
			
		||||
        private static string LauncherFullPath = Path.Combine(Application.dataPath, $"{K_ANRDROID_PLUGINS_NAME}/{LauncherName}.gradle");
 | 
			
		||||
        
 | 
			
		||||
        private const string MainName = "mainTemplate";
 | 
			
		||||
        private static readonly string MainFullPath = Path.Combine(Application.dataPath,  $"{K_ANDROID_PLUGINS_NAME}/{MainName}.gradle");
 | 
			
		||||
        private static string MainFullPath = Path.Combine(Application.dataPath,  $"{K_ANRDROID_PLUGINS_NAME}/{MainName}.gradle");
 | 
			
		||||
        
 | 
			
		||||
        private const string BaseProjectName = "baseProjectTemplate";
 | 
			
		||||
        private static readonly string BaseProjectFullPath = Path.Combine(Application.dataPath,  $"{K_ANDROID_PLUGINS_NAME}/{BaseProjectName}.gradle");
 | 
			
		||||
        private static string BaseProjectFullPath = Path.Combine(Application.dataPath,  $"{K_ANRDROID_PLUGINS_NAME}/{BaseProjectName}.gradle");
 | 
			
		||||
        
 | 
			
		||||
        private const string PropertiesName = "gradleTemplate";
 | 
			
		||||
        private const string K_ENABLE_R8 = "android.enableR8";
 | 
			
		||||
        private static readonly string PropertiesFullPath = Path.Combine(Application.dataPath,  $"{K_ANDROID_PLUGINS_NAME}/{PropertiesName}.properties");
 | 
			
		||||
        private static string PropertiesFullPath = Path.Combine(Application.dataPath,  $"{K_ANRDROID_PLUGINS_NAME}/{PropertiesName}.properties");
 | 
			
		||||
        
 | 
			
		||||
        private const string SettingsName = "settingsTemplate";
 | 
			
		||||
        private static readonly string SettingsFullPath = Path.Combine(Application.dataPath,  $"Plugins/Android/{SettingsName}.gradle");
 | 
			
		||||
        private const string K_LINE_UNITY_PROJECT = "def unityProjectPath";
 | 
			
		||||
        private static string SettingsFullPath = Path.Combine(Application.dataPath,  $"Plugins/Android/{SettingsName}.gradle");
 | 
			
		||||
        private const string K_LINE_UNITYPROJECT = "def unityProjectPath";
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        private const string ProguardUserName = "proguard-user";
 | 
			
		||||
        private static readonly string ProguardUserFullPath = Path.Combine(Application.dataPath,  $"{K_ANDROID_PLUGINS_NAME}/{ProguardUserName}.txt");
 | 
			
		||||
        private static string ProguardUserFullPath = Path.Combine(Application.dataPath,  $"{K_ANRDROID_PLUGINS_NAME}/{ProguardUserName}.txt");
 | 
			
		||||
        
 | 
			
		||||
        public static void Apply()
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -40,11 +40,12 @@ namespace Guru.Editor
 | 
			
		|||
            ApplyBaseProjectTemplates();
 | 
			
		||||
            ApplyMainTemplates();
 | 
			
		||||
            ApplyGradleTemplate();
 | 
			
		||||
            ApplySettings();
 | 
			
		||||
            // ApplySettings();
 | 
			
		||||
            ApplyProguardUser();
 | 
			
		||||
            CheckTargetSDKVersion();  // 强制修复构建版本号
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private static void ApplyLauncher()
 | 
			
		||||
        {
 | 
			
		||||
            if (!File.Exists(LauncherFullPath))
 | 
			
		||||
| 
						 | 
				
			
			@ -58,9 +59,10 @@ namespace Guru.Editor
 | 
			
		|||
            var ptn2 = "abortOnError false";
 | 
			
		||||
            var lines = File.ReadAllLines(LauncherFullPath);
 | 
			
		||||
 | 
			
		||||
            string line = "";
 | 
			
		||||
            for (int i = 0; i < lines.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var line = lines[i];
 | 
			
		||||
                line = lines[i];
 | 
			
		||||
                if (line.Contains(ptn1))
 | 
			
		||||
                {
 | 
			
		||||
                    lines[i] = line.Replace(ptn1, "\n\n\tpackagingOptions {\n\t\texclude(\"META-INF/*.kotlin_module\")\n\t}\n\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -96,6 +98,8 @@ namespace Guru.Editor
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        private static void ApplyGradleTemplate()
 | 
			
		||||
        {
 | 
			
		||||
            if (!File.Exists(PropertiesFullPath))
 | 
			
		||||
| 
						 | 
				
			
			@ -110,10 +114,6 @@ namespace Guru.Editor
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 该版本中不再使用 R8
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="filePath"></param>
 | 
			
		||||
        private static void FixGradleTemplate(string filePath)
 | 
			
		||||
        {
 | 
			
		||||
            if (File.Exists(filePath))
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +123,7 @@ namespace Guru.Editor
 | 
			
		|||
 | 
			
		||||
                for (int i = 0; i < lines.Length; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (lines[i].Contains(K_ENABLE_R8))
 | 
			
		||||
                    if (lines[i].StartsWith(K_ENABLE_R8))
 | 
			
		||||
                    {
 | 
			
		||||
                        lines[i] = $"# {lines[i]}"; // 禁用R8
 | 
			
		||||
                        isDirty = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +137,7 @@ namespace Guru.Editor
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 写入 settings.gradle 配置文件
 | 
			
		||||
        /// 写入所有的配置文件
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static void ApplySettings()
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +147,8 @@ namespace Guru.Editor
 | 
			
		|||
            }
 | 
			
		||||
            FixProjectPathInSettings(SettingsFullPath);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private static void FixProjectPathInSettings(string settingsPath)
 | 
			
		||||
        {
 | 
			
		||||
            bool isDirty = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +158,7 @@ namespace Guru.Editor
 | 
			
		|||
                var lines = File.ReadAllLines(settingsPath);
 | 
			
		||||
                for (int i = 0; i < lines.Length; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (lines[i].Contains(K_LINE_UNITY_PROJECT))
 | 
			
		||||
                    if (lines[i].Contains(K_LINE_UNITYPROJECT))
 | 
			
		||||
                    {
 | 
			
		||||
                        lines[i] = $"        def unityProjectPath = $/file:////{projectPath}/$.replace(\"\\\\\", \"/\")";
 | 
			
		||||
                        isDirty = true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -497,7 +497,6 @@ namespace Guru.Editor
 | 
			
		|||
                {
 | 
			
		||||
                    ReadServiceConfig(); // Read file again
 | 
			
		||||
                    CheckAllComponents();
 | 
			
		||||
                    ExecuteAdditionalCommands();
 | 
			
		||||
                }, null, GUILayout.Height(btnH));
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -505,14 +504,7 @@ namespace Guru.Editor
 | 
			
		|||
            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 执行其他的命令
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void ExecuteAdditionalCommands()
 | 
			
		||||
        {
 | 
			
		||||
            // 部署 Adjust Signature V3
 | 
			
		||||
            DeployAdjustSignatureV3Files(); 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
| 
						 | 
				
			
			@ -1253,18 +1245,6 @@ namespace Guru.Editor
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region OtherCommands
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 使用 Adjust 签名 V3 导入项目
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void DeployAdjustSignatureV3Files()
 | 
			
		||||
        {
 | 
			
		||||
            AdjustSignatureHelper.DeployFiles();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,8 +7,7 @@
 | 
			
		|||
        "Guru.LitJson",
 | 
			
		||||
        "Guru.Runtime",
 | 
			
		||||
        "MaxSdk.Scripts.IntegrationManager.Editor",
 | 
			
		||||
        "Guru.Editor",
 | 
			
		||||
        "GuruAdjust.Editor"
 | 
			
		||||
        "Guru.Editor"
 | 
			
		||||
    ],
 | 
			
		||||
    "includePlatforms": [
 | 
			
		||||
        "Editor"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
namespace Guru
 | 
			
		||||
{
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
| 
						 | 
				
			
			@ -8,10 +7,8 @@ namespace Guru
 | 
			
		|||
    /// <summary>
 | 
			
		||||
    /// 启动参数配置
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class GuruSDKInitConfig
 | 
			
		||||
    public partial class GuruSDKInitConfig
 | 
			
		||||
    {
 | 
			
		||||
        #region Properties
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 使用自定义的ConsentFlow启动流程
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -31,8 +28,7 @@ namespace Guru
 | 
			
		|||
        /// <summary>
 | 
			
		||||
        /// 自动记录完成的关卡
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        [Obsolete("Will be removed from InitConfig in next version. Use the <b_level> and <b_play> data from the GameUserData from game itself instead!")]
 | 
			
		||||
        public bool AutoRecordFinishedLevels = false;
 | 
			
		||||
        public bool AutoRecordFinishedLevels = true;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自定义 Service 云控 Key
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +36,7 @@ namespace Guru
 | 
			
		|||
        /// <summary>
 | 
			
		||||
        /// Banner 背景颜色 Hex 值
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string BannerBackgroundColor = "#00000040";
 | 
			
		||||
        public string BannerBackgroundColor = "#00000000";
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 已购买去广告道具
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -53,24 +49,11 @@ namespace Guru
 | 
			
		|||
        /// Debug模式下开启打点(默认关闭)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool EnableDebugLogEvent = false;
 | 
			
		||||
 | 
			
		||||
        private Dictionary<string, object> _defaultRemoteData = new Dictionary<string, object>();
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 云控参数的默认配置
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public Dictionary<string, object> DefaultRemoteData
 | 
			
		||||
        {
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if (value != null)
 | 
			
		||||
                {
 | 
			
		||||
                    _defaultRemoteData = value;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            get => _defaultRemoteData;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Dictionary<string, object> DefaultRemoteData = new Dictionary<string, object>();
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 启用 AdjustDeeplink
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -81,9 +64,52 @@ namespace Guru
 | 
			
		|||
        /// </summary>
 | 
			
		||||
        public byte[] GoogleKeys;       // 数据取自 GooglePlayTangle.Data();
 | 
			
		||||
        public byte[] AppleRootCerts;   // 数据取自 AppleTangle.Data();
 | 
			
		||||
        
 | 
			
		||||
        #region Initialization
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构建启动配置
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static GuruSDKInitConfig Build(
 | 
			
		||||
            bool useCustomConsent = false, 
 | 
			
		||||
            bool autoLoadAds = true, 
 | 
			
		||||
            bool iapEnabled = true, 
 | 
			
		||||
            bool autoRecordFinishedLevels = true, 
 | 
			
		||||
            bool isBuyNoAds = false,
 | 
			
		||||
            string bannerBackgroundColor = "#00000000",
 | 
			
		||||
            bool debugMode = false,
 | 
			
		||||
            Action<string> onAdjustDeeplinkCallback = null,
 | 
			
		||||
            Dictionary<string, object> defaultRemoteData = null,
 | 
			
		||||
            byte[] googleKeys = null,
 | 
			
		||||
            byte[] appleRootCerts = null,
 | 
			
		||||
            bool debugEnableEventLog = false)
 | 
			
		||||
        {
 | 
			
		||||
            // 创建启动用参数
 | 
			
		||||
            GuruSDKInitConfig config = new GuruSDKInitConfig()
 | 
			
		||||
            {
 | 
			
		||||
                UseCustomConsent = useCustomConsent,
 | 
			
		||||
                AutoLoadWhenAdsReady = autoLoadAds,
 | 
			
		||||
                IAPEnabled = iapEnabled,
 | 
			
		||||
                AutoRecordFinishedLevels = autoRecordFinishedLevels,
 | 
			
		||||
                IsBuyNoAds = isBuyNoAds,
 | 
			
		||||
                BannerBackgroundColor = bannerBackgroundColor,
 | 
			
		||||
                DebugMode = debugMode,
 | 
			
		||||
                OnAdjustDeeplinkCallback = onAdjustDeeplinkCallback,
 | 
			
		||||
                GoogleKeys = googleKeys,
 | 
			
		||||
                AppleRootCerts = appleRootCerts,
 | 
			
		||||
                DefaultRemoteData = defaultRemoteData ?? new Dictionary<string, object>(),
 | 
			
		||||
                EnableDebugLogEvent = debugEnableEventLog,
 | 
			
		||||
            };
 | 
			
		||||
#if UNITY_EDITOR
 | 
			
		||||
            config.DebugMode = true;
 | 
			
		||||
#endif
 | 
			
		||||
            return config;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        #region Print
 | 
			
		||||
 | 
			
		||||
        public override string ToString()
 | 
			
		||||
| 
						 | 
				
			
			@ -107,107 +133,5 @@ namespace Guru
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Builder
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构造器
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static GuruSDKInitConfigBuilder Builder() => new GuruSDKInitConfigBuilder();
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 构建器
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class GuruSDKInitConfigBuilder
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        private GuruSDKInitConfig _config = new GuruSDKInitConfig();
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 构建配置
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public GuruSDKInitConfig Build()
 | 
			
		||||
        {
 | 
			
		||||
            return _config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetUseCustomConsent(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.UseCustomConsent = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetAutoLoadWhenAdsReady(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.AutoLoadWhenAdsReady = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetIAPEnabled(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.IAPEnabled = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetAutoRecordFinishedLevels(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.AutoRecordFinishedLevels = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetIsBuyNoAds(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.IsBuyNoAds = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetBannerBackgroundColor(string value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.BannerBackgroundColor = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetDebugMode(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.DebugMode = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetOnAdjustDeeplinkCallback(Action<string> callback)
 | 
			
		||||
        {
 | 
			
		||||
            _config.OnAdjustDeeplinkCallback = callback;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetGoogleKeys(byte[] value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.GoogleKeys = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetAppleRootCerts(byte[]  value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.AppleRootCerts = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetDefaultRemoteData(Dictionary<string, object> value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.DefaultRemoteData = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetEnableDebugLogEvent(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.EnableDebugLogEvent = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetCustomServiceKey(string value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.CustomServiceKey = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public GuruSDKInitConfigBuilder SetAutoNotificationPermission(bool value)
 | 
			
		||||
        {
 | 
			
		||||
            _config.AutoNotificationPermission = value;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,8 @@
 | 
			
		|||
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace Guru
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
    using UnityEngine.Serialization;
 | 
			
		||||
    
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    public class GuruServicesConfig
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +61,7 @@ namespace Guru
 | 
			
		|||
        public string DMAMapRule() => parameters?.dma_map_rule ?? "";
 | 
			
		||||
        public bool UseUUID() => parameters?.using_uuid ?? false;
 | 
			
		||||
        public bool KeywordsEnabled() => parameters?.enable_keywords ?? false; 
 | 
			
		||||
        public int TokenValidTime() => parameters?.token_valid_time ?? 604800;
 | 
			
		||||
        public int TokenValidTime() => parameters?.token_vaild_time ?? 604800;
 | 
			
		||||
        public int LevelEndSuccessNum() => parameters?.level_end_success_num ?? 50;
 | 
			
		||||
        public string CdnHost() => parameters?.cdn_host ?? "";
 | 
			
		||||
        public bool UsingUUID() => parameters?.using_uuid ?? true;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,7 +91,7 @@ namespace Guru
 | 
			
		|||
    [Serializable]
 | 
			
		||||
    public class GuruParameters
 | 
			
		||||
    {
 | 
			
		||||
        public int token_valid_time = 604800;
 | 
			
		||||
        public int token_vaild_time = 604800;
 | 
			
		||||
        public int level_end_success_num = 50;
 | 
			
		||||
        public bool enable_keywords = false;
 | 
			
		||||
        public double tch_020 = 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,17 +7,14 @@ namespace Guru
 | 
			
		|||
        /// 获取BLevel
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        protected override int GetBLevel() => Model.BLevel; // BLevel
 | 
			
		||||
        protected override int GetBLevel() => GuruSDKModel.Instance.SuccessLevelId; // BLevel
 | 
			
		||||
 | 
			
		||||
        private GuruSDKModel Model => GuruSDKModel.Instance;
 | 
			
		||||
        
 | 
			
		||||
        protected override void OnPurchaseOver(bool success, string productName)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ClearData()
 | 
			
		||||
        {
 | 
			
		||||
            _model.ClearData();
 | 
			
		||||
            if (success)
 | 
			
		||||
            {
 | 
			
		||||
                
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -12,17 +12,27 @@ namespace Guru
 | 
			
		|||
            get => _value;
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if (_value.Equals(value)) return;
 | 
			
		||||
                
 | 
			
		||||
                _value = value;
 | 
			
		||||
                OnValueChanged?.Invoke(value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public event Action<T> OnValueChanged;
 | 
			
		||||
        
 | 
			
		||||
        public BindableProperty(T initValue)
 | 
			
		||||
        
 | 
			
		||||
        public BindableProperty() 
 | 
			
		||||
        {
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public BindableProperty(Action<T> onChanged)
 | 
			
		||||
        {
 | 
			
		||||
            OnValueChanged = onChanged;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public BindableProperty(T initValue, Action<T> onChanged)
 | 
			
		||||
        {
 | 
			
		||||
            _value = initValue;
 | 
			
		||||
            OnValueChanged = onChanged;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace Guru
 | 
			
		||||
{
 | 
			
		||||
    using System;
 | 
			
		||||
| 
						 | 
				
			
			@ -5,42 +8,11 @@ namespace Guru
 | 
			
		|||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    class PurchasedProduct
 | 
			
		||||
    {
 | 
			
		||||
        public string productName;
 | 
			
		||||
        public string productId;
 | 
			
		||||
        public string receipt;
 | 
			
		||||
        public bool appleProductIsRestored;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    class GuruSDKSerializedModel
 | 
			
		||||
    {
 | 
			
		||||
        //-------------- data ---------------
 | 
			
		||||
        
 | 
			
		||||
        public string uid = "";
 | 
			
		||||
        public int b_level = 0;
 | 
			
		||||
        public int b_play = 0;
 | 
			
		||||
        public bool no_ads = false;
 | 
			
		||||
        public List<PurchasedProduct> purchased = new List<PurchasedProduct>(10);
 | 
			
		||||
        
 | 
			
		||||
        //-------------- data ---------------
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    internal class GuruSDKModel
 | 
			
		||||
    {
 | 
			
		||||
        private const float SaveInterval = 3;
 | 
			
		||||
        private const string SaveKey = "com.guru.sdk.model.save";
 | 
			
		||||
        private DateTime _lastSavedTime = new DateTime(1970,1,1);
 | 
			
		||||
        
 | 
			
		||||
        private bool _noAds = false;
 | 
			
		||||
        private int _bLevel;
 | 
			
		||||
        private int _bPlay;
 | 
			
		||||
        private string _uid;
 | 
			
		||||
        private List<PurchasedProduct> _purchased;
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        private static GuruSDKModel _instance;
 | 
			
		||||
| 
						 | 
				
			
			@ -48,77 +20,111 @@ namespace Guru
 | 
			
		|||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (null == _instance) _instance = new GuruSDKModel();
 | 
			
		||||
                if (null == _instance) _instance = Load();
 | 
			
		||||
                return _instance;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public GuruSDKModel()
 | 
			
		||||
        {
 | 
			
		||||
            // 读取内存值
 | 
			
		||||
            GuruSDKSerializedModel model = LoadModel();
 | 
			
		||||
            _uid = model.uid;
 | 
			
		||||
            _noAds = model.no_ads;
 | 
			
		||||
            _bLevel = model.b_level;
 | 
			
		||||
            _bPlay = model.b_play;
 | 
			
		||||
            _purchased = model.purchased;
 | 
			
		||||
        }
 | 
			
		||||
        //-------------- data ---------------
 | 
			
		||||
        public string uid = "";
 | 
			
		||||
        public int b_level = 0;
 | 
			
		||||
        public int b_play = 0;
 | 
			
		||||
        public int buy_count = 0;
 | 
			
		||||
        public bool no_ads = false;
 | 
			
		||||
        
 | 
			
		||||
        public int BLevel
 | 
			
		||||
        public List<PurchasedProduct> purchased;
 | 
			
		||||
 | 
			
		||||
        public Dictionary<string, int> event_priorities;
 | 
			
		||||
        
 | 
			
		||||
        //-------------- data ---------------
 | 
			
		||||
 | 
			
		||||
        private float _lastSavedTime = 0;
 | 
			
		||||
        
 | 
			
		||||
        public int SuccessLevelId
 | 
			
		||||
        {
 | 
			
		||||
            get => _bLevel;
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if(_successLevel == null) InitProperties();
 | 
			
		||||
                return _successLevel.Value;
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if (value < _bLevel)
 | 
			
		||||
                {
 | 
			
		||||
                    // b_level 必须比上一次的值大
 | 
			
		||||
                    Debug.LogWarning($"[SDK] :: Set b_level [{value}] should not be less than original value [{_bLevel}]");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                _bLevel = value;
 | 
			
		||||
                Save();
 | 
			
		||||
                if(_successLevel == null) InitProperties();
 | 
			
		||||
                _successLevel.Value = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public int BPlay
 | 
			
		||||
        public int TotalPlayedCount
 | 
			
		||||
        {
 | 
			
		||||
            get => _bPlay;
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if(_totalPlayed == null) InitProperties();
 | 
			
		||||
                return _totalPlayed.Value;
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                _bPlay = value;
 | 
			
		||||
                Save();
 | 
			
		||||
                if(_totalPlayed == null) InitProperties();
 | 
			
		||||
                _totalPlayed.Value = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public int PurchasedCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if(_purchasedCount == null) InitProperties();
 | 
			
		||||
                return _purchasedCount.Value;
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                if(_purchasedCount == null) InitProperties();
 | 
			
		||||
                _purchasedCount.Value = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string UserId
 | 
			
		||||
        {
 | 
			
		||||
            get => _uid;
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if(_uid == null) InitProperties();
 | 
			
		||||
                return _uid.Value;
 | 
			
		||||
            }
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                _uid = value;
 | 
			
		||||
                Save();
 | 
			
		||||
                if(_uid == null) InitProperties();
 | 
			
		||||
                _uid.Value = value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public bool IsIapUser => _purchased.Count > 0;
 | 
			
		||||
        public bool IsIapUser => PurchasedCount > 0;
 | 
			
		||||
        
 | 
			
		||||
        public bool IsNoAds
 | 
			
		||||
        {
 | 
			
		||||
            get => _noAds;
 | 
			
		||||
            get => no_ads;
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                _noAds = value;
 | 
			
		||||
                no_ads = value;
 | 
			
		||||
                Save();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private BindableProperty<int> _successLevel;
 | 
			
		||||
        private BindableProperty<int> _totalPlayed;
 | 
			
		||||
        private BindableProperty<int> _purchasedCount;
 | 
			
		||||
        private BindableProperty<string> _uid;
 | 
			
		||||
        private BindableProperty<bool> _isIapUser;
 | 
			
		||||
        
 | 
			
		||||
        public BindableProperty<int> PropBLevel => _successLevel;
 | 
			
		||||
        public BindableProperty<int> PropBPlay => _totalPlayed;
 | 
			
		||||
        public BindableProperty<int> PropBuyCount => _purchasedCount;
 | 
			
		||||
        public BindableProperty<string> Uid => _uid;
 | 
			
		||||
 | 
			
		||||
        #region 初始化
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private GuruSDKSerializedModel LoadModel()
 | 
			
		||||
        
 | 
			
		||||
        public static GuruSDKModel Load()
 | 
			
		||||
        {
 | 
			
		||||
            GuruSDKSerializedModel model = null;
 | 
			
		||||
            GuruSDKModel model = null;
 | 
			
		||||
            if (PlayerPrefs.HasKey(SaveKey))
 | 
			
		||||
            {
 | 
			
		||||
                var json = PlayerPrefs.GetString(SaveKey, "");
 | 
			
		||||
| 
						 | 
				
			
			@ -126,62 +132,113 @@ namespace Guru
 | 
			
		|||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        model =  JsonUtility.FromJson<GuruSDKSerializedModel>(json);
 | 
			
		||||
                        model =  JsonUtility.FromJson<GuruSDKModel>(json);
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception e)
 | 
			
		||||
                    {
 | 
			
		||||
                        Debug.LogError(e);
 | 
			
		||||
                        UnityEngine.Debug.LogError(e);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if(model == null) model = new GuruSDKSerializedModel();
 | 
			
		||||
            if(model == null) model = new GuruSDKModel();
 | 
			
		||||
            model.InitProperties();
 | 
			
		||||
            return model;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 保存至 PlayerPrefs 数据
 | 
			
		||||
        /// 保存至数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void SetToMemory()
 | 
			
		||||
        private void SaveToPlayerPrefs()
 | 
			
		||||
        {
 | 
			
		||||
            var model = new GuruSDKSerializedModel()
 | 
			
		||||
            {
 | 
			
		||||
                uid = _uid,
 | 
			
		||||
                b_level = _bLevel,
 | 
			
		||||
                b_play = _bPlay,
 | 
			
		||||
                no_ads = _noAds,
 | 
			
		||||
                purchased = _purchased,
 | 
			
		||||
            };
 | 
			
		||||
            
 | 
			
		||||
            var json = JsonUtility.ToJson(model);
 | 
			
		||||
            if (!string.IsNullOrEmpty(json))
 | 
			
		||||
            {
 | 
			
		||||
                PlayerPrefs.SetString(SaveKey, json);
 | 
			
		||||
            }
 | 
			
		||||
            var json = JsonUtility.ToJson(this);
 | 
			
		||||
            PlayerPrefs.SetString(SaveKey, json);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void InitProperties()
 | 
			
		||||
        {
 | 
			
		||||
            if (_successLevel == null) _successLevel = new BindableProperty<int>(b_level, OnLevelChanged);
 | 
			
		||||
            if (_totalPlayed == null) _totalPlayed = new BindableProperty<int>(b_play, OnPlayedChanged);
 | 
			
		||||
            if (_purchasedCount == null) _purchasedCount = new BindableProperty<int>(buy_count, OnPurchasedNumChanged);
 | 
			
		||||
            if (_uid == null) _uid = new BindableProperty<string>(uid, OnUidChanged);
 | 
			
		||||
            if (purchased == null) purchased = new List<PurchasedProduct>(20);
 | 
			
		||||
            if (event_priorities == null) event_priorities = new Dictionary<string, int>(10);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 保存数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="forceSave"></param>
 | 
			
		||||
        public void Save(bool forceSave = false)
 | 
			
		||||
        /// <param name="force"></param>
 | 
			
		||||
        public void Save(bool force = false)
 | 
			
		||||
        {
 | 
			
		||||
            SetToMemory(); // 每次保存都要设置到 PlayerPrefs 内
 | 
			
		||||
            bool save = force || (Time.realtimeSinceStartup - _lastSavedTime>= SaveInterval);
 | 
			
		||||
            if (save)
 | 
			
		||||
            {
 | 
			
		||||
                _lastSavedTime = Time.realtimeSinceStartup;
 | 
			
		||||
                SaveToPlayerPrefs();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            bool shouldWriteToDisk = forceSave || (DateTime.Now - _lastSavedTime)>= TimeSpan.FromSeconds(SaveInterval);
 | 
			
		||||
            if (!shouldWriteToDisk) return;
 | 
			
		||||
            _lastSavedTime = DateTime.Now; // 更新最后保存时间
 | 
			
		||||
            PlayerPrefs.Save(); // 写入到磁盘
 | 
			
		||||
        internal void SetBLevelValue(int value) => OnLevelChanged(value);
 | 
			
		||||
        internal void SetBPlayValue(int value) => OnPlayedChanged(value);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region 数据绑定变化
 | 
			
		||||
        private void OnLevelChanged(int value)
 | 
			
		||||
        {
 | 
			
		||||
            b_level = value;
 | 
			
		||||
            Save();
 | 
			
		||||
        }
 | 
			
		||||
        private void OnPlayedChanged(int value)
 | 
			
		||||
        {
 | 
			
		||||
            b_play = value;
 | 
			
		||||
            Save();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnPurchasedNumChanged(int value)
 | 
			
		||||
        {
 | 
			
		||||
            buy_count = value;
 | 
			
		||||
            Save();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void OnUidChanged(string value)
 | 
			
		||||
        {
 | 
			
		||||
            uid = value;
 | 
			
		||||
            Save();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region 启动配置
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 从 Streaming 加载 AppServices 配置
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public string LoadDefaltServicesConfigJson()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var txt = Resources.Load<TextAsset>(GuruSDK.ServicesConfigKey);
 | 
			
		||||
                return txt?.text ?? "";
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception e)
 | 
			
		||||
            {
 | 
			
		||||
                Log.Exception(e);
 | 
			
		||||
            }
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region 订单记录
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public bool HasPurchasedProduct(string receipt)
 | 
			
		||||
        {
 | 
			
		||||
            if(_purchased.Count == 0) return false;
 | 
			
		||||
            return _purchased.Exists(p => p.receipt == receipt);
 | 
			
		||||
            if(purchased == null || purchased.Count == 0) return false;
 | 
			
		||||
            return purchased.Exists(p => p.receipt == receipt);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -190,12 +247,12 @@ namespace Guru
 | 
			
		|||
        /// <param name="receipt"></param>
 | 
			
		||||
        /// <param name="productName"></param>
 | 
			
		||||
        /// <param name="productId"></param>
 | 
			
		||||
        /// <param name="appleProductIsRestored"></param>
 | 
			
		||||
        public void AddReceipt(string receipt, string productName, string productId, bool appleProductIsRestored = false)
 | 
			
		||||
        {
 | 
			
		||||
            if (purchased == null) purchased = new List<PurchasedProduct>(20);
 | 
			
		||||
            if (!HasPurchasedProduct(receipt))
 | 
			
		||||
            {
 | 
			
		||||
                _purchased.Add(new PurchasedProduct()
 | 
			
		||||
                purchased.Add(new PurchasedProduct()
 | 
			
		||||
                {
 | 
			
		||||
                    receipt = receipt,
 | 
			
		||||
                    productName = productName,
 | 
			
		||||
| 
						 | 
				
			
			@ -208,16 +265,22 @@ namespace Guru
 | 
			
		|||
 | 
			
		||||
        public string[] GetReceipts(string productName)
 | 
			
		||||
        {
 | 
			
		||||
            var receipts = new List<string>();
 | 
			
		||||
            receipts.AddRange(from purchasedProduct in _purchased where purchasedProduct.productName == productName select purchasedProduct.receipt);
 | 
			
		||||
            int count = purchased?.Count ?? 0;
 | 
			
		||||
            if (count == 0) count = 20;
 | 
			
		||||
            if (purchased == null) purchased = new List<PurchasedProduct>(count);
 | 
			
		||||
            var receipts = new List<string>(count);
 | 
			
		||||
            receipts.AddRange(from purchasedProduct in purchased where purchasedProduct.productName == productName select purchasedProduct.receipt);
 | 
			
		||||
            return receipts.ToArray();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public string[] GetReceiptsById(string productId)
 | 
			
		||||
        {
 | 
			
		||||
            var receipts = new List<string>();
 | 
			
		||||
            receipts.AddRange(from purchasedProduct in _purchased where purchasedProduct.productId == productId select purchasedProduct.receipt);
 | 
			
		||||
            int count = purchased?.Count ?? 0;
 | 
			
		||||
            if (count == 0) count = 20;
 | 
			
		||||
            if (purchased  == null) purchased = new List<PurchasedProduct>(count);
 | 
			
		||||
            var receipts = new List<string>(count);
 | 
			
		||||
            receipts.AddRange(from purchasedProduct in purchased where purchasedProduct.productId == productId select purchasedProduct.receipt);
 | 
			
		||||
            return receipts.ToArray();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
| 
						 | 
				
			
			@ -225,18 +288,17 @@ namespace Guru
 | 
			
		|||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region 清除数据
 | 
			
		||||
 | 
			
		||||
        public void ClearData()
 | 
			
		||||
        {
 | 
			
		||||
            PlayerPrefs.DeleteKey(SaveKey);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [Serializable]
 | 
			
		||||
    internal class PurchasedProduct
 | 
			
		||||
    {
 | 
			
		||||
        public string productName;
 | 
			
		||||
        public string productId;
 | 
			
		||||
        public string receipt;
 | 
			
		||||
        public bool appleProductIsRestored;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ namespace Guru
 | 
			
		|||
            _adInitSpec = spec;
 | 
			
		||||
            if (InitConfig.UseCustomConsent)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Log($"{Tag} --- Call <color=orange>StartAdsWithCustomConsent</color> when you use custom consent, and pass the result (boolean) to the method.");
 | 
			
		||||
                UnityEngine.Debug.Log($"{Tag} --- Call <color=orange>StartAdsWithCustomConsent</color> when you use custom consent, and pass the result (boolean) to the method.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ namespace Guru
 | 
			
		|||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Log($"{Tag} --- User refuse to provide ads Id, Ads Service will be cancelled");
 | 
			
		||||
                UnityEngine.Debug.Log($"{Tag} --- User refuse to provide ads Id, Ads Service will be cancelled");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -185,7 +185,7 @@ namespace Guru
 | 
			
		|||
        {
 | 
			
		||||
            _attType = InitConfig.UseCustomConsent ? ATTManager.GUIDE_TYPE_CUSTOM : ATTManager.GUIDE_TYPE_ADMOB; // 点位属性确定
 | 
			
		||||
            _initialAttStatus = ATTManager.GetStatus();
 | 
			
		||||
            SetATTStatus(_initialAttStatus); // 上报一个初始的状态
 | 
			
		||||
            SetUserProperty(Analytics.ParameterATTStatus, _initialAttStatus); // 上报一个初始的状态
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -202,15 +202,14 @@ namespace Guru
 | 
			
		|||
        private void ReportAttStatus(string status)
 | 
			
		||||
        {
 | 
			
		||||
            LogI($"{Tag} --- Get Att status:{status}  att Type:{_attType}  recall:{_autoReCallAtt}");
 | 
			
		||||
            SetATTStatus(_initialAttStatus); // 上报一个初始的状态
 | 
			
		||||
            // SetUserProperty(Analytics.ParameterATTStatus, status); // 当前的状态
 | 
			
		||||
            SetUserProperty(Analytics.ParameterATTStatus, status); // 当前的状态
 | 
			
		||||
            
 | 
			
		||||
            if (!string.IsNullOrEmpty(status) 
 | 
			
		||||
                && status != _initialAttStatus 
 | 
			
		||||
                && status !=  ATTManager.ATT_STATUS_NOT_DETERMINED)
 | 
			
		||||
            {
 | 
			
		||||
                // 上报点位:
 | 
			
		||||
                SetATTStatus(_initialAttStatus);
 | 
			
		||||
                Analytics.AttResult(status, _attType);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch(status)
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +243,7 @@ namespace Guru
 | 
			
		|||
            // bool hasNotiGranted = false;
 | 
			
		||||
            _notiStatue = "no_determined";
 | 
			
		||||
            NotificationService.Initialize(); // 初始化 Noti 服务
 | 
			
		||||
            Analytics.SetNotiPerm(NotificationService.GetStatus());
 | 
			
		||||
            SetNotiPerm(NotificationService.GetStatus());
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -266,7 +265,7 @@ namespace Guru
 | 
			
		|||
            if (isGranted)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Log($"[SDK] ---- Set Notification Permission: {status}");
 | 
			
		||||
                Analytics.SetNotiPerm(status);
 | 
			
		||||
                SetNotiPerm(status);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -285,7 +284,7 @@ namespace Guru
 | 
			
		|||
            NotificationService.RequestPermission(status =>
 | 
			
		||||
            {
 | 
			
		||||
                Debug.Log($"[SDK] ---- Set Notification Permission: {status}");
 | 
			
		||||
                if(!string.IsNullOrEmpty(status)) Analytics.SetNotiPerm(status);
 | 
			
		||||
                if(!string.IsNullOrEmpty(status)) SetNotiPerm(status);
 | 
			
		||||
                
 | 
			
		||||
                callback?.Invoke(status);
 | 
			
		||||
            });
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +325,7 @@ namespace Guru
 | 
			
		|||
        /// <summary>
 | 
			
		||||
        /// 启动广告服务
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static void StartAdService(AdsInitSpec spec = null)
 | 
			
		||||
        internal static void StartAdService(AdsInitSpec spec = null)
 | 
			
		||||
        {
 | 
			
		||||
            
 | 
			
		||||
            //---------- Using InitConfig ----------
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,10 +10,9 @@ namespace Guru
 | 
			
		|||
    /// </summary>
 | 
			
		||||
    public partial class GuruSDK
 | 
			
		||||
    {
 | 
			
		||||
        #region 通用接口
 | 
			
		||||
        //TODO: 需要有一个通用的 IEventData 的接口, 需要实现 getName, getData, getSetting, getPriority 等方法
 | 
			
		||||
        //TODO: Analytics.Track 的参数改为 IEventData
 | 
			
		||||
        
 | 
			
		||||
        #region 通用接口
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 自定义事件打点
 | 
			
		||||
        /// </summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +21,14 @@ namespace Guru
 | 
			
		|||
        /// <param name="priority"></param>
 | 
			
		||||
        public static void LogEvent(string eventName, Dictionary<string, dynamic> data = null, int priority = -1)
 | 
			
		||||
        {
 | 
			
		||||
            // if (!IsInitialSuccess)
 | 
			
		||||
            // {
 | 
			
		||||
            //     UnityEngine.Debug.LogError($"{Tag} :: LogEvent {eventName} :: Please call <GuruSDK.Start()> first, before you call <LogEvent>.");
 | 
			
		||||
            //     return;
 | 
			
		||||
            // }
 | 
			
		||||
            
 | 
			
		||||
            if(priority < 0) priority = GetEventPriorityInt(eventName);
 | 
			
		||||
            
 | 
			
		||||
            Analytics.Track(eventName, data, null, priority);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,90 +42,6 @@ namespace Guru
 | 
			
		|||
            Analytics.SetCurrentScreen(screen, extra);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
        
 | 
			
		||||
        #region 设置用户属性
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置用户属性
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <param name="value"></param>
 | 
			
		||||
        public static void SetUserProperty(string key, string value)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.SetUserProperty(key, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetUID(string uid)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.SetUid(uid);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetUserBLevel(int bLevel)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.SetBLevel(bLevel);
 | 
			
		||||
            Model.BLevel = bLevel;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetUserBPlay(int bPlay)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.SetBPlay(bPlay);
 | 
			
		||||
            Model.BPlay = bPlay;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 上报用户全部的 Coin (当前值)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="coins"></param>
 | 
			
		||||
        public static void SetUserCoin(int coins)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyCoin, $"{coins}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 上报用户免费金币的 数量 (累加值)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="freeCoins"></param>
 | 
			
		||||
        public static void SetUserNonIapCoin(int freeCoins)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyNonIAPCoin, $"{freeCoins}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 上报用户付费金币的 数量 (累加值)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="paidCoins"></param>
 | 
			
		||||
        public static void SetUserIapCoin(int paidCoins)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyIAPCoin, $"{paidCoins}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetUserExp(int exp)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyExp, $"{exp}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetUserHp(int hp)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyHp, $"{hp}");        
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetUserGrade(int grade)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyGrade, $"{grade}");        
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetUserIsIAP(bool isIapUser)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.SetIsIapUser(isIapUser);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetATTStatus(string status)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.SetAttStatus(status);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        #endregion
 | 
			
		||||
        
 | 
			
		||||
        #region 游戏打点
 | 
			
		||||
| 
						 | 
				
			
			@ -196,9 +118,6 @@ namespace Guru
 | 
			
		|||
                    $"{Tag} :: LogLevelEnd {levelId} :: Please call <GuruSDK.Start()> first, before you call <LogLevelEnd>.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            if (extra == null) extra = new Dictionary<string, object>();
 | 
			
		||||
            
 | 
			
		||||
            // 优先打 level_end 事件
 | 
			
		||||
            Analytics.LogLevelEnd(levelId, result, levelName, levelType, itemId, duration, step, score, extra);
 | 
			
		||||
            
 | 
			
		||||
| 
						 | 
				
			
			@ -207,16 +126,18 @@ namespace Guru
 | 
			
		|||
            {
 | 
			
		||||
                if (result == Consts.EventLevelEndSuccess)
 | 
			
		||||
                {
 | 
			
		||||
                    if (levelType.ToLower() == Consts.LevelTypeMain)
 | 
			
		||||
                    if (levelType == Consts.LevelTypeMain)
 | 
			
		||||
                    {
 | 
			
		||||
                        Model.BLevel = levelId; // 自动记录 [主线] 关卡完成次数
 | 
			
		||||
                        if (levelId > Model.SuccessLevelId) Model.SuccessLevelId = levelId; // 自动记录关卡完成次数
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    Model.BPlay++; // 自动记录关卡总次数
 | 
			
		||||
                    Model.TotalPlayedCount++; // 自动记录关卡总次数
 | 
			
		||||
 | 
			
		||||
                    var eventData = new LevelEndSuccessEventData(Model.BPlay, extra);
 | 
			
		||||
                    Analytics.TrackLevelEndSuccessEvent(eventData); // 自动 level_end_success
 | 
			
		||||
                    Analytics.LevelEndSuccess(Model.TotalPlayedCount); // 自动 level_end_success
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                Analytics.BLevel = Model.SuccessLevelId; // 记录 BLevel
 | 
			
		||||
                Analytics.BPlay = Model.TotalPlayedCount; // 记录 BPlay
 | 
			
		||||
            }
 | 
			
		||||
           
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -243,8 +164,8 @@ namespace Guru
 | 
			
		|||
        /// /// <param name="extra">扩展参数</param>
 | 
			
		||||
        public static void LogLevelEndSuccess(int bPlay, Dictionary<string, object> extra = null)
 | 
			
		||||
        {
 | 
			
		||||
            var eventData = new LevelEndSuccessEventData(bPlay, extra);
 | 
			
		||||
            Analytics.TrackLevelEndSuccessEvent(eventData);
 | 
			
		||||
            if (InitConfig.AutoRecordFinishedLevels) return;
 | 
			
		||||
            Analytics.LevelEndSuccess(bPlay, extra);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -370,15 +291,182 @@ namespace Guru
 | 
			
		|||
            LogEvent(Consts.EventHpPoints, dict);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region 用户属性
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 提前调用用户属性
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static void InitUserProperties()
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsInitialSuccess)
 | 
			
		||||
            {
 | 
			
		||||
                Debug.LogError($"{Tag} :: InitUserProperties :: Please call <GuruSDK.Start()> first, before you call <InitUserProperties>.");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            Debug.Log($"[SDK] --- PurchasedCount:{Model.PurchasedCount}");
 | 
			
		||||
            Debug.Log($"[SDK] --- IsIapUser:{Model.IsIapUser}");
 | 
			
		||||
            
 | 
			
		||||
            SetUserIsIAP(Model.IsIapUser); // 预先设置用户的 IAP User 属性
 | 
			
		||||
            SetUserBLevel(Model.SuccessLevelId); // 预先设置用户的 BLevel 属性
 | 
			
		||||
            SetUserBPlay(Model.TotalPlayedCount);  // 预先设置用户的 BPlay 属性
 | 
			
		||||
            if (Model.IsNoAds) SetBuyNoAds(true); // 设置用户已经购买了去广告
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置用户属性
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="key"></param>
 | 
			
		||||
        /// <param name="value"></param>
 | 
			
		||||
        public static void SetUserProperty(string key, string value)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.SetUserProperty(key, value);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetUID(string uid)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyUserID, uid);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetUserBLevel(int blevel)
 | 
			
		||||
        {
 | 
			
		||||
            if (!InitConfig.AutoRecordFinishedLevels)
 | 
			
		||||
            {
 | 
			
		||||
                Model.SetBLevelValue(blevel);
 | 
			
		||||
                Analytics.BLevel = blevel;
 | 
			
		||||
            }
 | 
			
		||||
            SetUserProperty(Consts.PropertyLevel, $"{blevel}");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetUserBPlay(int bplay)
 | 
			
		||||
        {
 | 
			
		||||
            if (!InitConfig.AutoRecordFinishedLevels)
 | 
			
		||||
            {
 | 
			
		||||
                Model.SetBPlayValue(bplay);
 | 
			
		||||
                Analytics.BPlay = bplay;
 | 
			
		||||
            }
 | 
			
		||||
            SetUserProperty(Consts.PropertyPlay, $"{bplay}");
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 上报用户全部的 Coin (当前值)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="coins"></param>
 | 
			
		||||
        public static void SetUserCoin(int coins)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyCoin, $"{coins}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 上报用户免费金币的 数量 (累加值)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="freeCoins"></param>
 | 
			
		||||
        public static void SetUserNonIapCoin(int freeCoins)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyNonIAPCoin, $"{freeCoins}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 上报用户付费金币的 数量 (累加值)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="paidCoins"></param>
 | 
			
		||||
        public static void SetUserIapCoin(int paidCoins)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyIAPCoin, $"{paidCoins}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetUserExp(int exp)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyExp, $"{exp}");        
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetUserHp(int hp)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyHp, $"{hp}");        
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetUserGrade(int grade)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyGrade, $"{grade}");        
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetUserIsIAP(bool isIapUser)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyIsIAPUser, isIapUser? "true" : "false");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetFirstOpenTime(string timestamp)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Analytics.PropertyFirstOpenTime, timestamp);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetNotiPerm(string status)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyNotiPerm, status);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void SetATTStatus(string status)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyATTStatus, status);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetAdjustId(string adjustId)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyAdjustId, adjustId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetNetworkStatus()
 | 
			
		||||
        {
 | 
			
		||||
            SetUserProperty(Consts.PropertyNetwork, Instance.GetNetworkStatus());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool _hasUserPropertiesInitiallyUpdated = false;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 初始化时补全一下所有的属性打点 
 | 
			
		||||
        /// 如果用户已经设置过 Key, 则不会再次设置
 | 
			
		||||
        /// <a href="https://docs.google.com/spreadsheets/d/1N47rXgjatRHFvzWWx0Hqv5C1D9NHHGbggi6pQ65c-zQ/edit#gid=1858695240">用户属性文档</a>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static void InitiallyUpdateUserProperties()
 | 
			
		||||
        {
 | 
			
		||||
            if (_hasUserPropertiesInitiallyUpdated) return;
 | 
			
		||||
            _hasUserPropertiesInitiallyUpdated = true;
 | 
			
		||||
            
 | 
			
		||||
            SetFirstOpenTime(TimeUtil.GetCurrentTimeStamp().ToString());    //  first_open_time 
 | 
			
		||||
            SetUserIsIAP(Model?.IsIapUser ?? false);    // is_iap_user
 | 
			
		||||
            SetUserBLevel(Model?.SuccessLevelId ?? 0);  // b_level
 | 
			
		||||
            SetUserBLevel(Model?.TotalPlayedCount ?? 0); // b_play
 | 
			
		||||
            SetUserProperty(Consts.PropertyDeviceID, DeviceId); // device_id
 | 
			
		||||
        
 | 
			
		||||
            SetUserIapCoin(0); // iap_coin
 | 
			
		||||
            SetUserNonIapCoin(0); // non_iap_coin
 | 
			
		||||
            SetUserCoin(0);// coin
 | 
			
		||||
            SetUserGrade(0); // grade
 | 
			
		||||
            SetUserExp(0); // exp
 | 
			
		||||
            SetUserHp(0); // hp
 | 
			
		||||
            
 | 
			
		||||
            if(!string.IsNullOrEmpty(UID))
 | 
			
		||||
                SetUID(UID); // user_id
 | 
			
		||||
            
 | 
			
		||||
#if UNITY_IOS
 | 
			
		||||
            SetATTStatus("notDetermined"); // att_status
 | 
			
		||||
#endif
 | 
			
		||||
            SetNotiPerm("not_determined"); // noti_perm
 | 
			
		||||
            SetNetworkStatus(); // NetworkStatus
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region SDK 打点
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Log SDK boost time
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="time"></param>
 | 
			
		||||
        private static void LogSDKInfo(double time)
 | 
			
		||||
        private static void LogSDKInitTime(double time)
 | 
			
		||||
        {
 | 
			
		||||
            Analytics.Track(Consts.EventSDKInfo, new Dictionary<string, dynamic>()
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -390,18 +478,10 @@ namespace Guru
 | 
			
		|||
            {
 | 
			
		||||
                EnableFirebaseAnalytics = true,
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
            SetUserProperty("sdk_version", Version);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取 GuruSDK 实验分组
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public static string GetGuruExperimentGroupId()
 | 
			
		||||
        {
 | 
			
		||||
            if (!GuruAnalytics.IsReady) return "not_set";
 | 
			
		||||
            return GuruAnalytics.Instance.ExperimentGroupId;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region IAP 打点
 | 
			
		||||
| 
						 | 
				
			
			@ -1154,7 +1234,7 @@ namespace Guru
 | 
			
		|||
            CrashlyticsAgent.Log(message);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void CrashLogException(string message)
 | 
			
		||||
        public static void CrashException(string message)
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsFirebaseReady) return;
 | 
			
		||||
            CrashlyticsAgent.LogException(message);
 | 
			
		||||
| 
						 | 
				
			
			@ -1166,7 +1246,7 @@ namespace Guru
 | 
			
		|||
            CrashlyticsAgent.LogException(ex);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void CrashSetCustomKeys(string key, string value)
 | 
			
		||||
        public static void CrashCustomKeys(string key, string value)
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsFirebaseReady) return;
 | 
			
		||||
            CrashlyticsAgent.SetCustomKey(key, value);
 | 
			
		||||
| 
						 | 
				
			
			@ -1175,7 +1255,6 @@ namespace Guru
 | 
			
		|||
 | 
			
		||||
        #region 优先级设置
 | 
			
		||||
        
 | 
			
		||||
        private static readonly Dictionary<string, int> _eventPriorities = new Dictionary<string, int>(10);
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 设置
 | 
			
		||||
| 
						 | 
				
			
			@ -1184,13 +1263,15 @@ namespace Guru
 | 
			
		|||
        /// <param name="eventNames"></param>
 | 
			
		||||
        public static void SetEventPriority(EventPriority priority, string[] eventNames)
 | 
			
		||||
        {
 | 
			
		||||
            if (Model.event_priorities == null) Model.event_priorities = new Dictionary<string, int>(10);
 | 
			
		||||
 | 
			
		||||
            int i = 0;
 | 
			
		||||
            while (i < eventNames.Length)
 | 
			
		||||
            {
 | 
			
		||||
                var evt = eventNames[i];
 | 
			
		||||
                if (!string.IsNullOrEmpty(evt))
 | 
			
		||||
                {
 | 
			
		||||
                    _eventPriorities[evt] = (int)priority;
 | 
			
		||||
                    Model.event_priorities[evt] = (int)priority;
 | 
			
		||||
                }
 | 
			
		||||
                i++;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1203,14 +1284,15 @@ namespace Guru
 | 
			
		|||
 | 
			
		||||
        public static EventPriority GetEventPriority(string eventName)
 | 
			
		||||
        {
 | 
			
		||||
            if (_eventPriorities.TryGetValue(eventName, out int p))
 | 
			
		||||
            if (Model.event_priorities != null 
 | 
			
		||||
                && Model.event_priorities.TryGetValue(eventName, out int p))
 | 
			
		||||
            {
 | 
			
		||||
                return (EventPriority)p;
 | 
			
		||||
            }
 | 
			
		||||
            return EventPriority.Default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static int GetEventPriorityInt(string eventName)
 | 
			
		||||
        
 | 
			
		||||
        internal static int GetEventPriorityInt(string eventName)
 | 
			
		||||
        {
 | 
			
		||||
            return (int)GetEventPriority(eventName);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1218,7 +1300,7 @@ namespace Guru
 | 
			
		|||
        /// <summary>
 | 
			
		||||
        /// set all events as 'Emergence' event, which will be triggered immediately
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void SetSDKEventPriority()
 | 
			
		||||
        internal void SetSDKEventPriority()
 | 
			
		||||
        {
 | 
			
		||||
            SetEventPriority(EventPriority.Emergence, new []
 | 
			
		||||
            {
 | 
			
		||||
| 
						 | 
				
			
			@ -1226,13 +1308,9 @@ namespace Guru
 | 
			
		|||
                Consts.EventTchAdRev02Impression,
 | 
			
		||||
                Consts.EventLevelStart,
 | 
			
		||||
                Consts.EventLevelEnd,
 | 
			
		||||
                Consts.EventIAPReturnTrue,
 | 
			
		||||
                Consts.EventIAPPurchase,
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -334,16 +334,27 @@ namespace Guru
 | 
			
		|||
                }
 | 
			
		||||
                
 | 
			
		||||
                private static Action<bool> _onUserAuthResult;
 | 
			
		||||
                public static event Action<bool> OnGuruUserAuthResult
 | 
			
		||||
                public static event Action<bool> OnUserAuthResult
 | 
			
		||||
                {
 | 
			
		||||
                    add => _onUserAuthResult += value;
 | 
			
		||||
                    remove => _onUserAuthResult -= value;
 | 
			
		||||
                }
 | 
			
		||||
                internal static void InvokeOnGuruUserAuthResult(bool success)
 | 
			
		||||
                internal static void InvokeOnUserAuthResult(bool success)
 | 
			
		||||
                {
 | 
			
		||||
                    _onUserAuthResult?.Invoke(success);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                private static Action<bool> _onFirebaseAuthResult;
 | 
			
		||||
                public static event Action<bool> OnFirebaseAuthResult
 | 
			
		||||
                {
 | 
			
		||||
                    add => _onFirebaseAuthResult += value;
 | 
			
		||||
                    remove => _onFirebaseAuthResult -= value;
 | 
			
		||||
                }
 | 
			
		||||
                internal static void InvokeOnFirebaseAuthResult(bool success)
 | 
			
		||||
                {
 | 
			
		||||
                    _onFirebaseAuthResult?.Invoke(success);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // DeepLink 回调 
 | 
			
		||||
                private static Action<string> _onDeeplinkCallback;
 | 
			
		||||
                public static event Action<string> OnDeeplinkCallback
 | 
			
		||||
| 
						 | 
				
			
			@ -356,19 +367,6 @@ namespace Guru
 | 
			
		|||
                    _onDeeplinkCallback?.Invoke(deeplink);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // TODO: 之后需要添加 define 宏来控制是否可用
 | 
			
		||||
                // Firebase Auth 回调
 | 
			
		||||
                private static Action<bool, Firebase.Auth.FirebaseUser> _onFirebaseUserAuthResult;
 | 
			
		||||
                public static event Action<bool, Firebase.Auth.FirebaseUser> OnFirebaseUserAuthResult
 | 
			
		||||
                {
 | 
			
		||||
                    add => _onFirebaseUserAuthResult += value;
 | 
			
		||||
                    remove => _onFirebaseUserAuthResult -= value;
 | 
			
		||||
                }
 | 
			
		||||
                internal static void InvokeOnFirebaseAuthResult(bool success, Firebase.Auth.FirebaseUser firebaseUser = null)
 | 
			
		||||
                {
 | 
			
		||||
                    _onFirebaseUserAuthResult?.Invoke(success, firebaseUser);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,16 @@ namespace Guru
 | 
			
		|||
{
 | 
			
		||||
    public partial class GuruSDK
 | 
			
		||||
    {
 | 
			
		||||
	    
 | 
			
		||||
	    /// <summary>
 | 
			
		||||
	    /// 打点优先级
 | 
			
		||||
	    /// </summary>
 | 
			
		||||
		public enum EventPriority
 | 
			
		||||
		{
 | 
			
		||||
			Emergence = 0,
 | 
			
		||||
			High = 5,
 | 
			
		||||
			Default = 10,
 | 
			
		||||
			Low = 15
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Consts values
 | 
			
		||||
| 
						 | 
				
			
			@ -210,7 +219,7 @@ namespace Guru
 | 
			
		|||
			public const string ATTOptIn = "att_opt_in";
 | 
			
		||||
			public const string ATTOpOut = "att_opt_out";
 | 
			
		||||
			public const string ParameterATTStatus = "att_status";
 | 
			
		||||
			public const string EventAttResult = "att_result";
 | 
			
		||||
			public const string EventATTResult = "att_result";
 | 
			
		||||
			
 | 
			
		||||
			// 用户属性
 | 
			
		||||
			public const string PropertyFirstOpenTime = "first_open_time"; 		//用户第一次first_open的时间
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@ namespace Guru
 | 
			
		|||
        private const string K_CMD_NAME_WATERMARK = "gurusdk.unity.wm";
 | 
			
		||||
        private const string K_CMD_NAME_CONSOLE = "gurusdk.unity.con";
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        #region Android 测试入口
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,6 +180,7 @@ namespace Guru
 | 
			
		|||
        /// <param name="success"></param>
 | 
			
		||||
        private static void OnBuyEnd(string productName, bool success)
 | 
			
		||||
        {
 | 
			
		||||
            if (success) Model.PurchasedCount++;
 | 
			
		||||
            InvokeOnPurchaseCallback?.Invoke(productName, success);
 | 
			
		||||
            Callbacks.IAP.InvokeOnPurchaseEnd(productName, success);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
 | 
			
		||||
namespace Guru
 | 
			
		||||
{
 | 
			
		||||
    public partial class GuruSDK
 | 
			
		||||
| 
						 | 
				
			
			@ -76,30 +75,29 @@ namespace Guru
 | 
			
		|||
        {
 | 
			
		||||
            Model.IsNoAds = value;
 | 
			
		||||
            ADService.Instance.IsBuyNoAds = value;
 | 
			
		||||
            if (value)
 | 
			
		||||
            {
 | 
			
		||||
                Analytics.SetIsIapUser(true);
 | 
			
		||||
            }
 | 
			
		||||
            SetUserProperty(Consts.PropertyNoAds, value? "true" : "false");
 | 
			
		||||
            if(value) SetUserIsIAP(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 所有成功的主线关卡数量 (b_level)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static int BLevel
 | 
			
		||||
        public static int SuccessLevelCount
 | 
			
		||||
        {
 | 
			
		||||
            get => GuruSDKModel.Instance.BLevel;
 | 
			
		||||
            set => GuruSDKModel.Instance.BLevel = value;
 | 
			
		||||
            get => GuruSDKModel.Instance.SuccessLevelId;
 | 
			
		||||
            set => GuruSDKModel.Instance.SuccessLevelId = value;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 成功关卡总计数量 (b_play)
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static int BPlay
 | 
			
		||||
        public static int TotalPlayedCount
 | 
			
		||||
        {
 | 
			
		||||
            get => GuruSDKModel.Instance.BPlay;
 | 
			
		||||
            set => GuruSDKModel.Instance.BPlay = value;
 | 
			
		||||
            get => GuruSDKModel.Instance.TotalPlayedCount;
 | 
			
		||||
            set => GuruSDKModel.Instance.TotalPlayedCount = value;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,21 +77,5 @@ namespace Guru
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Clear Data Cache
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 清除数据缓存
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static void ClearData()
 | 
			
		||||
        {
 | 
			
		||||
            Model.ClearData();
 | 
			
		||||
            GuruIAP.Instance.ClearData();
 | 
			
		||||
            PlayerPrefs.DeleteAll();
 | 
			
		||||
            PlayerPrefs.Save();
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #endregion
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,9 +4,9 @@ namespace Guru
 | 
			
		|||
    using System;
 | 
			
		||||
    using System.Collections;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.IO;
 | 
			
		||||
    using Debug = UnityEngine.Debug;
 | 
			
		||||
    using Guru.Network;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
    
 | 
			
		||||
    public partial class GuruSDK: MonoBehaviour
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,12 +78,6 @@ namespace Guru
 | 
			
		|||
        /// </summary>
 | 
			
		||||
        public static bool IsServiceReady { get; private set; } = false;
 | 
			
		||||
 | 
			
		||||
        private Firebase.Auth.FirebaseUser _firebaseUser;
 | 
			
		||||
        [Obsolete("获取 FirebaseUser 的属性接口即将废弃,请改用 <GuruSDK.Callbacks.SDK.OnFirebaseUserAuthResult += OnMyGetFirebaseUserCallback> 来异步获取该属性")]
 | 
			
		||||
        public static Firebase.Auth.FirebaseUser FirebaseUser => Instance?._firebaseUser ?? null; 
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
        #region 初始化
 | 
			
		||||
        
 | 
			
		||||
        private static GuruSDK CreateInstance()
 | 
			
		||||
| 
						 | 
				
			
			@ -95,15 +89,38 @@ namespace Guru
 | 
			
		|||
        }
 | 
			
		||||
        
 | 
			
		||||
        // TODO : 下个版本需要将 整个 GuruSDK 做功能性的拆分
 | 
			
		||||
        
 | 
			
		||||
        // GuruSDk.Callbacks -> GuruSDkCallbacks 所有的内置回调改为成员变量, 
 | 
			
		||||
        // 去掉所有的内部类, 去掉所有的 Static
 | 
			
		||||
        // Static 只用于常量
 | 
			
		||||
        // TODO: 下一个版本改为标准的 Builder 模式
 | 
			
		||||
        public static GuruSDKInitConfig BuildConfig(
 | 
			
		||||
            bool useCustomConsent = false, 
 | 
			
		||||
            bool autoLoadAds = true, 
 | 
			
		||||
            bool iapEnabled = true, 
 | 
			
		||||
            bool autoRecordFinishedLevels = true, 
 | 
			
		||||
            bool debugMode = false,
 | 
			
		||||
            bool isBuyNoAds = false,
 | 
			
		||||
            Action<string> onAdjustDeeplinkCallback = null,
 | 
			
		||||
            string bannerColor = "#00000000",
 | 
			
		||||
            Dictionary<string, object> defaultRemoteData = null,
 | 
			
		||||
            byte[] googleKeys = null,
 | 
			
		||||
            byte[] appleRootCerts = null,
 | 
			
		||||
            bool debugEnableEventLog = false)
 | 
			
		||||
        {
 | 
			
		||||
            var config = GuruSDKInitConfig.Build(useCustomConsent, autoLoadAds, iapEnabled, 
 | 
			
		||||
                autoRecordFinishedLevels, isBuyNoAds, bannerColor,
 | 
			
		||||
                debugMode, onAdjustDeeplinkCallback, defaultRemoteData, googleKeys, appleRootCerts, debugEnableEventLog);
 | 
			
		||||
            return config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void Init(Action<bool> onComplete)
 | 
			
		||||
        {
 | 
			
		||||
            Init(GuruSDKInitConfig.Builder().Build(), onComplete);
 | 
			
		||||
            Init(GuruSDKInitConfig.Build(), onComplete);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void Init(GuruSDKInitConfig config, Action<bool> onComplete)
 | 
			
		||||
        {
 | 
			
		||||
            _initTime = DateTime.UtcNow;
 | 
			
		||||
            _initTime = DateTime.Now.ToUniversalTime();
 | 
			
		||||
            // ----- First Open Time -----
 | 
			
		||||
            // SetFirstOpenTime(GetFirstOpenTime());  // FirstOpenTime 
 | 
			
		||||
            LogI($"#1 ---- Guru SDK [{Version}] ----\n{config}");
 | 
			
		||||
| 
						 | 
				
			
			@ -117,6 +134,9 @@ namespace Guru
 | 
			
		|||
        /// <param name="onComplete"></param>
 | 
			
		||||
        private void StartWithConfig(GuruSDKInitConfig config, Action<bool> onComplete)
 | 
			
		||||
        {
 | 
			
		||||
            Model.PropBLevel.OnValueChanged += OnBLevelChanged;
 | 
			
		||||
            Model.PropBPlay.OnValueChanged += OnBPlayChanged;
 | 
			
		||||
            
 | 
			
		||||
            IsInitialSuccess = false;
 | 
			
		||||
            _initConfig = config;
 | 
			
		||||
            _isDebugEnabled = config.DebugMode;
 | 
			
		||||
| 
						 | 
				
			
			@ -128,26 +148,19 @@ namespace Guru
 | 
			
		|||
            InitThreadHandler(); // 初始化线程处理器
 | 
			
		||||
            InitServices(); // 初始化所有的服务
 | 
			
		||||
            InitNetworkMonitor(); // 网络状态
 | 
			
		||||
            InitiallyUpdateUserProperties(); // 上报所有初始化用户属性
 | 
			
		||||
            
 | 
			
		||||
            onComplete?.Invoke(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void InitServices()
 | 
			
		||||
        {
 | 
			
		||||
            //---------- Start Analytics ------------
 | 
			
		||||
            LogI($"#1.1 ---- Init Analytics ----");
 | 
			
		||||
            // 初始化打点类
 | 
			
		||||
            Analytics.Init(); 
 | 
			
		||||
            // 从 Model 中注入打点属性初始值
 | 
			
		||||
            Analytics.SetFirstOpenTime(IPMConfig.FIRST_OPEN_TIME);
 | 
			
		||||
            Analytics.SetIsIapUser(Model.IsIapUser);
 | 
			
		||||
            // Analytics.SetBLevel(Model.BLevel);
 | 
			
		||||
            // Analytics.SetBPlay(Model.BPlay);
 | 
			
		||||
            
 | 
			
		||||
            Analytics.InitAnalytics(); // 打点提前初始化
 | 
			
		||||
            //---- Start All tools ----
 | 
			
		||||
            LogI($"#2 --- InitFirebase ---");
 | 
			
		||||
            //---------- Start Firebase ------------
 | 
			
		||||
            StartFirebaseService();
 | 
			
		||||
            
 | 
			
		||||
            LogI($"#2.1 --- InitFacebook ---");
 | 
			
		||||
            //---------- Start Facebook ------------
 | 
			
		||||
            FBService.Instance.StartService(Analytics.OnFBInitComplete);
 | 
			
		||||
| 
						 | 
				
			
			@ -155,19 +168,89 @@ namespace Guru
 | 
			
		|||
            IsInitialSuccess = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 启动 Firebase 服务
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void StartFirebaseService()
 | 
			
		||||
        {
 | 
			
		||||
            FirebaseUtil.onInitComplete += OnFirebaseReady;
 | 
			
		||||
            FirebaseUtil.OnUserAuthResult += OnUserAuthResult;
 | 
			
		||||
            FirebaseUtil.OnFirebaseAuthResult += OnFirebaseAuthResult;
 | 
			
		||||
            
 | 
			
		||||
            if (InitConfig.OnAdjustDeeplinkCallback != null)
 | 
			
		||||
            {
 | 
			
		||||
                //TODO: 下个版本 AdjustService 和 Firebase 解耦 
 | 
			
		||||
                FirebaseUtil.OnAdjustDeeplinkCallback = InitConfig.OnAdjustDeeplinkCallback; // 挂载 Deeplink 的回调 
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            FirebaseUtil.InitFirebase(Analytics.OnFirebaseInitCompleted); // 确保所有的逻辑提前被调用到
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnUserAuthResult(bool success)
 | 
			
		||||
        {
 | 
			
		||||
            
 | 
			
		||||
            if (success && string.IsNullOrEmpty(IPMConfig.IPM_UID))
 | 
			
		||||
            {
 | 
			
		||||
                success = false;
 | 
			
		||||
            }
 | 
			
		||||
            Callbacks.SDK.InvokeOnUserAuthResult(success);
 | 
			
		||||
 | 
			
		||||
            if (success)
 | 
			
		||||
            {
 | 
			
		||||
                Model.UserId = IPMConfig.IPM_UID;
 | 
			
		||||
                if (GuruIAP.Instance != null)
 | 
			
		||||
                {
 | 
			
		||||
                    GuruIAP.Instance.SetUID(UID);
 | 
			
		||||
                    GuruIAP.Instance.SetUUID(UUID);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                SetUID(UID);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void OnFirebaseAuthResult(bool success)
 | 
			
		||||
        {
 | 
			
		||||
            Callbacks.SDK.InvokeOnFirebaseAuthResult(success);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 开始各种组件初始化
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void OnFirebaseReady(bool success)
 | 
			
		||||
        {
 | 
			
		||||
            FirebaseUtil.onInitComplete -= OnFirebaseReady;
 | 
			
		||||
            LogI($"#3 --- On FirebaseDeps: {success} ---");
 | 
			
		||||
            IsFirebaseReady = success;
 | 
			
		||||
            Callbacks.SDK.InvokeOnFirebaseReady(success);
 | 
			
		||||
            // LogFirebaseDeps(success);
 | 
			
		||||
 | 
			
		||||
            LogI($"#3.5 --- Call InitRemoteConfig ---");
 | 
			
		||||
            // 开始Remote Manager初始化 
 | 
			
		||||
            RemoteConfigManager.Init(BuildDefaultRemoteData(_initConfig.DefaultRemoteData));
 | 
			
		||||
            RemoteConfigManager.OnFetchCompleted += OnFetchRemoteCallback;
 | 
			
		||||
 | 
			
		||||
            LogI($"#4 --- Apply remote services config ---");
 | 
			
		||||
            // 根据缓存的云控配置来初始化参数
 | 
			
		||||
            InitAllGuruServices();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 注入云控参数基础数据
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="dict"></param>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        private string LoadDefaultGuruServiceJson()
 | 
			
		||||
        private Dictionary<string, object> BuildDefaultRemoteData(Dictionary<string, object> dict)
 | 
			
		||||
        {
 | 
			
		||||
            // 加载本地 Services 配置值
 | 
			
		||||
            var txtAsset = Resources.Load<TextAsset>(ServicesConfigKey);
 | 
			
		||||
            if (txtAsset != null)
 | 
			
		||||
            {
 | 
			
		||||
                return txtAsset.text;
 | 
			
		||||
            }
 | 
			
		||||
            return "";
 | 
			
		||||
            if (dict == null) dict = new Dictionary<string, object>(3);
 | 
			
		||||
            
 | 
			
		||||
            // 注入默认的 Services 配置值
 | 
			
		||||
            string json = Model.LoadDefaltServicesConfigJson(); 
 | 
			
		||||
            if (!string.IsNullOrEmpty(json)) dict[ServicesConfigKey] = json;
 | 
			
		||||
       
 | 
			
		||||
            return dict;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -181,6 +264,8 @@ namespace Guru
 | 
			
		|||
            Callbacks.Remote.InvokeOnRemoteFetchComplete(success);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private void Update()
 | 
			
		||||
        {
 | 
			
		||||
            UpdateAllUpdates(); // 驱动所有的更新器
 | 
			
		||||
| 
						 | 
				
			
			@ -197,6 +282,7 @@ namespace Guru
 | 
			
		|||
        private void InitAllGuruServices()
 | 
			
		||||
        {
 | 
			
		||||
            // -------- Init Analytics ---------
 | 
			
		||||
            InitUserProperties();
 | 
			
		||||
            SetSDKEventPriority();
 | 
			
		||||
            // -------- Init Notification -----------
 | 
			
		||||
            InitNotiPermission();
 | 
			
		||||
| 
						 | 
				
			
			@ -290,9 +376,10 @@ namespace Guru
 | 
			
		|||
                    LogI($"#4.3 --- Start IAP ---");
 | 
			
		||||
                    if (_initConfig.GoogleKeys == null || _initConfig.AppleRootCerts == null)
 | 
			
		||||
                    {
 | 
			
		||||
                        LogEx("[IAP] GoogleKeys is null when using IAPService! Integration failed. App will Exit");
 | 
			
		||||
                        LogException("[IAP] GoogleKeys is null when using IAPService! Integration failed. App will Exit");
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    InitIAP(UID, _initConfig.GoogleKeys, _initConfig.AppleRootCerts); // 初始化IAP
 | 
			
		||||
                }, ex =>
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -306,7 +393,7 @@ namespace Guru
 | 
			
		|||
                Try(() =>
 | 
			
		||||
                {
 | 
			
		||||
                    LogI($"#4.4 --- Start Keywords ---");
 | 
			
		||||
                    KeywordsManager.Install(Model.IsIapUser, Model.BLevel); // 启动Keyword管理器
 | 
			
		||||
                    KeywordsManager.Install(Model.IsIapUser, Model.SuccessLevelId); // 启动Keyword管理器
 | 
			
		||||
                }, ex =>
 | 
			
		||||
                {
 | 
			
		||||
                    Debug.LogError($"--- ERROR on Keywords: {ex.Message}");
 | 
			
		||||
| 
						 | 
				
			
			@ -319,7 +406,7 @@ namespace Guru
 | 
			
		|||
                // StartAppleReviewFlow(); // 直接显示 ATT 弹窗, 跳过 Consent 流程
 | 
			
		||||
                Try(() =>
 | 
			
		||||
                {
 | 
			
		||||
                    LogI($"#4.5 ---  StartAppleReviewFlow ---");
 | 
			
		||||
                    LogI($"#4.5.0 ---  StartAppleReviewFlow ---");
 | 
			
		||||
                    StartAppleReviewFlow(); // 直接显示 ATT 弹窗, 跳过 Consent 流程
 | 
			
		||||
                }, ex =>
 | 
			
		||||
                {
 | 
			
		||||
| 
						 | 
				
			
			@ -331,23 +418,27 @@ namespace Guru
 | 
			
		|||
            //----------- Set Consent ----------------
 | 
			
		||||
            if (!InitConfig.UseCustomConsent && !appleReview)
 | 
			
		||||
            {
 | 
			
		||||
                LogI($"#4.6 --- Start Consent Flow ---");
 | 
			
		||||
                // LogI($"--- #3 Start Consent Flow ---");
 | 
			
		||||
                // StartConsentFlow();
 | 
			
		||||
                Try(StartConsentFlow, ex =>
 | 
			
		||||
                {
 | 
			
		||||
                    Debug.LogError($"--- ERROR on StartConsentFlow: {ex.Message}");
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
#if UNITY_ANDROID
 | 
			
		||||
            LogI($"#5.1 --- Android StartAndroidDebug Cmd lines---");
 | 
			
		||||
            // Android 命令行调试
 | 
			
		||||
            StartAndroidDebugCmds();           
 | 
			
		||||
#endif
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            IsServiceReady = true;
 | 
			
		||||
            
 | 
			
		||||
            // 中台服务初始化结束
 | 
			
		||||
            Callbacks.SDK.InvokeOnGuruServiceReady();
 | 
			
		||||
            
 | 
			
		||||
#if UNITY_ANDROID
 | 
			
		||||
            // Android 命令行调试
 | 
			
		||||
            StartAndroidDebugCmds();           
 | 
			
		||||
#endif
 | 
			
		||||
            
 | 
			
		||||
            LogI($"#5 --- sync sdk time ---");
 | 
			
		||||
            // TODO: 本调用放在这里不合适, 应该和 Firebase 解耦
 | 
			
		||||
            LogSDKInitTime((DateTime.Now.ToUniversalTime() - _initTime).TotalSeconds);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
| 
						 | 
				
			
			@ -394,7 +485,7 @@ namespace Guru
 | 
			
		|||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                LogEx(ex);
 | 
			
		||||
                LogException(ex);
 | 
			
		||||
                // ignored
 | 
			
		||||
                onException?.Invoke(ex);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -418,30 +509,44 @@ namespace Guru
 | 
			
		|||
#endif
 | 
			
		||||
        #endregion
 | 
			
		||||
        
 | 
			
		||||
        #region Logging
 | 
			
		||||
        #region 数据
 | 
			
		||||
 | 
			
		||||
        private static void LogI(object message)
 | 
			
		||||
        private void OnBLevelChanged(int bLevel)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserBLevel(bLevel);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnBPlayChanged(int bPlay)
 | 
			
		||||
        {
 | 
			
		||||
            SetUserBPlay(bPlay);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #endregion
 | 
			
		||||
        
 | 
			
		||||
        #region Logging
 | 
			
		||||
        
 | 
			
		||||
        internal static void LogI(object message)
 | 
			
		||||
        {
 | 
			
		||||
            Debug.Log($"{Tag} {message}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void LogW(object message)
 | 
			
		||||
        
 | 
			
		||||
        internal static void LogW(object message)
 | 
			
		||||
        {
 | 
			
		||||
            Debug.LogWarning($"{Tag} {message}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void LogE(object message)
 | 
			
		||||
        
 | 
			
		||||
        internal static void LogE(object message)
 | 
			
		||||
        {
 | 
			
		||||
            Debug.LogError($"{Tag} {message}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private static void LogEx(string message)
 | 
			
		||||
        
 | 
			
		||||
        internal static void LogException(string message)
 | 
			
		||||
        {
 | 
			
		||||
            LogEx( new Exception($"{Tag} {message}"));
 | 
			
		||||
            LogException( new Exception($"{Tag} {message}"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void LogEx(Exception e)
 | 
			
		||||
        
 | 
			
		||||
        internal static void LogException(Exception e)
 | 
			
		||||
        {
 | 
			
		||||
            Debug.LogException(e);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -666,178 +771,33 @@ namespace Guru
 | 
			
		|||
        {
 | 
			
		||||
           Callbacks.SDK.InvokeDeeplinkCallback(deeplink); // 尝试调用回调
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region 网络状态上报
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        private NetworkStatusMonitor _networkStatusMonitor;
 | 
			
		||||
        private string _lastNetworkStatus;
 | 
			
		||||
        private string _networkStatus;
 | 
			
		||||
        
 | 
			
		||||
        private void InitNetworkMonitor()
 | 
			
		||||
        {
 | 
			
		||||
            _networkStatusMonitor = new NetworkStatusMonitor(Analytics.SetNetworkStatus, 
 | 
			
		||||
                lastStatus =>
 | 
			
		||||
            {
 | 
			
		||||
                LogEvent("guru_offline", new Dictionary<string, dynamic>()
 | 
			
		||||
                {
 | 
			
		||||
                    ["from"] = lastStatus
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 获取当前的网络状态
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        private string GetNetworkStatus() => _networkStatusMonitor.GetNetworkStatus();
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Firebase 服务
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 启动 Firebase 服务
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void StartFirebaseService()
 | 
			
		||||
        {
 | 
			
		||||
            FirebaseUtil.Init(OnFirebaseDepsCheckResult, 
 | 
			
		||||
                OnGetFirebaseId, 
 | 
			
		||||
                OnGetGuruUID, 
 | 
			
		||||
                OnFirebaseLoginResult); // 确保所有的逻辑提前被调用到
 | 
			
		||||
            // SetUserProperty(Consts.PropertyNetwork, GetNetworkStatus());
 | 
			
		||||
            // TODO: 下个版本加入真正的自动更新网络状态的实现
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void OnGetGuruUID(bool success)
 | 
			
		||||
        private string GetNetworkStatus()
 | 
			
		||||
        {
 | 
			
		||||
            if (success)
 | 
			
		||||
            if(_networkStatusMonitor == null)
 | 
			
		||||
            {
 | 
			
		||||
                Model.UserId = IPMConfig.IPM_UID;
 | 
			
		||||
                if (GuruIAP.Instance != null)
 | 
			
		||||
                {
 | 
			
		||||
                    GuruIAP.Instance.SetUID(UID);
 | 
			
		||||
                    GuruIAP.Instance.SetUUID(UUID);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // 自打点设置用户 ID
 | 
			
		||||
                Analytics.SetUid(UID);
 | 
			
		||||
                // Crashlytics 设置 uid
 | 
			
		||||
                CrashlyticsAgent.SetUserId(UID);
 | 
			
		||||
                // 上报所有的事件
 | 
			
		||||
                Analytics.ShouldFlushGuruEvents();
 | 
			
		||||
                _networkStatusMonitor = new NetworkStatusMonitor();
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            Callbacks.SDK.InvokeOnGuruUserAuthResult(success);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        private void OnGetFirebaseId(string fid)
 | 
			
		||||
        {
 | 
			
		||||
            // 初始化 Adjust 服务
 | 
			
		||||
            InitAdjustService(fid, InitConfig.OnAdjustDeeplinkCallback);
 | 
			
		||||
            // 初始化自打点
 | 
			
		||||
            Analytics.InitGuruAnalyticService(fid);
 | 
			
		||||
            
 | 
			
		||||
            //---------- Event SDK Info ------------
 | 
			
		||||
            LogI($"#6.0 --- SDK is ready, report Info ---");
 | 
			
		||||
            LogSDKInfo((DateTime.UtcNow - _initTime).TotalSeconds);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // TODO: 需要之后用宏隔离应用和实现
 | 
			
		||||
        // Auth 登录认证
 | 
			
		||||
        private void OnFirebaseLoginResult(bool success, Firebase.Auth.FirebaseUser firebaseUser)
 | 
			
		||||
        {
 | 
			
		||||
            _firebaseUser = firebaseUser;
 | 
			
		||||
            Callbacks.SDK.InvokeOnFirebaseAuthResult(success, firebaseUser);
 | 
			
		||||
            return _networkStatusMonitor.GetNetworkStatus();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 开始各种组件初始化
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private void OnFirebaseDepsCheckResult(bool success)
 | 
			
		||||
        {
 | 
			
		||||
            LogI($"#3 --- On FirebaseDeps: {success} ---");
 | 
			
		||||
            IsFirebaseReady = success;
 | 
			
		||||
            Callbacks.SDK.InvokeOnFirebaseReady(success);
 | 
			
		||||
 | 
			
		||||
            Analytics.OnFirebaseInitCompleted();
 | 
			
		||||
 | 
			
		||||
            LogI($"#3.5 --- Call InitRemoteConfig ---");
 | 
			
		||||
            // 开始Remote Manager初始化 
 | 
			
		||||
            
 | 
			
		||||
            var defaultGuruServiceJson = LoadDefaultGuruServiceJson();
 | 
			
		||||
 | 
			
		||||
            var dict = _initConfig.DefaultRemoteData.ToDictionary(
 | 
			
		||||
                entry => entry.Key,
 | 
			
		||||
                entry => entry.Value);
 | 
			
		||||
            
 | 
			
		||||
            if (!string.IsNullOrEmpty(defaultGuruServiceJson))
 | 
			
		||||
            {
 | 
			
		||||
                dict[ServicesConfigKey] = defaultGuruServiceJson;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            RemoteConfigManager.Init(dict);
 | 
			
		||||
            RemoteConfigManager.OnFetchCompleted += OnFetchRemoteCallback;
 | 
			
		||||
 | 
			
		||||
            LogI($"#4 --- Apply remote services config ---");
 | 
			
		||||
            // 根据缓存的云控配置来初始化参数
 | 
			
		||||
            InitAllGuruServices();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
        		
 | 
			
		||||
        #region Adjust服务
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// 启动 Adjust 服务
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static void InitAdjustService(string firebaseId, Action<string> onDeeplinkCallback = null)
 | 
			
		||||
        {
 | 
			
		||||
            // 启动 AdjustService
 | 
			
		||||
            string appToken = GuruSettings.Instance.AdjustSetting?.GetAppToken() ?? "";
 | 
			
		||||
            string fbAppId = GuruSettings.Instance.IPMSetting.FacebookAppId;
 | 
			
		||||
 | 
			
		||||
            // if (!string.IsNullOrEmpty(IPMConfig.ADJUST_ID))
 | 
			
		||||
            //     Analytics.SetAdjustId(IPMConfig.ADJUST_ID); // 二次启动后,若有值则立即上报属性
 | 
			
		||||
            
 | 
			
		||||
            AdjustService.Instance.Start(appToken, fbAppId, firebaseId, DeviceId,
 | 
			
		||||
                OnAdjustInitComplete, onDeeplinkCallback ,OnGetGoogleAdId );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Adjust 初始化结束
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="adjustId"></param>
 | 
			
		||||
        /// <param name="idfv"></param>
 | 
			
		||||
        /// <param name="idfa"></param>
 | 
			
		||||
        private static void OnAdjustInitComplete(string adjustId, string idfv, string idfa)
 | 
			
		||||
        {
 | 
			
		||||
            Debug.Log($"{Tag} --- OnAdjustInitComplete:  adjustId:{adjustId}  idfv:{idfv}  idfa:{idfa}");
 | 
			
		||||
            
 | 
			
		||||
            // 获取 ADID 
 | 
			
		||||
            if (string.IsNullOrEmpty(adjustId)) adjustId = "not_set";
 | 
			
		||||
            if (string.IsNullOrEmpty(idfv)) idfv = "not_set";
 | 
			
		||||
            if (string.IsNullOrEmpty(idfa)) idfa = "not_set";
 | 
			
		||||
            
 | 
			
		||||
            IPMConfig.ADJUST_ID = adjustId;
 | 
			
		||||
            IPMConfig.ADJUST_IDFV = idfv;
 | 
			
		||||
            IPMConfig.ADJUST_IDFA = idfa;
 | 
			
		||||
            
 | 
			
		||||
            Analytics.SetAdjustId(adjustId);
 | 
			
		||||
            Analytics.SetIDFV(idfv);
 | 
			
		||||
            Analytics.SetIDFA(idfa);
 | 
			
		||||
            Analytics.OnAdjustInitComplete();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void OnGetGoogleAdId(string googleAdId)
 | 
			
		||||
        {
 | 
			
		||||
            Debug.Log($"{Tag} --- OnGetGoogleAdId: {googleAdId}");
 | 
			
		||||
            // IPMConfig.ADJUST_GOOGLE_ADID = googleAdId;
 | 
			
		||||
            Analytics.SetGoogleAdId(googleAdId);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
       
 | 
			
		||||
        #endregion
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue