com.amanotes.gdk 0.2.68 → 0.2.70

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 (54) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/Editor/AmaGDKEditor.cs +78 -23
  3. package/Editor/AmaGDKExtra.cs +14 -13
  4. package/Editor/Extra/GDKAutoUpdateAdapter.cs +14 -1
  5. package/Editor/Extra/GDKSymbolDefine.cs +372 -0
  6. package/Editor/{AmaGDKManager.cs.meta → Extra/GDKSymbolDefine.cs.meta} +1 -1
  7. package/Editor/Utils/AmaGDKEditor.ExtractVersion.cs +41 -3
  8. package/Extra/AmaGDKInstaller.unitypackage +0 -0
  9. package/Extra/CheckDiskSpace.unitypackage +0 -0
  10. package/Extra/Consent.unitypackage +0 -0
  11. package/Extra/{GoogleCMP.unitypackage.meta → Consent.unitypackage.meta} +1 -1
  12. package/Extra/ForceUpdate.unitypackage +0 -0
  13. package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
  14. package/Extra/PostProcessor.unitypackage +0 -0
  15. package/Packages/AmaGDKConfig.unitypackage +0 -0
  16. package/Packages/AmaGDKExample.unitypackage +0 -0
  17. package/Packages/AmaGDKTest.unitypackage +0 -0
  18. package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
  19. package/Packages/AppsFlyerAdapter.unitypackage +0 -0
  20. package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
  21. package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
  22. package/Packages/IronSourceAdapter.unitypackage +0 -0
  23. package/Packages/MaxAdNetworkAdapter.unitypackage +0 -0
  24. package/{Editor/Resources.meta → Packages/MaxAdNetworkAdapter.unitypackage.meta} +1 -2
  25. package/Packages/RevenueCatAdapter.unitypackage +0 -0
  26. package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
  27. package/Runtime/Ad/AdExtension.cs +2 -0
  28. package/Runtime/Ad/AdLogic.cs +83 -70
  29. package/Runtime/Ad/AdShowContext.cs +1 -0
  30. package/Runtime/Ad/AmaGDK.Ads.cs +17 -3
  31. package/Runtime/AmaGDK.Adapters.cs +12 -5
  32. package/Runtime/AmaGDK.Analytics.cs +45 -38
  33. package/Runtime/AmaGDK.Consent.cs +259 -0
  34. package/Runtime/AmaGDK.Consent.cs.meta +11 -0
  35. package/Runtime/AmaGDK.Device.cs +4 -4
  36. package/Runtime/AmaGDK.RemoteConfig.cs +3 -1
  37. package/Runtime/AmaGDK.cs +28 -19
  38. package/Runtime/AnalyticQualityAsset.cs +16 -9
  39. package/Runtime/AudioToolkit/AmaGDK.Audio.Latency.cs +1 -3
  40. package/Runtime/AudioToolkit/AmaGDK.Audio.cs +41 -25
  41. package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +13 -12
  42. package/Runtime/Core/GDKPool.cs +83 -17
  43. package/Runtime/Fps/AmaFPS.cs +0 -1
  44. package/Runtime/Fps/AmaFPSVisualizer.cs +7 -7
  45. package/Runtime/Internal/AmaGDK.Internal.AmaGUI.cs +1 -1
  46. package/Runtime/Internal/AmaGDK.Internal.cs +2 -5
  47. package/Runtime/Internal/AmaGDK.Utils.cs +32 -81
  48. package/Runtime/Internal/GDKGeoLocationcs.cs +3 -1
  49. package/Runtime/Internal/GDKServerTime.cs +13 -10
  50. package/package.json +1 -1
  51. package/Editor/AmaGDKManager.cs +0 -235
  52. package/Editor/Resources/amasdk-modules.json +0 -31
  53. package/Editor/Resources/amasdk-modules.json.meta +0 -7
  54. package/Extra/GoogleCMP.unitypackage +0 -0
@@ -5,11 +5,14 @@ using System.Linq;
5
5
  using System.Reflection;
6
6
  using System.Xml;
7
7
  using Amanotes.Core.Internal;
