com.amanotes.gdk 0.2.62 → 0.2.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/Editor/AmaGDKEditor.cs +23 -7
  3. package/Editor/HideInNormalInspectorDrawer.cs +22 -0
  4. package/Editor/HideInNormalInspectorDrawer.cs.meta +3 -0
  5. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  6. package/Extra/CheckDiskSpace.unitypackage +0 -0
  7. package/Extra/ForceUpdate.unitypackage +0 -0
  8. package/Extra/PostProcessor.unitypackage +0 -0
  9. package/Extra/SDKVersionTracking.unitypackage +0 -0
  10. package/Packages/AmaGDKConfig.unitypackage +0 -0
  11. package/Packages/AmaGDKExample.unitypackage +0 -0
  12. package/Packages/AmaGDKTest.unitypackage +0 -0
  13. package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
  14. package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage.meta +7 -0
  15. package/Packages/AppsFlyerAdapter.unitypackage +0 -0
  16. package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
  17. package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
  18. package/Packages/IronSourceAdapter.unitypackage +0 -0
  19. package/Packages/RevenueCatAdapter.unitypackage +0 -0
  20. package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
  21. package/Runtime/AmaGDK.Adapters.cs +13 -2
  22. package/Runtime/AmaGDK.Ads.cs +36 -12
  23. package/Runtime/AmaGDK.Analytics.cs +8 -18
  24. package/Runtime/AmaGDK.RemoteConfig.cs +6 -2
  25. package/Runtime/AmaGDK.UserProfile.cs +118 -38
  26. package/Runtime/AmaGDK.cs +32 -5
  27. package/Runtime/Internal/AmaGDK.Internal.AmaGUI.cs +19 -2
  28. package/Runtime/Internal/AmaGDK.Internal.SemVer.cs +26 -2
  29. package/Runtime/Internal/AmaGDK.Internal.cs +1 -1
  30. package/Runtime/Internal/AmaGDK.Utils.cs +5 -1
  31. package/Runtime/Internal/HideInNormalInspectorAttribute.cs +9 -0
  32. package/Runtime/Internal/HideInNormalInspectorAttribute.cs.meta +3 -0
  33. package/Runtime/Klavar/Attributes/AccumulatedCountAttribute.cs +1 -0
  34. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.64 - 2024-06-06]
4
+ - [Dev] Log gdk_init
5
+ - [Fix] map_user_id must contain FRB, AF, [GAID, IDFA]
6
+ - [Dev] Check duplicated SKAdNetwork
7
+ - [Dev] New editor attribute [HideInNormalInspector]
8
+ - [Dev] Public ClearCacheData method
9
+ - [Feature] Add adapter config validation
10
+ - [Feature] Add DevMode for remote config fetching
11
+ - [Fix] Create button did not create a new AmaGDKConfig asset in Resources
12
+ - Also: Hide config details
13
+ - [Feature] Support AF Purchase Connector and deeplinking
14
+
15
+ ## [0.2.63 - 2024-06-01]
16
+ - [Fix] Do not include default GDK config asset
17
+ - [Fix] Support compare SemVer with an invalid value
18
+ - [Dev] Add ShowBanner/ HideBanner buttons to AmaGDKExample
19
+ - [Fix] Silent null exception when embedRemoteConfig == null (in Editor)
20
+ - [Dev] Improve banner loading with load failed handler (retry or skip)
21
+ - [Fix] Wrong condition flag for Banner enabled check
22
+ - [Dev] Upgrade Firebase 11.8.0, IronSource 7.9.1, GoogleMobileAds 9.0.0
23
+ - - Fix AppsFlyer error in iOS: Type specifier missing, defaults to ???int???
24
+ - - Min iOS 13.0
25
+ - [Klavar] Parse Klavar structure v0.3
26
+
3
27
  ## [0.2.62 - 2024-05-27]
4
28
  - [Dev] Remove pipeline for unity 2020
5
29
  - [Dev] Dispatch changes / support callback for when UserId updated
@@ -100,6 +100,11 @@ namespace Amanotes.Editor
100
100
  if (AmaGUI.BigButton("CREATE", 40f, BLUE))
101
101
  {
102
102
  AssetDatabase.ImportPackage(Res.AMAGDK_CONFIG_PACKAGE, false);
103
+
104
+ ScriptableObject config = CreateInstance("Amanotes.Core.AmaGDKConfigAsset");
105
+ AssetDatabase.CreateAsset(config, "Assets/AmaGDK/Resources/AmaGDKConfig.asset");
106
+ AssetDatabase.SaveAssets();
107
+ TryLoadConfigAsset();
103
108
  adapterScanned = false;
104
109
  }
105
110
 
@@ -301,17 +306,16 @@ namespace Amanotes.Editor
301
306
 
302
307
  configSO = new SerializedObject(configAsset);
303
308
  configSO.Update();
