com.amanotes.gdk 0.2.81-a4 → 0.2.81-alpha.6

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 (43) hide show
  1. package/CHANGELOG.md +11 -4
  2. package/Editor/Extra/GDKCIBuildCommand.cs +57 -55
  3. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  4. package/Extra/AutoEventQC.unitypackage +0 -0
  5. package/Extra/CheckDiskSpace.unitypackage +0 -0
  6. package/Extra/Consent.unitypackage +0 -0
  7. package/Extra/CrashlyticHook.unitypackage +0 -0
  8. package/Extra/ForceUpdate.unitypackage +0 -0
  9. package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
  10. package/Extra/PostProcessor.unitypackage +0 -0
  11. package/Packages/AmaGDKConfig.unitypackage +0 -0
  12. package/Packages/AmaGDKExample.unitypackage +0 -0
  13. package/Packages/AmaGDKTest.unitypackage +0 -0
  14. package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -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.AdQuality.unitypackage +0 -0
  19. package/Packages/IronSourceAdapter.unitypackage +0 -0
  20. package/Packages/MaxAdNetworkAdapter.unitypackage +0 -0
  21. package/Packages/RevenueCatAdapter.unitypackage +0 -0
  22. package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
  23. package/Runtime/Ad/AmaGDK.Ads.cs +1 -1
  24. package/Runtime/AmaGDK.Analytics.cs +3 -9
  25. package/Runtime/AmaGDK.IAP.cs +1 -1
  26. package/Runtime/AmaGDK.UserProfile.cs +2 -2
  27. package/Runtime/AmaGDK.cs +1 -1
  28. package/Runtime/Consent/AmaGDK.Consent.cs +224 -0
  29. package/Runtime/Consent/GDKPrivacyButton.cs +25 -0
  30. package/Runtime/Consent/GDKPrivacyButton.cs.meta +3 -0
  31. package/Runtime/Consent/GDKPrivacyButton.prefab +148 -0
  32. package/Runtime/Consent/GDKPrivacyButton.prefab.meta +7 -0
  33. package/Runtime/Consent.meta +3 -0
  34. package/Runtime/Core/GDKDebug.cs +13 -4
  35. package/Runtime/Core/GDKTaskTracker.cs +118 -0
  36. package/Runtime/Core/GDKTaskTracker.cs.meta +3 -0
  37. package/Runtime/Internal/AmaGDK.Utils.cs +1 -1
  38. package/Runtime/Internal/ForceQuitMonitor.cs +1 -1
  39. package/Runtime/Utils/GDKFileUtils.cs +1 -1
  40. package/Runtime/Utils/GDKUtils.cs +8 -0
  41. package/package.json +4 -4
  42. package/Runtime/AmaGDK.Consent.cs +0 -256
  43. /package/Runtime/{AmaGDK.Consent.cs.meta → Consent/AmaGDK.Consent.cs.meta} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,7 +1,12 @@
1
- # Changelog
2
-
3
- ## [0.2.81-a4] - 2024-11-21
4
- - [Dev] Add GDKPostBuild for iOS
1
+ ## [v0.2.81-alpha.6] - 2024-12-10
2
+ - [Dev] Refactor Consent module
3
+ - [Dev] Add GDKTaskTracker
4
+ - [Release] 0.2.81-alpha.5
5
+ - [Dev] Save build info
6
+ - Revert "[Dev] Analytics save file in async"
7
+ - [Dev] Make GDKDebug thread-safe
8
+ - [Dev] Add GDKPostBuildAsset
9
+ - [Fix] Retrieve the correct app version from CI variable
5
10
  - [Dev] Improve GDK editor experience before config asset imported
6
11
  - [Dev] Analytics save file in async
7
12
  - [Dev] Move GDKFileUtils to a separated file
@@ -9,6 +14,8 @@
9
14
  - [Dev] Add ABLab
10
15
  - [Dev] Move imported GDK Adapter from RawData to Modules
11
16
 
17
+ # Changelog
18
+
12
19
  ## [0.2.80] - 2024-11-13
13
20
  - [Dev] Don't use obsolete functions
14
21
  - [Dev] Add CrashlyticHook
@@ -17,22 +17,27 @@ namespace Amanotes.Core
17
17
  private const string KEY_ALIAS_NAME = "KEY_ALIAS_NAME";
18
18
  private const string KEYSTORE = "keystore.keystore";
19
19
  private const string BUILD_OPTIONS_ENV_VAR = "BuildOptions";
20
- private const string ANDROID_BUNDLE_VERSION_CODE = "VERSION_BUILD_VAR";
21
20
  private const string ANDROID_APP_BUNDLE = "BUILD_APP_BUNDLE";
22
21
  private const string SCRIPTING_BACKEND_ENV_VAR = "SCRIPTING_BACKEND";
23
22
  private const string EXPORT_ANDROID_PROJECT = "EXPORT_ANDROID_PROJECT";
24
23
  private const string VERSION_NUMBER_VAR = "VERSION_NUMBER_VAR";
25
- private const string VERSION_iOS = "VERSION_BUILD_VAR";
24
+ private const string VERSION_BUILD_VAR = "VERSION_BUILD_VAR";
26
25
 
27
26
  public static void InstallPod(EventHandler processExit, string buildPath = null)
28
27
  {
29
28
  try
30
29
  {
31
- var arguments = $"-c \"/usr/local/bin/pod install --project-directory={buildPath}\"";
30
+ string arguments = "";
32
31
  if (Application.isBatchMode && TryGetEnv("CI_SCRIPT_DIR", out string scriptDir))
33
32
  {
34
33
  arguments = $"{scriptDir}/utils.sh pod-install";
35
34
  }
35
+ else if (!Application.isBatchMode)
36
+ {
37
+ string podPath = "/usr/local/bin/pod";
38
+ if (!File.Exists(podPath)) podPath = "/opt/homebrew/bin/pod";
39
+ arguments = $"-c \"{podPath} install --project-directory={buildPath}\"";
40
+ }
36
41
 
37
42
  // Configure process start info
38
43
  var startInfo = new ProcessStartInfo
@@ -57,12 +62,6 @@ namespace Amanotes.Core
57
62
  if (args.Data == null) return; // End of the stream
58
63
  Debug.Log(args.Data);
59
64
  };
60
-
61
- // proc.ErrorDataReceived += (sender, args) =>
62
- // {
63
- // if (args.Data == null) return; // End of the stream
64
- // Debug.LogError(args.Data);
65
- // };
66
65
 
67
66
  proc.Exited += processExit;
68
67
 
@@ -71,9 +70,6 @@ namespace Amanotes.Core
71
70
  proc.BeginOutputReadLine();
72
71
  proc.BeginErrorReadLine();
73
72
  proc.WaitForExit();
74
-
75
- // Log exit code
76
- // Debug.LogWarning("Process exited with code: " + proc.ExitCode);
77
73
  }
