voice-react-native-sdk 1.6.2-fork.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.
Files changed (227) hide show
  1. package/LICENSE +206 -0
  2. package/README.md +179 -0
  3. package/android/build.gradle +113 -0
  4. package/android/gradle.properties +29 -0
  5. package/android/src/main/AndroidManifest.xml +30 -0
  6. package/android/src/main/java/com/twiliovoicereactnative/AudioSwitchManager.java +141 -0
  7. package/android/src/main/java/com/twiliovoicereactnative/CallListenerProxy.java +186 -0
  8. package/android/src/main/java/com/twiliovoicereactnative/CallMessageListenerProxy.java +103 -0
  9. package/android/src/main/java/com/twiliovoicereactnative/CallRecordDatabase.java +183 -0
  10. package/android/src/main/java/com/twiliovoicereactnative/CommonConstants.java +195 -0
  11. package/android/src/main/java/com/twiliovoicereactnative/ConfigurationProperties.java +41 -0
  12. package/android/src/main/java/com/twiliovoicereactnative/Constants.java +23 -0
  13. package/android/src/main/java/com/twiliovoicereactnative/ExpoActivityLifecycleListener.java +27 -0
  14. package/android/src/main/java/com/twiliovoicereactnative/ExpoApplicationLifecycleListener.java +14 -0
  15. package/android/src/main/java/com/twiliovoicereactnative/ExpoModule.kt +36 -0
  16. package/android/src/main/java/com/twiliovoicereactnative/ExpoPackage.java +20 -0
  17. package/android/src/main/java/com/twiliovoicereactnative/JSEventEmitter.java +98 -0
  18. package/android/src/main/java/com/twiliovoicereactnative/MediaPlayerManager.java +58 -0
  19. package/android/src/main/java/com/twiliovoicereactnative/NotificationUtility.java +363 -0
  20. package/android/src/main/java/com/twiliovoicereactnative/ReactNativeArgumentsSerializer.java +276 -0
  21. package/android/src/main/java/com/twiliovoicereactnative/SDKLog.java +74 -0
  22. package/android/src/main/java/com/twiliovoicereactnative/StatsListenerProxy.java +178 -0
  23. package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativeModule.java +778 -0
  24. package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativePackage.java +28 -0
  25. package/android/src/main/java/com/twiliovoicereactnative/VoiceActivityProxy.java +101 -0
  26. package/android/src/main/java/com/twiliovoicereactnative/VoiceApplicationProxy.java +133 -0
  27. package/android/src/main/java/com/twiliovoicereactnative/VoiceFirebaseMessagingService.java +88 -0
  28. package/android/src/main/java/com/twiliovoicereactnative/VoiceService.java +403 -0
  29. package/android/src/main/res/drawable/answered_call_small_icon.png +0 -0
  30. package/android/src/main/res/drawable/ic_launcher_round.png +0 -0
  31. package/android/src/main/res/drawable/ic_launcher_sdk.png +0 -0
  32. package/android/src/main/res/drawable/incoming_call_small_icon.png +0 -0
  33. package/android/src/main/res/drawable/outgoing_call_small_icon.png +0 -0
  34. package/android/src/main/res/raw/disconnect.wav +0 -0
  35. package/android/src/main/res/raw/incoming.wav +0 -0
  36. package/android/src/main/res/raw/outgoing.wav +0 -0
  37. package/android/src/main/res/raw/ringtone.wav +0 -0
  38. package/android/src/main/res/raw/silent.wav +0 -0
  39. package/android/src/main/res/values/colors.xml +11 -0
  40. package/android/src/main/res/values/config.xml +5 -0
  41. package/android/src/main/res/values/dimens.xml +7 -0
  42. package/android/src/main/res/values/strings.xml +25 -0
  43. package/android/src/main/res/values/styles.xml +10 -0
  44. package/android/src/main/res/values-night/colors.xml +11 -0
  45. package/expo-config-plugin/android.js +191 -0
  46. package/expo-config-plugin/ios.js +22 -0
  47. package/expo-module.config.json +6 -0
  48. package/ios/TwilioVoicePushRegistry.h +19 -0
  49. package/ios/TwilioVoicePushRegistry.m +72 -0
  50. package/ios/TwilioVoiceReactNative+CallInvite.m +56 -0
  51. package/ios/TwilioVoiceReactNative+CallKit.m +533 -0
  52. package/ios/TwilioVoiceReactNative+CallMessage.m +81 -0
  53. package/ios/TwilioVoiceReactNative.h +74 -0
  54. package/ios/TwilioVoiceReactNative.m +1046 -0
  55. package/ios/TwilioVoiceReactNative.xcodeproj/project.pbxproj +328 -0
  56. package/ios/TwilioVoiceReactNativeConstants.h +200 -0
  57. package/ios/Utilities/TwilioVoiceStatsReport.h +175 -0
  58. package/lib/commonjs/AudioDevice.js +101 -0
  59. package/lib/commonjs/AudioDevice.js.map +1 -0
  60. package/lib/commonjs/Call.js +765 -0
  61. package/lib/commonjs/Call.js.map +1 -0
  62. package/lib/commonjs/CallInvite.js +452 -0
  63. package/lib/commonjs/CallInvite.js.map +1 -0
  64. package/lib/commonjs/CallMessage/CallMessage.js +54 -0
  65. package/lib/commonjs/CallMessage/CallMessage.js.map +1 -0
  66. package/lib/commonjs/CallMessage/IncomingCallMessage.js +120 -0
  67. package/lib/commonjs/CallMessage/IncomingCallMessage.js.map +1 -0
  68. package/lib/commonjs/CallMessage/OutgoingCallMessage.js +148 -0
  69. package/lib/commonjs/CallMessage/OutgoingCallMessage.js.map +1 -0
  70. package/lib/commonjs/ExpoModule.js +69 -0
  71. package/lib/commonjs/ExpoModule.js.map +1 -0
  72. package/lib/commonjs/Voice.js +611 -0
  73. package/lib/commonjs/Voice.js.map +1 -0
  74. package/lib/commonjs/common.js +26 -0
  75. package/lib/commonjs/common.js.map +1 -0
  76. package/lib/commonjs/constants.js +158 -0
  77. package/lib/commonjs/constants.js.map +1 -0
  78. package/lib/commonjs/error/InvalidArgumentError.js +32 -0
  79. package/lib/commonjs/error/InvalidArgumentError.js.map +1 -0
  80. package/lib/commonjs/error/InvalidStateError.js +33 -0
  81. package/lib/commonjs/error/InvalidStateError.js.map +1 -0
  82. package/lib/commonjs/error/TwilioError.js +38 -0
  83. package/lib/commonjs/error/TwilioError.js.map +1 -0
  84. package/lib/commonjs/error/UnsupportedPlatformError.js +33 -0
  85. package/lib/commonjs/error/UnsupportedPlatformError.js.map +1 -0
  86. package/lib/commonjs/error/generated.js +2343 -0
  87. package/lib/commonjs/error/generated.js.map +1 -0
  88. package/lib/commonjs/error/index.js +112 -0
  89. package/lib/commonjs/error/index.js.map +1 -0
  90. package/lib/commonjs/error/utility.js +37 -0
  91. package/lib/commonjs/error/utility.js.map +1 -0
  92. package/lib/commonjs/index.js +95 -0
  93. package/lib/commonjs/index.js.map +1 -0
  94. package/lib/commonjs/type/AudioDevice.js +6 -0
  95. package/lib/commonjs/type/AudioDevice.js.map +1 -0
  96. package/lib/commonjs/type/Call.js +6 -0
  97. package/lib/commonjs/type/Call.js.map +1 -0
  98. package/lib/commonjs/type/CallInvite.js +6 -0
  99. package/lib/commonjs/type/CallInvite.js.map +1 -0
  100. package/lib/commonjs/type/CallKit.js +30 -0
  101. package/lib/commonjs/type/CallKit.js.map +1 -0
  102. package/lib/commonjs/type/CallMessage.js +6 -0
  103. package/lib/commonjs/type/CallMessage.js.map +1 -0
  104. package/lib/commonjs/type/Error.js +6 -0
  105. package/lib/commonjs/type/Error.js.map +1 -0
  106. package/lib/commonjs/type/NativeModule.js +6 -0
  107. package/lib/commonjs/type/NativeModule.js.map +1 -0
  108. package/lib/commonjs/type/RTCStats.js +29 -0
  109. package/lib/commonjs/type/RTCStats.js.map +1 -0
  110. package/lib/commonjs/type/Voice.js +6 -0
  111. package/lib/commonjs/type/Voice.js.map +1 -0
  112. package/lib/commonjs/type/common.js +2 -0
  113. package/lib/commonjs/type/common.js.map +1 -0
  114. package/lib/module/AudioDevice.js +97 -0
  115. package/lib/module/AudioDevice.js.map +1 -0
  116. package/lib/module/Call.js +766 -0
  117. package/lib/module/Call.js.map +1 -0
  118. package/lib/module/CallInvite.js +450 -0
  119. package/lib/module/CallInvite.js.map +1 -0
  120. package/lib/module/CallMessage/CallMessage.js +51 -0
  121. package/lib/module/CallMessage/CallMessage.js.map +1 -0
  122. package/lib/module/CallMessage/IncomingCallMessage.js +116 -0
  123. package/lib/module/CallMessage/IncomingCallMessage.js.map +1 -0
  124. package/lib/module/CallMessage/OutgoingCallMessage.js +154 -0
  125. package/lib/module/CallMessage/OutgoingCallMessage.js.map +1 -0
  126. package/lib/module/ExpoModule.js +58 -0
  127. package/lib/module/ExpoModule.js.map +1 -0
  128. package/lib/module/Voice.js +598 -0
  129. package/lib/module/Voice.js.map +1 -0
  130. package/lib/module/common.js +11 -0
  131. package/lib/module/common.js.map +1 -0
  132. package/lib/module/constants.js +151 -0
  133. package/lib/module/constants.js.map +1 -0
  134. package/lib/module/error/InvalidArgumentError.js +23 -0
  135. package/lib/module/error/InvalidArgumentError.js.map +1 -0
  136. package/lib/module/error/InvalidStateError.js +24 -0
  137. package/lib/module/error/InvalidStateError.js.map +1 -0
  138. package/lib/module/error/TwilioError.js +29 -0
  139. package/lib/module/error/TwilioError.js.map +1 -0
  140. package/lib/module/error/UnsupportedPlatformError.js +24 -0
  141. package/lib/module/error/UnsupportedPlatformError.js.map +1 -0
  142. package/lib/module/error/generated.js +2315 -0
  143. package/lib/module/error/generated.js.map +1 -0
  144. package/lib/module/error/index.js +6 -0
  145. package/lib/module/error/index.js.map +1 -0
  146. package/lib/module/error/utility.js +27 -0
  147. package/lib/module/error/utility.js.map +1 -0
  148. package/lib/module/index.js +23 -0
  149. package/lib/module/index.js.map +1 -0
  150. package/lib/module/type/AudioDevice.js +2 -0
  151. package/lib/module/type/AudioDevice.js.map +1 -0
  152. package/lib/module/type/Call.js +2 -0
  153. package/lib/module/type/Call.js.map +1 -0
  154. package/lib/module/type/CallInvite.js +2 -0
  155. package/lib/module/type/CallInvite.js.map +1 -0
  156. package/lib/module/type/CallKit.js +22 -0
  157. package/lib/module/type/CallKit.js.map +1 -0
  158. package/lib/module/type/CallMessage.js +2 -0
  159. package/lib/module/type/CallMessage.js.map +1 -0
  160. package/lib/module/type/Error.js +2 -0
  161. package/lib/module/type/Error.js.map +1 -0
  162. package/lib/module/type/NativeModule.js +2 -0
  163. package/lib/module/type/NativeModule.js.map +1 -0
  164. package/lib/module/type/RTCStats.js +21 -0
  165. package/lib/module/type/RTCStats.js.map +1 -0
  166. package/lib/module/type/Voice.js +2 -0
  167. package/lib/module/type/Voice.js.map +1 -0
  168. package/lib/module/type/common.js +2 -0
  169. package/lib/module/type/common.js.map +1 -0
  170. package/lib/typescript/AudioDevice.d.ts +74 -0
  171. package/lib/typescript/Call.d.ts +874 -0
  172. package/lib/typescript/CallInvite.d.ts +484 -0
  173. package/lib/typescript/CallMessage/CallMessage.d.ts +53 -0
  174. package/lib/typescript/CallMessage/IncomingCallMessage.d.ts +75 -0
  175. package/lib/typescript/CallMessage/OutgoingCallMessage.d.ts +198 -0
  176. package/lib/typescript/ExpoModule.d.ts +13 -0
  177. package/lib/typescript/Voice.d.ts +620 -0
  178. package/lib/typescript/common.d.ts +11 -0
  179. package/lib/typescript/constants.d.ts +148 -0
  180. package/lib/typescript/error/InvalidArgumentError.d.ts +11 -0
  181. package/lib/typescript/error/InvalidStateError.d.ts +12 -0
  182. package/lib/typescript/error/TwilioError.d.ts +14 -0
  183. package/lib/typescript/error/UnsupportedPlatformError.d.ts +12 -0
  184. package/lib/typescript/error/generated.d.ts +1558 -0
  185. package/lib/typescript/error/index.d.ts +5 -0
  186. package/lib/typescript/error/utility.d.ts +12 -0
  187. package/lib/typescript/index.d.ts +18 -0
  188. package/lib/typescript/type/AudioDevice.d.ts +15 -0
  189. package/lib/typescript/type/Call.d.ts +59 -0
  190. package/lib/typescript/type/CallInvite.d.ts +40 -0
  191. package/lib/typescript/type/CallKit.d.ts +60 -0
  192. package/lib/typescript/type/CallMessage.d.ts +20 -0
  193. package/lib/typescript/type/Error.d.ts +9 -0
  194. package/lib/typescript/type/NativeModule.d.ts +59 -0
  195. package/lib/typescript/type/RTCStats.d.ts +91 -0
  196. package/lib/typescript/type/Voice.d.ts +16 -0
  197. package/lib/typescript/type/common.d.ts +15 -0
  198. package/package.json +167 -0
  199. package/src/AudioDevice.tsx +88 -0
  200. package/src/Call.tsx +1343 -0
  201. package/src/CallInvite.tsx +757 -0
  202. package/src/CallMessage/CallMessage.ts +83 -0
  203. package/src/CallMessage/IncomingCallMessage.ts +104 -0
  204. package/src/CallMessage/OutgoingCallMessage.ts +308 -0
  205. package/src/ExpoModule.ts +59 -0
  206. package/src/Voice.tsx +1010 -0
  207. package/src/common.ts +16 -0
  208. package/src/constants.ts +193 -0
  209. package/src/error/InvalidArgumentError.ts +19 -0
  210. package/src/error/InvalidStateError.ts +19 -0
  211. package/src/error/TwilioError.ts +22 -0
  212. package/src/error/UnsupportedPlatformError.ts +19 -0
  213. package/src/error/generated.ts +2277 -0
  214. package/src/error/index.ts +18 -0
  215. package/src/error/utility.ts +36 -0
  216. package/src/index.tsx +24 -0
  217. package/src/type/AudioDevice.ts +18 -0
  218. package/src/type/Call.ts +102 -0
  219. package/src/type/CallInvite.ts +59 -0
  220. package/src/type/CallKit.ts +61 -0
  221. package/src/type/CallMessage.ts +31 -0
  222. package/src/type/Error.ts +11 -0
  223. package/src/type/NativeModule.ts +93 -0
  224. package/src/type/RTCStats.ts +99 -0
  225. package/src/type/Voice.ts +31 -0
  226. package/src/type/common.ts +16 -0
  227. package/twilio-voice-react-native.podspec +22 -0