304
-
305
309
  DrawProperty(configSO, "common");
310
+ EditorGUILayout.ObjectField("Config", configAsset, typeof(ScriptableObject), false);
306
311
  GUILayout.Space(8f);
307
312
  for (var i = 0; i < allAdapters.Count; i++)
308
313
  {
309
314
  var item = allAdapters[i];
310
315
  DrawAdapterDetail(item.id, item.adapter);
311
316
  }
312
-
313
317
  EditorGUILayout.Space();
314
- AmaGUI.Foldout("Config", ref showConfigDetail, DrawGUI_ConfigDetail, DrawGUI_ConfigAsset);
318
+
315
319
  AmaGUI.Foldout("Adapters", ref showAdapterInstaller, DrawGUI_AdapterList);
316
320
  AmaGUI.Foldout("Extras", ref showExtra, DrawGUI_ExtraList);
317
321
  Profiler.EndSample();
@@ -370,6 +374,11 @@ namespace Amanotes.Editor
370
374
  configOpen.Add(adapterId, isOpen = false);
371
375
  }
372
376
 
377
+ var configStatus = adapter?.configStatus ?? Adapter2.ConfigStatus.Ok;
378
+ Texture2D icon =
379
+ configStatus == Adapter2.ConfigStatus.Invalid ? (Texture2D)EditorGUIUtility.IconContent("console.erroricon.sml").image :
380
+ configStatus == Adapter2.ConfigStatus.Warning ? (Texture2D)EditorGUIUtility.IconContent("console.warnicon.sml").image : null;
381
+
373
382
  SDKStatus status = SDKStatus.Get(adapterId);
374
383
  bool changed = AmaGUI.Foldout(ObjectNames.NicifyVariableName(adapterId), ref isOpen, () =>
375
384
  {
@@ -392,10 +401,17 @@ namespace Amanotes.Editor
392
401
 
393
402
  }, () =>
394
403
  {
404
+ if (icon != null)
405
+ {
406
+ Rect rect = GUILayoutUtility.GetRect(6f, 6f, 16f, 16f);
407
+ rect.xMin -= 10f;
408
+ rect.y += 1f;
409
+ GUI.DrawTexture(rect, icon);
410
+ }
395
411
  GUILayout.FlexibleSpace();
396
-
412
+
397
413
  bool installed = status.adapterInstalled;
398
- bool adapterActive = installed && adapter.enabled;
414
+ bool adapterActive = installed && adapter != null && adapter.enabled;
399
415
 
400
416
  if (!adapterActive)
401
417
  {
@@ -407,7 +423,7 @@ namespace Amanotes.Editor
407
423
  GUILayout.Label(label, GUILayout.Width(w));
408
424
  GUI.color = c;
409
425
  }
410
-
426
+
411
427
  AmaGUI.DrawVersionTag(status.sdkVersion, adapterActive);
412
428
 
413
429
  if (installed)
@@ -421,7 +437,7 @@ namespace Amanotes.Editor
421
437
  }
422
438
  }
423
439
  });
424
-
440
+
425
441
 
426
442
 
427
443
  if (changed) configOpen[adapterId] = isOpen;
@@ -0,0 +1,22 @@
1
+ using UnityEngine;
2
+ using UnityEngine.UIElements;
3
+ using UnityEditor;
4
+
5
+ namespace Amanotes.Core.Editor
6
+ {
7
+ [CustomPropertyDrawer(typeof(HideInNormalInspectorAttribute))]
8
+ public class HideInNormalInspectorDrawer : PropertyDrawer
9
+ {
10
+ public override VisualElement CreatePropertyGUI(SerializedProperty property)
11
+ {
12
+ var mode = ActiveEditorTracker.sharedTracker.inspectorMode;
13
+ return mode == InspectorMode.Normal ? new VisualElement() : base.CreatePropertyGUI(property);
14
+ }
15
+
16
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
17
+ return 0f;
18
+ }
19
+
20
+ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {}
21
+ }
22
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 66d88278f0e44820aebc1e5a5e94e15f
3
+ timeCreated: 1717409948
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: d0d621a4b24af4e399401664334f0d2c
3
+ DefaultImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -6,16 +6,27 @@ using static Amanotes.Core.Internal.Logging;
6
6
 
7
7
  namespace Amanotes.Core.Internal