78
74
  catch (Exception e)
79
75
  {
@@ -245,20 +241,16 @@ namespace Amanotes.Core
245
241
  var buildTarget = GetBuildTarget();
246
242
 
247
243
  Console.WriteLine(":: Performing build");
248
- if (TryGetEnv(VERSION_NUMBER_VAR, out var bundleVersionNumber))
244
+ if (TryGetEnv(VERSION_NUMBER_VAR, out string bundleVersionNumber))
249
245
  {
250
- if (buildTarget == BuildTarget.iOS)
251
- {
252
- bundleVersionNumber = GetIosVersion();
253
- }
254
246
  Console.WriteLine($":: Setting bundleVersionNumber to '{bundleVersionNumber}' (Length: {bundleVersionNumber.Length})");
255
247
  PlayerSettings.bundleVersion = bundleVersionNumber;
256
248
  }
249
+ HandleBuildNumber(buildTarget);
257
250
 
258
251
  if (buildTarget == BuildTarget.Android)
259
252
  {
260
253
  HandleAndroidAppBundle();
261
- HandleAndroidBundleVersionCode();
262
254
  HandleAndroidKeystore();
263
255
  HandleDebugSymbols();
264
256
  HandleExportAndroidProject();
@@ -276,6 +268,7 @@ namespace Amanotes.Core
276
268
  if (buildReport.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded)
277
269
  throw new Exception($"Build ended with {buildReport.summary.result} status");
278
270
 
271
+ BuildMetadata.Save(buildPath, buildTarget);
279
272
  Console.WriteLine(":: Done with build");
280
273
  }
281
274
 
@@ -299,18 +292,24 @@ namespace Amanotes.Core
299
292
  }
300
293
  }
301
294
 
302
- private static void HandleAndroidBundleVersionCode()
295
+ private static void HandleBuildNumber(BuildTarget buildTarget)
303
296
  {
304
- if (TryGetEnv(ANDROID_BUNDLE_VERSION_CODE, out string value))
297
+ if (!TryGetEnv(VERSION_BUILD_VAR, out string value)) return;
298
+ if (int.TryParse(value, out int version))
305
299
  {
306
- if (int.TryParse(value, out int version))
300
+ if (buildTarget == BuildTarget.Android)
307
301
  {
308
- PlayerSettings.Android.bundleVersionCode = version;
309
- Console.WriteLine($":: {ANDROID_BUNDLE_VERSION_CODE} env var detected, set the bundle version code to {value}.");
302
+ PlayerSettings.Android.bundleVersionCode = version;
310
303
  }
311
- else
312
- Console.WriteLine($":: {ANDROID_BUNDLE_VERSION_CODE} env var detected but the version value \"{value}\" is not an integer.");
304
+ else if (buildTarget == BuildTarget.iOS)
305
+ {
306
+ PlayerSettings.iOS.buildNumber = version.ToString();
307
+ }
308
+
309
+ Console.WriteLine($":: {VERSION_BUILD_VAR} env var detected, set the bundle version code to {value}.");
313
310
  }
311
+ else
312
+ Console.WriteLine($":: {VERSION_BUILD_VAR} env var detected but the version value \"{value}\" is not an integer.");
314
313
  }
315
314
 
316
315
  private static void HandleExportAndroidProject()
@@ -323,22 +322,6 @@ namespace Amanotes.Core
323
322
  }
324
323
  }
325
324
 
326
- private static string GetIosVersion()
327
- {
328
- if (TryGetEnv(VERSION_iOS, out string value))
329
- {
330
- if (int.TryParse(value, out int version))
331
- {
332
- Console.WriteLine($":: {VERSION_iOS} env var detected, set the version to {value}.");
333
- return version.ToString();
334
- }
335
- else
336
- Console.WriteLine($":: {VERSION_iOS} env var detected but the version value \"{value}\" is not an integer.");
337
- }
338
-
339
- throw new ArgumentNullException(nameof(value), $":: Error finding {VERSION_iOS} env var");
340
- }
341
-
342
325
  private static void HandleAndroidKeystore()
343
326
  {
344
327
  #if UNITY_2019_1_OR_NEWER
@@ -394,6 +377,31 @@ namespace Amanotes.Core
394
377
  }
395
378
  }
396
379
 
380
+ [Serializable]
381
+ public class BuildMetadata
382
+ {
383
+ public string appVersion;
384
+ public string buildNumber;
385
+ public string buildTarget;
386
+
387
+ public static void Save(string buildPath, BuildTarget buildTarget)
388
+ {
389
+ string outputFile = Path.Combine(buildPath, "build_info.json");
390
+
391
+ var metadata = new BuildMetadata
392
+ {
393
+ appVersion = PlayerSettings.bundleVersion,
394
+ buildNumber = buildTarget == BuildTarget.Android ? PlayerSettings.Android.bundleVersionCode.ToString() : PlayerSettings.iOS.buildNumber,
395
+ buildTarget = buildTarget.ToString()
396
+ };
397
+
398
+ string json = JsonUtility.ToJson(metadata, prettyPrint: true);
399
+ File.WriteAllText(outputFile, json);
400
+
401
+ Console.WriteLine($":: Build information saved to {outputFile}");
402
+ }
403
+ }
404
+
397
405
  public class GDKPreProcessBuild: IPreprocessBuildWithReport
398
406
  {
399
407
  public int callbackOrder
@@ -402,20 +410,14 @@ namespace Amanotes.Core
402
410
  }
403
411
  public void OnPreprocessBuild(BuildReport report)