@@ -0,0 +1,141 @@
1
+ package com.twiliovoicereactnative;
2
+
3
+ import android.content.Context;
4
+
5
+ import com.twilio.audioswitch.AudioDevice;
6
+ import com.twilio.audioswitch.AudioSwitch;
7
+
8
+ import java.util.HashMap;
9
+ import java.util.Map;
10
+ import java.util.UUID;
11
+
12
+ import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeyEarpiece;
13
+ import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeySpeaker;
14
+ import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeyBluetooth;
15
+
16
+ import kotlin.Unit;
17
+
18
+ /**
19
+ * AudioSwitchManager maintains a persistent AudioSwitch object and listens for audio
20
+ * device changes. Generates UUIDs per audio device when the AudioSwitch library updates available
21
+ * audio devices.
22
+ */
23
+ class AudioSwitchManager {
24
+ /**
25
+ * The functional interface of a listener to be bound to the AudioSwitchManager.
26
+ */
27
+ @FunctionalInterface
28
+ interface AudioManagerListener {
29
+ void apply(
30
+ Map<String, AudioDevice> audioDevices,
31
+ String selectedAudioDeviceUuid,
32
+ AudioDevice selectedDevice
33
+ );
34
+ }
35
+
36
+ /**
37
+ * Audio device type mapping. Normalizes the class name into a string the JS layer expects.
38
+ */
39
+ public static final Map<String, String> AUDIO_DEVICE_TYPE = Map.of(
40
+ "Speakerphone", AudioDeviceKeySpeaker,
41
+ "BluetoothHeadset", AudioDeviceKeyBluetooth,
42
+ "WiredHeadset", AudioDeviceKeyEarpiece,
43
+ "Earpiece", AudioDeviceKeyEarpiece);
44
+
45
+ /**
46
+ * Map of UUIDs to all available AudioDevices. Kept up-to-date by the AudioSwitch.
47
+ */
48
+ private final HashMap<String, AudioDevice> audioDevices;
49
+ /**
50
+ * The AudioSwitch.
51
+ */
52
+ private final AudioSwitch audioSwitch;
53
+ /**
54
+ * A listener function that is invoked when the AudioSwitch updates.
55
+ */
56
+ private AudioManagerListener listener = null;
57
+ /**
58
+ * The UUID of the selected audio device.
59
+ */
60
+ private String selectedAudioDeviceUuid = null;
61
+
62
+ /**
63
+ * Constructor for the AudioSwitchManager class. Intended to be a singleton.
64
+ * @param context The Android application context
65
+ */
66
+ public AudioSwitchManager(Context context) {
67
+ audioDevices = new HashMap<>();
68
+ audioSwitch = new AudioSwitch(context);
69
+ }
70
+
71
+ public void start() {
72
+ audioSwitch.start((devices, selectedDevice) -> {
73
+
74
+ audioDevices.clear();
75
+ for (AudioDevice device : devices) {
76
+ String uuid = UUID.randomUUID().toString();
77
+ audioDevices.put(uuid, device);
78
+ if (device.equals(selectedDevice)) {
79
+ selectedAudioDeviceUuid = uuid;
80
+ }
81
+ }
82
+
83
+ if (this.listener != null) {
84
+ this.listener.apply(audioDevices, selectedAudioDeviceUuid, selectedDevice);
85
+ }
86
+ return Unit.INSTANCE;
87
+ });
88
+ }
89
+
90
+ public void stop() {
91
+ audioSwitch.stop();
92
+ }
93
+
94
+ /**
95
+ * Set a listener for the AudioSwitchManager. The listener function is invoked every time the
96
+ * AudioSwitch updates. Also invoked at the point the listener is set.
97
+ * @param listener A listener function.
98
+ * @return The singleton AudioSwitchManager.
99
+ */
100
+ public AudioSwitchManager setListener(AudioManagerListener listener) {
101
+ this.listener = listener;
102
+
103
+ this.listener.apply(audioDevices, selectedAudioDeviceUuid, getSelectedAudioDevice());
104
+
105
+ return this;
106
+ }
107
+
108
+ /**
109
+ * Get the AudioSwitch. Note that the AudioSwitchManager is a singleton, and only instantiates an
110
+ * AudioSwitch once in the construction of the AudioSwitchManager. Therefore, there should only be one
111
+ * AudioSwitch object and it is effectively a singleton.
112
+ * @return The AudioSwitch singleton
113
+ */
114
+ public AudioSwitch getAudioSwitch() {
115
+ return audioSwitch;
116
+ }
117
+
118
+ /**
119
+ * Get the audio devices.
120
+ * @return A map of UUIDs to available audio devices
121
+ */
122
+ public HashMap<String, AudioDevice> getAudioDevices() {
123
+ return audioDevices;
124
+ }
125
+
126
+ /**
127
+ * Get the UUID of the selected audio device.
128
+ * @return The UUID of the selected audio device.
129
+ */
130
+ public String getSelectedAudioDeviceUuid() {
131
+ return selectedAudioDeviceUuid;
132
+ }
133
+
134
+ /**
135
+ * Get the selected audio device.
136
+ * @return The selected audio device.
137
+ */
138
+ public AudioDevice getSelectedAudioDevice() {
139
+ return audioDevices.get(selectedAudioDeviceUuid);
140
+ }
141
+ }
@@ -0,0 +1,186 @@
1
+ package com.twiliovoicereactnative;
2
+
3
+ import android.content.Context;
4
+ import android.util.Pair;
5
+
6
+ import androidx.annotation.NonNull;
7
+ import androidx.annotation.Nullable;
8
+
9
+ import com.facebook.react.bridge.WritableMap;
10
+ import com.twilio.voice.Call;
11
+ import com.twilio.voice.CallException;
12
+
13
+ import static com.twiliovoicereactnative.CommonConstants.CallEventConnected;
14
+ import static com.twiliovoicereactnative.CommonConstants.CallEventDisconnected;
15
+ import static com.twiliovoicereactnative.CommonConstants.CallEventReconnected;
16
+ import static com.twiliovoicereactnative.CommonConstants.CallEventReconnecting;
17
+ import static com.twiliovoicereactnative.CommonConstants.CallEventRinging;
18
+ import static com.twiliovoicereactnative.CommonConstants.ScopeCall;
19
+ import static com.twiliovoicereactnative.CommonConstants.VoiceEventType;
20
+ import static com.twiliovoicereactnative.CommonConstants.VoiceErrorKeyError;
21
+ import static com.twiliovoicereactnative.CommonConstants.CallEventCurrentWarnings;
22
+ import static com.twiliovoicereactnative.CommonConstants.CallEventPreviousWarnings;
23
+ import static com.twiliovoicereactnative.CommonConstants.CallEventConnectFailure;
24
+ import static com.twiliovoicereactnative.CommonConstants.CallEventQualityWarningsChanged;
25
+ import static com.twiliovoicereactnative.Constants.JS_EVENT_KEY_CALL_INFO;
26
+ import static com.twiliovoicereactnative.VoiceApplicationProxy.getCallRecordDatabase;
27
+ import static com.twiliovoicereactnative.VoiceApplicationProxy.getJSEventEmitter;
28
+ import static com.twiliovoicereactnative.VoiceApplicationProxy.getAudioSwitchManager;
29
+ import static com.twiliovoicereactnative.VoiceApplicationProxy.getMediaPlayerManager;
30
+ import static com.twiliovoicereactnative.VoiceApplicationProxy.getVoiceServiceApi;
31
+ import static com.twiliovoicereactnative.JSEventEmitter.constructJSMap;
32
+ import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.*;
33
+
34
+ import com.twiliovoicereactnative.CallRecordDatabase.CallRecord;
35
+
36
+ import java.util.Date;
37
+ import java.util.Objects;
38
+ import java.util.Set;
39
+ import java.util.UUID;
40
+
41
+ class CallListenerProxy implements Call.Listener {
42
+ private static final SDKLog logger = new SDKLog(CallListenerProxy.class);
43
+ private final UUID uuid;
44
+ private final Context context;
45
+
46
+ public CallListenerProxy(UUID uuid, Context context) {
47
+ this.uuid = uuid;
48
+ this.context = context;
49
+ }
50
+
51
+ @Override
52
+ public void onConnectFailure(@NonNull Call call, @NonNull CallException callException) {
53
+ debug("onConnectFailure");
54
+
55
+ // stop sound and routing
56
+ getMediaPlayerManager().stop();
57
+ getAudioSwitchManager().getAudioSwitch().deactivate();
58
+
59
+ // find call record & remove
60
+ CallRecord callRecord = Objects.requireNonNull(getCallRecordDatabase().remove(new CallRecord(uuid)));
61
+
62
+ // take down notification
63
+ getVoiceServiceApi().cancelActiveCallNotification(callRecord);
64
+
65
+ // serialize and notify JS
66
+ sendJSEvent(
67
+ constructJSMap(
68
+ new Pair<>(VoiceEventType, CallEventConnectFailure),
69
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializeCall(callRecord)),
70
+ new Pair<>(VoiceErrorKeyError, serializeVoiceException(callException))));
71
+ }
72
+
73
+ @Override
74
+ public void onRinging(@NonNull Call call) {
75
+ debug("onRinging");
76
+
77
+ // find call record
78
+ CallRecord callRecord = Objects.requireNonNull(getCallRecordDatabase().get(new CallRecord(uuid)));
79
+ callRecord.setCall(call);
80
+
81
+ // create notification & sound
82
+ callRecord.setNotificationId(NotificationUtility.createNotificationIdentifier());
83
+ getAudioSwitchManager().getAudioSwitch().activate();
84
+ getMediaPlayerManager().play(MediaPlayerManager.SoundTable.RINGTONE);
85
+ getVoiceServiceApi().raiseOutgoingCallNotification(callRecord);
86
+
87
+ // notify JS layer
88
+ sendJSEvent(
89
+ constructJSMap(
90
+ new Pair<>(VoiceEventType, CallEventRinging),
91
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializeCall(callRecord))));
92
+ }
93
+
94
+ @Override
95
+ public void onConnected(@NonNull Call call) {
96
+ debug("onConnected");
97
+
98
+ // find call record
99
+ CallRecord callRecord = Objects.requireNonNull(getCallRecordDatabase().get(new CallRecord(uuid)));
100
+ callRecord.setCall(call);
101
+ callRecord.setTimestamp(new Date());
102
+ getMediaPlayerManager().stop();
103
+
104
+ // notify JS layer
105
+ sendJSEvent(
106
+ constructJSMap(
107
+ new Pair<>(VoiceEventType, CallEventConnected),
108
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializeCall(callRecord))));
109
+ }
110
+
111
+ @Override
112
+ public void onReconnecting(@NonNull Call call, @NonNull CallException callException) {
113
+ debug("onReconnecting");
114
+
115
+ // find & update call record
116
+ CallRecord callRecord = Objects.requireNonNull(getCallRecordDatabase().get(new CallRecord(uuid)));
117
+
118
+ // notify JS layer
119
+ sendJSEvent(
120
+ constructJSMap(
121
+ new Pair<>(VoiceEventType, CallEventReconnecting),
122
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializeCall(callRecord)),
123
+ new Pair<>(VoiceErrorKeyError, serializeVoiceException(callException))));
124
+ }
125
+
126
+ @Override
127
+ public void onReconnected(@NonNull Call call) {
128
+ debug("onReconnected");
129
+
130
+ // find & update call record
131
+ CallRecord callRecord = Objects.requireNonNull(getCallRecordDatabase().get(new CallRecord(uuid)));
132
+
133
+ // notify JS layer
134
+ sendJSEvent(
135
+ constructJSMap(
136
+ new Pair<>(VoiceEventType, CallEventReconnected),
137
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializeCall(callRecord))));
138
+ }
139
+
140
+ @Override
141
+ public void onDisconnected(@NonNull Call call, @Nullable CallException callException) {
142
+ debug("onDisconnected");
143
+
144
+ // find & remove call record
145
+ CallRecord callRecord = Objects.requireNonNull(getCallRecordDatabase().remove(new CallRecord(uuid)));
146
+
147
+ // stop audio & cancel notification
148
+ getMediaPlayerManager().stop();
149
+ getMediaPlayerManager().play(MediaPlayerManager.SoundTable.DISCONNECT);
150
+ getAudioSwitchManager().getAudioSwitch().deactivate();
151
+ getVoiceServiceApi().cancelActiveCallNotification(callRecord);
152
+
153
+ // notify JS layer
154
+ sendJSEvent(
155
+ constructJSMap(
156
+ new Pair<>(VoiceEventType, CallEventDisconnected),
157
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializeCall(callRecord)),
158
+ new Pair<>(VoiceErrorKeyError, serializeVoiceException(callException))));
159
+ }
160
+
161
+ @Override
162
+ public void onCallQualityWarningsChanged(@NonNull Call call,
163
+ @NonNull Set<Call.CallQualityWarning> currentWarnings,
164
+ @NonNull Set<Call.CallQualityWarning> previousWarnings) {
165
+ debug("onCallQualityWarningsChanged");
166
+
167
+ // find call record
168
+ CallRecord callRecord = Objects.requireNonNull(getCallRecordDatabase().get(new CallRecord(uuid)));
169
+
170
+ // notify JS layer
171
+ sendJSEvent(
172
+ constructJSMap(
173
+ new Pair<>(VoiceEventType, CallEventQualityWarningsChanged),
174
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializeCall(callRecord)),
175
+ new Pair<>(CallEventCurrentWarnings, serializeCallQualityWarnings(currentWarnings)),
176
+ new Pair<>(CallEventPreviousWarnings, serializeCallQualityWarnings(previousWarnings))));
177
+ }
178
+
179
+ private void sendJSEvent(@NonNull WritableMap event) {
180
+ getJSEventEmitter().sendEvent(ScopeCall, event);
181
+ }
182
+
183
+ private void debug(final String message) {
184
+ logger.debug(String.format("%s UUID:%s", message, uuid.toString()));
185
+ }
186
+ }
@@ -0,0 +1,103 @@
1
+ package com.twiliovoicereactnative;
2
+
3
+ import static com.twiliovoicereactnative.CommonConstants.CallEventMessageFailure;
4
+ import static com.twiliovoicereactnative.CommonConstants.CallEventMessageReceived;
5
+ import static com.twiliovoicereactnative.CommonConstants.CallEventMessageSent;
6
+ import static com.twiliovoicereactnative.CommonConstants.CallInviteEventKeyCallSid;
7
+ import static com.twiliovoicereactnative.CommonConstants.ScopeCall;
8
+ import static com.twiliovoicereactnative.CommonConstants.ScopeCallInvite;
9
+ import static com.twiliovoicereactnative.CommonConstants.ScopeCallMessage;
10
+ import static com.twiliovoicereactnative.CommonConstants.VoiceErrorKeyError;
11
+ import static com.twiliovoicereactnative.CommonConstants.VoiceEventSid;
12
+ import static com.twiliovoicereactnative.CommonConstants.VoiceEventType;
13
+ import static com.twiliovoicereactnative.CommonConstants.JSEventKeyCallMessageInfo;
14
+ import static com.twiliovoicereactnative.Constants.JS_EVENT_KEY_CALL_INFO;
15
+ import static com.twiliovoicereactnative.JSEventEmitter.constructJSMap;
16
+ import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeCall;
17
+ import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeCallMessage;
18
+ import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeVoiceException;
19
+ import static com.twiliovoicereactnative.VoiceApplicationProxy.getCallRecordDatabase;
20
+ import static com.twiliovoicereactnative.VoiceApplicationProxy.getJSEventEmitter;
21
+
22
+ import android.util.Pair;
23
+
24
+ import androidx.annotation.NonNull;
25
+ import androidx.annotation.Nullable;
26
+
27
+ import com.facebook.react.bridge.Arguments;
28
+ import com.facebook.react.bridge.WritableMap;
29
+ import com.twilio.voice.Call;
30
+ import com.twilio.voice.CallMessage;
31
+ import com.twilio.voice.VoiceException;
32
+
33
+ import com.twiliovoicereactnative.CallRecordDatabase.CallRecord;
34
+
35
+ import java.util.Objects;
36
+
37
+
38
+ public class CallMessageListenerProxy implements Call.CallMessageListener {
39
+ private static final SDKLog logger = new SDKLog(CallMessageListenerProxy.class);
40
+
41
+ @Override
42
+ public void onMessageFailure(String callSid, String voiceEventSID, VoiceException voiceException) {
43
+ logger.debug("onMessageFailure");
44
+
45
+ // notify JS layer
46
+ sendJSEvent(
47
+ constructJSMap(
48
+ new Pair<>(VoiceEventType, CallEventMessageFailure),
49
+ new Pair<>(VoiceEventSid, voiceEventSID),
50
+ new Pair<>(VoiceErrorKeyError, serializeVoiceException(voiceException))
51
+ )
52
+ );
53
+ }
54
+
55
+ @Override
56
+ public void onMessageSent(String callSid, String voiceEventSID) {
57
+ logger.debug("onMessageSent");
58
+
59
+ // notify JS layer
60
+ sendJSEvent(
61
+ constructJSMap(
62
+ new Pair<>(VoiceEventType, CallEventMessageSent),
63
+ new Pair<>(VoiceEventSid, voiceEventSID)
64
+ ));
65
+ }
66
+
67
+ @Override
68
+ public void onMessageReceived(String callSid, CallMessage callMessage) {
69
+ logger.debug("onMessageReceived");
70
+
71
+ //final call record
72
+ final CallRecord callRecord =
73
+ Objects.requireNonNull(getCallRecordDatabase().get(new CallRecord(callSid)));
74
+
75
+ // notify JS layer ScopeCallInvite or ScopeCall
76
+ final String event =
77
+ CallRecord.CallInviteState.ACTIVE == callRecord.getCallInviteState()
78
+ ? ScopeCallInvite
79
+ : ScopeCall;
80
+ final WritableMap serializedCallMap =
81
+ CallRecord.CallInviteState.ACTIVE == callRecord.getCallInviteState()
82
+ ? null
83
+ : serializeCall(callRecord);
84
+ final @Nullable String optionalCallSid =
85
+ CallRecord.CallInviteState.ACTIVE == callRecord.getCallInviteState()
86
+ ? callSid
87
+ : null;
88
+
89
+ getJSEventEmitter().sendEvent(
90
+ event,
91
+ constructJSMap(
92
+ new Pair<>(VoiceEventType, CallEventMessageReceived),
93
+ new Pair<>(JS_EVENT_KEY_CALL_INFO, serializedCallMap),
94
+ new Pair<>(JSEventKeyCallMessageInfo, serializeCallMessage(callMessage)),
95
+ new Pair<>(CallInviteEventKeyCallSid, optionalCallSid)
96
+ )
97
+ );
98
+ }
99
+
100
+ private void sendJSEvent(@NonNull WritableMap event) {
101
+ getJSEventEmitter().sendEvent(ScopeCallMessage, event);
102
+ }
103
+ }
@@ -0,0 +1,183 @@
1
+ package com.twiliovoicereactnative;
2
+
3
+ import static com.twiliovoicereactnative.CallRecordDatabase.CallRecord.CallInviteState.ACTIVE;
4
+ import static com.twiliovoicereactnative.CallRecordDatabase.CallRecord.CallInviteState.NONE;
5
+ import static com.twiliovoicereactnative.CallRecordDatabase.CallRecord.CallInviteState.USED;
6
+
7
+ import java.util.Collection;
8
+ import java.util.Date;
9
+ import java.util.List;
10
+ import java.util.UUID;
11
+ import java.util.Vector;
12
+ import java.util.Map;
13
+
14
+ import androidx.annotation.NonNull;
15
+
16
+ import com.facebook.react.bridge.Promise;
17
+ import com.twilio.voice.Call;
18
+ import com.twilio.voice.CallException;
19
+ import com.twilio.voice.CallInvite;
20
+ import com.twilio.voice.CancelledCallInvite;
21
+
22
+ class CallRecordDatabase {
23
+ public static class CallRecord {
24
+ public enum CallInviteState { NONE, ACTIVE, USED }
25
+ public enum Direction { INCOMING, OUTGOING }
26
+ private final UUID uuid;
27
+ private String callSid = null;
28
+ private Date timestamp = null;
29
+ private int notificationId = -1;
30
+ private Call voiceCall = null;
31
+ private String callRecipient = "";
32
+ private CallInvite callInvite = null;
33
+ private CallInviteState callInviteState = NONE;
34
+ private CancelledCallInvite cancelledCallInvite = null;
35
+ private Promise callAcceptedPromise = null;
36
+ private Promise callRejectedPromise = null;
37
+ private CallException callException = null;
38
+ private Map<String, String> customParameters = null;
39
+ private String notificationDisplayName = null;
40
+ private Direction direction = Direction.INCOMING;
41
+ public CallRecord(final UUID uuid) {
42
+ this.uuid = uuid;
43
+ }
44
+ public CallRecord(final String callSid) {
45
+ this.uuid = null;
46
+ this.callSid = callSid;
47
+ }
48
+ public CallRecord(final UUID uuid, final CallInvite callInvite) {
49
+ this.uuid = uuid;
50
+ this.callSid = callInvite.getCallSid();
51
+ this.callInvite = callInvite;
52
+ this.callInviteState = ACTIVE;
53
+ }
54
+ public CallRecord(
55
+ final UUID uuid,
56
+ final Call call,
57
+ final String recipient,
58
+ final Map<String, String> customParameters,
59
+ final Direction direction,
60
+ final String notificationDisplayName
61
+ ) {
62
+ this.uuid = uuid;
63
+ this.callSid = call.getSid();
64
+ this.voiceCall = call;
65
+ this.callRecipient = recipient;
66
+ this.customParameters = customParameters;
67
+ this.direction = direction;
68
+ this.notificationDisplayName = notificationDisplayName;
69
+ }
70
+ public final UUID getUuid() {
71
+ return uuid;
72
+ }
73
+ public String getCallSid() {
74
+ return callSid;
75
+ }
76
+ public int getNotificationId() {
77
+ return notificationId;
78
+ }
79
+ public Date getTimestamp() {
80
+ return timestamp;
81
+ }
82
+ public Call getVoiceCall() {
83
+ return this.voiceCall;
84
+ }
85
+ public final Map<String, String> getCustomParameters() {
86
+ if (this.direction == Direction.INCOMING) {
87
+ return this.callInvite.getCustomParameters();
88
+ }
89
+ return this.customParameters;
90
+ }
91
+ public final String getNotificationDisplayName() {
92
+ return this.notificationDisplayName;
93
+ }
94
+ public final Direction getDirection() {
95
+ return this.direction;
96
+ }
97
+ public CallInvite getCallInvite() {
98
+ return this.callInvite;
99
+ }
100
+ public CallInviteState getCallInviteState() {
101
+ return this.callInviteState;
102
+ }
103
+ public CancelledCallInvite getCancelledCallInvite() {
104
+ return this.cancelledCallInvite;
105
+ }
106
+ public Promise getCallAcceptedPromise() {
107
+ return this.callAcceptedPromise;
108
+ }
109
+ public Promise getCallRejectedPromise() {
110
+ return this.callRejectedPromise;
111
+ }
112
+ public CallException getCallException() {
113
+ return this.callException;
114
+ }
115
+ public String getCallRecipient() { return this.callRecipient; }
116
+ public void setNotificationId(int notificationId) {
117
+ this.notificationId = notificationId;
118
+ }
119
+ public void setTimestamp(Date timestamp) {
120
+ this.timestamp = timestamp;
121
+ }
122
+ public void setCall(@NonNull Call voiceCall) {
123
+ this.callSid = voiceCall.getSid();
124
+ this.voiceCall = voiceCall;
125
+ }
126
+ public void setCallInviteUsedState() {
127
+ this.callInviteState = (this.callInviteState == ACTIVE) ? USED : this.callInviteState;
128
+ }
129
+ public void setCancelledCallInvite(@NonNull CancelledCallInvite cancelledCallInvite) {
130
+ this.callSid = cancelledCallInvite.getCallSid();
131
+ this.cancelledCallInvite = cancelledCallInvite;
132
+ this.callInvite = null;
133
+ this.callInviteState = NONE;
134
+ }
135
+ public void setCallAcceptedPromise(@NonNull Promise callAcceptedPromise) {
136
+ this.callAcceptedPromise = callAcceptedPromise;
137
+ }
138
+ public void setCallRejectedPromise(@NonNull Promise callRejectedPromise) {
139
+ this.callRejectedPromise = callRejectedPromise;
140
+ }
141
+ public void setCallException(CallException callException) {
142
+ this.callException = callException;
143
+ }
144
+ @Override
145
+ public boolean equals(Object obj) {
146
+ return (obj instanceof CallRecord) && comparator(this, (CallRecord)obj);
147
+ }
148
+ }
149
+ private final List<CallRecord> callRecordList = new Vector<>();
150
+
151
+ public void add(final CallRecord callRecord) {
152
+ callRecordList.add(callRecord);
153
+ }
154
+ public void clear() {
155
+ callRecordList.clear();
156
+ }
157
+
158
+ public CallRecord get(final CallRecord record) {
159
+ try {
160
+ return callRecordList.get(callRecordList.indexOf(record));
161
+ } catch (IndexOutOfBoundsException e) {
162
+ return null;
163
+ }
164
+ }
165
+ public CallRecord remove(final CallRecord record) {
166
+ try {
167
+ return callRecordList.remove(callRecordList.indexOf(record));
168
+ } catch (IndexOutOfBoundsException e) {
169
+ return null;
170
+ }
171
+ }
172
+ public Collection<CallRecord> getCollection() {
173
+ return callRecordList;
174
+ }
175
+ private static boolean comparator(@NonNull final CallRecord lhs, @NonNull final CallRecord rhs) {
176
+ if (null != lhs.uuid && null != rhs.uuid) {
177
+ return lhs.uuid.equals(rhs.uuid);
178
+ } else if (null != lhs.callSid && null != rhs.callSid) {
179
+ return lhs.callSid.equals(rhs.callSid);
180
+ }
181
+ return false;
182
+ }
183
+ }