8
+ using System.Text.RegularExpressions;
9
+
8
10
  #if !UNITY_2021_1_OR_NEWER
9
- using UnityEditor;
10
11
  using UnityEditor.PackageManager;
11
12
  using UnityEditor.PackageManager.Requests;
12
13
  #endif
14
+
15
+ using UnityEditor;
13
16
  using UnityEngine;
14
17
  using static Amanotes.Core.AmaGDK.AdapterID;
15
18
 
@@ -179,8 +182,10 @@ namespace Amanotes.Editor
179
182
  case FIREBASE_ANALYTICS: return FirebaseAnalytics();
180
183
  case FIREBASE_REMOTE_CONFIG: return FirebaseRemoteConfig();
181
184
  case APPSFLYER: return AppsFlyer();
182
- case IRONSOURCE: return Ironsource();
185
+ case IRONSOURCE: return IronSource();
186
+ case MAX: return Max();
183
187
  case REVENUECAT: return RevenueCat();
188
+ case SQLITE_ANALYTICS: return SqliteAnalytics();
184
189
  default:
185
190
  Debug.LogWarning($"Unsupported sdkID <{sdkId}>");
186
191
  break;
@@ -261,7 +266,35 @@ namespace Amanotes.Editor
261
266
  return version.Trim();
262
267
  }
263
268
 
264
- internal static string Ironsource()
269
+ internal static string Max()
270
+ {
271
+ string[] guids = AssetDatabase.FindAssets("t:monoscript MaxSdk");
272
+ if (guids.Length == 0) return string.Empty;
273
+
274
+ foreach (string guid in guids)
275
+ {
276
+ string path = AssetDatabase.GUIDToAssetPath(guid);
277
+ if (!path.EndsWith("MaxSdk.cs")) continue;
278
+
279
+ try
280
+ {
281
+ string fileContent = File.ReadAllText(path);
282
+ const string pattern = @"private const string _version = ""(?<version>[\d\.]+)"";";
283
+ var regex = new Regex(pattern);
284
+ Match match = regex.Match(fileContent);
285
+ return match.Success ? match.Groups["version"].Value : string.Empty;
286
+ }
287
+ catch (IOException ex)
288
+ {
289
+ Debug.LogWarning($"Can not get Max Version : {ex}");
290
+ return string.Empty;
291
+ }
292
+ }
293
+
294
+ return string.Empty;
295
+ }
296
+
297
+ internal static string IronSource()
265
298
  {
266
299
  var version = "";
267
300
  string[] issdk = Directory.GetFiles("Assets", "IronSourceSDKDependencies.xml", SearchOption.AllDirectories);
@@ -297,6 +330,11 @@ namespace Amanotes.Editor
297
330
  return version?.Trim();
298
331
  }
299
332
 
333
+ internal static string SqliteAnalytics()
334
+ {
335
+ return "1.0.0";
336
+ }
337
+
300
338
  internal static string RevenueCat()
301
339
  {
302
340
  string[] files = Directory.GetFiles("Assets", "PurchasesWrapper.java", SearchOption.AllDirectories);
Binary file
Binary file
Binary file
@@ -1,5 +1,5 @@
1
1
  fileFormatVersion: 2
2
- guid: 4e220bd58ce0646bcbbb209dc8451d25
2
+ guid: c76a726b63046449ab0d11191aa3980b
3
3
  DefaultImporter:
4
4
  externalObjects: {}
5
5
  userData:
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,6 +1,5 @@
1
1
  fileFormatVersion: 2
2
- guid: aa56aa5c6656f415ebac7089cf7cf7dc
3
- folderAsset: yes
2
+ guid: 4d9f3e2a9be574df390eff5ef9f11fa9
4
3
  DefaultImporter:
5
4
  externalObjects: {}
6
5
  userData:
@@ -76,10 +76,12 @@ namespace Amanotes.Core
76
76
  AmaGDK.Ads.context.onAdShowReadyStatus += callback;
77
77
  return ad;
78
78
  }
79
+
79
80
  /// <summary>
80
81
  /// The finalize callback that will always trigger to mark an end for the AdShowRoutine