404
412
  {
405
- if (report.summary.platform == BuildTarget.Android)
406
- {
407
- // Change Gradle path when running in headless mode (CI Machine)
408
- if (Application.isBatchMode)
409
- {
410
- if (GDKCIBuildCommand.TryGetEnv("GRADLE_PATH", out string envGradlePath))
411
- {
412
- EditorPrefs.SetBool("GradleUseEmbedded", false);
413
- EditorPrefs.SetString("GradlePath", envGradlePath);
414
- Debug.Log("Update gradle path to: " + envGradlePath);
415
- }
416
- }
417
- }
418
-
413
+ if (report.summary.platform != BuildTarget.Android) return;
414
+ // Change Gradle path when running in headless mode (CI Machine)
415
+ if (!Application.isBatchMode) return;
416
+ if (!GDKCIBuildCommand.TryGetEnv("GRADLE_PATH", out string envGradlePath)) return;
417
+ EditorPrefs.SetBool("GradleUseEmbedded", false);
418
+ EditorPrefs.SetString("GradlePath", envGradlePath);
419
+ Debug.Log("Update gradle path to: " + envGradlePath);
420
+
419
421
  }
420
422
  }
421
423
  }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -93,7 +93,7 @@ namespace Amanotes.Core
93
93
 
94
94
  internal void Save()
95
95
  {
96
- this.SaveJsonToFile(false);
96
+ this.SaveJsonToFile();
97
97
  }
98
98
  }
99
99
 
@@ -135,7 +135,7 @@ namespace Amanotes.Core
135
135
 
136
136
  if (!localData._dirty) return;
137
137
  localData._dirty = false;
138
- localData.SaveJsonToFile(true); // immediately = true
138
+ localData.SaveJsonToFile();
139
139
  }
140
140
 
141
141
  public static IEventParamsBuilder LogFunnelEvent(string eventName, string signature = "")
@@ -314,7 +314,7 @@ namespace Amanotes.Core
314
314
  internal static readonly GDKPool.Pool<EventParams> epPool = new GDKPool.Pool<EventParams>(1);
315
315
 
316
316
  private static readonly Lazy<AnalyticsData> _localData = new Lazy<AnalyticsData>(
317
- () => new AnalyticsData().ReloadDataFromLocal());
317
+ () => new AnalyticsData().LoadJsonFromFile().BuildCache());
318
318
  internal static AnalyticsData localData => _localData.Value;
319
319
 
320
320
  internal static readonly Dictionary<string, string> reservedPrefixes = new Dictionary<string, string>()
@@ -800,12 +800,6 @@ namespace Amanotes.Core
800
800
  return this;
801
801
  }
802
802
 
803
- public AnalyticsData ReloadDataFromLocal()
804
- {
805
- this.LoadJsonFromFile().BuildCache();
806
- return this;
807
- }
808
-
809
803
  internal EventDetail GetEventDetail(string eventName, bool autoNew = false)
810
804
  {
811
805
  if (string.IsNullOrEmpty(eventName)) return null;
@@ -849,7 +843,7 @@ namespace Amanotes.Core
849
843
  if (!Config.analytics.autoFlushEventDetail) return;
850
844
  if (!_dirty) return;
851
845
  _dirty = false;
852
- this.SaveJsonToFile(false);
846
+ this.SaveJsonToFile();
853
847
  }
854
848
 
855
849
  internal void UpdateMigrationLog()
@@ -306,7 +306,7 @@ namespace Amanotes.Core
306
306
  subscriptionExpiredDate = _subscriptionExpiredDate?.ToString(DATE_FORMAT);
307
307
  _unsubscribedDate = Adapter.GetUnsubscribedDate();
308
308
  unsubscribedDate = _unsubscribedDate?.ToString(DATE_FORMAT);
309
- this.SaveJsonToFile(false);
309
+ this.SaveJsonToFile();
310
310
  }
311
311
  }
312
312
  }
@@ -33,14 +33,14 @@ namespace Amanotes.Core
33
33
  private bool _dirty = false;
34
34
  private void Save()
35
35
  {
36
- this.SaveJsonToFile(false);
36
+ this.SaveJsonToFile();
37
37
  }
38
38
 
39
39
  private void SaveIfDirty()
40
40
  {
41
41
  if (!_dirty) return;
42
42
  _dirty = false;
43
- this.SaveJsonToFile(false);
43
+ this.SaveJsonToFile();
44
44
  }
45
45
  }
46
46
 