8
8
  {
9
+
10
+
9
11
  public abstract partial class Adapter2
10
12
  {
13
+ internal protected enum ConfigStatus
14
+ {
15
+ Ok,
16
+ Invalid,
17
+ Warning
18
+ }
19
+
11
20
  // internal use
12
- [HideInInspector] [SerializeField] internal int initOrder;
13
- [HideInInspector] [SerializeField] internal bool enabled = true;
21
+ [HideInNormalInspector] [SerializeField] internal int initOrder;
22
+ [HideInNormalInspector] [SerializeField] internal bool enabled = true;
14
23
  [NonSerialized] internal string adapterId;
15
24
  [NonSerialized] internal string adapterVersion;
16
25
  [NonSerialized] internal protected Status status = Status.None;
17
26
 
18
27
  protected abstract void Init(Action<bool> onComplete);
28
+ internal protected abstract string GetServiceKey();
29
+ internal protected abstract ConfigStatus configStatus { get; }
19
30
 
20
31
  public bool IsReady => status == Status.Ready;
21
32
 
@@ -321,23 +321,37 @@ namespace Amanotes.Core
321
321
  public static bool IsRewardedVideoShowing => (context != null) && (context.adType == AdType.VideoReward);
322
322
 
323
323
 
324
- private static bool _isBannerShowing;
324
+ [NonSerialized] private static bool _isBannerShowing = false;
325
325
 
326
326
  public static void ShowBanner()
327
327
  {
328
- if (_config.ad.enableBanner) return;
328
+ if (!_config.ad.enableBanner)
329
+ {
330
+ LogWarning($"Banner not enabled! {_config.ad.enableBanner}");
331
+ return;
332
+ }
333
+
334
+ if (_isBannerShowing)
335
+ {
336
+ LogWarning($"Banner is showing!");
337
+ return;
338
+ }
329
339
 
330
- if (_isBannerShowing) return;
331
340
  _isBannerShowing = true;
332
- if (_adapter == null) return;
341
+
342
+ if (_adapter == null)
343
+ {
344
+ LogWarning($"Adapter is null!");
345
+ return;
346
+ }
333
347
 
334
348
  dispatcher.Dispatch(Event.BANNER_SHOW);
335
- _adapter.ShowBanner();
349
+ _adapter.ShowBanner();
336
350
  }
337
351
 
338
352
  public static void HideBanner()
339
353
  {
340
- if (_config.ad.enableBanner) return;
354
+ if (!_config.ad.enableBanner) return;
341
355
  if (!_isBannerShowing) return;
342
356
  _isBannerShowing = false;
343
357
  if (_adapter == null) return;
@@ -402,9 +416,9 @@ namespace Amanotes.Core.Internal
402
416
  [Tooltip("When an ad is not ready to show, verify that there is an internet connection by ping the internet check URL .\nIf there is no internet connection, we will not need to wait for adShowTimeout secs")]
403
417
  public bool checkInternet = true;
404
418
 
405
- [HideInInspector] public bool enableInterstitial = true;
406
- [HideInInspector] public bool enableRewarded = true;
407
- [HideInInspector] public bool enableBanner = true;
419
+ [NonSerialized] public bool enableInterstitial = true;
420
+ [NonSerialized] public bool enableRewarded = true;
421
+ [NonSerialized] public bool enableBanner = true;
408
422
 
409
423
  [Tooltip("Before showing an ad: set AudioListener.volume to 0\nAfter the ad is closed: restore the previously saved AudioListener.volume")]
410
424
  public bool autoMute = true;
@@ -929,7 +943,15 @@ namespace Amanotes.Core.Internal
929
943
  protected void OnAdShowFailed()
930
944
  {
931
945
  Log($"[Ad] {adType} OnAdShowFailed");
932
-
946
+
947
+ // 509 Show Fail: No ads to show
948
+ // 520 Show Fail: No internet connection; ShouldTrackNetworkState is enabled
949
+ // 524 Show Fail: Placement %@ has reached its limit as defined per pace
950
+ // 526 Show Fail: Ad unit has reached its daily cap per session
951
+ // 1022 Show Fail: Cannot show an RV while another RV is showing
952
+ // 1023 Show Fail: Show RV called when there are no available ads to show
953
+ // 1036 Show Fail: Cannot show an while another is showing
954
+
933
955
  if (Ads.context != null)
934
956
  {
935
957
  Ads.context.adCallback |= AdCallback.Fail;
@@ -1014,10 +1036,12 @@ namespace Amanotes.Core.Internal
1014
1036
  {
1015
1037
  LogWarning("[Ad] Something wrong? OnAdReady called when no ad is loading! AdType=" + adType);
1016
1038
  }
1017
-
1039
+
1018
1040
  _isRequesting = false;
1019
1041
  }
1020
-
1042
+
1043
+
1044
+
1021
1045
  protected void OnAdLoadFailed(string error)
1022
1046
  {
1023
1047
  Log($"[Ad] {adType} OnAdLoadFailed: {error}");
@@ -160,14 +160,6 @@ namespace Amanotes.Core
160
160
  logEventHook = condition;
161
161
  }
162
162
 
163
- public static void SetUserId(string userId)
164
- {
165
- foreach (AnalyticsAdapter s in listAdapters)
166
- {
167
- s.SetUserId(userId);
168
- }
169
- }
170
-
171
163
  public static void SetUserProperty(string key, string value)
172
164
  {
173
165
  foreach (AnalyticsAdapter s in listAdapters)
@@ -1104,11 +1096,11 @@ namespace Amanotes.Core.Internal
1104
1096
  {
1105
1097
  // [Header("----- MODULE CONFIG -----")]
1106
1098
  public bool showAnalyticsLog;
1107
- [HideInInspector] public bool normalizeEventName = true;
1108
- [HideInInspector] public bool checkMigrationIntegrity = true;
1109
- [HideInInspector] public bool migrateAccumulatedCount = true;
1110
- [HideInInspector] public bool enableEventStat;
1111
- [HideInInspector] public List<string> immediatelyLoggedEvents = new List<string>(){"ad_impression", "ad_impression_ama"};
1099
+ [HideInNormalInspector] public bool normalizeEventName = true;
1100
+ [HideInNormalInspector] public bool checkMigrationIntegrity = true;
1101
+ [HideInNormalInspector] public bool migrateAccumulatedCount = true;
1102
+ [HideInNormalInspector] public bool enableEventStat;
1103
+ [HideInNormalInspector] public List<string> immediatelyLoggedEvents = new List<string>(){"ad_impression", "ad_impression_ama"};
1112
1104
  public AnalyticQualityConfig quality;
1113
1105
  }
1114
1106
 
@@ -1134,8 +1126,8 @@ namespace Amanotes.Core.Internal
1134
1126
 
1135
1127
  public abstract class AnalyticsAdapter : Adapter2
1136
1128
  {
1137
- [HideInInspector] public List<string> NeverSend = new List<string>();
1138
- [HideInInspector] public List<string> AlwaysSend = new List<string>();
1129
+ [HideInNormalInspector] public List<string> NeverSend = new List<string>();
1130
+ [HideInNormalInspector] public List<string> AlwaysSend = new List<string>();
1139
1131
  protected abstract bool SendEventByDefault { get; }
1140
1132
 
1141
1133
  public bool IsForbidden(string eventName)
@@ -1147,10 +1139,8 @@ namespace Amanotes.Core.Internal
1147
1139
 
1148
1140
  public abstract void LogEvent(string eventNameToSend, Dictionary<string, object> parameters);
1149
1141
 
1150
- public abstract void SetUserId(string userId);
1142
+ // public abstract void SetUserId(string userId);
1151
1143
 
1152
1144
  public abstract void SetUserProperty(string key, string value);
1153
-
1154
- public abstract void GetAppInstanceID(Action<string> appId);
1155
1145
  }
1156
1146
  }
@@ -5,6 +5,7 @@ using System.Text;
5
5
  using UnityEngine;
6
6
  using Amanotes.Core.Internal;
7
7
  using UnityEngine.Profiling;
8
+ using UnityEngine.Serialization;
8
9
  using static Amanotes.Core.Internal.Logging;
9
10
 
10
11
  #if UNITY_EDITOR
@@ -69,11 +70,12 @@ namespace Amanotes.Core
69
70
 
70
71
  public static T Get<T>(string key, T defaultValue = default(T))
71
72
  {
73
+ var embed = Config.remoteConfig.embedRemoteConfig;
72
74
  #if UNITY_EDITOR
73
75
  //Override value in editor environment
74
- if (Config.remoteConfig.embedRemoteConfig.overrideInEditor)
76
+ if (embed != null && embed.overrideInEditor)
75
77
  {
76
- foreach (var c in Config.remoteConfig.embedRemoteConfig.overrideConfig)
78
+ foreach (var c in embed.overrideConfig)
77
79
  if (c.key == key)
78
80
  return (T)Convert.ChangeType(c.value, typeof(T));
79
81
  }
@@ -368,9 +370,11 @@ namespace Amanotes.Core.Internal
368
370
  [Serializable]
369
371
  public class RemoteConfigConfig
370
372
  {
373
+ [FormerlySerializedAs("firstFetchTimeOutInSeconds")]
371
374
  [Tooltip("Fetch timeout for first session (in secs)")]
372
375
  public float firstFetchTimeOutInSeconds = 10;
373
376
 
377
+ [FormerlySerializedAs("defaultTimeOutInSeconds")]
374
378
  [Tooltip("Fetch timeout for 2nd+ session (in secs)")]
375
379
  public float defaultTimeOutInSeconds = 3;
376
380
 
@@ -72,83 +72,152 @@ namespace Amanotes.Core
72
72
  _userId = value;
73
73
  Logging.Log($"GDK UserID Updated: {_userId}");
74
74
  dispatcher.Dispatch(Event.GDK_USER_ID_UPDATED, _userId);
75
- Save();
75
+ _dirty = true;
76
+ if (isReady) SendMapUserId();
76
77
  }
77
78
  }
78
79
 
79
80
  public string GAId
80
81
  {
81
82
  get => _gaid;
82
- set => _gaid = ValidateId(value, ALPHANUMERIC_HYPHEN_PATTERN);
83
+ set
84
+ {
85
+ if (!ValidateId(value, ALPHANUMERIC_HYPHEN_PATTERN))
86
+ {
87
+ Logging.LogError($"[UserProfile] Wrong format for GAId. Value: {value}");
88
+ return;
89
+ }
90
+ _gaid = value;
91
+ UpdateUserId();
92
+ }
83
93
  }
84
94
 
85
95
  public string IDFA
86
96
  {
87
97
  get => _idfa;
88
- set => _idfa = ValidateId(value, ALPHANUMERIC_HYPHEN_PATTERN);
98
+ set
99
+ {
100
+ if (!ValidateId(value, ALPHANUMERIC_HYPHEN_PATTERN))
101
+ {
102
+ Logging.LogError($"[UserProfile] Wrong format for IDFA. Value: {value}");
103
+ return;
104
+ }
105
+ _idfa = value;
106
+ UpdateUserId();
107
+ }
89
108
  }
90
-
109
+
91
110
  public string IDFV
92
111
  {
93
112
  get => _idfv;
94
- set => _idfv = ValidateId(value, ALPHANUMERIC_HYPHEN_PATTERN);
113
+ set
114
+ {
115
+ if (!ValidateId(value, ALPHANUMERIC_HYPHEN_PATTERN))
116
+ {
117
+ Logging.LogError($"[UserProfile] Wrong format for IDFV. Value: {value}");
118
+ return;
119
+ }
120
+ _idfv = value;
121
+ UpdateUserId();
122
+ }
95
123
  }
96
-
124
+
97
125
  public string AndroidId
98
126
  {
99
127
  get => _androidId;
100
- set => _androidId = ValidateId(value, ALPHANUMERIC_PATTERN);
128
+ set
129
+ {
130
+ if (!ValidateId(value, ALPHANUMERIC_PATTERN))
131
+ {
132
+ Logging.LogError($"[UserProfile] Wrong format for AndroidId. Value: {value}");
133
+ return;
134
+ }
135
+ _androidId = value;
136
+ UpdateUserId();
137
+ }
101
138
  }
102
-
139
+
103
140
  public string PseudoId
104
141
  {
105
142
  get => _pseudoId;
106
- set => _pseudoId = ValidateId(value, ALPHANUMERIC_PATTERN);
143
+ set
144
+ {
145
+ if (!ValidateId(value, ALPHANUMERIC_PATTERN))
146
+ {
147
+ Logging.LogError($"[UserProfile] Wrong format for PseudoId. Value: {value}");
148
+ return;
149
+ }
150
+ _pseudoId = value;
151
+ UpdateUserId();
152
+ }
107
153
  }
108
154
 
109
- #if UNITY_ANDROID && !UNITY_EDITOR
110
155
  public string AmaDeviceId
111
156
  {
112
157
  get => _amaDeviceId;
113
- set => _amaDeviceId = ValidateId(value, ALPHANUMERIC_PATTERN);
114
- }
115
- #else
116
- public string AmaDeviceId
117
- {
118
- get => _amaDeviceId;
119
- set => _amaDeviceId = ValidateId(value, ALPHANUMERIC_HYPHEN_PATTERN);
158
+ set
159
+ {
160
+ var pattern = ALPHANUMERIC_HYPHEN_PATTERN;
161
+ #if UNITY_ANDROID && !UNITY_EDITOR
162
+ pattern = ALPHANUMERIC_PATTERN;
163
+ #endif
164
+ if (!ValidateId(value, pattern))
165
+ {
166
+ Logging.LogError($"[UserProfile] Wrong format for AmaDeviceId. Value: {value}");
167
+ return;
168
+ }
169
+ _amaDeviceId = value;
170
+ UpdateUserId();
171
+ }
120
172
  }
121
- #endif
173
+
122
174
 
123
175
  public string AppsFlyerId
124
176
  {
125
177
  get => _appsFlyerId;
126
- set => _appsFlyerId = ValidateId(value, NUMERIC_HYPHEN_PATTERN);
178
+ set
179
+ {
180
+ if (!Application.isEditor && !ValidateId(value, NUMERIC_HYPHEN_PATTERN))
181
+ {
182
+ Logging.LogError($"[UserProfile] Wrong format for AppsFlyerId. Value: {value}");
183
+ return;
184
+ }
185
+ _appsFlyerId = value;
186
+ UpdateUserId();
187
+ }
127
188
  }
128
-
189
+
129
190
  public string InstallationId
130
191
  {
131
192
  get => _installationId;
132
- set => _installationId = ValidateId(value, ALPHANUMERIC_PATTERN);
193
+ set
194
+ {
195
+ if (!ValidateId(value, ALPHANUMERIC_PATTERN))
196
+ {
197
+ Logging.LogError($"[UserProfile] Wrong format for InstallationId. Value: {value}");
198
+ return;
199
+ }
200
+ _installationId = value;
201
+ UpdateUserId();
202
+ }
133
203
  }
134
204
 
135
- public int Session
136
- {
137
- get => _session;
138
- }
205
+ public int Session => _session;
139
206
 
140
207
  public string Country
141
208
  {
142
209
  get => _country;
143
210
  set
144
211
  {
145
- _country = ValidateId(value, COUNTRY_CODE_PATTERN);
146
- SaveIfDirty();
212
+ if (!ValidateId(value, COUNTRY_CODE_PATTERN)) return;
213
+ _country = value;
214
+ _dirty = true;
147
215
  }
148
216
  }
149
217
 
150
- public void UpdateUserId()
218
+ private void UpdateUserId()
151
219
  {
220
+ _dirty = true;
152
221
  #if UNITY_ANDROID
153
222
  if (!string.IsNullOrWhiteSpace(_gaid))
154
223
  {
@@ -241,14 +310,14 @@ namespace Amanotes.Core
241
310
  {
242
311
  User.LoadJsonFromFile();
243
312
 
244
- #if UNITY_ANDROID
313
+ #if UNITY_ANDROID && !UNITY_EDITOR
245
314
  AndroidId = SystemInfo.deviceUniqueIdentifier;
246
315
  #elif UNITY_IOS
247
316
  IDFV = SystemInfo.deviceUniqueIdentifier;
248
317
  #endif
249
318
  GetAmaDeviceId();
250
319
  UpdateUserId();
251
- _session = _session + 1;
320
+ _session += 1;
252
321
  _dirty = true;
253
322
  }
254
323
 
@@ -259,6 +328,19 @@ namespace Amanotes.Core
259
328
  Logging.Log($"[UserProfile] user_id: {_userId}");
260
329
  onFrameUpdate -= SaveIfDirty;
261
330
  onFrameUpdate += SaveIfDirty;
331
+
332
+ var adsId = Application.platform == RuntimePlatform.Android ? GAId : IDFA;
333
+ var delay = string.IsNullOrEmpty(AppsFlyerId)
334
+ || string.IsNullOrEmpty(adsId)
335
+ || string.IsNullOrEmpty(PseudoId);
336
+
337
+ GDKUtils.DelayCall(delay ? 1 : 0, SendMapUserId);
338
+ }
339
+
340
+ private void SendMapUserId()
341
+ {
342
+ Analytics.LogEvent("map_user_id", AmaGDK.User.CollectAllUserIds())
343
+ .OnlyTo(AmaGDK.AdapterID.FIREBASE_ANALYTICS);
262
344
  }
263
345
 
264
346
  private void SetAdvertisingID(string id)
@@ -280,8 +362,7 @@ namespace Amanotes.Core
280
362
  {
281
363
  GDKUtils.DelayCall(0, () =>
282
364
  {
283
- SetAdvertisingID(advertisingId);
284
- Save();
365
+ SetAdvertisingID(advertisingId);
285
366
  });
286
367
  });
287
368
  }
@@ -292,7 +373,7 @@ namespace Amanotes.Core
292
373
  switch (Application.platform)
293
374
  {
294
375
  case RuntimePlatform.IPhonePlayer:
295
- string v = KeyChain.GetKeyChain(AMA_DEVICE_ID_KEY);
376
+ var v = KeyChain.GetKeyChain(AMA_DEVICE_ID_KEY);
296
377
  if (string.IsNullOrEmpty(v))
297
378
  {
298
379
  v = Guid.NewGuid().ToString();
@@ -302,7 +383,7 @@ namespace Amanotes.Core
302
383
  break;
303
384
 
304
385
  case RuntimePlatform.Android:
305
- string cachedAmaDeviceId = PlayerPrefs.GetString(AMA_DEVICE_ID_KEY);
386
+ var cachedAmaDeviceId = PlayerPrefs.GetString(AMA_DEVICE_ID_KEY);
306
387
  if (string.IsNullOrEmpty(cachedAmaDeviceId))
307
388
  {
308
389
  cachedAmaDeviceId = SystemInfo.deviceUniqueIdentifier;
@@ -318,11 +399,10 @@ namespace Amanotes.Core
318
399
  Save();
319
400
  }
320
401
 
321
- private string ValidateId (string id, string pattern)
402
+ private bool ValidateId (string id, string pattern)
322
403
  {
323
- if (string.IsNullOrWhiteSpace(id)) return null;
324
- if (!Regex.IsMatch(id, pattern)) return null;
325
- return id;
404
+ if (string.IsNullOrWhiteSpace(id)) return false;
405
+ return Regex.IsMatch(id, pattern);
326
406
  }
327
407
  }
328
408
  }
package/Runtime/AmaGDK.cs CHANGED
@@ -17,7 +17,7 @@ namespace Amanotes.Core
17
17
  {
18
18
  public partial class AmaGDK : MonoBehaviour
19
19
  {
20
- public const string VERSION = "0.2.62";
20
+ public const string VERSION = "0.2.64";
21
21
 
22
22
  internal static AmaGDK _instance;
23
23
  internal static bool _allowInit = false;
@@ -179,16 +179,17 @@ namespace Amanotes.Core
179
179
  throw new Exception("[AmaGDK] " + CONFIG_NOT_FOUND);
180
180
  }
181
181
 
182
- float startTime = Time.realtimeSinceStartup;
182
+ var startTime = Time.realtimeSinceStartup;
183
183
  var sb = new StringBuilder();
184
184
 
185
185
  InitModules();
186
186
 
187
- float moduleTime = Time.realtimeSinceStartup - startTime;
187
+ var moduleTime = Time.realtimeSinceStartup - startTime;
188
188
  sb.Append($"- InitModules() took (~ {moduleTime:#0.00}s)\n");
189
189
 
190
190
  yield return InitHook(); //Google CMP takes long at first time (~ 1.7s)
191
- float hookTime = Time.realtimeSinceStartup - moduleTime - startTime;
191
+
192
+ var hookTime = Time.realtimeSinceStartup - moduleTime - startTime;
192
193
  sb.Append($"- InitHook() took (~ {hookTime:#0.00}s)\n\n");
193
194
 
194
195
  _status = Status.Initialize;
@@ -206,9 +207,12 @@ namespace Amanotes.Core
206
207
 
207
208
  _status = Status.Ready;
208
209
  dispatcher.Dispatch(Event.GDK_READY);
210
+
211
+ var initDuration = Time.realtimeSinceStartup - startTime;
212
+ LogEvent_GDKInit(Mathf.RoundToInt(initDuration));
209
213
 
210
214
  sb.Append($"\nMapping UserId: {User.UserId}\n");
211
- Debug.Log($"AmaGDK v{VERSION} | {READY} in {Time.realtimeSinceStartup - startTime:#0.00}s\n\n{sb}");
215
+ Debug.Log($"AmaGDK v{VERSION} | {READY} in {initDuration:#0.00}s\n\n{sb}");
212
216
  }
213
217
 
214
218
  private void ConfigGeoLocation()
@@ -230,6 +234,29 @@ namespace Amanotes.Core
230
234
  }
231
235
  }
232
236
  }
