com.amanotes.gdk 0.2.65-2 → 0.2.65-4
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/Editor/Extra/GDKLocalBuild.cs +24 -57
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/CheckDiskSpace.unitypackage +0 -0
- package/Extra/ForceUpdate.unitypackage +0 -0
- package/Extra/GoogleCMP.unitypackage +0 -0
- package/Extra/PostProcessor.unitypackage +0 -0
- package/Extra/SDKVersionTracking.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/RevenueCatAdapter.unitypackage +0 -0
- package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
- package/Runtime/AmaGDK.Analytics.cs +10 -4
- package/Runtime/AmaGDK.Mono.cs +0 -2
- package/Runtime/AmaGDK.UserProfile.cs +1 -1
- package/Runtime/AmaGDK.cs +2 -1
- package/Runtime/AudioToolkit/AmaGDK.Audio.Latency.cs +165 -0
- package/Runtime/AudioToolkit/AmaGDK.Audio.Latency.cs.meta +11 -0
- package/Runtime/AudioToolkit/AmaGDK.Audio.cs +158 -0
- package/Runtime/AudioToolkit/AmaGDK.Audio.cs.meta +11 -0
- package/Runtime/AudioToolkit/Plugins/Android/AudioDeviceDetector.java +321 -0
- package/Runtime/AudioToolkit/Plugins/Android/AudioDeviceDetector.java.meta +32 -0
- package/Runtime/AudioToolkit/Plugins/Android.meta +8 -0
- package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +208 -0
- package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs.meta +3 -0
- package/Runtime/AudioToolkit/Plugins/iOS/AudioDeviceDetector.mm +163 -0
- package/Runtime/AudioToolkit/Plugins/iOS/AudioDeviceDetector.mm.meta +33 -0
- package/Runtime/AudioToolkit/Plugins/iOS.meta +8 -0
- package/Runtime/AudioToolkit/Plugins.meta +8 -0
- package/Runtime/AudioToolkit/Resources/device-latency.txt +256 -0
- package/Runtime/AudioToolkit/Resources/device-latency.txt.meta +7 -0
- package/Runtime/AudioToolkit/Resources.meta +8 -0
- package/Runtime/AudioToolkit.meta +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
package com.amanotes.audio;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.media.AudioDeviceInfo;
|
|
5
|
+
import android.media.AudioDeviceCallback;
|
|
6
|
+
import android.media.AudioManager;
|
|
7
|
+
import android.media.MediaRouter;
|
|
8
|
+
import android.os.Build;
|
|
9
|
+
import android.util.Log;
|
|
10
|
+
import java.util.HashMap;
|
|
11
|
+
import java.util.Map;
|
|
12
|
+
|
|
13
|
+
import com.unity3d.player.UnityPlayer;
|
|
14
|
+
|
|
15
|
+
public class AudioDeviceDetector
|
|
16
|
+
{
|
|
17
|
+
private static boolean isRegistered = false;
|
|
18
|
+
private static boolean isFirstCallback = true;
|
|
19
|
+
|
|
20
|
+
private static final String PARAM_FORMAT = "%s;%s";
|
|
21
|
+
private static final String DEFAULT_HEADPHONE_NAME = "h2w";
|
|
22
|
+
|
|
23
|
+
private static MediaRouter.RouteInfo currentRoute;
|
|
24
|
+
|
|
25
|
+
private static final Map<Integer, String> DEVICE_TYPE_MAP = new HashMap<>();
|
|
26
|
+
static {
|
|
27
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_UNKNOWN, "TYPE_UNKNOWN");
|
|
28
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_EARPIECE, "TYPE_BUILTIN_EARPIECE");
|
|
29
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "TYPE_BUILTIN_SPEAKER");
|
|
30
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_WIRED_HEADSET, "TYPE_WIRED_HEADSET");
|
|
31
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, "TYPE_WIRED_HEADPHONES");
|
|
32
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_LINE_ANALOG, "TYPE_LINE_ANALOG");
|
|
33
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_LINE_DIGITAL, "TYPE_LINE_DIGITAL");
|
|
34
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "TYPE_BLUETOOTH_SCO");
|
|
35
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, "TYPE_BLUETOOTH_A2DP");
|
|
36
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HDMI, "TYPE_HDMI");
|
|
37
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HDMI_ARC, "TYPE_HDMI_ARC");
|
|
38
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_USB_DEVICE, "TYPE_USB_DEVICE");
|
|
39
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_USB_ACCESSORY, "TYPE_USB_ACCESSORY");
|
|
40
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_DOCK, "TYPE_DOCK");
|
|
41
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_FM, "TYPE_FM");
|
|
42
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_MIC, "TYPE_BUILTIN_MIC");
|
|
43
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_FM_TUNER, "TYPE_FM_TUNER");
|
|
44
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_TV_TUNER, "TYPE_TV_TUNER");
|
|
45
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_TELEPHONY, "TYPE_TELEPHONY");
|
|
46
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_AUX_LINE, "TYPE_AUX_LINE");
|
|
47
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_IP, "TYPE_IP");
|
|
48
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUS, "TYPE_BUS");
|
|
49
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_USB_HEADSET, "TYPE_USB_HEADSET");
|
|
50
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HEARING_AID, "TYPE_HEARING_AID");
|
|
51
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER_SAFE, "TYPE_BUILTIN_SPEAKER_SAFE");
|
|
52
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_REMOTE_SUBMIX, "TYPE_REMOTE_SUBMIX");
|
|
53
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLE_HEADSET, "TYPE_BLE_HEADSET");
|
|
54
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLE_SPEAKER, "TYPE_BLE_SPEAKER");
|
|
55
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_HDMI_EARC, "TYPE_HDMI_EARC");
|
|
56
|
+
DEVICE_TYPE_MAP.put(AudioDeviceInfo.TYPE_BLE_BROADCAST, "TYPE_BLE_BROADCAST");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public static void registerEvents() {
|
|
60
|
+
if (isRegistered)
|
|
61
|
+
return;
|
|
62
|
+
isRegistered = true;
|
|
63
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
64
|
+
registerForVersionM();
|
|
65
|
+
} else {
|
|
66
|
+
registerForVersionBeforeM();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public static String getAudioInfo() {
|
|
71
|
+
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|
72
|
+
? getActiveParamM()
|
|
73
|
+
: getActiveParamBeforeM();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private static void registerForVersionM() {
|
|
77
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
|
78
|
+
return;
|
|
79
|
+
Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
|
|
80
|
+
if (unityContext == null)
|
|
81
|
+
return;
|
|
82
|
+
AudioManager audioManager = (AudioManager) unityContext.getSystemService(Context.AUDIO_SERVICE);
|
|
83
|
+
if (audioManager == null)
|
|
84
|
+
return;
|
|
85
|
+
|
|
86
|
+
audioManager.registerAudioDeviceCallback(new AudioDeviceCallback() {
|
|
87
|
+
@Override
|
|
88
|
+
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
|
|
89
|
+
super.onAudioDevicesAdded(addedDevices);
|
|
90
|
+
if (isFirstCallback) {
|
|
91
|
+
isFirstCallback = false;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (AudioDeviceInfo deviceInfo : addedDevices) {
|
|
95
|
+
if (deviceInfo == null)
|
|
96
|
+
continue;
|
|
97
|
+
if (deviceInfo.isSink()) {
|
|
98
|
+
String param = GetParamForDevice(deviceInfo);
|
|
99
|
+
UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceAdded", param);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Override
|
|
105
|
+
public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
|
|
106
|
+
super.onAudioDevicesRemoved(removedDevices);
|
|
107
|
+
for (AudioDeviceInfo deviceInfo : removedDevices) {
|
|
108
|
+
if (deviceInfo == null)
|
|
109
|
+
continue;
|
|
110
|
+
if (deviceInfo.isSink()) {
|
|
111
|
+
String param = GetParamForDevice(deviceInfo);
|
|
112
|
+
UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceRemoved", param);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}, null);
|
|
117
|
+
|
|
118
|
+
MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
|
|
119
|
+
if (mediaRouter == null)
|
|
120
|
+
return;
|
|
121
|
+
//listen to route change
|
|
122
|
+
mediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_AUDIO, new MediaRouter.SimpleCallback() {
|
|
123
|
+
@Override
|
|
124
|
+
public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
|
|
125
|
+
super.onRouteChanged(router, route);
|
|
126
|
+
//detect if change active device
|
|
127
|
+
if (route == router.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO))
|
|
128
|
+
return;
|
|
129
|
+
if (route.isEnabled() && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL && route.getPlaybackStream() == AudioManager.STREAM_MUSIC) {
|
|
130
|
+
//sent empty string to update current
|
|
131
|
+
UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioRouteChanged", "");
|
|
132
|
+
currentRoute = route;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@Override
|
|
137
|
+
public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) {
|
|
138
|
+
super.onRouteSelected(router, type, info);
|
|
139
|
+
//sent empty string to update current
|
|
140
|
+
UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioRouteChanged", "");
|
|
141
|
+
currentRoute = info;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private static String getActiveParamM() {
|
|
147
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
|
148
|
+
return "";
|
|
149
|
+
|
|
150
|
+
Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
|
|
151
|
+
if (unityContext == null)
|
|
152
|
+
return "";
|
|
153
|
+
|
|
154
|
+
MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
|
|
155
|
+
if(mediaRouter == null)
|
|
156
|
+
return "";
|
|
157
|
+
|
|
158
|
+
AudioManager am = (AudioManager) unityContext.getSystemService(Context.AUDIO_SERVICE);
|
|
159
|
+
if (am == null)
|
|
160
|
+
return "";
|
|
161
|
+
|
|
162
|
+
if (currentRoute == null) {
|
|
163
|
+
currentRoute = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
AudioDeviceInfo device = null;
|
|
167
|
+
AudioDeviceInfo[] activeDevices = am.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
|
|
168
|
+
|
|
169
|
+
if(activeDevices == null || activeDevices.length == 0)
|
|
170
|
+
return "";
|
|
171
|
+
|
|
172
|
+
String name = currentRoute.getName() != null ? currentRoute.getName().toString() : "";
|
|
173
|
+
for (AudioDeviceInfo deviceInfo : activeDevices) {
|
|
174
|
+
int type = deviceInfo.getType();
|
|
175
|
+
if (deviceInfo.getType() == AudioDeviceInfo.TYPE_BLUETOOTH_SCO)
|
|
176
|
+
continue;
|
|
177
|
+
if (isWiredDevice(type) || name.contentEquals(deviceInfo.getProductName())) {
|
|
178
|
+
device = deviceInfo;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if(device != null)
|
|
184
|
+
return GetParamForDevice(device);
|
|
185
|
+
|
|
186
|
+
device = activeDevices[0];
|
|
187
|
+
for (AudioDeviceInfo deviceInfo : activeDevices) {
|
|
188
|
+
int type = deviceInfo.getType();
|
|
189
|
+
if (!deviceInfo.isSink())
|
|
190
|
+
continue;
|
|
191
|
+
if (am.isSpeakerphoneOn() && (type == AudioDeviceInfo.TYPE_BUILTIN_EARPIECE || type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)) {
|
|
192
|
+
device = deviceInfo;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
if (am.isBluetoothA2dpOn() && type == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP) {
|
|
196
|
+
device = deviceInfo;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
if (am.isBluetoothScoOn() && type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
|
|
200
|
+
device = deviceInfo;
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (device == null)
|
|
206
|
+
return "";
|
|
207
|
+
return GetParamForDevice(device);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private static boolean isWiredDevice(int type)
|
|
211
|
+
{
|
|
212
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
|
213
|
+
{
|
|
214
|
+
return type == AudioDeviceInfo.TYPE_WIRED_HEADSET
|
|
215
|
+
|| type == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
|
|
216
|
+
|| type == AudioDeviceInfo.TYPE_LINE_ANALOG
|
|
217
|
+
|| type == AudioDeviceInfo.TYPE_LINE_DIGITAL;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private static String GetParamForDevice(AudioDeviceInfo device)
|
|
224
|
+
{
|
|
225
|
+
if(device == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
|
226
|
+
return "";
|
|
227
|
+
|
|
228
|
+
int type = device.getType();
|
|
229
|
+
if (type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO)
|
|
230
|
+
return "";
|
|
231
|
+
|
|
232
|
+
CharSequence name = device.getProductName();
|
|
233
|
+
if (isWiredDevice(type) || DEFAULT_HEADPHONE_NAME.contentEquals(name)) {
|
|
234
|
+
return getReturnParam("Headphones", toTypeString(type));
|
|
235
|
+
}
|
|
236
|
+
return getReturnParam(name, toTypeString(type));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private static String getReturnParam(CharSequence name, String type)
|
|
240
|
+
{
|
|
241
|
+
return String.format(PARAM_FORMAT, name, type);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private static String toTypeString(int AudioDeviceType)
|
|
245
|
+
{
|
|
246
|
+
return DEVICE_TYPE_MAP.getOrDefault(AudioDeviceType, "TYPE_UNKNOWN");
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// API For Version before M
|
|
250
|
+
private static String getActiveParamBeforeM()
|
|
251
|
+
{
|
|
252
|
+
Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
|
|
253
|
+
if (unityContext == null)
|
|
254
|
+
return "";
|
|
255
|
+
AudioManager audioManager = (AudioManager) unityContext.getSystemService(Context.AUDIO_SERVICE);
|
|
256
|
+
if (audioManager == null)
|
|
257
|
+
return "";
|
|
258
|
+
MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
|
|
259
|
+
if (mediaRouter == null)
|
|
260
|
+
return "";
|
|
261
|
+
|
|
262
|
+
String type = "NOT_AVAILABLE";
|
|
263
|
+
MediaRouter.RouteInfo routeInfo = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
|
|
264
|
+
if (audioManager.isBluetoothA2dpOn())
|
|
265
|
+
type = "TYPE_BLUETOOTH_A2DP";
|
|
266
|
+
else if (audioManager.isBluetoothScoOn())
|
|
267
|
+
type = "TYPE_BLUETOOTH_SCO";
|
|
268
|
+
else if (audioManager.isSpeakerphoneOn())
|
|
269
|
+
type = "TYPE_BUILTIN_SPEAKER";
|
|
270
|
+
return getReturnParam(routeInfo.getName(), type);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private static void registerForVersionBeforeM()
|
|
274
|
+
{
|
|
275
|
+
Context unityContext = UnityPlayer.currentActivity.getApplicationContext();
|
|
276
|
+
if (unityContext == null)
|
|
277
|
+
return;
|
|
278
|
+
MediaRouter mediaRouter = (MediaRouter) unityContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
|
|
279
|
+
if (mediaRouter == null)
|
|
280
|
+
return;
|
|
281
|
+
|
|
282
|
+
mediaRouter.addCallback(MediaRouter.ROUTE_TYPE_LIVE_AUDIO, new MediaRouter.SimpleCallback() {
|
|
283
|
+
@Override
|
|
284
|
+
public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
|
|
285
|
+
super.onRouteChanged(router, route);
|
|
286
|
+
//detect if change active device
|
|
287
|
+
if (route == router.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO))
|
|
288
|
+
return;
|
|
289
|
+
if (route.isEnabled() && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL && route.getPlaybackStream() == AudioManager.STREAM_MUSIC) {
|
|
290
|
+
UnityPlayer.UnitySendMessage("AmaGDK","OnAudioDeviceAdded", formatToParam(route));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@Override
|
|
295
|
+
public void onRouteSelected(MediaRouter router,int type, MediaRouter.RouteInfo info) {
|
|
296
|
+
super.onRouteRemoved(router, info);
|
|
297
|
+
UnityPlayer.UnitySendMessage("AmaGDK","OnAudioDeviceAdded", formatToParam(info));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@Override
|
|
301
|
+
public void onRouteUnselected(MediaRouter router,int type, MediaRouter.RouteInfo info) {
|
|
302
|
+
super.onRouteAdded(router, info);
|
|
303
|
+
UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceRemoved", formatToParam(info));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
@Override
|
|
307
|
+
public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) {
|
|
308
|
+
super.onRouteRemoved(router, info);
|
|
309
|
+
UnityPlayer.UnitySendMessage("AmaGDK", "OnAudioDeviceRemoved", formatToParam(info));
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private String formatToParam(MediaRouter.RouteInfo info)
|
|
313
|
+
{
|
|
314
|
+
if (info == null) return "";
|
|
315
|
+
String type = "NOT_AVAILABLE";
|
|
316
|
+
CharSequence name = info.getName();
|
|
317
|
+
return getReturnParam(name, type);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
fileFormatVersion: 2
|
|
2
|
+
guid: 1db90e301ca5c40dcb36104b951a9cbc
|
|
3
|
+
PluginImporter:
|
|
4
|
+
externalObjects: {}
|
|
5
|
+
serializedVersion: 2
|
|
6
|
+
iconMap: {}
|
|
7
|
+
executionOrder: {}
|
|
8
|
+
defineConstraints: []
|
|
9
|
+
isPreloaded: 0
|
|
10
|
+
isOverridable: 0
|
|
11
|
+
isExplicitlyReferenced: 0
|
|
12
|
+
validateReferences: 1
|
|
13
|
+
platformData:
|
|
14
|
+
- first:
|
|
15
|
+
Android: Android
|
|
16
|
+
second:
|
|
17
|
+
enabled: 1
|
|
18
|
+
settings: {}
|
|
19
|
+
- first:
|
|
20
|
+
Any:
|
|
21
|
+
second:
|
|
22
|
+
enabled: 0
|
|
23
|
+
settings: {}
|
|
24
|
+
- first:
|
|
25
|
+
Editor: Editor
|
|
26
|
+
second:
|
|
27
|
+
enabled: 0
|
|
28
|
+
settings:
|
|
29
|
+
DefaultValueInitialized: true
|
|
30
|
+
userData:
|
|
31
|
+
assetBundleName:
|
|
32
|
+
assetBundleVariant:
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Runtime.InteropServices;
|
|
4
|
+
using System.Text;
|
|
5
|
+
using Amanotes.Core.Internal;
|
|
6
|
+
using UnityEngine;
|
|
7
|
+
|
|
8
|
+
namespace Amanotes.Core
|
|
9
|
+
{
|
|
10
|
+
internal class AudioDeviceDetector : MonoBehaviour
|
|
11
|
+
{
|
|
12
|
+
#if !UNITY_EDITOR && UNITY_IOS
|
|
13
|
+
[DllImport("__Internal")]
|
|
14
|
+
private static extern void _RegisterAudioInfoChanged();
|
|
15
|
+
|
|
16
|
+
[DllImport("__Internal")]
|
|
17
|
+
private static extern string _GetAudioInfo();
|
|
18
|
+
|
|
19
|
+
[DllImport("__Internal")]
|
|
20
|
+
private static extern string _GetCurrentRouteInputs();
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
#if !UNITY_EDITOR && UNITY_ANDROID
|
|
24
|
+
private readonly AndroidJavaClass _detectorClass = new AndroidJavaClass("com.amanotes.audio.AudioDeviceDetector");
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
private static readonly Dictionary<string, AudioDeviceType> deviceTypeMapping = new Dictionary<string, AudioDeviceType>(StringComparer.OrdinalIgnoreCase)
|
|
28
|
+
{
|
|
29
|
+
//iOS
|
|
30
|
+
{ "AVAudioSessionPortAirPlay", AudioDeviceType.Wireless },
|
|
31
|
+
{ "AVAudioSessionPortBluetoothA2DP", AudioDeviceType.Bluetooth },
|
|
32
|
+
{ "AVAudioSessionPortBluetoothLE", AudioDeviceType.Bluetooth },
|
|
33
|
+
{ "AVAudioSessionPortBluetoothHFP", AudioDeviceType.Bluetooth },
|
|
34
|
+
{ "AVAudioSessionPortBuiltInReceiver", AudioDeviceType.Internal },
|
|
35
|
+
{ "AVAudioSessionPortBuiltInSpeaker", AudioDeviceType.Internal },
|
|
36
|
+
{ "AVAudioSessionPortHDMI", AudioDeviceType.Wire },
|
|
37
|
+
{ "AVAudioSessionPortHeadphones", AudioDeviceType.Wire },
|
|
38
|
+
{ "AVAudioSessionPortLineOut", AudioDeviceType.Wire },
|
|
39
|
+
{ "AVAudioSessionPortDisplayPort", AudioDeviceType.Wire },
|
|
40
|
+
{ "AVAudioSessionPortCarAudio", AudioDeviceType.Wire },
|
|
41
|
+
{ "AVAudioSessionPortFireWire", AudioDeviceType.Wire },
|
|
42
|
+
{ "AVAudioSessionPortPCI", AudioDeviceType.Wire },
|
|
43
|
+
{ "AVAudioSessionPortThunderbolt", AudioDeviceType.Wire },
|
|
44
|
+
{ "AVAudioSessionPortUSBAudio", AudioDeviceType.Wire },
|
|
45
|
+
{ "AVAudioSessionPortVirtual", AudioDeviceType.Wire },
|
|
46
|
+
//Android
|
|
47
|
+
{ "TYPE_BLUETOOTH_SCO", AudioDeviceType.Bluetooth },
|
|
48
|
+
{ "TYPE_BLUETOOTH_A2DP", AudioDeviceType.Bluetooth },
|
|
49
|
+
{ "TYPE_BLE_HEADSET", AudioDeviceType.Bluetooth },
|
|
50
|
+
{ "TYPE_BLE_SPEAKER", AudioDeviceType.Bluetooth },
|
|
51
|
+
{ "TYPE_BLE_BROADCAST", AudioDeviceType.Bluetooth },
|
|
52
|
+
{ "TYPE_BUILTIN_SPEAKER_SAFE", AudioDeviceType.Internal },
|
|
53
|
+
{ "TYPE_BUILTIN_MIC", AudioDeviceType.Internal },
|
|
54
|
+
{ "TYPE_BUILTIN_EARPIECE", AudioDeviceType.Internal },
|
|
55
|
+
{ "TYPE_BUILTIN_SPEAKER", AudioDeviceType.Internal },
|
|
56
|
+
{ "TYPE_USB_HEADSET", AudioDeviceType.Wire },
|
|
57
|
+
{ "TYPE_USB_DEVICE", AudioDeviceType.Wire },
|
|
58
|
+
{ "TYPE_USB_ACCESSORY", AudioDeviceType.Wire },
|
|
59
|
+
{ "TYPE_TELEPHONY", AudioDeviceType.Wire },
|
|
60
|
+
{ "TYPE_LINE_ANALOG", AudioDeviceType.Wire },
|
|
61
|
+
{ "TYPE_LINE_DIGITAL", AudioDeviceType.Wire },
|
|
62
|
+
{ "TYPE_HDMI_ARC", AudioDeviceType.Wire },
|
|
63
|
+
{ "TYPE_HDMI_EARC", AudioDeviceType.Wire },
|
|
64
|
+
{ "TYPE_HDMI", AudioDeviceType.Wire },
|
|
65
|
+
{ "TYPE_DOCK", AudioDeviceType.Wire },
|
|
66
|
+
{ "TYPE_AUX_LINE", AudioDeviceType.Wire },
|
|
67
|
+
{ "TYPE_WIRED_HEADSET", AudioDeviceType.Wire },
|
|
68
|
+
{ "TYPE_WIRED_HEADPHONES", AudioDeviceType.Wire },
|
|
69
|
+
{ "TYPE_FM", AudioDeviceType.Wireless },
|
|
70
|
+
{ "TYPE_FM_TUNER", AudioDeviceType.Wireless },
|
|
71
|
+
{ "TYPE_IP", AudioDeviceType.Wireless },
|
|
72
|
+
{ "TYPE_REMOTE_SUBMIX", AudioDeviceType.Unknown },
|
|
73
|
+
{ "TYPE_BUS", AudioDeviceType.Unknown },
|
|
74
|
+
{ "TYPE_HEARING_AID", AudioDeviceType.Unknown },
|
|
75
|
+
{ "TYPE_UNKNOWN", AudioDeviceType.Unknown },
|
|
76
|
+
{ "TYPE_TV_TUNER", AudioDeviceType.Unknown }
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
internal event Action<string> onChanged;
|
|
80
|
+
internal event Action<string> onInterrupted;
|
|
81
|
+
|
|
82
|
+
private void OnAudioInterrupted(string param)
|
|
83
|
+
{
|
|
84
|
+
onInterrupted?.Invoke(param);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private void OnAudioDeviceAdded(string param)
|
|
88
|
+
{
|
|
89
|
+
if (string.IsNullOrEmpty(param))
|
|
90
|
+
return;
|
|
91
|
+
onChanged?.Invoke(param);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private void OnAudioDeviceRemoved(string param)
|
|
95
|
+
{
|
|
96
|
+
if (string.IsNullOrEmpty(param))
|
|
97
|
+
return;
|
|
98
|
+
onChanged?.Invoke(param);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private void OnAudioRouteChanged(string param)
|
|
102
|
+
{
|
|
103
|
+
onChanged?.Invoke(param);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
internal void RegisterEvents()
|
|
107
|
+
{
|
|
108
|
+
#if !UNITY_EDITOR && UNITY_IOS
|
|
109
|
+
_RegisterAudioInfoChanged();
|
|
110
|
+
#elif !UNITY_EDITOR && UNITY_ANDROID
|
|
111
|
+
_detectorClass.CallStatic("registerEvents");
|
|
112
|
+
#endif
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
internal (AudioDeviceType AudioDeviceType, string RawType, string Name) GetInfo()
|
|
116
|
+
{
|
|
117
|
+
string param = string.Empty;
|
|
118
|
+
#if !UNITY_EDITOR && UNITY_IOS
|
|
119
|
+
param = _GetAudioInfo();
|
|
120
|
+
#elif !UNITY_EDITOR && UNITY_ANDROID
|
|
121
|
+
param = _detectorClass.CallStatic<string>("getAudioInfo");
|
|
122
|
+
#endif
|
|
123
|
+
return ParseStringInfo(param);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
internal string GetCurrentRouteInputs()
|
|
127
|
+
{
|
|
128
|
+
#if !UNITY_EDITOR && UNITY_IOS
|
|
129
|
+
return _GetCurrentRouteInputs();
|
|
130
|
+
#else
|
|
131
|
+
return string.Empty;
|
|
132
|
+
#endif
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
internal (AudioDeviceType AudioDeviceType, string RawType, string Name) ParseStringInfo(string param)
|
|
136
|
+
{
|
|
137
|
+
if (string.IsNullOrEmpty(param))
|
|
138
|
+
return (AudioDeviceType.Unknown, null, null);
|
|
139
|
+
|
|
140
|
+
string[] parameters = param.Split(';');
|
|
141
|
+
|
|
142
|
+
if (parameters.Length < 2)
|
|
143
|
+
return (AudioDeviceType.Unknown, null, null);
|
|
144
|
+
|
|
145
|
+
string name = RemoveSurrogatePairs(parameters[0]);
|
|
146
|
+
string rawType = parameters[1];
|
|
147
|
+
AudioDeviceType type = MapDeviceType(rawType);
|
|
148
|
+
if (type == AudioDeviceType.Internal)
|
|
149
|
+
{
|
|
150
|
+
name = string.Empty;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return (type, rawType, name);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private AudioDeviceType MapDeviceType(string rawType)
|
|
157
|
+
{
|
|
158
|
+
if (deviceTypeMapping.TryGetValue(rawType, out var type))
|
|
159
|
+
{
|
|
160
|
+
return type;
|
|
161
|
+
}
|
|
162
|
+
return AudioDeviceType.Unknown;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private static string RemoveSurrogatePairs(string str, string replacementCharacter = "?")
|
|
166
|
+
{
|
|
167
|
+
if (str == null)
|
|
168
|
+
{
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
StringBuilder sb = null;
|
|
173
|
+
|
|
174
|
+
for (int i = 0; i < str.Length; i++)
|
|
175
|
+
{
|
|
176
|
+
char ch = str[i];
|
|
177
|
+
|
|
178
|
+
if (char.IsSurrogate(ch))
|
|
179
|
+
{
|
|
180
|
+
sb ??= new StringBuilder(str, 0, i, str.Length);
|
|
181
|
+
|
|
182
|
+
sb.Append(replacementCharacter);
|
|
183
|
+
|
|
184
|
+
// If there is a high+low surrogate, skip the low surrogate
|
|
185
|
+
if (i + 1 < str.Length && char.IsHighSurrogate(ch) && char.IsLowSurrogate(str[i + 1]))
|
|
186
|
+
{
|
|
187
|
+
i++;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else if (sb != null)
|
|
191
|
+
{
|
|
192
|
+
sb.Append(ch);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return sb == null ? str : sb.ToString();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
internal enum AudioDeviceType
|
|
201
|
+
{
|
|
202
|
+
Unknown = 0,
|
|
203
|
+
Internal,
|
|
204
|
+
Wire,
|
|
205
|
+
Wireless,
|
|
206
|
+
Bluetooth,
|
|
207
|
+
}
|
|
208
|
+
}
|