package/Runtime/AmaGDK.cs CHANGED
@@ -27,7 +27,7 @@ namespace Amanotes.Core
27
27
  {
28
28
  public partial class AmaGDK : MonoBehaviour
29
29
  {
30
- public const string VERSION = "0.2.81-a4";
30
+ public const string VERSION = "v0.2.81-alpha.6";
31
31
 
32
32
  internal static Status _status = Status.None;
33
33
  internal static ConfigAsset _config = null;
@@ -0,0 +1,224 @@
1
+ using System;
2
+ using Amanotes.Core.Internal;
3
+ using UnityEngine;
4
+ using static Amanotes.Core.GDKDebug;
5
+
6
+ namespace Amanotes.Core
7
+ {
8
+ public partial class AmaGDK //Consent
9
+ {
10
+ public static partial class Consent //Public
11
+ {
12
+ private static readonly GDKTaskTracker _allConsentTaskTracker = new GDKTaskTracker();
13
+ public static void RequestAllConsents(Action onComplete)
14
+ {
15
+ _allConsentTaskTracker.RegisterOnCompleteCallback(onComplete);
16
+ if (_allConsentTaskTracker.HasStarted) return;
17
+
18
+ _allConsentTaskTracker.MarkStarted();
19
+
20
+ void CompleteRequestAllConsents()
21
+ {
22
+ _allConsentTaskTracker.MarkCompleted();
23
+ }
24
+ void ShowConsentIfRequired()
25
+ {
26
+ CMP.ShowConsentFormIfRequired(
27
+ _ => CompleteRequestAllConsents(),
28
+ _ => CompleteRequestAllConsents());
29
+ }
30
+ #if UNITY_IOS
31
+ ATT.Request(
32
+ allow =>
33
+ {
34
+ if (allow)
35
+ {
36
+ ShowConsentIfRequired();
37
+ return;
38
+ }
39
+ CompleteRequestAllConsents();
40
+ });
41
+ #else
42
+ ShowConsentIfRequired();
43
+ #endif
44
+ }
45
+ }
46
+
47
+ public static partial class Consent //ATT
48
+ {
49
+ public static class ATT
50
+ {
51
+ public static bool IsAllowed
52
+ {
53
+ get
54
+ {
55
+ if (checkedATT) return allowedATT;
56
+ LogWarning("[Consent] ATT has not completed yet");
57
+ return false;
58
+ }
59
+ }
60
+
61
+ public static void Request(Action<bool> onComplete)
62
+ {
63
+ if (checkedATT)
64
+ {
65
+ Log("[Consent] ATT has already completed");
66
+ onComplete?.Invoke(allowedATT);
67
+ return;
68
+ }
69
+ if (ConsentHook.ATTRequest == null)
70
+ {
71
+ LogWarning("[Consent] ConsentHook.ATTRequest is not implemented");
72
+ onComplete?.Invoke(false);
73
+ return;
74
+ }
75
+
76
+ ConsentHook.ATTRequest(isAllowed =>
77
+ {
78
+ data.att = isAllowed ? Status.Allowed : Status.NotAllowed;
79
+ data.SaveJsonToFile();
80
+ onComplete?.Invoke(allowedATT);
81
+ });
82
+ }
83
+ }
84
+
85
+ }
86
+
87
+ public static partial class Consent //CMP
88
+ {
89
+ public static class CMP
90
+ {
91
+ /// <summary>
92
+ /// Determines if a consent popup should be shown to the user and displays it if required.
93
+ /// The consent popup will be shown only once in the lifecycle of the app if this function is used.
94
+ /// </summary>
95
+ /// <remarks>
96
+ /// The consent popup is required in the European Economic Area (EEA) and
97
+ /// other countries that have implemented the General Data Protection Regulation (GDPR).
98
+ /// </remarks>
99
+ /// <param name="onComplete">Callback invoked with a boolean indicating the
100
+ /// ConsentInformation.CanRequestAds() result
101
+ /// </param>
102
+ /// <param name="onError">Callback invoked with an error message if the consent
103
+ /// form could not be loaded or shown.</param>
104
+ public static void ShowConsentFormIfRequired(Action<bool> onComplete, Action<string> onError)
105
+ {
106
+ if (ConsentHook.ShowConsentFormIfRequired == null)
107
+ {
108
+ LogWarning("[Consent] ConsentHook.ShowConsentFormIfRequired is not implemented");
109
+ onError?.Invoke("ShowPrivacyForm is not implemented");
110
+ return;
111
+ }
112
+ if (data.consentAlreadyShown)
113
+ {
114
+ Log("[Consent] Consent form has already been shown");
115
+ onComplete?.Invoke(data.canShowAds);
116
+ return;
117
+ }
118
+ ConsentHook.ShowConsentFormIfRequired(canShowAd =>
119
+ {
120
+ data.canShowAds = canShowAd;
121
+ data.consentAlreadyShown = true;
122
+ data.SaveJsonToFile();
123
+ onComplete?.Invoke(canShowAd);
124
+ }, onError);
125
+ }
126
+
127
+ /// <summary>
128
+ /// Forces the consent popup to be shown to the user, regardless of previous
129
+ /// consent status.
130
+ /// </summary>
131
+ /// <param name="onComplete">Callback invoked with a boolean indicating the
132
+ /// ConsentInformation.CanRequestAds() result
133
+ /// </param>
134
+ /// <param name="onError">Callback invoked with an error message if the consent
135
+ /// form could not be loaded or shown.</param>
136
+ public static void ShowPrivacyForm(Action<bool> onComplete, Action<string> onError)
137
+ {
138
+ if (ConsentHook.CheckPrivacyOptionsRequired == null)
139
+ {
140
+ LogWarning("[Consent] ConsentHook.ShowPrivacyForm is not implemented");
141
+ onError?.Invoke("ShowPrivacyForm is not implemented");
142
+ return;
143
+ }
144
+ ConsentHook.ShowPrivacyForm(onComplete, onError);
145
+ }
146
+
147
+ /// <summary>
148
+ /// Determines whether privacy options are required for the current user.
149
+ /// Updates the consent information before returning the result.
150
+ /// </summary>
151
+ /// <param name="onComplete">Callback invoked with `true` if privacy options are required, otherwise `false`.</param>
152
+ public static void CheckPrivacyOptionsRequired(Action<bool> onComplete)
153
+ {
154
+ if (ConsentHook.CheckPrivacyOptionsRequired == null)
155
+ {
156
+ LogWarning("[Consent] ConsentHook.CheckPrivacyOptionsRequired is not implemented");
157
+ onComplete?.Invoke(false);
158
+ return;
159
+ }
160
+ ConsentHook.CheckPrivacyOptionsRequired(onComplete);
161
+ }
162
+
163
+ [Obsolete("Use ShowPrivacyForm instead")]
164
+ public static void ForceShowPopup(Action<bool> onComplete)
165
+ {
166
+ ShowPrivacyForm(onComplete, s => onComplete?.Invoke(false));
167
+ }
168
+ }
169
+ }
170
+
171
+ public static partial class Consent //Internal
172
+ {
173
+ private static readonly Lazy<ConsentData> _data = new Lazy<ConsentData>(() => new ConsentData().LoadJsonFromFile());
174
+ private static ConsentData data => _data.Value;
175
+ private static Action _onConsentComplete;
176
+
177
+ internal static bool checkedATT => data.att >= Status.Allowed;
178
+ internal static bool allowedATT => data.att == Status.Allowed;
179
+
180
+ internal enum Status
181
+ {
182
+ None,
183
+ NotRequired,
184
+ Allowed,
185
+ NotAllowed
186
+ }
187
+
188
+ internal static bool InitModule()
189
+ {
190
+ if (_config.autoGetConsent)
191
+ {
192
+ RequestAllConsents(null);
193
+ }
194
+ return true;
195
+ }
196
+ }
197
+ }
198
+
199
+ [Serializable]
200
+ public class ConsentData : IJsonFile
201
+ {
202
+ [SerializeField] internal AmaGDK.Consent.Status att;
203
+ [SerializeField] internal bool consentAlreadyShown;
204
+ [SerializeField] internal bool canShowAds;
205
+ }
206
+
207
+ public static class ConsentHook
208
+ {
209
+ public static Action<Action<bool>, Action<string>> ShowConsentFormIfRequired;
210
+ public static Action<Action<bool>, Action<string>> ShowPrivacyForm;
211
+ public static Action<Action<bool>> CheckPrivacyOptionsRequired;
212
+ public static Action<Action<bool>> ATTRequest;
213
+ }
214
+ }
215
+
216
+ namespace Amanotes.Core.Internal
217
+ {
218
+ public partial class ConfigAsset
219
+ {
220
+ [SerializeField]
221
+ [Tooltip("Auto pop-up ATT and CMP form")]
222
+ public bool autoGetConsent = true;
223
+ }
224
+ }
@@ -0,0 +1,25 @@
1
+ using System;
2
+ using UnityEngine;
3
+ using UnityEngine.UI;
4
+ namespace Amanotes.Core
5
+ {
6
+ public class GDKPrivacyButton: MonoBehaviour
7
+ {
8
+ public Button button;
9
+ private void Start()
10
+ {
11
+ gameObject.SetActive(false);
12
+ UpdateUI();
13
+ }
14
+
15
+ public void OnButtonClick()
16
+ {
17
+ AmaGDK.Consent.CMP.ShowPrivacyForm(canShowAd => UpdateUI(), GDKDebug.LogWarning);
18
+ }
19
+
20
+ private void UpdateUI()
21
+ {
22
+ AmaGDK.Consent.CMP.CheckPrivacyOptionsRequired(required => button.interactable = required);
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 23184a9779a949419e702ce599a0dcc5
3
+ timeCreated: 1733448516
@@ -0,0 +1,148 @@
1
+ %YAML 1.1
2
+ %TAG !u! tag:unity3d.com,2011:
3
+ --- !u!1 &4256389965931995120
4
+ GameObject:
5
+ m_ObjectHideFlags: 0
6
+ m_CorrespondingSourceObject: {fileID: 0}
7
+ m_PrefabInstance: {fileID: 0}
8
+ m_PrefabAsset: {fileID: 0}
9
+ serializedVersion: 6
10
+ m_Component:
11
+ - component: {fileID: 1151037748665809425}
12
+ - component: {fileID: 981792811258053838}
13
+ - component: {fileID: 6086753863169534924}
14
+ - component: {fileID: 3785844084317390329}
15
+ - component: {fileID: 2957037893780307854}
16
+ m_Layer: 0
17
+ m_Name: GDKPrivacyButton
18
+ m_TagString: Untagged
19
+ m_Icon: {fileID: 0}
20
+ m_NavMeshLayer: 0
21
+ m_StaticEditorFlags: 0
22
+ m_IsActive: 1
23
+ --- !u!224 &1151037748665809425
24
+ RectTransform:
25
+ m_ObjectHideFlags: 0
26
+ m_CorrespondingSourceObject: {fileID: 0}
27
+ m_PrefabInstance: {fileID: 0}
28
+ m_PrefabAsset: {fileID: 0}
29
+ m_GameObject: {fileID: 4256389965931995120}
30
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
31
+ m_LocalPosition: {x: 0, y: 0, z: 0}
32
+ m_LocalScale: {x: 1, y: 1, z: 1}
33
+ m_Children: []
34
+ m_Father: {fileID: 0}
35
+ m_RootOrder: 0
36
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
37
+ m_AnchorMin: {x: 0.5, y: 0.5}
38
+ m_AnchorMax: {x: 0.5, y: 0.5}
39
+ m_AnchoredPosition: {x: 0, y: 0}
40
+ m_SizeDelta: {x: 100, y: 100}
41
+ m_Pivot: {x: 0.5, y: 0.5}
42
+ --- !u!114 &981792811258053838
43
+ MonoBehaviour:
44
+ m_ObjectHideFlags: 0
45
+ m_CorrespondingSourceObject: {fileID: 0}
46
+ m_PrefabInstance: {fileID: 0}
47
+ m_PrefabAsset: {fileID: 0}
48
+ m_GameObject: {fileID: 4256389965931995120}
49
+ m_Enabled: 1
50
+ m_EditorHideFlags: 0
51
+ m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
52
+ m_Name:
53
+ m_EditorClassIdentifier:
54
+ m_Navigation:
55
+ m_Mode: 3
56
+ m_WrapAround: 0
57
+ m_SelectOnUp: {fileID: 0}
58
+ m_SelectOnDown: {fileID: 0}
59
+ m_SelectOnLeft: {fileID: 0}
60
+ m_SelectOnRight: {fileID: 0}
61
+ m_Transition: 1
62
+ m_Colors:
63
+ m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
64
+ m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
65
+ m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
66
+ m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
67
+ m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
68
+ m_ColorMultiplier: 1
69
+ m_FadeDuration: 0.1
70
+ m_SpriteState:
71
+ m_HighlightedSprite: {fileID: 0}
72
+ m_PressedSprite: {fileID: 0}
73
+ m_SelectedSprite: {fileID: 0}
74
+ m_DisabledSprite: {fileID: 0}
75
+ m_AnimationTriggers:
76
+ m_NormalTrigger: Normal
77
+ m_HighlightedTrigger: Highlighted
78
+ m_PressedTrigger: Pressed
79
+ m_SelectedTrigger: Selected
80
+ m_DisabledTrigger: Disabled
81
+ m_Interactable: 1
82
+ m_TargetGraphic: {fileID: 2957037893780307854}
83
+ m_OnClick:
84
+ m_PersistentCalls:
85
+ m_Calls:
86
+ - m_Target: {fileID: 6086753863169534924}
87
+ m_TargetAssemblyTypeName: Amanotes.Core.GDKPrivacyButton, AmaGDK
88
+ m_MethodName: OnButtonClick
89
+ m_Mode: 1
90
+ m_Arguments:
91
+ m_ObjectArgument: {fileID: 0}
92
+ m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
93
+ m_IntArgument: 0
94
+ m_FloatArgument: 0
95
+ m_StringArgument:
96
+ m_BoolArgument: 0
97
+ m_CallState: 2
98
+ --- !u!114 &6086753863169534924
99
+ MonoBehaviour:
100
+ m_ObjectHideFlags: 0
101
+ m_CorrespondingSourceObject: {fileID: 0}
102
+ m_PrefabInstance: {fileID: 0}
103
+ m_PrefabAsset: {fileID: 0}
104
+ m_GameObject: {fileID: 4256389965931995120}
105
+ m_Enabled: 1
106
+ m_EditorHideFlags: 0
107
+ m_Script: {fileID: 11500000, guid: 23184a9779a949419e702ce599a0dcc5, type: 3}
108
+ m_Name:
109
+ m_EditorClassIdentifier:
110
+ button: {fileID: 981792811258053838}
111
+ --- !u!222 &3785844084317390329
112
+ CanvasRenderer:
113
+ m_ObjectHideFlags: 0
114
+ m_CorrespondingSourceObject: {fileID: 0}
115
+ m_PrefabInstance: {fileID: 0}
116
+ m_PrefabAsset: {fileID: 0}
117
+ m_GameObject: {fileID: 4256389965931995120}
118
+ m_CullTransparentMesh: 1
119
+ --- !u!114 &2957037893780307854
120
+ MonoBehaviour:
121
+ m_ObjectHideFlags: 0
122
+ m_CorrespondingSourceObject: {fileID: 0}
123
+ m_PrefabInstance: {fileID: 0}
124
+ m_PrefabAsset: {fileID: 0}
125
+ m_GameObject: {fileID: 4256389965931995120}
126
+ m_Enabled: 1
127
+ m_EditorHideFlags: 0
128
+ m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
129
+ m_Name:
130
+ m_EditorClassIdentifier:
131
+ m_Material: {fileID: 0}
132
+ m_Color: {r: 1, g: 1, b: 1, a: 1}
133
+ m_RaycastTarget: 1
134
+ m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
135
+ m_Maskable: 1
136
+ m_OnCullStateChanged:
137
+ m_PersistentCalls:
138
+ m_Calls: []
139
+ m_Sprite: {fileID: 0}
140
+ m_Type: 0
141
+ m_PreserveAspect: 0
142
+ m_FillCenter: 1
143
+ m_FillMethod: 4
144
+ m_FillAmount: 1
145
+ m_FillClockwise: 1
146
+ m_FillOrigin: 0
147
+ m_UseSpriteMesh: 0
148
+ m_PixelsPerUnitMultiplier: 1
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: a0f053cea7e1d4184afef07fdb572024
3
+ PrefabImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: fd1abbc2a7bd48d9b0f429852b96daa9
3
+ timeCreated: 1733448490
@@ -38,13 +38,16 @@ namespace Amanotes.Core
38
38
  {
39
39
  public static Action<string> logNonfatalErrorHook = null;
40
40
  private static readonly HashSet<string> nonFatalDict = new HashSet<string>();
41
- public static readonly HashSet<string> logWarningDict = new HashSet<string>();
41
+ private static readonly HashSet<string> logWarningDict = new HashSet<string>();
42
42
 
43
43
  public static void LogWarningOnce(string message, string key = null)
44
44
  {
45
45
  if (AmaGDK.logLevel < LogLevel.Warning) return;
46
46
  if (string.IsNullOrEmpty(key)) key = message;
47
- if (!logWarningDict.Add(key)) return;
47
+ lock (logWarningDict)
48
+ {
49
+ if (!logWarningDict.Add(key)) return;
50
+ }
48
51
 
49
52
  using (NoStackTrace.Warning)
50
53
  {
@@ -71,14 +74,20 @@ namespace Amanotes.Core
71
74
 
72
75
  if (GDKUtils.isOnMainThread) // Most of the time
73
76
  {
74
- if (!nonFatalDict.Add(message)) return;
77
+ lock (nonFatalDict)
78
+ {
79
+ if (!nonFatalDict.Add(message)) return;
80
+ }
75
81
  logNonfatalErrorHook(message);
76
82
  return;
77
83
  }
78
84
 
79
85
  GDKUtils.DoOnMainThread(() =>
80
86
  {
81
- if (!nonFatalDict.Add(message)) return; // LogOnce
87
+ lock (nonFatalDict)
88
+ {
89
+ if (!nonFatalDict.Add(message)) return; // LogOnce
90
+ }
82
91
  logNonfatalErrorHook(message);
83
92
  });
84
93
  }
@@ -0,0 +1,118 @@
1
+ using Amanotes.Core.Internal;
2
+ using System;
3
+
4
+ namespace Amanotes.Core
5
+ {
6
+ internal abstract class GDKTaskTrackerBase
7
+ {
8
+ protected enum GDKTaskState
9
+ {
10
+ None,
11
+ Running,
12
+ Completed,
13
+ }
14
+
15
+ protected GDKTaskState state;
16
+ public bool HasCompleted => state == GDKTaskState.Completed;
17
+ public bool HasStarted => state >= GDKTaskState.Running;
18
+
19
+ public void MarkStarted()
20
+ {
21
+ if (HasStarted)
22
+ {
23
+ GDKDebug.LogWarning("[GDKTaskTracker] Task already started");
24
+ return;
25
+ }
26
+
27
+ state = GDKTaskState.Running;
28
+ }
29
+
30
+ public virtual void Reset()
31
+ {
32
+ if (state == GDKTaskState.Running)
33
+ {
34
+ GDKDebug.LogWarning("[GDKTaskTracker] Task stop abruptly because of Reset()");
35
+ }
36
+ state = GDKTaskState.None;
37
+ }
38
+
39
+ protected bool ValidateMarkComplete()
40
+ {
41
+ if (HasCompleted)
42
+ {
43
+ GDKDebug.LogWarning("[GDKTaskTracker] Task already completed");
44
+ return false;
45
+ }
46
+
47
+ if (!HasStarted)
48
+ {
49
+ GDKDebug.LogWarning("[GDKTaskTracker] Task not yet started or been reset?");
50
+ }
51
+
52
+ state = GDKTaskState.Completed;
53
+ return true;
54
+ }
55
+ }
56
+
57
+
58
+ internal class GDKTaskTracker : GDKTaskTrackerBase
59
+ {
60
+ private Action callback;
61
+ public void RegisterOnCompleteCallback(Action onComplete)
62
+ {
63
+ if (HasCompleted)
64
+ {
65
+ onComplete?.Invoke();
66
+ }
67
+ else
68
+ {
69
+ callback -= onComplete;
70
+ callback += onComplete;
71
+ }
72
+ }
73
+
74
+ public void MarkCompleted()
75
+ {
76
+ if (!ValidateMarkComplete()) return;
77
+ GDKUtils.SafeInvokeAndClear(ref callback);
78
+ }
79
+
80
+ public override void Reset()
81
+ {
82
+ base.Reset();
83
+ callback = null;
84
+ }
85
+ }
86
+
87
+ internal class GDKTaskTracker<T> : GDKTaskTrackerBase
88
+ {
89
+ public T Result { get; private set; }
90
+ private Action<T> callback;
91
+
92
+ public void RegisterOnCompleteCallback(Action<T> onComplete)
93
+ {
94
+ if (HasCompleted)
95
+ {
96
+ onComplete?.Invoke(Result);
97
+ }
98
+ else
99
+ {
100
+ callback -= onComplete;
101
+ callback += onComplete;
102
+ }
103
+ }
104
+
105
+ public void MarkCompleted(T result)
106
+ {
107
+ if (!ValidateMarkComplete()) return;
108
+ Result = result;
109
+ GDKUtils.SafeInvokeAndClear(ref callback, Result);
110
+ }
111
+
112
+ public override void Reset()
113
+ {
114
+ base.Reset();
115
+ callback = null;
116
+ }
117
+ }
118
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 5c024a021cd0415bb5aace8887625c3d
3
+ timeCreated: 1733366401
@@ -200,7 +200,7 @@ namespace Amanotes.Core.Internal
200
200
  return GDKFileUtils.LoadJsonFromFile(instance);
201
201
  }
202
202
 
203
- internal static void SaveJsonToFile<T>(this T instance, bool immediately) where T: IJsonFile
203
+ internal static void SaveJsonToFile<T>(this T instance, bool immediately = true) where T: IJsonFile
204
204
  {
205
205
  GDKFileUtils.SaveJsonToFile(instance, immediately);
206
206
  }
@@ -34,7 +34,7 @@ namespace Amanotes.Core.Internal
34
34
  internal void SaveIfDirty(bool forceSave = false)
35
35
  {
36
36
  if (!isDirty && !forceSave) return;
37
- this.SaveJsonToFile(true);
37
+ this.SaveJsonToFile();
38
38
  isDirty = false;
39
39
  }
40
40
  }
@@ -236,7 +236,7 @@ namespace Amanotes.Core.Internal
236
236
  return instance;
237
237
  }
238
238
 
239
- public static void SaveJsonToFile<T>(T instance, bool immediately)
239
+ public static void SaveJsonToFile<T>(T instance, bool immediately = true)
240
240
  {
241
241
  string fileName = instance.GetType().Name;
242
242
  string json = JsonUtility.ToJson(instance);
@@ -14,6 +14,14 @@ namespace Amanotes.Core.Internal
14
14
  SafeInvoke(temp);
15
15
  }
16
16
 
17
+ public static void SafeInvokeAndClear<T>(ref Action<T> action, T data)
18
+ {
19
+ if (action == null) return;
20
+ Action<T> temp = action;
21
+ action = null;
22
+ SafeInvoke(temp, data);
23
+ }
24
+
17
25
  public static void SafeInvoke(Action action)
18
26
  {
19
27
  if (action == null) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.amanotes.gdk",
3
- "version": "0.2.81-a4",
3
+ "version": "0.2.81-alpha.6",
4
4
  "displayName": "AmaGDK",
5
5
  "description": "Amanotes Game Development Kit",
6
6
  "unity": "2019.4",
@@ -8,7 +8,7 @@
8
8
  "Amanotes",
9
9
  "Amanotes GDK",
10
10
  "vh-name:AmaGDK"
11
- ],
11
+ ],
12
12
  "author": {
13
13
  "name": "Amanotes",
14
14
  "email": "tech.support@amanotes.com",
@@ -16,5 +16,5 @@
16
16
  },
17
17
  "changelogUrl": "https://amagdk.notion.site/Change-Log-6dfd4b67d64f496bbd9eb04ccb4ef95a",
18
18
  "documentationUrl": "https://amagdk.notion.site/amagdk/Ama-GDK-a73596617ab247b6a43c8f12a1581415",
19
- "license": "MIT"
20
- }
19
+ "license": "MIT"
20
+ }
@@ -1,256 +0,0 @@
1
- using System;
2
- using Amanotes.Core.Internal;
3
- using UnityEngine;
4
- using static Amanotes.Core.GDKDebug;
5
-
6
- namespace Amanotes.Core
7
- {
8
- public partial class AmaGDK //Consent
9
- {
10
- public static partial class Consent //Public
11
- {
12
- private static bool _onGoingRequestAllConsents;
13
- public static void RequestAllConsents(Action onComplete)
14
- {
15
- OnAllConsentComplete(onComplete);
16
-
17
- if (_onGoingRequestAllConsents)
18
- {
19
- LogWarning($"[Consent] RequestAllConsents is called multiple times.");
20
- return;
21
- }
22
-
23
- _onGoingRequestAllConsents = true;
24
- #if UNITY_IOS
25
- ATT.Request(ConsiderCMP);
26
- #else
27
- CMP.Request(EndConsent);
28
- #endif
29
- }
30
-
31
- public static void OnAllConsentComplete(Action onComplete)
32
- {
33
- if (allConsentChecked)
34
- {
35
- onComplete?.Invoke();
36
- return;
37
- }
38
-
39
- _onConsentComplete -= onComplete;
40
- _onConsentComplete += onComplete;
41
- }
42
- }
43
-
44
- public static partial class Consent //ATT
45
- {
46
- public static class ATT
47
- {
48
- public static bool IsAllowed
49
- {
50
- get
51
- {
52
- if (checkedATT) return allowedATT;
53
- LogWarning("[Consent] ATT has not completed yet");
54
- return false;
55
- }
56
- }
57
-
58
- public static void Request(Action<bool> onComplete)
59
- {
60
- if (checkedATT)
61
- {
62
- onComplete?.Invoke(allowedATT);
63
- return;
64
- }
65
-
66
- ConsentHook.ATTRequest(isAllowed =>
67
- {
68
- data.att = isAllowed ? Status.Allowed : Status.NotAllowed;
69
- data.SaveJsonToFile(false);
70
- onComplete?.Invoke(allowedATT);
71
- });
72
- }
73
- }
74
-
75
- }
76
-
77
- public static partial class Consent //CMP
78
- {
79
- public static class CMP
80
- {
81
- public static bool IsRequired
82
- {
83
- get
84
- {
85
- if (checkedCMP) return data.cmp >= Status.Allowed;
86
-
87
- if (!ConsentHook.IsRequiredCMP.HasValue)
88
- {
89
- LogWarningOnce("[Consent] CMP is not available or not ready");
90
- return false;
91
- }
92
-
93
- return ConsentHook.IsRequiredCMP.Value;
94
- }
95
- }
96
-
97
- public static void Request(Action<bool> onComplete)
98
- {
99
- if (checkedCMP)
100
- {
101
- onComplete?.Invoke(checkedCMP);
102
- return;
103
- }
104
-
105
- ConsentHook.TryToShowCMP(successful =>
106
- {
107
- if (successful)
108
- {
109
- data.cmp = !IsRequired ? Status.NotRequired : Status.Allowed;
110
- data.SaveJsonToFile(false);
111
- }
112
- onComplete?.Invoke(checkedCMP);
113
- });
114
- }
115
-
116
- public static void ForceShowPopUp(Action onComplete)
117
- {
118
- OnAllConsentComplete(onComplete);
119
- ConsentHook.ForceShowCMP(EndConsent);
120
- }
121
- }
122
- }
123
-
124
- public static partial class Consent //Internal
125
- {
126
- private static readonly Lazy<ConsentData> _data = new Lazy<ConsentData>(() => new ConsentData().LoadJsonFromFile());
127
- private static ConsentData data => _data.Value;
128
- private static Action _onConsentComplete;
129
-
130
- internal static bool checkedATT => data.att >= Status.Allowed;
131
- internal static bool allowedATT => data.att == Status.Allowed;
132
- internal static bool checkedCMP => data.cmp >= Status.NotRequired;
133
- internal static bool allConsentChecked => checkedATT && checkedCMP;
134
-
135
- internal enum Status
136
- {
137
- None,
138
- NotRequired,
139
- Allowed,
140
- NotAllowed
141
- }
142
-
143
- internal static bool InitModule()
144
- {
145
- if (allConsentChecked) return true;
146
- if (!_config.autoGetConsent) return true;
147
- RequestAllConsents(null);
148
- return true;
149
- }
150
-
151
- private static void ConsiderCMP(bool needToShowCMP)
152
- {
153
- if (checkedCMP)
154
- {
155
- EndConsent(true);
156
- return;
157
- }
158
-
159
- if (needToShowCMP)
160
- {
161
- ConsentHook.TryToShowCMP(EndConsent);
162
- }
163
- else
164
- {
165
- ConsentHook.SetNotRequiredCMP(EndConsent);
166
- }
167
- }
168
-
169
- private static void EndConsent(bool isConsentSuccess)
170
- {
171
- var tmpAction = _onConsentComplete;
172
- _onConsentComplete = null;
173
- tmpAction?.Invoke();
174
- Log("[Consent] End consent checking");
175
- }
176
- }
177
- }
178
-
179
- [Serializable]
180
- public class ConsentData : IJsonFile
181
- {
182
- [SerializeField] internal AmaGDK.Consent.Status att;
183
- [SerializeField] internal AmaGDK.Consent.Status cmp;
184
- }
185
-
186
- public static class ConsentHook
187
- {
188
- public static bool? IsRequiredCMP;
189
-
190
- private static Action<Action<bool>> _tryToShowCMP;
191
- public static Action<Action<bool>> TryToShowCMP
192
- {
193
- get
194
- {
195
- if (_tryToShowCMP != null) return _tryToShowCMP;
196
-
197
- LogWarning("[Consent] ConsentHook.TryToShowCMP is null");
198
- _tryToShowCMP = callback => callback(false);
199
- return _tryToShowCMP;
200
- }
201
- set => _tryToShowCMP = value;
202
- }
203
-
204
- private static Action<Action<bool>> _forceShowCMP;
205
- public static Action<Action<bool>> ForceShowCMP
206
- {
207
- get
208
- {
209
- if (_forceShowCMP != null) return _forceShowCMP;
210
-
211
- LogWarning("[Consent] ConsentHook.ForceShowCMP is null");
212
- _forceShowCMP = callback => callback(false);
213
- return _forceShowCMP;
214
- }
215
- set => _forceShowCMP = value;
216
- }
217
-
218
- private static Action<Action<bool>> _setNotRequiredCMP;
219
- public static Action<Action<bool>> SetNotRequiredCMP
220
- {
221
- get
222
- {
223
- if (_setNotRequiredCMP != null) return _setNotRequiredCMP;
224
-
225
- LogWarning("[Consent] ConsentHook.SetNotRequiredCMP is null");
226
- _setNotRequiredCMP = callback => callback(false);
227
- return _setNotRequiredCMP;
228
- }
229
- set => _setNotRequiredCMP = value;
230
- }
231
-
232
- private static Action<Action<bool>> _attRequest;
233
- public static Action<Action<bool>> ATTRequest
234
- {
235
- get
236
- {
237
- if (_attRequest != null) return _attRequest;
238
-
239
- LogWarning("[Consent] ConsentHook.ATTRequest is null");
240
- _attRequest = callback => callback(false);
241
- return _attRequest;
242
- }
243
- set => _attRequest = value;
244
- }
245
- }
246
- }
247
-
248
- namespace Amanotes.Core.Internal
249
- {
250
- public partial class ConfigAsset
251
- {
252
- [SerializeField]
253
- [Tooltip("Auto pop-up ATT and CMP form")]
254
- public bool autoGetConsent = true;
255
- }
256
- }