237
+
238
+ private static void LogEvent_GDKInit(int initDuration)
239
+ {
240
+ var _dicKey = new Dictionary<string, object>
241
+ {
242
+ ["gdk_version"] = VERSION,
243
+ ["session"] = User.Session,
244
+ ["gdk_init_duration"] = initDuration,
245
+ ["user_id"] = User.UserId
246
+ };
247
+
248
+ void AppendServiceKey(string adapterId, string paramName)
249
+ {
250
+ var serviceKey = Adapter2.GetAdapterById(adapterId)?.GetServiceKey();
251
+ if (string.IsNullOrEmpty(serviceKey)) return;
252
+ _dicKey[paramName] = serviceKey;
253
+ }
254
+
255
+ AppendServiceKey(AdapterID.APPSFLYER, "appsflyer_key");
256
+ AppendServiceKey(AdapterID.IRONSOURCE, "ironsource_key");
257
+ AppendServiceKey(AdapterID.REVENUECAT, "revenuecat_key");
258
+ Analytics.LogEvent("gdk_init", _dicKey);
259
+ }
233
260
  }
234
261
 
235
262
  public partial class AmaGDK // PUBLIC APIS
@@ -149,10 +149,27 @@ namespace Amanotes.Core.Internal
149
149
  return true;
150
150
  }