81
82
  ///
82
83
  /// </summary>
84
+ [Obsolete("OnAdResult is obsolete. Please use the onAdResult callback in AmaGDK.Ads.ShowInterstitial(Action<bool> onAdResult) or AmaGDK.Ads.ShowRewardedVideo(Action<bool> onAdResult) instead.")]
83
85
  public static IAdCallback OnAdResult(this IAdCallback ad, Action<bool> callback)
84
86
  {
85
87
  if (!MakeSureAdNotNull(ad)) return null;
@@ -7,6 +7,7 @@ namespace Amanotes.Core.Internal
7
7
  {
8
8
  public abstract class AdLogic
9
9
  {
10
+ private const int MAX_FRAMES_WAIT_FOR_CALLBACK = 60;
10
11
  protected AdModuleConfig adConfig => Config.ad;
11
12
  protected AdShowContext context => Ads.context;
12
13
 
@@ -130,9 +131,11 @@ namespace Amanotes.Core.Internal
130
131
  private Coroutine _showAdRoutine;
131
132
  protected bool _isRequesting;
132
133
  protected bool _isInterstitial => adType == AdType.Interstitial;
134
+ private bool isFocus;
133
135
 
134
136
  public void StartShowAd()
135
137
  {
138
+ isFocus = false;
136
139
  unityCallbacks.OnApplicationFocus -= OnApplicationFocus;
137
140
  unityCallbacks.OnApplicationFocus += OnApplicationFocus;
138
141
 
@@ -157,16 +160,12 @@ namespace Amanotes.Core.Internal
157
160
  _showAdRoutine = _instance.StartCoroutine(ShowAdRoutine());
158
161
  }
159
162
 
160
- void OnApplicationFocus(bool isFocus)
163
+ private void OnApplicationFocus(bool focus)
161
164
  {
162
- if (!isFocus) return;
165
+ if (!focus) return;
163
166
 
164
167
  unityCallbacks.OnApplicationFocus -= OnApplicationFocus;
165
- if (context == null) return;
166
-
167
- Log($"OnApplicationFocus Before: {context.hasClosed}");
168
- context.adCallback |= AdCallback.Close;
169
- Log($"OnApplicationFocus After: {context.hasClosed}");
168
+ isFocus = true;
170
169
  }
171
170
 
172
171
  public void StopShowAd()
@@ -209,55 +208,26 @@ namespace Amanotes.Core.Internal
209
208
 
210
209
  if (!HasLocalNetworkConnection)
211
210
  {
212
- _showState = ShowAdsState.ShowFail;
213
- OnAdShowReadyStatus(false, AdShowReadyStatus.Wifi3GDisabled);
214
- ShowAdRoutineCompleted(false);
211
+ EndShowAdRoutineWithFailure(AdShowReadyStatus.Wifi3GDisabled);
215
212
  yield break;
216
213
  }
217
214
 
218
215
  int timeout = Config.ad.adShowTimeoutInSecs;
219
216
  if (timeout == 0) // do not wait for Ad
220
217
  {
221
- _showState = ShowAdsState.ShowFail;
222
- OnAdShowReadyStatus(false, AdShowReadyStatus.TimeOut);
223
- ShowAdRoutineCompleted(false);
218
+ EndShowAdRoutineWithFailure(AdShowReadyStatus.TimeOut);
224
219
  yield break;
225
220
  }
226
221
 
227
222
  _showState = ShowAdsState.WaitForAd;
228
223
  OnAdShowReadyStatus(false, AdShowReadyStatus.WaitForAd);
229
224
 
230
- if (_loadState != LoadAdsState.Requesting) StartLoadAd();
231
- var counter = 0;
232
- bool? hasInternet = null;
233
- if (adConfig.checkInternet) _instance.StartCoroutine(WebUtils.CheckInternet(result => hasInternet = result));
234
-
235
- var wait1Sec = new WaitForSecondsRealtime(1f);
236
- while (counter < timeout || timeout == -1)
237
- {
238
- yield return wait1Sec;
239
- counter++;
240
-
241
- // finish checking internet & result is false
242
- if (adConfig.checkInternet && hasInternet == false)
243
- {
244
- Log("[Ad] Stop WaitForAd : No internet!");
245
- _showState = ShowAdsState.ShowFail;
246
- OnAdShowReadyStatus(false, AdShowReadyStatus.NoInternet);
247
- ShowAdRoutineCompleted(false);
248
- yield break;
249
- }
250
-
251
- if (_loadState != LoadAdsState.Ready) continue;
252
- Log("[Ad] WaitForAd success after " + counter + " | timeout = " + timeout + " secs");
253
- break;
254
- }
255
-
225
+ yield return WaitForAdReadyWithTimeout(timeout);
226
+
256
227
  if (!isAdReady)
257
228
  {
258
- Log("[Ad] WaitForAd failed (timeout) " + counter + " | timeout = " + timeout + " secs");
259
- OnAdShowReadyStatus(false, AdShowReadyStatus.TimeOut);
260
- ShowAdRoutineCompleted(false);
229
+ Log("[Ad] WaitForAd failed (timeout) " + " | timeout = " + timeout + " secs");
230
+ EndShowAdRoutineWithFailure(AdShowReadyStatus.TimeOut);
261
231
  yield break;
262
232
  }
263
233
  }
@@ -266,43 +236,78 @@ namespace Amanotes.Core.Internal
266
236
  OnAdShowReadyStatus(true, AdShowReadyStatus.Ready);
267
237
  TriggerBeforeAdShow();
268
238
  ShowAd();
239
+
240
+ yield return WaitForMediationCallback();
269
241
 
270
- while (!context.potentiallyCompleted)
271
- {
272
- yield return null; // callback as quickly as possible
273
- }
242
+ // wait 1 frame in case hasReward callback after onClose
243
+ if (!context.hasReward && adType == AdType.VideoReward && !context.hasFailedOrCancelled) yield return null;
244
+ ShowAdRoutineCompleted(context.isSuccess);
245
+ }
274
246
 
275
- if (adType == AdType.Interstitial)
276
- {
277
- ShowAdRoutineCompleted(!context.hasFailedOrCancelled);
278
- yield break;
279
- }
247
+ private void EndShowAdRoutineWithFailure(AdShowReadyStatus status)
248
+ {
249
+ _showState = ShowAdsState.ShowFail;
250
+ OnAdShowReadyStatus(false, status);
251
+ ShowAdRoutineCompleted(false);
252
+ }
280
253
 
281
- if (context.hasFailedOrCancelled)
254
+ private IEnumerator WaitForAdReadyWithTimeout(int timeout)
255
+ {
256
+ if (_loadState != LoadAdsState.Requesting) StartLoadAd();
257
+ var counter = 0;
258
+ bool? hasInternet = null;
259
+ if (adConfig.checkInternet) _instance.StartCoroutine(WebUtils.CheckInternet(result => hasInternet = result));
260
+
261
+ var wait1Sec = new WaitForSecondsRealtime(1f);
262
+ while (counter < timeout || timeout == -1)
282
263
  {
283
- Log($"[Ad] {adType} Waiting for [close]");
284
- yield return null;
285
- ShowAdRoutineCompleted(false);
286
- yield break;
264
+ yield return wait1Sec;
265
+ counter++;
266
+ Log($"[Ad] Waiting for ad {counter} secs");
267
+
268
+ // finish checking internet & result is false
269
+ if (adConfig.checkInternet && hasInternet == false)
270
+ {
271
+ Log("[Ad] Stop WaitForAd : No internet!");
272
+ EndShowAdRoutineWithFailure(AdShowReadyStatus.NoInternet);
273
+ yield break;
274
+ }
275
+
276
+ if (_loadState != LoadAdsState.Ready) continue;
277
+ Log("[Ad] WaitForAd success after " + counter + " | timeout = " + timeout + " secs");
278
+ break;
287
279
  }
280
+ }
288
281
 
289
- if (context.hasClosed)
282
+ private IEnumerator WaitForMediationCallback()
283
+ {
284
+ #if !UNITY_EDITOR
285
+ while (!isFocus) yield return null;
286
+ #endif
287
+
288
+ int wait4CallbackCounter = 0;
289
+ while (!context.potentiallyCompleted && wait4CallbackCounter <= MAX_FRAMES_WAIT_FOR_CALLBACK)
290
290
  {
291
- // wait 1 frame in case hasReward callback after onClose
292
- if (!context.hasReward) yield return null;
293
- ShowAdRoutineCompleted(context.hasReward);
294
- yield break;
291
+ wait4CallbackCounter++;
292
+ yield return null;
295
293
  }
294
+ Log($"[Ad] Waiting for potentially completed callback: {wait4CallbackCounter} frames");
295
+
296
+ if (!context.hasClosed) yield return WaitForAdClosedCallback();
297
+ }
296
298
 
297
- var wait4CloseCounter = 0;
298
- while (!context.hasClosed)
299
+ private IEnumerator WaitForAdClosedCallback()
300
+ {
301
+ int counter = 0;
302
+ while (!context.hasClosed && counter <= MAX_FRAMES_WAIT_FOR_CALLBACK)
299
303
  {
300
- wait4CloseCounter++;
301
- Log($"[Ad] {adType} Waiting for [close]: {wait4CloseCounter}");
304
+ counter++;
302
305
  yield return null;
303
306
  }
304
-
305
- ShowAdRoutineCompleted(true);
307
+ Log($"[Ad] Waiting for ad closed callback: {counter} frames");
308
+ if (context.hasClosed) yield break;
309
+ LogWarning("[Ad] Force close ad (mediation missing OnAdClose callback)");
310
+ OnAdClosed();
306
311
  }
307
312
 
308
313
  private void ShowAdRoutineCompleted(bool isSuccess)
@@ -315,9 +320,7 @@ namespace Amanotes.Core.Internal
315
320
 
316
321
  _showState = isSuccess ? ShowAdsState.ShowSuccess : ShowAdsState.ShowFail;
317
322
 
318
- // Extra callback
319
- Ads.context.showFinishAt = Time.realtimeSinceStartup;
320
- Ads.context.onAdResult?.Invoke(isSuccess);
323
+
321
324
 
322
325
  var localData = Ads.localData;
323
326
  var stat = _isInterstitial ? localData.interstitial : localData.reward;
@@ -336,8 +339,13 @@ namespace Amanotes.Core.Internal
336
339
  TriggerOnAfterAdShow();
337
340
 
338
341
  Log($"[Ad] {adType} ShowAdRoutineCompleted: {isSuccess}\n{JsonUtility.ToJson(Ads.context)}");
342
+
343
+ // Extra callback
344
+ context.showFinishAt = Time.realtimeSinceStartup;
345
+ var resultCallback = context.onAdResult;
339
346
  Ads.context = null;
340
347
  _showState = ShowAdsState.None;
348
+ resultCallback?.Invoke(isSuccess);
341
349
  }
