com.amanotes.gdk 0.1.8 → 0.1.10
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 +9 -0
- package/Editor/AmaGDKEditor.cs +3 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter_v9.1.0.unitypackage +0 -0
- package/Packages/IronsourceAdapter_v7.2.6.unitypackage +3 -0
- package/{Runtime/Interfaces.meta → Packages/IronsourceAdapter_v7.2.6.unitypackage.meta} +1 -2
- package/Runtime/AmaGDK.Adapters.cs +85 -17
- package/Runtime/AmaGDK.Ads.cs +235 -0
- package/Runtime/{Interfaces/Analytics/IAnalytics.cs.meta → AmaGDK.Ads.cs.meta} +1 -1
- package/Runtime/AmaGDK.Analytics.cs +59 -23
- package/Runtime/AmaGDK.Config.cs +82 -1
- package/Runtime/AmaGDK.Internal.cs +14 -41
- package/Runtime/AmaGDK.cs +27 -14
- package/Tests/Runtime/AmaGDKCoreTest.cs +2 -3
- package/Tests/Runtime/MigrationTest.cs +3 -3
- package/package.json +2 -1
- package/Runtime/Interfaces/Analytics/IAnalytics.cs +0 -6
- package/Runtime/Interfaces/Analytics.meta +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.10 - 2023-02-17]
|
|
4
|
+
### Release AmaGDK v0.1.10
|
|
5
|
+
### Support accumulated event within session
|
|
6
|
+
|
|
7
|
+
## [0.1.9 - 2023-02-15]
|
|
8
|
+
### Release AmaGDK v0.1.9
|
|
9
|
+
### Change Documentation URL
|
|
10
|
+
### Support API LogEvent(eventName, parameters)
|
|
11
|
+
|
|
3
12
|
## [0.1.8 - 2023-02-15]
|
|
4
13
|
### Release AmaGDK v0.1.8
|
|
5
14
|
### Add AdapterID
|
package/Editor/AmaGDKEditor.cs
CHANGED
|
@@ -108,7 +108,10 @@ namespace Amanotes.Core
|
|
|
108
108
|
void DrawGUI_ConfigDetail()
|
|
109
109
|
{
|
|
110
110
|
CreateCachedEditor(configAsset, null, ref editor);
|
|
111
|
+
var lbWidth = EditorGUIUtility.labelWidth;
|
|
112
|
+
EditorGUIUtility.labelWidth = 200f;
|
|
111
113
|
editor.OnInspectorGUI();
|
|
114
|
+
EditorGUIUtility.labelWidth = lbWidth;
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
void DrawGUI_ConfigAsset(){
|
|
Binary file
|
|
Binary file
|
|
@@ -5,41 +5,109 @@ using ConfigAsset = Amanotes.Core.Internal.ConfigAsset;
|
|
|
5
5
|
using Status = Amanotes.Core.Internal.Status;
|
|
6
6
|
using static Amanotes.Core.Internal.Logging;
|
|
7
7
|
using static Amanotes.Core.Internal.Messsage;
|
|
8
|
+
using System.Linq;
|
|
8
9
|
|
|
9
10
|
namespace Amanotes.Core.Internal
|
|
10
11
|
{
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
[Serializable] public class AdapterInfo
|
|
12
14
|
{
|
|
13
|
-
string
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
public string id;
|
|
16
|
+
public string version;
|
|
17
|
+
public int initOrder;
|
|
18
|
+
public Status status = Status.None;
|
|
19
|
+
public IAdapter adapter;
|
|
20
|
+
|
|
21
|
+
public bool IsReady { get { return status == Status.Ready; }}
|
|
22
|
+
|
|
23
|
+
public void Init(){
|
|
24
|
+
if (status != Status.None)
|
|
25
|
+
{
|
|
26
|
+
LogWarning($"Invalid status: {status}");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
status = Status.Initialize;
|
|
31
|
+
adapter.Init((success) =>
|
|
32
|
+
{
|
|
33
|
+
status = success ? Status.Ready : Status.Failed;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public T GetAdapterApi<T>(){ return (T)adapter; }
|
|
16
38
|
}
|
|
17
39
|
|
|
18
|
-
public
|
|
40
|
+
public interface IAdapter
|
|
19
41
|
{
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
42
|
+
void Init(Action<bool> onCompleted);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// public static class AdapterExtension
|
|
46
|
+
// {
|
|
47
|
+
// public static string GetId<T>(this T adapter) where T: IAdapter {
|
|
48
|
+
// return Adapter.GetId(typeof(T));
|
|
49
|
+
// }
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
public static class Adapter
|
|
53
|
+
{
|
|
54
|
+
internal static readonly List<AdapterInfo> listAdapters = new List<AdapterInfo>();
|
|
55
|
+
|
|
56
|
+
public static string GetId(Type adapterType) {
|
|
57
|
+
return adapterType.Name.Replace("Adapter", string.Empty);
|
|
58
|
+
}
|
|
24
59
|
|
|
25
|
-
public void
|
|
60
|
+
public static void Register<T>(string version) where T : IAdapter, new()
|
|
26
61
|
{
|
|
27
|
-
|
|
62
|
+
var typeT = typeof(T);
|
|
63
|
+
var id = GetId(typeT);
|
|
64
|
+
|
|
65
|
+
if (AmaGDK._status != Status.None)
|
|
28
66
|
{
|
|
29
|
-
|
|
67
|
+
LogWarningOnce($"RegisterAdapter - Invalid status: {AmaGDK._status}");
|
|
30
68
|
return;
|
|
31
69
|
}
|
|
32
70
|
|
|
33
|
-
|
|
34
|
-
|
|
71
|
+
var orderConfig = AmaGDK.Config.initOrder.FirstOrDefault(item => item.id == id);
|
|
72
|
+
listAdapters.Add(new AdapterInfo()
|
|
35
73
|
{
|
|
36
|
-
|
|
74
|
+
id = id,
|
|
75
|
+
version = version,
|
|
76
|
+
initOrder = (orderConfig != null) ? orderConfig.order : 0,
|
|
77
|
+
adapter = new T()
|
|
37
78
|
});
|
|
38
79
|
}
|
|
39
80
|
|
|
40
|
-
|
|
81
|
+
public static AdapterInfo Find<T>()
|
|
41
82
|
{
|
|
42
|
-
|
|
83
|
+
for (var i = 0; i < listAdapters.Count; i++)
|
|
84
|
+
{
|
|
85
|
+
var item = listAdapters[i];
|
|
86
|
+
var itemType = item.adapter.GetType();
|
|
87
|
+
if (!typeof(T).IsAssignableFrom(itemType)) continue;
|
|
88
|
+
return item;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return default;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public static List<AdapterInfo> FindAll<T>()
|
|
95
|
+
{
|
|
96
|
+
var result = new List<AdapterInfo>();
|
|
97
|
+
for (var i = 0; i < listAdapters.Count; i++)
|
|
98
|
+
{
|
|
99
|
+
var item = listAdapters[i];
|
|
100
|
+
var itemType = item.adapter.GetType();
|
|
101
|
+
if (!typeof(T).IsAssignableFrom(itemType)) continue;
|
|
102
|
+
result.Add(item);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public static T GetConfig<T>() where T : ConfigAsset
|
|
109
|
+
{
|
|
110
|
+
return (T)AmaGDK.Config;
|
|
43
111
|
}
|
|
44
112
|
}
|
|
45
113
|
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections;
|
|
3
|
+
|
|
4
|
+
using UnityEngine;
|
|
5
|
+
|
|
6
|
+
using Amanotes.Core.Internal;
|
|
7
|
+
using static Amanotes.Core.Internal.Logging;
|
|
8
|
+
|
|
9
|
+
namespace Amanotes.Core
|
|
10
|
+
{
|
|
11
|
+
public interface IAds
|
|
12
|
+
{
|
|
13
|
+
bool IsAdReady(AdType Type);
|
|
14
|
+
|
|
15
|
+
#region Interstitial
|
|
16
|
+
event Action InterstitialShowSucceededCallback;
|
|
17
|
+
event Action InterstitialShowFailedCallback;
|
|
18
|
+
event Action InterstitialClickedCallback;
|
|
19
|
+
void RequestInterstitial();
|
|
20
|
+
void ShowInterstitial();
|
|
21
|
+
void ShowInterstitial(string placementName);
|
|
22
|
+
#endregion FullAds
|
|
23
|
+
|
|
24
|
+
#region VideoAds
|
|
25
|
+
event Action RewardedVideoShowFailedCallback;
|
|
26
|
+
event Action RewardedVideoClosedCallback;
|
|
27
|
+
event Action RewardedCallback;
|
|
28
|
+
event Action RewardedVideoClickCallback;
|
|
29
|
+
void RequestRewardedVideo();
|
|
30
|
+
void ShowRewardedVideo();
|
|
31
|
+
void ShowRewardedVideo(string placementName);
|
|
32
|
+
#endregion VideoAds
|
|
33
|
+
|
|
34
|
+
#region Banner
|
|
35
|
+
event Action BannerAdsClickCallback;
|
|
36
|
+
event Action BannerShowCallback;
|
|
37
|
+
void RequestBanner(BannerPosition position = BannerPosition.TOP);
|
|
38
|
+
void RequestBanner(BannerPosition position, string placementName);
|
|
39
|
+
void ShowBanner();
|
|
40
|
+
void HideBanner();
|
|
41
|
+
#endregion Banner
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public enum BannerPosition
|
|
45
|
+
{
|
|
46
|
+
TOP = 1,
|
|
47
|
+
BOTTOM = 2
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
public enum AdType : byte
|
|
51
|
+
{
|
|
52
|
+
Interstitial,
|
|
53
|
+
Reward,
|
|
54
|
+
Banner
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
public partial class AmaGDK // IAds module
|
|
58
|
+
{
|
|
59
|
+
public static class Ads
|
|
60
|
+
{
|
|
61
|
+
internal static IAds adsModule;
|
|
62
|
+
public static Action<string> OnInterstitalFailCallback;
|
|
63
|
+
public static Action<string> OnRewardedVideoFailCallback;
|
|
64
|
+
|
|
65
|
+
public static void Init()
|
|
66
|
+
{
|
|
67
|
+
var adsModules = Adapter.FindAll<IAds>();
|
|
68
|
+
|
|
69
|
+
if (adsModules == null || adsModules.Count < 1)
|
|
70
|
+
{
|
|
71
|
+
LogError("Ads module not found!");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (adsModules.Count > 1)
|
|
76
|
+
{
|
|
77
|
+
LogError("Multiple Ads modules is not supported!");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
adsModule = adsModules[0].GetAdapterApi<IAds>();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public static void RequestBanner(BannerPosition position)
|
|
85
|
+
{
|
|
86
|
+
if (adsModule == null)
|
|
87
|
+
{
|
|
88
|
+
LogWarning("Ads module is not initialized");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
adsModule.RequestBanner(position);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public static void ShowBanner()
|
|
95
|
+
{
|
|
96
|
+
adsModule.ShowBanner();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public static void HideBanner()
|
|
100
|
+
{
|
|
101
|
+
if (!adsModule.IsAdReady(AdType.Banner))
|
|
102
|
+
{
|
|
103
|
+
LogWarning("Banner is not ready");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
adsModule.HideBanner();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public static void RequestInterstitial()
|
|
111
|
+
{
|
|
112
|
+
if (adsModule == null)
|
|
113
|
+
{
|
|
114
|
+
LogWarning("Ads module is not initialized");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
adsModule.RequestInterstitial();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
public static void ShowInterstitial()
|
|
121
|
+
{
|
|
122
|
+
if (!adsModule.IsAdReady(AdType.Interstitial))
|
|
123
|
+
{
|
|
124
|
+
LogWarning("Interstitial is not ready");
|
|
125
|
+
BeginCoroutine(IWaitShowInterstitial());
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
adsModule.ShowInterstitial();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
public static void RequestRewardedVideo()
|
|
132
|
+
{
|
|
133
|
+
if (adsModule == null)
|
|
134
|
+
{
|
|
135
|
+
LogWarning("Ads module is not initialized");
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
adsModule.RequestRewardedVideo();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public static void ShowRewardedVideo()
|
|
142
|
+
{
|
|
143
|
+
if (!adsModule.IsAdReady(AdType.Reward))
|
|
144
|
+
{
|
|
145
|
+
LogWarning("Reward is not ready");
|
|
146
|
+
BeginCoroutine(IWaitShowRewardedVideo());
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
adsModule.ShowRewardedVideo();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private static IEnumerator IWaitShowRewardedVideo()
|
|
153
|
+
{
|
|
154
|
+
LogWarning("Wait Show Rewarded Video");
|
|
155
|
+
if (adsModule == null)
|
|
156
|
+
{
|
|
157
|
+
OnRewardedVideoFailCallback?.Invoke("Not found ads module");
|
|
158
|
+
OnRewardedVideoFailCallback = null;
|
|
159
|
+
yield break;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
var startTime = Time.time;
|
|
163
|
+
float timeout = 5;
|
|
164
|
+
string error = null;
|
|
165
|
+
while (!adsModule.IsAdReady(AdType.Reward))
|
|
166
|
+
{
|
|
167
|
+
if (Application.internetReachability == NetworkReachability.NotReachable)
|
|
168
|
+
{
|
|
169
|
+
error = Application.internetReachability.ToString();
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if ((Time.time - startTime) > timeout)
|
|
174
|
+
{
|
|
175
|
+
error = "Timeout";
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
yield return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (adsModule.IsAdReady(AdType.Reward))
|
|
183
|
+
{
|
|
184
|
+
adsModule.ShowRewardedVideo();
|
|
185
|
+
}
|
|
186
|
+
else
|
|
187
|
+
{
|
|
188
|
+
OnRewardedVideoFailCallback?.Invoke(error);
|
|
189
|
+
OnRewardedVideoFailCallback = null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private static IEnumerator IWaitShowInterstitial()
|
|
194
|
+
{
|
|
195
|
+
LogWarning("Wait Show Interstitial");
|
|
196
|
+
if (adsModule == null)
|
|
197
|
+
{
|
|
198
|
+
OnInterstitalFailCallback?.Invoke("Not found ads module");
|
|
199
|
+
OnInterstitalFailCallback = null;
|
|
200
|
+
yield break;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
var startTime = Time.time;
|
|
204
|
+
float timeout = 5;
|
|
205
|
+
string error = null;
|
|
206
|
+
while (!adsModule.IsAdReady(AdType.Interstitial))
|
|
207
|
+
{
|
|
208
|
+
if (Application.internetReachability == NetworkReachability.NotReachable)
|
|
209
|
+
{
|
|
210
|
+
error = Application.internetReachability.ToString();
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if ((Time.time - startTime) > timeout)
|
|
215
|
+
{
|
|
216
|
+
error = "Timeout";
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
yield return null;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (adsModule.IsAdReady(AdType.Interstitial))
|
|
224
|
+
{
|
|
225
|
+
adsModule.ShowInterstitial();
|
|
226
|
+
}
|
|
227
|
+
else
|
|
228
|
+
{
|
|
229
|
+
OnInterstitalFailCallback?.Invoke(error);
|
|
230
|
+
OnInterstitalFailCallback = null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -22,6 +22,7 @@ namespace Amanotes.Core
|
|
|
22
22
|
public Dictionary<string, object> parameters = new Dictionary<string, object>();
|
|
23
23
|
public string funnelSignature;
|
|
24
24
|
public bool accumulated;
|
|
25
|
+
public bool withinSession;
|
|
25
26
|
public HashSet<string> ignoreAnalyticIds = new HashSet<string>();
|
|
26
27
|
public HashSet<string> allowAnalyticIds = new HashSet<string>();
|
|
27
28
|
|
|
@@ -43,15 +44,44 @@ namespace Amanotes.Core
|
|
|
43
44
|
return result;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
public static IEventParamsBuilder LogEvent(string eventName, Dictionary<string, object> parameters)
|
|
48
|
+
{
|
|
49
|
+
var result = new EventParams(eventName);
|
|
50
|
+
result.AddParam(parameters);
|
|
51
|
+
eventQueue.Enqueue(result);
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public static IEventParamsBuilder LogEvent(string eventName, params (string, object)[] parameters)
|
|
56
|
+
{
|
|
57
|
+
var result = new EventParams(eventName);
|
|
58
|
+
for (var i = 0;i < parameters.Length; i++)
|
|
59
|
+
{
|
|
60
|
+
result.AddParam(parameters[i].Item1, parameters[i].Item2);
|
|
61
|
+
}
|
|
62
|
+
eventQueue.Enqueue(result);
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
|
|
46
66
|
public static IEventParamsBuilder LogFunnelEvent(string eventName, string signature = "")
|
|
47
67
|
{
|
|
48
68
|
return LogEvent(eventName).SetAsFunnel(signature);
|
|
49
69
|
}
|
|
50
70
|
|
|
51
|
-
public static
|
|
71
|
+
public static IEventParamsBuilder LogFunnelEvent(string eventName, Dictionary<string, object> parameters, string signature = "")
|
|
72
|
+
{
|
|
73
|
+
return LogEvent(eventName, parameters).SetAsFunnel(signature);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public static IEventParamsBuilder LogFunnelEvent(string eventName, string signature = "", params (string, object)[] parameters)
|
|
77
|
+
{
|
|
78
|
+
return LogEvent(eventName, parameters).SetAsFunnel(signature);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public static int GetAccumulatedCount(string eventName, bool withinSession = false)
|
|
52
82
|
{
|
|
53
83
|
var eventDetail = localData.GetEventDetail(eventName);
|
|
54
|
-
return eventDetail != null ? eventDetail.
|
|
84
|
+
return eventDetail != null ? (withinSession ? eventDetail.countInSession : eventDetail.totalCount) : 0;
|
|
55
85
|
}
|
|
56
86
|
|
|
57
87
|
public static void SetLogEventCondition(Predicate<EventDetail> condition)
|
|
@@ -70,7 +100,7 @@ namespace Amanotes.Core
|
|
|
70
100
|
|
|
71
101
|
foreach (var s in listAdapters)
|
|
72
102
|
{
|
|
73
|
-
s.SetUserId(userId);
|
|
103
|
+
s.GetAdapterApi<IAnalyticAdapter>().SetUserId(userId);
|
|
74
104
|
}
|
|
75
105
|
}
|
|
76
106
|
|
|
@@ -84,10 +114,10 @@ namespace Amanotes.Core
|
|
|
84
114
|
|
|
85
115
|
foreach (var s in listAdapters)
|
|
86
116
|
{
|
|
87
|
-
s.SetUserProperty(key, value);
|
|
117
|
+
s.GetAdapterApi<IAnalyticAdapter>().SetUserProperty(key, value);
|
|
88
118
|
}
|
|
89
119
|
}
|
|
90
|
-
|
|
120
|
+
|
|
91
121
|
private static IntegrityFlag MergeData(List<string> funnelEvents, Dictionary<string, int> eventCountMap, bool sumEventCount)
|
|
92
122
|
{
|
|
93
123
|
var flag = IntegrityFlag.Ok;
|
|
@@ -108,20 +138,20 @@ namespace Amanotes.Core
|
|
|
108
138
|
localData.eventDetails.Add(new EventDetail
|
|
109
139
|
{
|
|
110
140
|
eventName = e.Key,
|
|
111
|
-
|
|
141
|
+
totalCount = e.Value
|
|
112
142
|
});
|
|
113
143
|
flag |= IntegrityFlag.NewEvent;
|
|
114
144
|
continue;
|
|
115
145
|
}
|
|
116
146
|
|
|
117
|
-
if (eventDetail.
|
|
147
|
+
if (eventDetail.totalCount != e.Value)
|
|
118
148
|
{
|
|
119
149
|
flag |= IntegrityFlag.DifferentCount;
|
|
120
150
|
}
|
|
121
151
|
|
|
122
152
|
if (sumEventCount)
|
|
123
153
|
{
|
|
124
|
-
eventDetail.
|
|
154
|
+
eventDetail.totalCount += e.Value;
|
|
125
155
|
}
|
|
126
156
|
}
|
|
127
157
|
|
|
@@ -158,13 +188,16 @@ namespace Amanotes.Core
|
|
|
158
188
|
{
|
|
159
189
|
internal static Predicate<EventDetail> logEventHook = null;
|
|
160
190
|
internal static readonly Queue<EventParams> eventQueue = new Queue<EventParams>();
|
|
161
|
-
internal static readonly List<
|
|
191
|
+
internal static readonly List<AdapterInfo> listAdapters = new List<AdapterInfo>();
|
|
162
192
|
internal static readonly AnalyticsData localData = new AnalyticsData().LoadJsonFromFile();
|
|
163
193
|
|
|
164
|
-
internal static void
|
|
194
|
+
internal static void Init()
|
|
165
195
|
{
|
|
166
196
|
listAdapters.Clear();
|
|
167
197
|
listAdapters.AddRange(Adapter.FindAll<IAnalyticAdapter>());
|
|
198
|
+
|
|
199
|
+
_frameUpdate -= ProcessEventQueue;
|
|
200
|
+
_frameUpdate += ProcessEventQueue;
|
|
168
201
|
}
|
|
169
202
|
|
|
170
203
|
internal static void ProcessEventQueue()
|
|
@@ -179,24 +212,22 @@ namespace Amanotes.Core
|
|
|
179
212
|
if (!NormalizeEventName(ref eventData.eventName))
|
|
180
213
|
continue;
|
|
181
214
|
|
|
182
|
-
var
|
|
215
|
+
var (countInSession, totalCount) = localData.IncreaseCounter(eventData.eventName);
|
|
183
216
|
|
|
184
217
|
if (!ShouldSendEvent(eventData))
|
|
185
218
|
continue;
|
|
186
219
|
|
|
187
220
|
if (eventData.accumulated)
|
|
188
221
|
{
|
|
189
|
-
eventData.AddParam("accumulated_count",
|
|
222
|
+
eventData.AddParam("accumulated_count", eventData.withinSession ? countInSession : totalCount);
|
|
190
223
|
}
|
|
191
224
|
|
|
192
225
|
foreach (var m in listAdapters)
|
|
193
226
|
{
|
|
194
|
-
|
|
195
|
-
if (eventData.ignoreAnalyticIds.Contains(id))
|
|
227
|
+
if (eventData.ignoreAnalyticIds.Contains(m.id))
|
|
196
228
|
continue;
|
|
197
|
-
|
|
198
|
-
m.
|
|
199
|
-
if (showAnalyticsLog) Debug.Log($"[{id}] Sent event <{eventData.eventName}> ({counter})");
|
|
229
|
+
m.GetAdapterApi<IAnalyticAdapter>().LogEvent(eventData);
|
|
230
|
+
if (showAnalyticsLog) Debug.Log($"[{m.id}] Sent event <{eventData.eventName}> (in session: {countInSession}, total: {totalCount})");
|
|
200
231
|
}
|
|
201
232
|
}
|
|
202
233
|
|
|
@@ -258,7 +289,9 @@ namespace Amanotes.Core
|
|
|
258
289
|
public class EventDetail
|
|
259
290
|
{
|
|
260
291
|
public string eventName;
|
|
261
|
-
public int
|
|
292
|
+
public int totalCount;
|
|
293
|
+
[NonSerialized]
|
|
294
|
+
public int countInSession;
|
|
262
295
|
}
|
|
263
296
|
|
|
264
297
|
[Flags]
|
|
@@ -324,12 +357,13 @@ namespace Amanotes.Core
|
|
|
324
357
|
return true;
|
|
325
358
|
}
|
|
326
359
|
|
|
327
|
-
internal int IncreaseCounter(string eventName)
|
|
360
|
+
internal (int countInSession, int totalCount) IncreaseCounter(string eventName)
|
|
328
361
|
{
|
|
329
362
|
var result = GetEventDetail(eventName, true);
|
|
330
|
-
result.
|
|
363
|
+
result.totalCount++;
|
|
364
|
+
result.countInSession++;
|
|
331
365
|
_dirty = true;
|
|
332
|
-
return result.
|
|
366
|
+
return (result.countInSession, result.totalCount);
|
|
333
367
|
}
|
|
334
368
|
|
|
335
369
|
internal void SaveIfDirty()
|
|
@@ -377,11 +411,13 @@ namespace Amanotes.Core
|
|
|
377
411
|
data.funnelSignature = string.IsNullOrEmpty(signature) ? data.eventName : signature;
|
|
378
412
|
return ap;
|
|
379
413
|
}
|
|
380
|
-
public static IEventParamsBuilder SetAsAccumulated(this IEventParamsBuilder ap)
|
|
414
|
+
public static IEventParamsBuilder SetAsAccumulated(this IEventParamsBuilder ap, bool withinSession = false)
|
|
381
415
|
{
|
|
382
416
|
if (ap == null) return null;
|
|
383
417
|
|
|
384
|
-
|
|
418
|
+
EventParams data = ap as EventParams;
|
|
419
|
+
data.accumulated = true;
|
|
420
|
+
if (withinSession) data.withinSession = true;
|
|
385
421
|
return ap;
|
|
386
422
|
}
|
|
387
423
|
|
package/Runtime/AmaGDK.Config.cs
CHANGED
|
@@ -1,13 +1,94 @@
|
|
|
1
1
|
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Reflection;
|
|
2
4
|
using UnityEngine;
|
|
3
5
|
|
|
6
|
+
#if UNITY_EDITOR
|
|
7
|
+
using UnityEditor;
|
|
8
|
+
#endif
|
|
9
|
+
|
|
4
10
|
namespace Amanotes.Core.Internal {
|
|
5
11
|
public partial class ConfigAsset : ScriptableObject
|
|
6
12
|
{
|
|
13
|
+
[SerializeField] internal bool simpleOrder = true;
|
|
14
|
+
[SerializeField] internal List<InitOrder> initOrder = new List<InitOrder>();
|
|
7
15
|
[SerializeField] internal SDKConfig common;
|
|
16
|
+
|
|
17
|
+
#if UNITY_EDITOR
|
|
18
|
+
void OnValidate()
|
|
19
|
+
{
|
|
20
|
+
if (Application.isPlaying) return;
|
|
21
|
+
if (simpleOrder) {
|
|
22
|
+
EditorApplication.update -= DelayCheckOrder;
|
|
23
|
+
EditorApplication.update += DelayCheckOrder;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
void DelayCheckOrder()
|
|
28
|
+
{
|
|
29
|
+
EditorApplication.update -= DelayCheckOrder;
|
|
30
|
+
var dirty = false;
|
|
31
|
+
for (var i =0 ;i < initOrder.Count;i++){
|
|
32
|
+
if (initOrder[i].order == i) continue;
|
|
33
|
+
dirty = true;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!dirty) return;
|
|
38
|
+
initOrder.Sort((a1, a2)=> a1.order.CompareTo(a2.order));
|
|
39
|
+
for (var i =0 ;i < initOrder.Count;i++){
|
|
40
|
+
initOrder[i].order = i;
|
|
41
|
+
}
|
|
42
|
+
EditorUtility.SetDirty(this);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[ContextMenu("Scan Adapters")]
|
|
46
|
+
void ScanAdapters()
|
|
47
|
+
{
|
|
48
|
+
initOrder.Clear();
|
|
49
|
+
|
|
50
|
+
var counter = 0;
|
|
51
|
+
foreach (var adapter in GetAllAdapters<IAdapter>())
|
|
52
|
+
{
|
|
53
|
+
var id = adapter.Name.Replace("Adapter", string.Empty);
|
|
54
|
+
initOrder.Add(new InitOrder(){ id = id, order = counter++ });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
[ContextMenu("Refresh Order")]
|
|
59
|
+
void UpdateOrderToPosition()
|
|
60
|
+
{
|
|
61
|
+
for (var i =0 ;i < initOrder.Count; i++)
|
|
62
|
+
{
|
|
63
|
+
initOrder[i].order = i;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public static IEnumerable<Type> GetAllAdapters<T>()
|
|
68
|
+
{
|
|
69
|
+
var typeT = typeof(T);
|
|
70
|
+
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
|
|
71
|
+
{
|
|
72
|
+
if (!a.FullName.Contains("Assembly-CSharp")) continue;
|
|
73
|
+
|
|
74
|
+
foreach (var type in a.GetTypes()){
|
|
75
|
+
if (typeT.IsAssignableFrom(type)) yield return type;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
#endif
|
|
8
80
|
}
|
|
9
81
|
|
|
10
|
-
[Serializable]
|
|
82
|
+
[Serializable]
|
|
83
|
+
internal partial class SDKConfig
|
|
84
|
+
{
|
|
11
85
|
public bool verboseLog = false;
|
|
12
86
|
}
|
|
87
|
+
|
|
88
|
+
[Serializable]
|
|
89
|
+
internal class InitOrder
|
|
90
|
+
{
|
|
91
|
+
public string id;
|
|
92
|
+
public int order;
|
|
93
|
+
}
|
|
13
94
|
}
|
|
@@ -25,20 +25,21 @@ namespace Amanotes.Core.Internal
|
|
|
25
25
|
|
|
26
26
|
public static class Res
|
|
27
27
|
{
|
|
28
|
-
|
|
28
|
+
#if AMAGDK_DEV
|
|
29
29
|
public const string BASE_PATH = "Assets/AmaGDKCore/";
|
|
30
|
-
|
|
30
|
+
#else
|
|
31
31
|
public const string BASE_PATH = "Packages/com.amanotes.gdk/";
|
|
32
|
-
|
|
32
|
+
#endif
|
|
33
33
|
|
|
34
34
|
public const string PACKAGE_PATH = BASE_PATH + "Packages/";
|
|
35
35
|
public const string AMAGDK_PREFAB = BASE_PATH + "Runtime/AmaGDK.prefab";
|
|
36
36
|
public const string AMAGDK_CONFIG_PACKAGE = PACKAGE_PATH + "AmaGDKConfig.unitypackage";
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
public static readonly string[] AMAGDK_ADAPTERS = new string[]
|
|
39
39
|
{
|
|
40
40
|
"FirebaseAnalyticsAdapter_v9.1.0",
|
|
41
41
|
//"AppsflyerAdapter_v6.5.4",
|
|
42
|
+
// "IronsourceAdapter_v7.2.6",
|
|
42
43
|
};
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -69,55 +70,27 @@ namespace Amanotes.Core.Internal
|
|
|
69
70
|
}
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
public static class
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
public static void Register(IAdapter adapter)
|
|
76
|
-
{
|
|
77
|
-
if (AmaGDK._status != Status.None)
|
|
78
|
-
{
|
|
79
|
-
Logging.LogWarningOnce($"RegisterAdapter - Invalid status: {AmaGDK._status}");
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
listAdapters.Add(adapter);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
public static T Find<T>()
|
|
87
|
-
{
|
|
88
|
-
return listAdapters.OfType<T>().FirstOrDefault();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
public static T[] FindAll<T>()
|
|
92
|
-
{
|
|
93
|
-
return listAdapters.OfType<T>().ToArray();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
public static T GetConfig<T>() where T: ConfigAsset {
|
|
98
|
-
return (T) AmaGDK.Config;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public static class Forbidden {
|
|
73
|
+
public static class Forbidden
|
|
74
|
+
{
|
|
103
75
|
public static void DestroyAndReset()
|
|
104
76
|
{
|
|
105
|
-
if (AmaGDK._instance != null)
|
|
77
|
+
if (AmaGDK._instance != null)
|
|
78
|
+
{
|
|
106
79
|
UnityObject.Destroy(AmaGDK._instance);
|
|
107
80
|
AmaGDK._instance = null;
|
|
108
81
|
}
|
|
109
82
|
|
|
110
83
|
var result = Resources.FindObjectsOfTypeAll<AmaGDK>();
|
|
111
|
-
for (var i = 0;i < result.Length; i++)
|
|
112
|
-
{
|
|
84
|
+
for (var i = 0; i < result.Length; i++)
|
|
85
|
+
{
|
|
113
86
|
if (result[i] == null) continue;
|
|
114
|
-
|
|
115
|
-
|
|
87
|
+
|
|
88
|
+
#if UNITY_EDITOR // Ignore loaded prefabs assets
|
|
116
89
|
{
|
|
117
90
|
var path = UnityEditor.AssetDatabase.GetAssetPath(result[i]);
|
|
118
91
|
if (!string.IsNullOrEmpty(path)) continue;
|
|
119
92
|
}
|
|
120
|
-
|
|
93
|
+
#endif
|
|
121
94
|
|
|
122
95
|
// Logging.LogWarning("Something wrong: another AmaGDK instance found!");
|
|
123
96
|
UnityObject.Destroy(result[i].gameObject);
|
package/Runtime/AmaGDK.cs
CHANGED
|
@@ -12,9 +12,10 @@ namespace Amanotes.Core
|
|
|
12
12
|
{
|
|
13
13
|
public partial class AmaGDK : MonoBehaviour
|
|
14
14
|
{
|
|
15
|
-
public const string VERSION = "0.1.
|
|
15
|
+
public const string VERSION = "0.1.10";
|
|
16
16
|
|
|
17
17
|
internal static AmaGDK _instance;
|
|
18
|
+
internal static event Action _frameUpdate;
|
|
18
19
|
private static ConfigAsset _config = null;
|
|
19
20
|
internal static ConfigAsset Config {
|
|
20
21
|
get {
|
|
@@ -24,7 +25,7 @@ namespace Amanotes.Core
|
|
|
24
25
|
return _config;
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
|
|
28
29
|
internal static Status _status = Status.None;
|
|
29
30
|
internal static Action _onReadyCallback;
|
|
30
31
|
internal static bool _allowInit = false;
|
|
@@ -51,9 +52,7 @@ namespace Amanotes.Core
|
|
|
51
52
|
_allowInit = _allowInit || autoInit;
|
|
52
53
|
StartCoroutine(InitRoutine());
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
|
|
57
56
|
IEnumerator InitRoutine()
|
|
58
57
|
{
|
|
59
58
|
if (Config == null)
|
|
@@ -63,10 +62,7 @@ namespace Amanotes.Core
|
|
|
63
62
|
|
|
64
63
|
float time = 0;
|
|
65
64
|
float timeout = 3;
|
|
66
|
-
|
|
67
|
-
// Wait 1 frame to make sure all adapters have finished registering
|
|
68
|
-
yield return null;
|
|
69
|
-
|
|
65
|
+
|
|
70
66
|
var counter = 0;
|
|
71
67
|
const int INIT_TOLERANCE = 10 * 60;
|
|
72
68
|
const int INIT_WARN_CYCLE = 5 * 60;
|
|
@@ -83,8 +79,12 @@ namespace Amanotes.Core
|
|
|
83
79
|
}
|
|
84
80
|
|
|
85
81
|
_status = Status.Initialize;
|
|
82
|
+
|
|
83
|
+
// sort on priority
|
|
84
|
+
Adapter.listAdapters.Sort((a1, a2)=> a1.initOrder.CompareTo(a2.initOrder));
|
|
86
85
|
foreach (var adapter in Adapter.listAdapters)
|
|
87
86
|
{
|
|
87
|
+
Log($"Initing {adapter.id} --> initOrder: {adapter.initOrder}");
|
|
88
88
|
adapter.Init();
|
|
89
89
|
|
|
90
90
|
while (!adapter.IsReady)
|
|
@@ -92,13 +92,16 @@ namespace Amanotes.Core
|
|
|
92
92
|
time += Time.deltaTime;
|
|
93
93
|
yield return null;
|
|
94
94
|
if (time <= timeout) continue;
|
|
95
|
-
LogWarningOnce($"{adapter.
|
|
95
|
+
LogWarningOnce($"{adapter.id} init time out: {timeout}");
|
|
96
96
|
}
|
|
97
|
-
}
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
Log($"Adapter {adapter.id} inited!");
|
|
99
|
+
}
|
|
101
100
|
|
|
101
|
+
// Init modules (Adapter managers)
|
|
102
|
+
Analytics.Init();
|
|
103
|
+
Ads.Init();
|
|
104
|
+
|
|
102
105
|
_status = Status.Ready;
|
|
103
106
|
_onReadyCallback?.Invoke();
|
|
104
107
|
_onReadyCallback = null;
|
|
@@ -108,7 +111,7 @@ namespace Amanotes.Core
|
|
|
108
111
|
private void Update()
|
|
109
112
|
{
|
|
110
113
|
if (!isReady) return;
|
|
111
|
-
|
|
114
|
+
_frameUpdate?.Invoke();
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
117
|
|
|
@@ -144,6 +147,16 @@ namespace Amanotes.Core
|
|
|
144
147
|
_instance = sdk.AddComponent<AmaGDK>();
|
|
145
148
|
}
|
|
146
149
|
|
|
150
|
+
public static void BeginCoroutine(IEnumerator enumerator)
|
|
151
|
+
{
|
|
152
|
+
_instance.StartCoroutine(enumerator);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public static void EndCoroutine(IEnumerator enumerator)
|
|
156
|
+
{
|
|
157
|
+
_instance.StopCoroutine(enumerator);
|
|
158
|
+
}
|
|
159
|
+
|
|
147
160
|
public static void AddCallback(Action onReady)
|
|
148
161
|
{
|
|
149
162
|
if (onReady == null)
|
|
@@ -70,8 +70,7 @@ public class AmaGDKCoreTest
|
|
|
70
70
|
|
|
71
71
|
AmaGDK.Init();
|
|
72
72
|
SceneManager.LoadScene(SCENE_WITH_AUTOINIT_OFF, LoadSceneMode.Single);
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
|
|
75
74
|
yield return new WaitForSeconds(AMAGDK_INIT_DURATION);
|
|
76
75
|
Assert.IsTrue(AmaGDK.isReady);
|
|
77
76
|
}
|
|
@@ -85,8 +84,8 @@ public class AmaGDKCoreTest
|
|
|
85
84
|
SceneManager.LoadScene(SCENE_WITH_AUTOINIT_OFF, LoadSceneMode.Single);
|
|
86
85
|
yield return null; // Took 1 frame for scene ready (call Awake)
|
|
87
86
|
AmaGDK.Init();
|
|
88
|
-
LogAssert.NoUnexpectedReceived();
|
|
89
87
|
|
|
88
|
+
|
|
90
89
|
yield return new WaitForSeconds(AMAGDK_INIT_DURATION);
|
|
91
90
|
Assert.IsTrue(AmaGDK.isReady);
|
|
92
91
|
}
|
|
@@ -123,7 +123,7 @@ public class MigrationTest
|
|
|
123
123
|
analyticsData.eventDetails.Add(new EventDetail
|
|
124
124
|
{
|
|
125
125
|
eventName = e.Key,
|
|
126
|
-
|
|
126
|
+
totalCount = e.Value
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -132,7 +132,7 @@ public class MigrationTest
|
|
|
132
132
|
analyticsData.eventDetails.Add(new EventDetail
|
|
133
133
|
{
|
|
134
134
|
eventName = "migration_error",
|
|
135
|
-
|
|
135
|
+
totalCount = migrationError
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
138
|
|
|
@@ -154,7 +154,7 @@ public class MigrationTest
|
|
|
154
154
|
var eventDetail = analyticsData.GetEventDetail(errEventName);
|
|
155
155
|
if (eventDetail != null)
|
|
156
156
|
{
|
|
157
|
-
Assert.IsTrue(eventDetail.
|
|
157
|
+
Assert.IsTrue(eventDetail.totalCount == 1);
|
|
158
158
|
}
|
|
159
159
|
else
|
|
160
160
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.amanotes.gdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"displayName": "AmaGDK",
|
|
5
5
|
"description": "Amanotes Game Development Kit",
|
|
6
6
|
"unity": "2020.3",
|
|
@@ -14,5 +14,6 @@
|
|
|
14
14
|
"email": "tech.support@amanotes.com",
|
|
15
15
|
"url": "https://amanotes.com"
|
|
16
16
|
},
|
|
17
|
+
"documentationUrl": "https://amagdk.notion.site/amagdk/Ama-GDK-a73596617ab247b6a43c8f12a1581415",
|
|
17
18
|
"license": "MIT"
|
|
18
19
|
}
|