151
151
 
152
- public static bool Foldout(string label, ref bool isOpen, Action drawFunc, Action titleFunc = null, GUIStyle style = null)
152
+ public static bool Foldout(string label, ref bool isOpen, Action drawFunc, Action titleFunc = null)
153
+ {
154
+ return Foldout(label, null, ref isOpen, drawFunc, titleFunc);
155
+ }
156
+
157
+ public static bool Foldout(string label, Texture icon, ref bool isOpen, Action drawFunc, Action titleFunc = null)
153
158
  {
154
159
  GUILayout.BeginHorizontal();
155
- bool newValue = EditorGUILayout.Foldout(isOpen, label, EditorStyles.foldoutHeader);
160
+ float labelWidth = EditorGUIUtility.labelWidth;
161
+
162
+ var content = new GUIContent(label, icon);
163
+ float w = EditorStyles.foldoutHeader.CalcSize(content).x;
164
+ EditorGUIUtility.labelWidth = w;
165
+
166
+ // var c = GUI.color;
167
+ // GUI.color = Color.red;
168
+ Rect rect = GUILayoutUtility.GetRect(w, w, 18f, 18f);
169
+ bool newValue = EditorGUI.Foldout(rect, isOpen, content, EditorStyles.foldoutHeader);
170
+ EditorGUIUtility.labelWidth = labelWidth;
171
+ // GUI.color = c;
172
+
156
173
  bool changed = newValue != isOpen;
157
174
  titleFunc?.Invoke();
158
175
  GUILayout.EndHorizontal();
@@ -1,6 +1,7 @@
1
1
  using System;
2
2
  using System.Collections.Generic;
3
3
  using System.Text.RegularExpressions;
4
+ using UnityEngine;
4
5
  using UnityEngine.Profiling;
5
6
  using static Amanotes.Core.Internal.Logging;
6
7
 
@@ -9,7 +10,7 @@ namespace Amanotes.Core.Internal
9
10
  public struct SemVer : IComparable<SemVer>, IComparer<SemVer>
10
11
  {
11
12
  public static readonly SemVer ZERO = new SemVer(0, 0, 0);
12
- private static readonly Regex VERSION_PATTERN = new Regex(@"^(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?$");
13
+ private static readonly Regex VERSION_PATTERN = new Regex(@"^(\d+)\.(\d+)(?:\.(\d+))?(?:\.(\d+))?$");
13
14
 
14
15
  public int major;
15
16
  public int minor;
@@ -45,13 +46,21 @@ namespace Amanotes.Core.Internal
45
46
  }
46
47
  major = int.Parse(match.Groups[1].Value);
47
48
  minor = int.Parse(match.Groups[2].Value);
48
- patch = int.Parse(match.Groups[3].Value);
49
+ if (match.Groups.Count > 2)
50
+ {
51
+ if (!int.TryParse(match.Groups[3].Value, out patch))
52
+ {
53
+ patch = 0;
54
+ }
55
+ }
49
56
  if (match.Groups.Count > 3)
50
57
  {
51
58
  if (!int.TryParse(match.Groups[4].Value, out extra))
59
+ {
52
60
  extra = -1;
53
61
  }
54
62
  }
63
+ }
55
64
  Profiler.EndSample();