342
350
 
343
351
  private void TriggerBeforeAdShow()
@@ -399,6 +407,11 @@ namespace Amanotes.Core.Internal
399
407
 
400
408
  if (Ads.context != null)
401
409
  {
410
+ if ((Ads.context.adCallback & AdCallback.Close) != 0)
411
+ {
412
+ LogWarning("[Ad] OnAdClosed() has been called multiple times for the same ad.");
413
+ return;
414
+ }
402
415
  Ads.context.adCallback |= AdCallback.Close;
403
416
  Ads.context.onClosed?.Invoke();
404
417
  } else
@@ -39,5 +39,6 @@ namespace Amanotes.Core.Internal
39
39
  public bool hasReward => (adCallback & AdCallback.Reward) != 0;
40
40
  public bool hasClosed => (adCallback & AdCallback.Close) != 0;
41
41
  public bool hasClicked => (adCallback & AdCallback.Click) != 0;
42
+ public bool isSuccess => (hasReward || adType == AdType.Interstitial) && !hasFailedOrCancelled;
42
43
  }
43
44
  }
@@ -150,8 +150,12 @@ namespace Amanotes.Core
150
150
  {
151
151
  internal static bool InitModule()
152
152
  {
153
+ if (Adapter2.GetAllAdapter<AdAdapter>().Count > 1)
154
+ {
155
+ Utils.ThrowExceptionIfEditor("Multiple AdAdapters is not supported!");
156
+ }
153
157
  _adapter = Adapter2.GetAdapter<AdAdapter>();
154
- return _adapter == null;
158
+ return _adapter != null;
155
159
  }
156
160
 
157
161
  internal static void StartModule()
@@ -181,24 +185,34 @@ namespace Amanotes.Core
181
185
  return false;
182
186
  }
