com.amanotes.gdk 0.2.68 → 0.2.70-1
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 +39 -0
- package/Editor/AmaGDKEditor.cs +78 -23
- package/Editor/AmaGDKExtra.cs +14 -13
- package/Editor/Extra/GDKAutoUpdateAdapter.cs +14 -1
- package/Editor/Extra/GDKCIBuildCommand.cs +2 -16
- package/Editor/Extra/GDKSymbolDefine.cs +372 -0
- package/Editor/{AmaGDKManager.cs.meta → Extra/GDKSymbolDefine.cs.meta} +1 -1
- package/Editor/Utils/AmaGDKEditor.ExtractVersion.cs +41 -3
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/CheckDiskSpace.unitypackage +0 -0
- package/Extra/Consent.unitypackage +0 -0
- package/Extra/{GoogleCMP.unitypackage.meta → Consent.unitypackage.meta} +1 -1
- package/Extra/ForceUpdate.unitypackage +0 -0
- package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
- package/Extra/PostProcessor.unitypackage +0 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.PurchaseConnector.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/MaxAdNetworkAdapter.unitypackage +0 -0
- package/{Editor/Resources.meta → Packages/MaxAdNetworkAdapter.unitypackage.meta} +1 -2
- package/Packages/RevenueCatAdapter.unitypackage +0 -0
- package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
- package/Runtime/Ad/AdExtension.cs +2 -0
- package/Runtime/Ad/AdLogic.cs +83 -70
- package/Runtime/Ad/AdShowContext.cs +1 -0
- package/Runtime/Ad/AmaGDK.Ads.cs +17 -3
- package/Runtime/AmaGDK.Adapters.cs +12 -5
- package/Runtime/AmaGDK.Analytics.cs +45 -38
- package/Runtime/AmaGDK.Consent.cs +259 -0
- package/Runtime/AmaGDK.Consent.cs.meta +11 -0
- package/Runtime/AmaGDK.Device.cs +4 -4
- package/Runtime/AmaGDK.RemoteConfig.cs +3 -1
- package/Runtime/AmaGDK.cs +28 -19
- package/Runtime/AnalyticQualityAsset.cs +16 -9
- package/Runtime/AudioToolkit/AmaGDK.Audio.Latency.cs +1 -3
- package/Runtime/AudioToolkit/AmaGDK.Audio.cs +41 -25
- package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +13 -12
- package/Runtime/Core/GDKPool.cs +83 -17
- package/Runtime/Fps/AmaFPS.cs +0 -1
- package/Runtime/Fps/AmaFPSVisualizer.cs +7 -7
- package/Runtime/Internal/AmaGDK.Internal.AmaGUI.cs +1 -1
- package/Runtime/Internal/AmaGDK.Internal.cs +2 -5
- package/Runtime/Internal/AmaGDK.Utils.cs +32 -81
- package/Runtime/Internal/GDKGeoLocationcs.cs +3 -1
- package/Runtime/Internal/GDKServerTime.cs +13 -10
- package/package.json +1 -1
- package/Editor/AmaGDKManager.cs +0 -235
- package/Editor/Resources/amasdk-modules.json +0 -31
- package/Editor/Resources/amasdk-modules.json.meta +0 -7
- package/Extra/GoogleCMP.unitypackage +0 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using Amanotes.Core.Internal;
|
|
3
|
+
using UnityEngine;
|
|
4
|
+
|
|
5
|
+
namespace Amanotes.Core
|
|
6
|
+
{
|
|
7
|
+
public partial class AmaGDK //Consent
|
|
8
|
+
{
|
|
9
|
+
public static partial class Consent //Public
|
|
10
|
+
{
|
|
11
|
+
private static bool _onGoingRequestAllConsents;
|
|
12
|
+
public static void RequestAllConsents(Action onComplete)
|
|
13
|
+
{
|
|
14
|
+
OnAllConsentComplete(onComplete);
|
|
15
|
+
|
|
16
|
+
if (_onGoingRequestAllConsents)
|
|
17
|
+
{
|
|
18
|
+
Logging.LogWarning($"[Consent] RequestAllConsents is called multiple times.");
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_onGoingRequestAllConsents = true;
|
|
23
|
+
#if UNITY_IOS
|
|
24
|
+
ATT.Request(ConsiderCMP);
|
|
25
|
+
#else
|
|
26
|
+
CMP.Request(EndConsent);
|
|
27
|
+
#endif
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public static void OnAllConsentComplete(Action onComplete)
|
|
31
|
+
{
|
|
32
|
+
if (allConsentChecked)
|
|
33
|
+
{
|
|
34
|
+
onComplete?.Invoke();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_onConsentComplete -= onComplete;
|
|
39
|
+
_onConsentComplete += onComplete;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public static partial class Consent //ATT
|
|
44
|
+
{
|
|
45
|
+
public static class ATT
|
|
46
|
+
{
|
|
47
|
+
public static bool IsAllowed
|
|
48
|
+
{
|
|
49
|
+
get
|
|
50
|
+
{
|
|
51
|
+
if (checkedATT) return allowedATT;
|
|
52
|
+
Logging.LogWarning("[Consent] ATT has not completed yet");
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public static void Request(Action<bool> onComplete)
|
|
58
|
+
{
|
|
59
|
+
if (checkedATT)
|
|
60
|
+
{
|
|
61
|
+
onComplete?.Invoke(allowedATT);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
ConsentHook.ATTRequest(isAllowed =>
|
|
66
|
+
{
|
|
67
|
+
data.att = isAllowed ? Status.Allowed : Status.NotAllowed;
|
|
68
|
+
data.SaveJsonToFile();
|
|
69
|
+
onComplete?.Invoke(allowedATT);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
public static partial class Consent //CMP
|
|
77
|
+
{
|
|
78
|
+
public static class CMP
|
|
79
|
+
{
|
|
80
|
+
public static bool IsRequired
|
|
81
|
+
{
|
|
82
|
+
get
|
|
83
|
+
{
|
|
84
|
+
if (checkedCMP) return data.cmp >= Status.Allowed;
|
|
85
|
+
|
|
86
|
+
if (!ConsentHook.IsRequiredCMP.HasValue)
|
|
87
|
+
{
|
|
88
|
+
Logging.LogWarningOnce("[Consent] CMP is not available or not ready");
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return ConsentHook.IsRequiredCMP.Value;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public static void Request(Action<bool> onComplete)
|
|
97
|
+
{
|
|
98
|
+
if (checkedCMP)
|
|
99
|
+
{
|
|
100
|
+
onComplete?.Invoke(checkedCMP);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
ConsentHook.TryToShowCMP(successful =>
|
|
105
|
+
{
|
|
106
|
+
if (successful)
|
|
107
|
+
{
|
|
108
|
+
data.cmp = !IsRequired ? Status.NotRequired : Status.Allowed;
|
|
109
|
+
data.SaveJsonToFile();
|
|
110
|
+
}
|
|
111
|
+
onComplete?.Invoke(checkedCMP);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public static void ForceShowPopUp(Action onComplete)
|
|
116
|
+
{
|
|
117
|
+
OnAllConsentComplete(onComplete);
|
|
118
|
+
ConsentHook.ForceShowCMP(EndConsent);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
public static partial class Consent //Internal
|
|
124
|
+
{
|
|
125
|
+
private static readonly ConsentData data = new ConsentData().LoadJsonFromFile();
|
|
126
|
+
private static Action _onConsentComplete;
|
|
127
|
+
|
|
128
|
+
internal static bool checkedATT => data.att >= Status.Allowed;
|
|
129
|
+
internal static bool allowedATT => data.att == Status.Allowed;
|
|
130
|
+
internal static bool checkedCMP => data.cmp >= Status.NotRequired;
|
|
131
|
+
internal static bool allConsentChecked => checkedATT && checkedCMP;
|
|
132
|
+
|
|
133
|
+
internal enum Status
|
|
134
|
+
{
|
|
135
|
+
None,
|
|
136
|
+
NotRequired,
|
|
137
|
+
Allowed,
|
|
138
|
+
NotAllowed
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
internal static bool InitModule()
|
|
142
|
+
{
|
|
143
|
+
if (allConsentChecked) return true;
|
|
144
|
+
if (!_config.consent.autoGetConsent) return true;
|
|
145
|
+
RequestAllConsents(null);
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private static void ConsiderCMP(bool needToShowCMP)
|
|
150
|
+
{
|
|
151
|
+
if (checkedCMP)
|
|
152
|
+
{
|
|
153
|
+
EndConsent(true);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (needToShowCMP)
|
|
158
|
+
{
|
|
159
|
+
ConsentHook.TryToShowCMP(EndConsent);
|
|
160
|
+
}
|
|
161
|
+
else
|
|
162
|
+
{
|
|
163
|
+
ConsentHook.SetNotRequiredCMP(EndConsent);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private static void EndConsent(bool isConsentSuccess)
|
|
168
|
+
{
|
|
169
|
+
var tmpAction = _onConsentComplete;
|
|
170
|
+
_onConsentComplete = null;
|
|
171
|
+
tmpAction?.Invoke();
|
|
172
|
+
Logging.Log("[Consent] End consent checking");
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
[Serializable]
|
|
178
|
+
public class ConsentData : IJsonFile
|
|
179
|
+
{
|
|
180
|
+
[SerializeField] internal AmaGDK.Consent.Status att;
|
|
181
|
+
[SerializeField] internal AmaGDK.Consent.Status cmp;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public static class ConsentHook
|
|
185
|
+
{
|
|
186
|
+
public static bool? IsRequiredCMP;
|
|
187
|
+
|
|
188
|
+
private static Action<Action<bool>> _tryToShowCMP;
|
|
189
|
+
public static Action<Action<bool>> TryToShowCMP
|
|
190
|
+
{
|
|
191
|
+
get
|
|
192
|
+
{
|
|
193
|
+
if (_tryToShowCMP != null) return _tryToShowCMP;
|
|
194
|
+
|
|
195
|
+
Logging.LogWarning("[Consent] ConsentHook.TryToShowCMP is null");
|
|
196
|
+
_tryToShowCMP = callback => callback(false);
|
|
197
|
+
return _tryToShowCMP;
|
|
198
|
+
}
|
|
199
|
+
set => _tryToShowCMP = value;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private static Action<Action<bool>> _forceShowCMP;
|
|
203
|
+
public static Action<Action<bool>> ForceShowCMP
|
|
204
|
+
{
|
|
205
|
+
get
|
|
206
|
+
{
|
|
207
|
+
if (_forceShowCMP != null) return _forceShowCMP;
|
|
208
|
+
|
|
209
|
+
Logging.LogWarning("[Consent] ConsentHook.ForceShowCMP is null");
|
|
210
|
+
_forceShowCMP = callback => callback(false);
|
|
211
|
+
return _forceShowCMP;
|
|
212
|
+
}
|
|
213
|
+
set => _forceShowCMP = value;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private static Action<Action<bool>> _setNotRequiredCMP;
|
|
217
|
+
public static Action<Action<bool>> SetNotRequiredCMP
|
|
218
|
+
{
|
|
219
|
+
get
|
|
220
|
+
{
|
|
221
|
+
if (_setNotRequiredCMP != null) return _setNotRequiredCMP;
|
|
222
|
+
|
|
223
|
+
Logging.LogWarning("[Consent] ConsentHook.SetNotRequiredCMP is null");
|
|
224
|
+
_setNotRequiredCMP = callback => callback(false);
|
|
225
|
+
return _setNotRequiredCMP;
|
|
226
|
+
}
|
|
227
|
+
set => _setNotRequiredCMP = value;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private static Action<Action<bool>> _attRequest;
|
|
231
|
+
public static Action<Action<bool>> ATTRequest
|
|
232
|
+
{
|
|
233
|
+
get
|
|
234
|
+
{
|
|
235
|
+
if (_attRequest != null) return _attRequest;
|
|
236
|
+
|
|
237
|
+
Logging.LogWarning("[Consent] ConsentHook.ATTRequest is null");
|
|
238
|
+
_attRequest = callback => callback(false);
|
|
239
|
+
return _attRequest;
|
|
240
|
+
}
|
|
241
|
+
set => _attRequest = value;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
namespace Amanotes.Core.Internal
|
|
247
|
+
{
|
|
248
|
+
[Serializable]
|
|
249
|
+
public class ConsentConfig
|
|
250
|
+
{
|
|
251
|
+
[Tooltip("Auto pop-up ATT and CMP form")]
|
|
252
|
+
public bool autoGetConsent = true;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
public partial class ConfigAsset
|
|
256
|
+
{
|
|
257
|
+
[SerializeField] public ConsentConfig consent;
|
|
258
|
+
}
|
|
259
|
+
}
|
package/Runtime/AmaGDK.Device.cs
CHANGED
|
@@ -67,16 +67,16 @@ namespace Amanotes.Core.Internal
|
|
|
67
67
|
|
|
68
68
|
if (AmaGDK.Config.common.logLevel == LogLevel.Verbose)
|
|
69
69
|
{
|
|
70
|
-
var stringBuilder =
|
|
70
|
+
var stringBuilder = GDKPool.GetStringBuilder();
|
|
71
71
|
stringBuilder.Append("Device info:");
|
|
72
72
|
stringBuilder.AppendLine("DeviceSpec: " + result);
|
|
73
73
|
stringBuilder.AppendLine("systemMemorySize: " + SystemInfo.systemMemorySize);
|
|
74
74
|
stringBuilder.AppendLine("processorCount: " + SystemInfo.processorCount);
|
|
75
75
|
stringBuilder.AppendLine("processorFrequency: " + SystemInfo.processorFrequency);
|
|
76
|
-
stringBuilder.AppendLine("graphicsMemorySize: " + SystemInfo.graphicsMemorySize);
|
|
77
|
-
|
|
78
|
-
Logging.Log(stringBuilder.ToString());
|
|
76
|
+
stringBuilder.AppendLine("graphicsMemorySize: " + SystemInfo.graphicsMemorySize);
|
|
77
|
+
Logging.Log(GDKPool.ReturnString(stringBuilder));
|
|
79
78
|
}
|
|
79
|
+
|
|
80
80
|
return result;
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -214,7 +214,7 @@ namespace Amanotes.Core
|
|
|
214
214
|
Profiler.BeginSample("AmaGDK.RemoteConfig.SaveCache()");
|
|
215
215
|
|
|
216
216
|
_fetchState = FetchState.SaveCache;
|
|
217
|
-
StringBuilder sb =
|
|
217
|
+
StringBuilder sb = GDKPool.GetStringBuilder(8);
|
|
218
218
|
|
|
219
219
|
//Add embedded remote config version to force load from embedded config after app update
|
|
220
220
|
sb.AppendLine($"{VERSION_PREFIX}{EmbedVersion}");
|
|
@@ -226,6 +226,8 @@ namespace Amanotes.Core
|
|
|
226
226
|
|
|
227
227
|
string filePath = GDKFileUtils.GetPath(fileName);
|
|
228
228
|
GDKFileUtils.Save(filePath, sb.ToString());
|
|
229
|
+
GDKPool.Return(sb);
|
|
230
|
+
|
|
229
231
|
Log($"[RemoteConfig] Saved remote config to {filePath}");
|
|
230
232
|
Profiler.EndSample();
|
|
231
233
|
NextState();
|
package/Runtime/AmaGDK.cs
CHANGED
|
@@ -17,7 +17,7 @@ namespace Amanotes.Core
|
|
|
17
17
|
{
|
|
18
18
|
public partial class AmaGDK : MonoBehaviour
|
|
19
19
|
{
|
|
20
|
-
public const string VERSION = "0.2.
|
|
20
|
+
public const string VERSION = "0.2.70-1";
|
|
21
21
|
|
|
22
22
|
internal static Status _status = Status.None;
|
|
23
23
|
private static ConfigAsset _config = null;
|
|
@@ -100,15 +100,12 @@ namespace Amanotes.Core
|
|
|
100
100
|
Profiler.BeginSample("AmaGDK.InitModules()");
|
|
101
101
|
{
|
|
102
102
|
User.InitModule();
|
|
103
|
+
Consent.InitModule();
|
|
103
104
|
Analytics.InitModule();
|
|
104
105
|
Ads.InitModule();
|
|
105
106
|
IAP.InitModule();
|
|
106
107
|
RemoteConfig.InitModule();
|
|
107
|
-
|
|
108
|
-
if (Config.enableAudioModule)
|
|
109
|
-
{
|
|
110
|
-
Audio.InitModule();
|
|
111
|
-
}
|
|
108
|
+
if (Config.enableAudioModule) Audio.InitModule();
|
|
112
109
|
}
|
|
113
110
|
Profiler.EndSample();
|
|
114
111
|
}
|
|
@@ -128,8 +125,6 @@ namespace Amanotes.Core
|
|
|
128
125
|
|
|
129
126
|
IEnumerator InitAdapters(StringBuilder sb)
|
|
130
127
|
{
|
|
131
|
-
float TIMEOUT = 1;
|
|
132
|
-
|
|
133
128
|
// sort on priority
|
|
134
129
|
List<Adapter2> listAdapters = Adapter2.adapterMap
|
|
135
130
|
.Values.ToList();
|
|
@@ -137,21 +132,32 @@ namespace Amanotes.Core
|
|
|
137
132
|
|
|
138
133
|
foreach (Adapter2 adapter in listAdapters)
|
|
139
134
|
{
|
|
140
|
-
|
|
141
|
-
float startTime = Time.realtimeSinceStartup;
|
|
142
|
-
Profiler.BeginSample($"AmaGDK.adapter.InitSDK-{adapter.adapterId}");
|
|
135
|
+
if (!adapter.enabled)
|
|
143
136
|
{
|
|
144
|
-
adapter.
|
|
137
|
+
Log($"Adapter <{adapter.adapterId} is disabled!");
|
|
138
|
+
continue;
|
|
145
139
|
}
|
|
146
|
-
Profiler.EndSample();
|
|
147
|
-
|
|
148
|
-
yield return GDKUtils.Timeout(TIMEOUT,() => adapter.status != Status.Initialize);
|
|
149
140
|
|
|
150
|
-
|
|
141
|
+
// Log($"Initiating {adapter.adapterId} --> initOrder: {adapter.initOrder} | {adapter.status}");
|
|
142
|
+
var startTime = Time.realtimeSinceStartup;
|
|
143
|
+
Profiler.BeginSample($"AmaGDK.adapter.InitSDK-{adapter.adapterId}");
|
|
144
|
+
adapter.InitSDK();
|
|
145
|
+
Profiler.EndSample();
|
|
146
|
+
|
|
147
|
+
if (adapter.status != Status.Ready)
|
|
151
148
|
{
|
|
152
|
-
|
|
149
|
+
var beginTime = Time.realtimeSinceStartup;
|
|
150
|
+
yield return GDKUtils.Timeout(adapter.Timeout,() => adapter.status != Status.Initialize);
|
|
151
|
+
var endTime = Time.realtimeSinceStartup;
|
|
152
|
+
|
|
153
|
+
if (adapter.status == Status.Initialize)
|
|
154
|
+
{
|
|
155
|
+
LogWarning($"{adapter.adapterId} init time out: {adapter.Timeout:#0.00}");
|
|
156
|
+
} else
|
|
157
|
+
{
|
|
158
|
+
Log($"{adapter.adapterId} init took: {(endTime-beginTime):#0.00} s");
|
|
159
|
+
}
|
|
153
160
|
}
|
|
154
|
-
|
|
155
161
|
dispatcher.Dispatch(Event.ADAPTER_READY, adapter.adapterId);
|
|
156
162
|
sb.AppendLine($"[{(adapter.IsReady ? " OK " : "FAIL")}] {adapter.adapterId} (~ {Time.realtimeSinceStartup - startTime:#0.00}s)");
|
|
157
163
|
|
|
@@ -170,7 +176,7 @@ namespace Amanotes.Core
|
|
|
170
176
|
}
|
|
171
177
|
|
|
172
178
|
var startTime = Time.realtimeSinceStartup;
|
|
173
|
-
var sb =
|
|
179
|
+
var sb = GDKPool.GetStringBuilder();
|
|
174
180
|
|
|
175
181
|
InitModules();
|
|
176
182
|
|
|
@@ -205,6 +211,7 @@ namespace Amanotes.Core
|
|
|
205
211
|
|
|
206
212
|
sb.Append($"\nMapping UserId: {User.UserId}\n");
|
|
207
213
|
Debug.Log($"AmaGDK v{VERSION} | {READY} in {initDuration:#0.00}s\n\n{sb}");
|
|
214
|
+
GDKPool.Return(sb);
|
|
208
215
|
}
|
|
209
216
|
|
|
210
217
|
private void ConfigGeoLocation()
|
|
@@ -346,7 +353,9 @@ namespace Amanotes.Core
|
|
|
346
353
|
public const string FIREBASE_REMOTE_CONFIG = "FirebaseRemoteConfig";
|
|
347
354
|
public const string APPSFLYER = "AppsFlyer";
|
|
348
355
|
public const string IRONSOURCE = "IronSource";
|
|
356
|
+
public const string MAX = "Max";
|
|
349
357
|
public const string REVENUECAT = "RevenueCat";
|
|
358
|
+
public const string SQLITE_ANALYTICS = "SqliteAnalytics";
|
|
350
359
|
}
|
|
351
360
|
}
|
|
352
361
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
using Amanotes.Core.Internal;
|
|
1
2
|
using System;
|
|
2
3
|
using System.Collections.Generic;
|
|
3
4
|
using System.Linq;
|
|
@@ -82,14 +83,15 @@ namespace Amanotes.Core
|
|
|
82
83
|
|
|
83
84
|
internal void ValidateParams(string eventName, Dictionary<string, object> eventParams)
|
|
84
85
|
{
|
|
85
|
-
|
|
86
|
+
var logBuilder = GDKPool.GetStringBuilder();
|
|
87
|
+
|
|
86
88
|
logBuilder.AppendLine($"Analytics quality violation found for event <{eventName}>");
|
|
87
|
-
|
|
88
|
-
HashSet<string> checkedParameters =
|
|
89
|
+
var isValid = true;
|
|
90
|
+
HashSet<string> checkedParameters = GDKPool.GetHashSet();
|
|
89
91
|
|
|
90
92
|
foreach (var kvp in DicParam)
|
|
91
93
|
{
|
|
92
|
-
if (!eventParams.
|
|
94
|
+
if (!eventParams.TryGetValue(kvp.Key, out object paramValue))
|
|
93
95
|
{
|
|
94
96
|
if (!kvp.Value.isOptional)
|
|
95
97
|
{
|
|
@@ -99,8 +101,6 @@ namespace Amanotes.Core
|
|
|
99
101
|
continue;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
object paramValue = eventParams[kvp.Key];
|
|
103
|
-
|
|
104
104
|
if (!ValidateParamType(paramValue, kvp.Value.type))
|
|
105
105
|
{
|
|
106
106
|
isValid = false;
|
|
@@ -117,8 +117,11 @@ namespace Amanotes.Core
|
|
|
117
117
|
isValid = false;
|
|
118
118
|
logBuilder.AppendLine($"[+] {parameter.Key}");
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
if (!isValid) LogWarningOnce(logBuilder.ToString());
|
|
122
|
+
|
|
123
|
+
GDKPool.Return(logBuilder);
|
|
124
|
+
GDKPool.Return(checkedParameters);
|
|
122
125
|
}
|
|
123
126
|
|
|
124
127
|
private bool ValidateParamType(object paramValue, ParamType paramType)
|
|
@@ -179,7 +182,7 @@ namespace Amanotes.Core
|
|
|
179
182
|
[ContextMenu("Validate Unique EventNames")]
|
|
180
183
|
private void ValidateUniqueEventNames()
|
|
181
184
|
{
|
|
182
|
-
HashSet<string> eventNames =
|
|
185
|
+
HashSet<string> eventNames = GDKPool.GetHashSet();
|
|
183
186
|
|
|
184
187
|
lstEvent = lstEvent.OrderBy(evt => evt.eventName).ToList();
|
|
185
188
|
|
|
@@ -189,7 +192,7 @@ namespace Amanotes.Core
|
|
|
189
192
|
|
|
190
193
|
if (!eventNames.Add(eventQuality.eventName)) Debug.LogWarning($"Duplicate event name found: {eventQuality.eventName}. Event names must be unique.");
|
|
191
194
|
|
|
192
|
-
HashSet<string> paramNames =
|
|
195
|
+
HashSet<string> paramNames = GDKPool.GetHashSet();
|
|
193
196
|
|
|
194
197
|
eventQuality.lstParam = eventQuality.lstParam.OrderBy(param => param.paramName).ToList();
|
|
195
198
|
|
|
@@ -199,7 +202,11 @@ namespace Amanotes.Core
|
|
|
199
202
|
|
|
200
203
|
if (!paramNames.Add(param.paramName)) Debug.LogWarning($"Duplicate parameter name found in event {eventQuality.eventName}: {param.paramName}. Parameter names must be unique within an event.");
|
|
201
204
|
}
|
|
205
|
+
|
|
206
|
+
GDKPool.Return(paramNames);
|
|
202
207
|
}
|
|
208
|
+
|
|
209
|
+
GDKPool.Return(eventNames);
|
|
203
210
|
EditorUtility.SetDirty(this);
|
|
204
211
|
}
|
|
205
212
|
#endif
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
using System;
|
|
2
|
-
using System.Collections;
|
|
3
|
-
using Amanotes.Core.Internal;
|
|
4
2
|
using UnityEngine;
|
|
5
3
|
|
|
6
4
|
namespace Amanotes.Core
|
|
@@ -75,7 +73,7 @@ namespace Amanotes.Core
|
|
|
75
73
|
return DEFAULT_FOR_SPEAKER;
|
|
76
74
|
}
|
|
77
75
|
|
|
78
|
-
string deviceName =
|
|
76
|
+
string deviceName = currentDevice.name;
|
|
79
77
|
int savedLatency = PlayerPrefs.GetInt(PREF_AUDIO_LATENCY + deviceName, -1);
|
|
80
78
|
|
|
81
79
|
if (savedLatency >= 0)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
using UnityEngine;
|
|
2
2
|
using System;
|
|
3
|
-
using System.Collections;
|
|
4
|
-
using System.Text;
|
|
5
3
|
using Amanotes.Core.Internal;
|
|
6
4
|
|
|
7
5
|
namespace Amanotes.Core.Internal
|
|
@@ -9,7 +7,8 @@ namespace Amanotes.Core.Internal
|
|
|
9
7
|
public partial class ConfigAsset
|
|
10
8
|
{
|
|
11
9
|
[SerializeField]
|
|
12
|
-
|
|
10
|
+
[Tooltip("Enable to get accurate audio latency & be informed when audio device changed\n\nApi: AmaGDK.Audio.DeviceInfo")]
|
|
11
|
+
public bool enableAudioModule = true;
|
|
13
12
|
}
|
|
14
13
|
}
|
|
15
14
|
|
|
@@ -23,21 +22,38 @@ namespace Amanotes.Core
|
|
|
23
22
|
public const string GDK_AUDIO_INTERRUPT_BEGIN = nameof(GDK_AUDIO_INTERRUPT_BEGIN);
|
|
24
23
|
public const string GDK_AUDIO_INTERRUPT_END = nameof(GDK_AUDIO_INTERRUPT_END);
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
internal AudioDeviceType Type;
|
|
29
|
-
internal string RawType;
|
|
30
|
-
public string Name;
|
|
31
|
-
public int LatencyMs;
|
|
32
|
-
}
|
|
25
|
+
|
|
33
26
|
// Public Usage
|
|
34
|
-
public partial class Audio
|
|
27
|
+
public static partial class Audio
|
|
35
28
|
{
|
|
36
|
-
public
|
|
29
|
+
public class AudioDeviceInfo
|
|
30
|
+
{
|
|
31
|
+
internal AudioDeviceType type;
|
|
32
|
+
internal string rawType;
|
|
33
|
+
public string name;
|
|
34
|
+
public int latencyMs;
|
|
35
|
+
|
|
36
|
+
public override string ToString()
|
|
37
|
+
{
|
|
38
|
+
if (string.IsNullOrEmpty(rawType) || string.IsNullOrEmpty(name)) return base.ToString();
|
|
39
|
+
return $"type: {type.ToString().ToLower()} rawType:{rawType} name:{name}";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private static AudioDeviceInfo _currentDevice;
|
|
44
|
+
|
|
45
|
+
public static AudioDeviceInfo currentDevice
|
|
46
|
+
{
|
|
47
|
+
get => _currentDevice ?? NO_DEVICE;
|
|
48
|
+
private set => _currentDevice = value;
|
|
49
|
+
}
|
|
37
50
|
|
|
38
51
|
private static readonly AudioDeviceInfo NO_DEVICE = new AudioDeviceInfo()
|
|
39
52
|
{
|
|
40
|
-
|
|
53
|
+
type = AudioDeviceType.Unknown,
|
|
54
|
+
rawType = string.Empty,
|
|
55
|
+
name = "NO_DEVICE",
|
|
56
|
+
latencyMs = DEFAULT_FOR_SPEAKER
|
|
41
57
|
};
|
|
42
58
|
|
|
43
59
|
/// <remarks>
|
|
@@ -87,8 +103,8 @@ namespace Amanotes.Core
|
|
|
87
103
|
_audioDeviceDetector.RegisterEvents();
|
|
88
104
|
RegisterCallbacks();
|
|
89
105
|
|
|
90
|
-
|
|
91
|
-
|
|
106
|
+
currentDevice = DetectAudioInfo();
|
|
107
|
+
currentDevice.latencyMs = GetAudioDeviceLatency();
|
|
92
108
|
}
|
|
93
109
|
|
|
94
110
|
private static AudioDeviceInfo DetectAudioInfo()
|
|
@@ -102,9 +118,9 @@ namespace Amanotes.Core
|
|
|
102
118
|
var info = _audioDeviceDetector.GetInfo();
|
|
103
119
|
return new AudioDeviceInfo
|
|
104
120
|
{
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
121
|
+
type = info.AudioDeviceType,
|
|
122
|
+
rawType = info.RawType,
|
|
123
|
+
name = info.Name
|
|
108
124
|
};
|
|
109
125
|
}
|
|
110
126
|
}
|
|
@@ -125,9 +141,9 @@ namespace Amanotes.Core
|
|
|
125
141
|
{
|
|
126
142
|
GDKUtils.DelayCall(1f, () =>
|
|
127
143
|
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
dispatcher.Dispatch(Event.GDK_AUDIO_INFO_CHANGE,
|
|
144
|
+
currentDevice = DetectAudioInfo();
|
|
145
|
+
currentDevice.latencyMs = GetAudioDeviceLatency();
|
|
146
|
+
dispatcher.Dispatch(Event.GDK_AUDIO_INFO_CHANGE, currentDevice);
|
|
131
147
|
});
|
|
132
148
|
}
|
|
133
149
|
|
|
@@ -144,10 +160,10 @@ namespace Amanotes.Core
|
|
|
144
160
|
{
|
|
145
161
|
GDKUtils.ThrowIf(!Config.enableAudioModule, "Audio Module is disabled, Please enable it in the AmaGDKConfig");
|
|
146
162
|
|
|
147
|
-
return
|
|
148
|
-
&& (
|
|
149
|
-
||
|
|
150
|
-
||
|
|
163
|
+
return currentDevice != null
|
|
164
|
+
&& (currentDevice.rawType == "AVAudioSessionPortBluetoothA2DP"
|
|
165
|
+
|| currentDevice.rawType == "TYPE_BLUETOOTH_A2DP"
|
|
166
|
+
|| currentDevice.rawType == "AVAudioSessionPortBluetoothHFP");
|
|
151
167
|
}
|
|
152
168
|
|
|
153
169
|
private static string GetCurrentRouteInputs()
|
|
@@ -86,15 +86,13 @@ namespace Amanotes.Core
|
|
|
86
86
|
|
|
87
87
|
private void OnAudioDeviceAdded(string param)
|
|
88
88
|
{
|
|
89
|
-
if (string.IsNullOrEmpty(param))
|
|
90
|
-
return;
|
|
89
|
+
if (string.IsNullOrEmpty(param)) return;
|
|
91
90
|
onChanged?.Invoke(param);
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
private void OnAudioDeviceRemoved(string param)
|
|
95
94
|
{
|
|
96
|
-
if (string.IsNullOrEmpty(param))
|
|
97
|
-
return;
|
|
95
|
+
if (string.IsNullOrEmpty(param)) return;
|
|
98
96
|
onChanged?.Invoke(param);
|
|
99
97
|
}
|
|
100
98
|
|
|
@@ -170,15 +168,18 @@ namespace Amanotes.Core
|
|
|
170
168
|
}
|
|
171
169
|
|
|
172
170
|
StringBuilder sb = null;
|
|
173
|
-
|
|
174
|
-
for (int i = 0; i < str.Length; i++)
|
|
171
|
+
for (var i = 0; i < str.Length; i++)
|
|
175
172
|
{
|
|
176
173
|
char ch = str[i];
|
|
177
174
|
|
|
178
175
|
if (char.IsSurrogate(ch))
|
|
179
176
|
{
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
if (sb == null)
|
|
178
|
+
{
|
|
179
|
+
sb = GDKPool.GetStringBuilder();
|
|
180
|
+
sb.Append(str, 0, i);
|
|
181
|
+
}
|
|
182
|
+
|
|
182
183
|
sb.Append(replacementCharacter);
|
|
183
184
|
|
|
184
185
|
// If there is a high+low surrogate, skip the low surrogate
|
|
@@ -187,13 +188,13 @@ namespace Amanotes.Core
|
|
|
187
188
|
i++;
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
|
-
else
|
|
191
|
+
else
|
|
191
192
|
{
|
|
192
|
-
sb
|
|
193
|
+
sb?.Append(ch);
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
|
-
|
|
196
|
-
return sb == null ? str :
|
|
196
|
+
|
|
197
|
+
return sb == null ? str : GDKPool.ReturnString(sb);
|
|
197
198
|
}
|
|
198
199
|
}
|
|
199
200
|
|