56
65
  }
57
66
 
@@ -66,6 +75,21 @@ namespace Amanotes.Core.Internal
66
75
 
67
76
  public int CompareTo(SemVer other)
68
77
  {
78
+ if (!isValid)
79
+ {
80
+ if (!other.isValid)
81
+ {
82
+ return 0;
83
+ }
84
+ return -1;
85
+ }
86
+
87
+ if (!other.isValid)
88
+ {
89
+ return 1;
90
+ }
91
+
92
+
69
93
  if (major != other.major) return major.CompareTo(other.major);
70
94
  if (minor != other.minor) return minor.CompareTo(other.minor);
71
95
  if (patch != other.patch) return patch.CompareTo(other.patch);
@@ -175,7 +175,7 @@ namespace Amanotes.Core.Internal
175
175
  analyticsData.cachedEventDetails.Clear();
176
176
  analyticsData.migrationLog = new MigrationLog();
177
177
  analyticsData.SaveIfDirty();
178
- sessionStat.Clear();
178
+ sessionStat?.Clear();
179
179
  #if UNITY_2021_3_OR_NEWER
180
180
  eventQueue.Clear();
181
181
  #else
@@ -14,6 +14,10 @@ namespace Amanotes.Core.Internal
14
14
  {
15
15
  public static class GDKUtils
16
16
  {
17
+ public static void StartCoroutine(IEnumerator action)
18
+ {
19
+ AmaGDK._instance.StartCoroutine(action);
20
+ }
17
21
  public static void DelayCall(float seconds, Action action)
18
22
  {
19
23
  AmaGDK._instance.StartCoroutine(DelayCallRoutine(seconds, action));
@@ -321,7 +325,7 @@ namespace Amanotes.Core.Internal
321
325
  }
322
326
  }
323
327
 
324
- internal static void ClearCacheData()
328
+ public static void ClearCacheData()
325
329
  {
326
330
  var sb = new StringBuilder();
327
331
  sb.AppendLine("[AmaGDK] All cached data & stats cleared");
@@ -0,0 +1,9 @@
1
+ using UnityEngine;
2
+
3
+ namespace Amanotes.Core
4
+ {
5
+ public class HideInNormalInspectorAttribute : PropertyAttribute
6
+ {
7
+ public HideInNormalInspectorAttribute() { }
8
+ }
9
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 988f818f8951413e9813008614e04a4a
3
+ timeCreated: 1717410575
@@ -16,4 +16,5 @@ namespace Amanotes.Core
16
16
  return AmaGDK.Analytics.GetAccumulatedCount(attr.name) + 1;
17
17
  }
18
18
  }
19
+ public class LifetimeCountAttribute : AccumulatedCountAttribute { }
19
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.amanotes.gdk",
3
- "version": "0.2.62",
3
+ "version": "0.2.64",
4
4
  "displayName": "AmaGDK",
5
5
  "description": "Amanotes Game Development Kit",
6
6
  "unity": "2019.4",