183
187
 
184
- public static IAdCallback ShowInterstitial(string placementName = null, Dictionary<string, object> userData = null)
188
+ public static IAdCallback ShowInterstitial(Action<bool> onAdResult = null, string placementName = null, Dictionary<string, object> userData = null)
185
189
  {
186
190
  if (_adapter == null) return null;
187
191
  if (!ClearPrevContext()) return null;
188
192
 
189
193
  context = new AdShowContext(AdType.Interstitial, placementName, userData);
194
+ if (onAdResult != null)
195
+ {
196
+ context.onAdResult += onAdResult;
197
+ }
198
+
190
199
  _adapter.interstitial.StartShowAd();
191
200
  return context;
192
201
  }
193
202
 
194
203
  public static bool IsInterstitialShowing => (context != null) && (context.adType == AdType.Interstitial);
195
204
 
196
- public static IAdCallback ShowRewardedVideo(string placementName = null, Dictionary<string, object> userData = null)
205
+ public static IAdCallback ShowRewardedVideo(Action<bool> onAdResult = null, string placementName = null, Dictionary<string, object> userData = null)
197
206
  {
198
207
  if (_adapter == null) return null;
199
208
  if (!ClearPrevContext()) return null;
200
209
 
201
210
  context = new AdShowContext(AdType.VideoReward, placementName, userData);
211
+ if (onAdResult != null)
212
+ {
213
+ context.onAdResult += onAdResult;
214
+ }
215
+
202
216
  _adapter.rewardVideo.StartShowAd();
203
217
  return context;
204
218
  }
