com.amanotes.gdk 0.2.48 → 0.2.49
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.
- package/CHANGELOG.md +10 -0
- package/Editor/AmaGDKEditor.cs +133 -65
- package/Editor/AmaGDKExtra.cs +31 -0
- package/Editor/AmaGDKExtra.cs.meta +11 -0
- package/Editor/Utils/AmaGDKEditor.ExtractVersion.cs +1 -1
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/AmaGDKProject.unitypackage +0 -0
- package/Extra/SDKVersionTracking.unitypackage +0 -0
- package/Extra/SDKVersionTracking.unitypackage.meta +7 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
- package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
- package/Packages/IronSourceAdapter.unitypackage +0 -0
- package/Packages/RevenueCatAdapter.unitypackage +0 -0
- package/Runtime/AmaGDK.Adapters.cs +0 -4
- package/Runtime/AmaGDK.Ads.cs +89 -29
- package/Runtime/AmaGDK.Analytics.cs +97 -64
- package/Runtime/AmaGDK.IAP.cs +39 -45
- package/Runtime/AmaGDK.RemoteConfig.cs +76 -52
- package/Runtime/AmaGDK.UserProfile.cs +106 -124
- package/Runtime/AmaGDK.cs +46 -35
- package/Runtime/Internal/AmaGDK.Event.cs +185 -0
- package/Runtime/Internal/AmaGDK.Event.cs.meta +3 -0
- package/Runtime/Internal/AmaGDK.Internal.cs +3 -0
- package/Runtime/Internal/AmaGDK.Utils.cs +85 -24
- package/Runtime/Klavar/Attributes.meta +0 -4
- package/Runtime/Klavar.meta +0 -4
- package/package.json +1 -1
package/Runtime/AmaGDK.Ads.cs
CHANGED
|
@@ -9,6 +9,8 @@ using static Amanotes.Core.AmaGDK;
|
|
|
9
9
|
|
|
10
10
|
namespace Amanotes.Core
|
|
11
11
|
{
|
|
12
|
+
|
|
13
|
+
|
|
12
14
|
public static class AdExtension
|
|
13
15
|
{
|
|
14
16
|
public static IAdCallback OnAdOpened(this IAdCallback ad, Action callback)
|
|
@@ -18,7 +20,7 @@ namespace Amanotes.Core
|
|
|
18
20
|
Ads.context.onOpened += callback;
|
|
19
21
|
return ad;
|
|
20
22
|
}
|
|
21
|
-
|
|
23
|
+
|
|
22
24
|
public static IAdCallback OnRewardReceived(this IAdCallback ad, Action callback)
|
|
23
25
|
{
|
|
24
26
|
if (!MakeSureAdNotNull(ad)) return null;
|
|
@@ -26,7 +28,7 @@ namespace Amanotes.Core
|
|
|
26
28
|
Ads.context.onRewardReceived += callback;
|
|
27
29
|
return ad;
|
|
28
30
|
}
|
|
29
|
-
|
|
31
|
+
|
|
30
32
|
public static IAdCallback OnAdClicked(this IAdCallback ad, Action callback)
|
|
31
33
|
{
|
|
32
34
|
if (!MakeSureAdNotNull(ad)) return null;
|
|
@@ -34,7 +36,7 @@ namespace Amanotes.Core
|
|
|
34
36
|
Ads.context.onClicked += callback;
|
|
35
37
|
return ad;
|
|
36
38
|
}
|
|
37
|
-
|
|
39
|
+
|
|
38
40
|
public static IAdCallback OnAdShowFailed(this IAdCallback ad, Action callback)
|
|
39
41
|
{
|
|
40
42
|
if (!MakeSureAdNotNull(ad)) return null;
|
|
@@ -42,7 +44,7 @@ namespace Amanotes.Core
|
|
|
42
44
|
Ads.context.onShowFailed += callback;
|
|
43
45
|
return ad;
|
|
44
46
|
}
|
|
45
|
-
|
|
47
|
+
|
|
46
48
|
public static IAdCallback OnAdShowSuccess(this IAdCallback ad, Action callback)
|
|
47
49
|
{
|
|
48
50
|
if (!MakeSureAdNotNull(ad)) return null;
|
|
@@ -50,7 +52,7 @@ namespace Amanotes.Core
|
|
|
50
52
|
Ads.context.onShowSuccess += callback;
|
|
51
53
|
return ad;
|
|
52
54
|
}
|
|
53
|
-
|
|
55
|
+
|
|
54
56
|
public static IAdCallback OnAdClosed(this IAdCallback ad, Action callback)
|
|
55
57
|
{
|
|
56
58
|
if (!MakeSureAdNotNull(ad)) return null;
|
|
@@ -99,6 +101,27 @@ namespace Amanotes.Core
|
|
|
99
101
|
}
|
|
100
102
|
public partial class AmaGDK // Ads module
|
|
101
103
|
{
|
|
104
|
+
public static partial class Event
|
|
105
|
+
{
|
|
106
|
+
public const string INTER_REQUEST = nameof(INTER_REQUEST);
|
|
107
|
+
public const string INTER_SHOW_CALLED = nameof(INTER_SHOW_CALLED);
|
|
108
|
+
public const string INTER_SHOW_READY = nameof(INTER_SHOW_READY);
|
|
109
|
+
public const string INTER_SHOW_NOT_READY = nameof(INTER_SHOW_NOT_READY); // reason: string
|
|
110
|
+
public const string INTER_SHOW_BEGIN = nameof(INTER_SHOW_BEGIN); // always call result: true / false
|
|
111
|
+
public const string INTER_SHOW_END = nameof(INTER_SHOW_END); // always call result: true / false
|
|
112
|
+
|
|
113
|
+
public const string REWARD_REQUEST = nameof(REWARD_REQUEST);
|
|
114
|
+
public const string REWARD_VIDEO_SHOW_CALLED = nameof(REWARD_VIDEO_SHOW_CALLED);
|
|
115
|
+
public const string REWARD_VIDEO_SHOW_READY = nameof(REWARD_VIDEO_SHOW_READY);
|
|
116
|
+
public const string REWARD_VIDEO_SHOW_NOT_READY = nameof(REWARD_VIDEO_SHOW_NOT_READY); // reason: string
|
|
117
|
+
// public const string REWARD_VIDEO_REWARD_GRANTED = nameof(REWARD_VIDEO_REWARD_GRANTED);
|
|
118
|
+
public const string REWARD_VIDEO_SHOW_BEGIN = nameof(REWARD_VIDEO_SHOW_BEGIN); // always call result: true / false
|
|
119
|
+
public const string REWARD_VIDEO_SHOW_END = nameof(REWARD_VIDEO_SHOW_END); // always call result: true / false
|
|
120
|
+
|
|
121
|
+
public const string BANNER_SHOW = nameof(BANNER_SHOW);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
102
125
|
[Serializable]
|
|
103
126
|
internal class AdStat
|
|
104
127
|
{
|
|
@@ -177,6 +200,41 @@ namespace Amanotes.Core
|
|
|
177
200
|
internal protected static AdAdapter _adapter;
|
|
178
201
|
internal protected static float _savedVolume = -1;
|
|
179
202
|
internal protected static float _savedTimeScale = -1;
|
|
203
|
+
|
|
204
|
+
public static void OnInter_Request(Action callback)
|
|
205
|
+
{
|
|
206
|
+
dispatcher.AddListener(Event.INTER_REQUEST, callback, false);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public static void OnInter_ShowCalled(Action callback)
|
|
210
|
+
{
|
|
211
|
+
dispatcher.AddListener(Event.INTER_SHOW_CALLED, callback, false);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
public static void OnReward_ShowCalled(Action callback)
|
|
215
|
+
{
|
|
216
|
+
dispatcher.AddListener(Event.REWARD_VIDEO_SHOW_CALLED, callback, false);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public static void OnInter_ShowReady(Action callback)
|
|
220
|
+
{
|
|
221
|
+
dispatcher.AddListener(Event.INTER_SHOW_READY, callback, false);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
public static void OnReward_ShowReady(Action callback)
|
|
225
|
+
{
|
|
226
|
+
dispatcher.AddListener(Event.REWARD_VIDEO_SHOW_READY, callback, false);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public static void OnInter_ShowNotReady(Action<AdShowReadyStatus> callback)
|
|
230
|
+
{
|
|
231
|
+
dispatcher.AddListener(Event.INTER_SHOW_NOT_READY, callback, false);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
public static void OnReward_ShowNotReady(Action<AdShowReadyStatus> callback)
|
|
235
|
+
{
|
|
236
|
+
dispatcher.AddListener(Event.REWARD_VIDEO_SHOW_NOT_READY, callback, false);
|
|
237
|
+
}
|
|
180
238
|
}
|
|
181
239
|
|
|
182
240
|
public partial class Ads // Public
|
|
@@ -247,10 +305,11 @@ namespace Amanotes.Core
|
|
|
247
305
|
|
|
248
306
|
if (_adapter == null)
|
|
249
307
|
{
|
|
250
|
-
//Debug.LogWarning("Adapter not found???");
|
|
251
308
|
return;
|
|
252
309
|
}
|
|
253
310
|
|
|
311
|
+
|
|
312
|
+
dispatcher.Dispatch(Event.BANNER_SHOW);
|
|
254
313
|
_adapter.ShowBanner(_showingBannerPosition);
|
|
255
314
|
}
|
|
256
315
|
|
|
@@ -344,8 +403,6 @@ namespace Amanotes.Core.Internal
|
|
|
344
403
|
public abstract void HideBanner();
|
|
345
404
|
|
|
346
405
|
// Internally used
|
|
347
|
-
internal protected abstract void HandleBeforeAdShow();
|
|
348
|
-
internal protected abstract void HandleAfterAdShow();
|
|
349
406
|
internal protected abstract void SetUserId(string userId);
|
|
350
407
|
}
|
|
351
408
|
|
|
@@ -524,6 +581,9 @@ namespace Amanotes.Core.Internal
|
|
|
524
581
|
_isRequesting = true;
|
|
525
582
|
Log("[Ad] LoadAdRoutine: RequestAd()");
|
|
526
583
|
RequestAd();
|
|
584
|
+
dispatcher.Dispatch(
|
|
585
|
+
_isInterstitial ? AmaGDK.Event.INTER_REQUEST : AmaGDK.Event.REWARD_REQUEST
|
|
586
|
+
);
|
|
527
587
|
|
|
528
588
|
int timeout = Config.ad.adLoadTimeoutInSecs;
|
|
529
589
|
var counter = 0;
|
|
@@ -581,7 +641,9 @@ namespace Amanotes.Core.Internal
|
|
|
581
641
|
AdStat stat = Ads.localData.GetStat(adType);
|
|
582
642
|
stat.callCount++;
|
|
583
643
|
stat.lastCallTime = Time.realtimeSinceStartup;
|
|
584
|
-
|
|
644
|
+
dispatcher.Dispatch(
|
|
645
|
+
_isInterstitial ? AmaGDK.Event.INTER_SHOW_CALLED : AmaGDK.Event.REWARD_VIDEO_SHOW_CALLED
|
|
646
|
+
);
|
|
585
647
|
|
|
586
648
|
if (_showAdRoutine != null) _instance.StopCoroutine(_showAdRoutine);
|
|
587
649
|
_showAdRoutine = _instance.StartCoroutine(ShowAdRoutine());
|
|
@@ -597,7 +659,7 @@ namespace Amanotes.Core.Internal
|
|
|
597
659
|
StartLoadAd();
|
|
598
660
|
}
|
|
599
661
|
|
|
600
|
-
|
|
662
|
+
TriggerOnAfterAdShow();
|
|
601
663
|
if (_showAdRoutine == null) return;
|
|
602
664
|
_instance.StopCoroutine(_showAdRoutine);
|
|
603
665
|
_showAdRoutine = null;
|
|
@@ -682,10 +744,9 @@ namespace Amanotes.Core.Internal
|
|
|
682
744
|
|
|
683
745
|
_showState = ShowAdsState.Showing;
|
|
684
746
|
OnAdShowReadyStatus(true, AdShowReadyStatus.Ready);
|
|
685
|
-
|
|
747
|
+
TriggerBeforeAdShow();
|
|
686
748
|
ShowAd();
|
|
687
|
-
|
|
688
|
-
AdShowContext context = Ads.context;
|
|
749
|
+
|
|
689
750
|
while (!context.potentiallyCompleted)
|
|
690
751
|
{
|
|
691
752
|
yield return null; // callback as quickly as possible
|
|
@@ -750,14 +811,14 @@ namespace Amanotes.Core.Internal
|
|
|
750
811
|
}
|
|
751
812
|
|
|
752
813
|
localData.Save();
|
|
753
|
-
|
|
814
|
+
TriggerOnAfterAdShow();
|
|
754
815
|
|
|
755
816
|
Log($"[Ad] {adType} ShowAdRoutineCompleted: {isSuccess}\n{JsonUtility.ToJson(Ads.context)}");
|
|
756
817
|
Ads.context = null;
|
|
757
818
|
_showState = ShowAdsState.None;
|
|
758
819
|
}
|
|
759
820
|
|
|
760
|
-
private void
|
|
821
|
+
private void TriggerBeforeAdShow()
|
|
761
822
|
{
|
|
762
823
|
bool willSaveVolume = Config.ad.autoMute
|
|
763
824
|
&& AudioListener.volume > 0
|
|
@@ -779,11 +840,11 @@ namespace Amanotes.Core.Internal
|
|
|
779
840
|
Time.timeScale = 0;
|
|
780
841
|
}
|
|
781
842
|
|
|
843
|
+
dispatcher.Dispatch(_isInterstitial ? AmaGDK.Event.INTER_SHOW_BEGIN : AmaGDK.Event.REWARD_VIDEO_SHOW_BEGIN);
|
|
782
844
|
Ads.context.onBeforeAdOpen?.Invoke();
|
|
783
|
-
Ads._adapter.HandleBeforeAdShow();
|
|
784
845
|
}
|
|
785
846
|
|
|
786
|
-
private void
|
|
847
|
+
private void TriggerOnAfterAdShow()
|
|
787
848
|
{
|
|
788
849
|
bool willRestoreVolume = Config.ad.autoMute
|
|
789
850
|
&& AudioListener.volume == 0
|
|
@@ -804,8 +865,9 @@ namespace Amanotes.Core.Internal
|
|
|
804
865
|
Time.timeScale = Ads._savedTimeScale;
|
|
805
866
|
Ads._savedTimeScale = -1;
|
|
806
867
|
}
|
|
807
|
-
|
|
808
|
-
|
|
868
|
+
|
|
869
|
+
bool isSuccess = _showState == ShowAdsState.ShowSuccess;
|
|
870
|
+
dispatcher.Dispatch(_isInterstitial ? AmaGDK.Event.INTER_SHOW_END : AmaGDK.Event.REWARD_VIDEO_SHOW_END, isSuccess);
|
|
809
871
|
}
|
|
810
872
|
|
|
811
873
|
// Default implementation
|
|
@@ -877,20 +939,18 @@ namespace Amanotes.Core.Internal
|
|
|
877
939
|
Ads.context.onAdShowReadyStatus?.Invoke(status);
|
|
878
940
|
if (status == AdShowReadyStatus.Ready)
|
|
879
941
|
{
|
|
880
|
-
|
|
942
|
+
dispatcher.Dispatch(
|
|
943
|
+
_isInterstitial ? AmaGDK.Event.INTER_SHOW_READY : AmaGDK.Event.REWARD_VIDEO_SHOW_READY
|
|
944
|
+
);
|
|
881
945
|
} else if (status == AdShowReadyStatus.NoInternet || status == AdShowReadyStatus.TimeOut || status == AdShowReadyStatus.Wifi3GDisabled)
|
|
882
946
|
{
|
|
883
|
-
|
|
947
|
+
dispatcher.Dispatch(
|
|
948
|
+
_isInterstitial ? AmaGDK.Event.INTER_SHOW_NOT_READY : AmaGDK.Event.REWARD_VIDEO_SHOW_NOT_READY,
|
|
949
|
+
status
|
|
950
|
+
);
|
|
884
951
|
}
|
|
885
952
|
}
|
|
886
|
-
|
|
887
|
-
protected virtual void OnAdShowCalled()
|
|
888
|
-
{ }
|
|
889
|
-
protected virtual void OnAdShowReady()
|
|
890
|
-
{ }
|
|
891
|
-
protected virtual void OnAdShowNotReady(AdShowReadyStatus status)
|
|
892
|
-
{ }
|
|
893
|
-
|
|
953
|
+
|
|
894
954
|
protected void OnAdOpen()
|
|
895
955
|
{
|
|
896
956
|
Log($"[Ad] {adType} OnAdOpen");
|
|
@@ -26,6 +26,7 @@ namespace Amanotes.Core
|
|
|
26
26
|
public string funnelSignature;
|
|
27
27
|
public bool accumulated;
|
|
28
28
|
public bool withinSession;
|
|
29
|
+
public bool doNotIncreaseCounter;
|
|
29
30
|
|
|
30
31
|
public bool overrideConfig;
|
|
31
32
|
public HashSet<string> ignoreAdapterIds = new HashSet<string>();
|
|
@@ -241,11 +242,15 @@ namespace Amanotes.Core
|
|
|
241
242
|
internal static readonly List<AnalyticsAdapter> listAdapters = new List<AnalyticsAdapter>();
|
|
242
243
|
internal static readonly AnalyticsData localData = new AnalyticsData().LoadJsonFromFile();
|
|
243
244
|
internal static readonly SessionStat sessionStat = new SessionStat();
|
|
244
|
-
|
|
245
|
-
internal static readonly
|
|
246
|
-
|
|
245
|
+
|
|
246
|
+
internal static readonly Dictionary<string, string> reservedPrefixes = new Dictionary<string, string>()
|
|
247
|
+
{
|
|
248
|
+
{ "firebase_", "frb_" },
|
|
249
|
+
{ "google_", "ggl_" },
|
|
250
|
+
{ "ga_", "gga_" }
|
|
247
251
|
};
|
|
248
|
-
|
|
252
|
+
|
|
253
|
+
internal static readonly HashSet<string> reservedEvents = new HashSet<string>()
|
|
249
254
|
{
|
|
250
255
|
"ad_activeview",
|
|
251
256
|
"ad_click",
|
|
@@ -284,8 +289,6 @@ namespace Amanotes.Core
|
|
|
284
289
|
{
|
|
285
290
|
listAdapters.Clear();
|
|
286
291
|
listAdapters.AddRange(Adapter2.GetAllAdapter<AnalyticsAdapter>());
|
|
287
|
-
if (listAdapters.Count != 0)
|
|
288
|
-
primaryAdapter = listAdapters.Find(a => a.adapterId == AdapterID.FIREBASE_ANALYTICS) ?? listAdapters[0];
|
|
289
292
|
}
|
|
290
293
|
|
|
291
294
|
internal static void StartModule()
|
|
@@ -320,19 +323,34 @@ namespace Amanotes.Core
|
|
|
320
323
|
UpdateAccumulatedCount(eventData, countInSession, totalCount);
|
|
321
324
|
}
|
|
322
325
|
|
|
323
|
-
eventData.
|
|
326
|
+
if (!eventData.parameters.ContainsKey("ama_device_id"))
|
|
327
|
+
eventData.AddParam("ama_device_id", User.AmaDeviceId);
|
|
324
328
|
|
|
325
329
|
string eventNameToSend = GetEventNameToSend(eventData.eventName, countInSession, totalCount);
|
|
326
330
|
if (config.normalizeEventName) NormalizeEventName(ref eventNameToSend);
|
|
327
331
|
|
|
328
|
-
if (showAnalyticsLog)
|
|
332
|
+
if (showAnalyticsLog)
|
|
333
|
+
{
|
|
334
|
+
Debug.Log($"AmaGDK [Analytics] Event <{eventNameToSend}> (in session: {countInSession}, total: {totalCount})\n{JsonUtils.DictionaryToJson(eventData.parameters, true)}");
|
|
335
|
+
}
|
|
329
336
|
|
|
330
337
|
config.quality.CheckEventQuality(eventData.eventName, eventData.parameters);
|
|
331
338
|
|
|
332
339
|
var inUseAdapterIDs = new List<string>();
|
|
333
340
|
foreach (AnalyticsAdapter m in listAdapters)
|
|
334
341
|
{
|
|
335
|
-
if (
|
|
342
|
+
if (eventData.overrideConfig)
|
|
343
|
+
{
|
|
344
|
+
// IMPORTANT NOTE:
|
|
345
|
+
//
|
|
346
|
+
// Once set overrideConfig, we should skip the adapter config completely!!!
|
|
347
|
+
//
|
|
348
|
+
if (eventData.IsAdapterForbidden(m.adapterId)) continue;
|
|
349
|
+
}
|
|
350
|
+
else // Do not remove else
|
|
351
|
+
{
|
|
352
|
+
if (m.IsForbidden(eventData.eventName)) continue;
|
|
353
|
+
}
|
|
336
354
|
m.LogEvent(eventNameToSend, eventData.parameters);
|
|
337
355
|
inUseAdapterIDs.Add(m.adapterId);
|
|
338
356
|
}
|
|
@@ -356,35 +374,18 @@ namespace Amanotes.Core
|
|
|
356
374
|
}
|
|
357
375
|
|
|
358
376
|
int.TryParse(eventData.parameters[ACCUMULATED_COUNT].ToString(), out int oriAccCount);
|
|
359
|
-
if (oriAccCount
|
|
360
|
-
{
|
|
361
|
-
eventData.AddParam(ACCUMULATED_COUNT, countByGDK);
|
|
362
|
-
}
|
|
363
|
-
else
|
|
377
|
+
if (oriAccCount != countByGDK)
|
|
364
378
|
{
|
|
365
379
|
LogWarning($"[Analytics] event <{eventData.eventName}> has difference in accumulated count. Original count: {oriAccCount}. AmaGDK count: {countByGDK}");
|
|
380
|
+
if (Config.analytics.migrateAccumulatedCount && !eventData.withinSession)
|
|
381
|
+
{
|
|
382
|
+
Log($"[Analytics] Update event count of event <{eventData.eventName}> from {countByGDK} to {oriAccCount}");
|
|
383
|
+
eventData.EventDetail.totalCount = oriAccCount;
|
|
384
|
+
localData._dirty = true;
|
|
385
|
+
}
|
|
366
386
|
}
|
|
367
387
|
}
|
|
368
388
|
|
|
369
|
-
internal static bool IsAdapterForbidden(AnalyticsAdapter adapter, EventParams eventData)
|
|
370
|
-
{
|
|
371
|
-
if (adapter == null) return false;
|
|
372
|
-
if (eventData.overrideConfig)
|
|
373
|
-
{
|
|
374
|
-
// IMPORTANT NOTE:
|
|
375
|
-
//
|
|
376
|
-
// Once set overrideConfig, we should skip the adapter config completely!!!
|
|
377
|
-
//
|
|
378
|
-
if (eventData.IsAdapterForbidden(adapter.adapterId)) return true;
|
|
379
|
-
}
|
|
380
|
-
else // Do not remove else
|
|
381
|
-
{
|
|
382
|
-
if (adapter.IsForbidden(eventData.eventName)) return true;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
389
|
internal static string GetEventNameToSend(string eventName, int countInSession, int totalCount)
|
|
389
390
|
{
|
|
390
391
|
if (!sendAtCount.TryGetValue(eventName, out var config)) return eventName;
|
|
@@ -401,14 +402,14 @@ namespace Amanotes.Core
|
|
|
401
402
|
StringBuilder sb = tmpWarningSB;
|
|
402
403
|
sb.Clear();
|
|
403
404
|
NormalizeKeyString(ref eventName, sb, dryRun);
|
|
404
|
-
if (
|
|
405
|
+
if (reservedEvents.Contains(eventName))
|
|
405
406
|
sb.AppendLine($" - EventName <{eventName}> is reserved and should not be used");
|
|
406
407
|
if (sb.Length > 0 && dryRun) LogWarningOnce($"Warning for event name <{eventName}>:\n{sb}", $"NormalizeEventName<{eventName}>");
|
|
407
408
|
}
|
|
408
409
|
Profiler.EndSample();
|
|
409
410
|
}
|
|
410
411
|
|
|
411
|
-
internal static void NormalizeKeyString(ref string key, StringBuilder warningLog, bool dryRun
|
|
412
|
+
internal static void NormalizeKeyString(ref string key, StringBuilder warningLog, bool dryRun)
|
|
412
413
|
{
|
|
413
414
|
Profiler.BeginSample("AmaGDK.Analytics.NormalizeEventName()");
|
|
414
415
|
{
|
|
@@ -418,47 +419,53 @@ namespace Amanotes.Core
|
|
|
418
419
|
Profiler.EndSample();
|
|
419
420
|
return;
|
|
420
421
|
}
|
|
422
|
+
|
|
423
|
+
var sb = new StringBuilder();
|
|
421
424
|
|
|
422
425
|
string normalizedString = key.Trim()
|
|
423
426
|
.Replace(' ', '_')
|
|
424
427
|
.Replace('-', '_');
|
|
425
|
-
|
|
426
428
|
if (key != normalizedString)
|
|
427
429
|
{
|
|
428
|
-
|
|
429
|
-
{
|
|
430
|
-
key = normalizedString;
|
|
431
|
-
} else
|
|
432
|
-
{
|
|
433
|
-
warningLog.AppendLine($" - Malformed name (should not contains <space> or <dash>): <{key}>");
|
|
434
|
-
}
|
|
430
|
+
sb.Append($" - Malformed name (should not contains <space> or <dash>): <{key}>");
|
|
435
431
|
}
|
|
436
432
|
|
|
437
433
|
var r = new Regex("^[a-zA-Z0-9_]*$");
|
|
438
434
|
if (!r.IsMatch(normalizedString))
|
|
439
435
|
{
|
|
440
|
-
|
|
436
|
+
normalizedString = Regex.Replace(normalizedString, "[^a-zA-Z0-9_]", "");
|
|
437
|
+
sb.Append(" - Name may only contain alphanumeric characters and underscores");
|
|
441
438
|
}
|
|
442
439
|
|
|
443
|
-
if (!char.IsLetter(
|
|
440
|
+
if (!char.IsLetter(normalizedString[0]))
|
|
444
441
|
{
|
|
445
|
-
|
|
442
|
+
normalizedString = "E" + normalizedString;
|
|
443
|
+
sb.Append($" - Name must start with a letter: <{key}> ");
|
|
446
444
|
}
|
|
447
445
|
|
|
448
|
-
foreach (var prefix in
|
|
446
|
+
foreach (var prefix in reservedPrefixes)
|
|
449
447
|
{
|
|
450
|
-
if (!normalizedString.StartsWith(prefix)) continue;
|
|
451
|
-
|
|
448
|
+
if (!normalizedString.StartsWith(prefix.Key)) continue;
|
|
449
|
+
normalizedString = prefix.Value + normalizedString.Remove(0, prefix.Key.Length);
|
|
450
|
+
sb.AppendLine($" - <{key}> starts with reserved prefix <{prefix}>");
|
|
452
451
|
}
|
|
453
452
|
|
|
454
|
-
if (
|
|
453
|
+
if (normalizedString.Length > 40)
|
|
454
|
+
{
|
|
455
|
+
sb.AppendLine($" - Name is too long ({key.Length} > 40): <{key}> ");
|
|
456
|
+
normalizedString = normalizedString.Substring(0, 40);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (dryRun)
|
|
455
460
|
{
|
|
456
|
-
warningLog.
|
|
461
|
+
warningLog.Append(sb);
|
|
462
|
+
} else {
|
|
463
|
+
key = normalizedString;
|
|
457
464
|
}
|
|
458
465
|
}
|
|
459
466
|
Profiler.EndSample();
|
|
460
467
|
}
|
|
461
|
-
|
|
468
|
+
|
|
462
469
|
internal static bool ShouldSendEvent(EventParams eventData)
|
|
463
470
|
{
|
|
464
471
|
//Funnel event
|
|
@@ -609,8 +616,7 @@ namespace Amanotes.Core
|
|
|
609
616
|
internal (int countInSession, int totalCount) IncreaseCounter(EventParams eventParams)
|
|
610
617
|
{
|
|
611
618
|
EventDetail result = GetEventDetail(eventParams.eventName, true);
|
|
612
|
-
if (
|
|
613
|
-
return (result.countInSession, result.totalCount);
|
|
619
|
+
if (eventParams.doNotIncreaseCounter) return (result.countInSession, result.totalCount);
|
|
614
620
|
result.countInSession++;
|
|
615
621
|
result.totalCount++;
|
|
616
622
|
_dirty = true;
|
|
@@ -708,6 +714,15 @@ namespace Amanotes.Core
|
|
|
708
714
|
return ap;
|
|
709
715
|
}
|
|
710
716
|
|
|
717
|
+
public static IEventParamsBuilder SkipAccumulatedCount(this IEventParamsBuilder ap)
|
|
718
|
+
{
|
|
719
|
+
if (ap == null) return null;
|
|
720
|
+
|
|
721
|
+
var data = ap as EventParams;
|
|
722
|
+
data!.doNotIncreaseCounter = true;
|
|
723
|
+
return ap;
|
|
724
|
+
}
|
|
725
|
+
|
|
711
726
|
public static IEventParamsBuilder Except(this IEventParamsBuilder ap, params string[] analyticIds)
|
|
712
727
|
{
|
|
713
728
|
if (ap == null) return null;
|
|
@@ -759,7 +774,7 @@ namespace Amanotes.Core
|
|
|
759
774
|
public static IEventParamsBuilder AddParam(this IEventParamsBuilder ap, string key, object value)
|
|
760
775
|
{
|
|
761
776
|
if (ap == null) return null;
|
|
762
|
-
if (!IsValidKeyValue(ap, key, value)) return ap;
|
|
777
|
+
if (!IsValidKeyValue(ap, ref key, ref value)) return ap;
|
|
763
778
|
|
|
764
779
|
var eventParams = ap as EventParams;
|
|
765
780
|
Dictionary<string, object> parameters = eventParams?.parameters;
|
|
@@ -789,10 +804,12 @@ namespace Amanotes.Core
|
|
|
789
804
|
return ap;
|
|
790
805
|
}
|
|
791
806
|
|
|
792
|
-
foreach (
|
|
807
|
+
foreach (var kvp in dictParams)
|
|
793
808
|
{
|
|
794
|
-
|
|
795
|
-
|
|
809
|
+
var key = kvp.Key;
|
|
810
|
+
var value = kvp.Value;
|
|
811
|
+
if (IsValidKeyValue(ap, ref key, ref value))
|
|
812
|
+
ap.AddParam(key, value);
|
|
796
813
|
}
|
|
797
814
|
return ap;
|
|
798
815
|
}
|
|
@@ -808,33 +825,48 @@ namespace Amanotes.Core
|
|
|
808
825
|
|
|
809
826
|
foreach (var kvp in parameters)
|
|
810
827
|
{
|
|
811
|
-
|
|
812
|
-
|
|
828
|
+
var key = kvp.key;
|
|
829
|
+
var value = kvp.value;
|
|
830
|
+
if (IsValidKeyValue(ap, ref key, ref value))
|
|
831
|
+
ap.AddParam(key, value);
|
|
813
832
|
}
|
|
814
833
|
return ap;
|
|
815
834
|
}
|
|
816
835
|
|
|
817
836
|
//https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Param
|
|
818
|
-
private static bool IsValidKeyValue(IEventParamsBuilder ap, string key, object value)
|
|
837
|
+
private static bool IsValidKeyValue(IEventParamsBuilder ap, ref string key, ref object value)
|
|
819
838
|
{
|
|
820
839
|
string eventName = (ap as EventParams)?.eventName;
|
|
821
840
|
|
|
822
841
|
StringBuilder sb = tmpWarningSB;
|
|
823
842
|
sb.Clear();
|
|
824
|
-
NormalizeKeyString(ref key, sb);
|
|
825
|
-
|
|
843
|
+
NormalizeKeyString(ref key, sb, AmaGDK.Config.analytics.normalizeEventName);
|
|
844
|
+
|
|
845
|
+
if (sb.Length > 0) LogWarningOnce($"Warning for event <{eventName}>, param <{key}>:\n{sb}", $"NormalizeParamKey <{eventName}>");
|
|
826
846
|
|
|
827
847
|
if (string.IsNullOrWhiteSpace(key))
|
|
828
848
|
{
|
|
829
849
|
LogWarning($"Param key is empty. Event name: {eventName}!");
|
|
830
850
|
return false;
|
|
831
851
|
}
|
|
852
|
+
|
|
832
853
|
if (value == null)
|
|
833
854
|
{
|
|
834
|
-
LogWarning($"Param value
|
|
855
|
+
LogWarning($"Param value is null. Event name: {eventName}, key: {key}!");
|
|
835
856
|
return false;
|
|
836
857
|
}
|
|
837
858
|
|
|
859
|
+
if (value.GetType() == typeof(string))
|
|
860
|
+
{
|
|
861
|
+
var v = value.ToString();
|
|
862
|
+
var strLimit = 100;
|
|
863
|
+
if (v.Length > strLimit)
|
|
864
|
+
{
|
|
865
|
+
value = v.Substring(0, strLimit);
|
|
866
|
+
LogWarning($"Param value exceeds the length limit ({strLimit}). Event name: {eventName}, key: {key}!");
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
|
|
838
870
|
return true;
|
|
839
871
|
}
|
|
840
872
|
}
|
|
@@ -848,6 +880,7 @@ namespace Amanotes.Core.Internal
|
|
|
848
880
|
public bool showAnalyticsLog = true;
|
|
849
881
|
public bool normalizeEventName = true;
|
|
850
882
|
public bool checkMigrationIntegrity = true;
|
|
883
|
+
public bool migrateAccumulatedCount = true;
|
|
851
884
|
public bool enableEventStat;
|
|
852
885
|
public AnalyticQualityConfig quality;
|
|
853
886
|
}
|