@@ -10,7 +10,7 @@ namespace Amanotes.Core.Internal
10
10
 
11
11
  public abstract partial class Adapter2
12
12
  {
13
- internal protected enum ConfigStatus
13
+ protected internal enum ConfigStatus
14
14
  {
15
15
  Ok,
16
16
  Invalid,
@@ -22,12 +22,15 @@ namespace Amanotes.Core.Internal
22
22
  [HideInNormalInspector] [SerializeField] internal bool enabled = true;
23
23
  [NonSerialized] internal string adapterId;
24
24
  [NonSerialized] internal string adapterVersion;
25
- [NonSerialized] internal protected Status status = Status.None;
25
+ [NonSerialized] protected internal Status status = Status.None;
26
26
 
27
27
  protected abstract void Init(Action<bool> onComplete);
28
- internal protected abstract string GetServiceKey();
29
- internal protected abstract ConfigStatus configStatus { get; }
30
-
28
+ protected internal abstract string GetServiceKey();
29
+ protected virtual float GetTimeoutInEditor() => 0.1f;
30
+ protected virtual float GetTimeoutInRuntime() => 0.1f;
31
+ protected internal abstract ConfigStatus configStatus { get; }
32
+ protected internal float Timeout => Application.isEditor ? GetTimeoutInEditor() : GetTimeoutInRuntime();
33
+
31
34
  public bool IsReady => status == Status.Ready;
32
35
 
33
36
  internal void InitSDK() // call by AmaGDK
@@ -63,6 +66,10 @@ namespace Amanotes.Core.Internal
63
66
  LogWarning($"Adapter <{id}> == null in ConfigAsset? (non-serialized?)");
64
67
  return false;
65
68
  }
69
+ if (!adapter.enabled)
70
+ {
71
+ return false;
72
+ }
66
73
 
67
74
  adapter.adapterId = id;
68
75
  adapter.adapterVersion = version;