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.
- package/LICENSE +206 -0
- package/README.md +179 -0
- package/android/build.gradle +113 -0
- package/android/gradle.properties +29 -0
- package/android/src/main/AndroidManifest.xml +30 -0
- package/android/src/main/java/com/twiliovoicereactnative/AudioSwitchManager.java +141 -0
- package/android/src/main/java/com/twiliovoicereactnative/CallListenerProxy.java +186 -0
- package/android/src/main/java/com/twiliovoicereactnative/CallMessageListenerProxy.java +103 -0
- package/android/src/main/java/com/twiliovoicereactnative/CallRecordDatabase.java +183 -0
- package/android/src/main/java/com/twiliovoicereactnative/CommonConstants.java +195 -0
- package/android/src/main/java/com/twiliovoicereactnative/ConfigurationProperties.java +41 -0
- package/android/src/main/java/com/twiliovoicereactnative/Constants.java +23 -0
- package/android/src/main/java/com/twiliovoicereactnative/ExpoActivityLifecycleListener.java +27 -0
- package/android/src/main/java/com/twiliovoicereactnative/ExpoApplicationLifecycleListener.java +14 -0
- package/android/src/main/java/com/twiliovoicereactnative/ExpoModule.kt +36 -0
- package/android/src/main/java/com/twiliovoicereactnative/ExpoPackage.java +20 -0
- package/android/src/main/java/com/twiliovoicereactnative/JSEventEmitter.java +98 -0
- package/android/src/main/java/com/twiliovoicereactnative/MediaPlayerManager.java +58 -0
- package/android/src/main/java/com/twiliovoicereactnative/NotificationUtility.java +363 -0
- package/android/src/main/java/com/twiliovoicereactnative/ReactNativeArgumentsSerializer.java +276 -0
- package/android/src/main/java/com/twiliovoicereactnative/SDKLog.java +74 -0
- package/android/src/main/java/com/twiliovoicereactnative/StatsListenerProxy.java +178 -0
- package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativeModule.java +778 -0
- package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativePackage.java +28 -0
- package/android/src/main/java/com/twiliovoicereactnative/VoiceActivityProxy.java +101 -0
- package/android/src/main/java/com/twiliovoicereactnative/VoiceApplicationProxy.java +133 -0
- package/android/src/main/java/com/twiliovoicereactnative/VoiceFirebaseMessagingService.java +88 -0
- package/android/src/main/java/com/twiliovoicereactnative/VoiceService.java +403 -0
- package/android/src/main/res/drawable/answered_call_small_icon.png +0 -0
- package/android/src/main/res/drawable/ic_launcher_round.png +0 -0
- package/android/src/main/res/drawable/ic_launcher_sdk.png +0 -0
- package/android/src/main/res/drawable/incoming_call_small_icon.png +0 -0
- package/android/src/main/res/drawable/outgoing_call_small_icon.png +0 -0
- package/android/src/main/res/raw/disconnect.wav +0 -0
- package/android/src/main/res/raw/incoming.wav +0 -0
- package/android/src/main/res/raw/outgoing.wav +0 -0
- package/android/src/main/res/raw/ringtone.wav +0 -0
- package/android/src/main/res/raw/silent.wav +0 -0
- package/android/src/main/res/values/colors.xml +11 -0
- package/android/src/main/res/values/config.xml +5 -0
- package/android/src/main/res/values/dimens.xml +7 -0
- package/android/src/main/res/values/strings.xml +25 -0
- package/android/src/main/res/values/styles.xml +10 -0
- package/android/src/main/res/values-night/colors.xml +11 -0
- package/expo-config-plugin/android.js +191 -0
- package/expo-config-plugin/ios.js +22 -0
- package/expo-module.config.json +6 -0
- package/ios/TwilioVoicePushRegistry.h +19 -0
- package/ios/TwilioVoicePushRegistry.m +72 -0
- package/ios/TwilioVoiceReactNative+CallInvite.m +56 -0
- package/ios/TwilioVoiceReactNative+CallKit.m +533 -0
- package/ios/TwilioVoiceReactNative+CallMessage.m +81 -0
- package/ios/TwilioVoiceReactNative.h +74 -0
- package/ios/TwilioVoiceReactNative.m +1046 -0
- package/ios/TwilioVoiceReactNative.xcodeproj/project.pbxproj +328 -0
- package/ios/TwilioVoiceReactNativeConstants.h +200 -0
- package/ios/Utilities/TwilioVoiceStatsReport.h +175 -0
- package/lib/commonjs/AudioDevice.js +101 -0
- package/lib/commonjs/AudioDevice.js.map +1 -0
- package/lib/commonjs/Call.js +765 -0
- package/lib/commonjs/Call.js.map +1 -0
- package/lib/commonjs/CallInvite.js +452 -0
- package/lib/commonjs/CallInvite.js.map +1 -0
- package/lib/commonjs/CallMessage/CallMessage.js +54 -0
- package/lib/commonjs/CallMessage/CallMessage.js.map +1 -0
- package/lib/commonjs/CallMessage/IncomingCallMessage.js +120 -0
- package/lib/commonjs/CallMessage/IncomingCallMessage.js.map +1 -0
- package/lib/commonjs/CallMessage/OutgoingCallMessage.js +148 -0
- package/lib/commonjs/CallMessage/OutgoingCallMessage.js.map +1 -0
- package/lib/commonjs/ExpoModule.js +69 -0
- package/lib/commonjs/ExpoModule.js.map +1 -0
- package/lib/commonjs/Voice.js +611 -0
- package/lib/commonjs/Voice.js.map +1 -0
- package/lib/commonjs/common.js +26 -0
- package/lib/commonjs/common.js.map +1 -0
- package/lib/commonjs/constants.js +158 -0
- package/lib/commonjs/constants.js.map +1 -0
- package/lib/commonjs/error/InvalidArgumentError.js +32 -0
- package/lib/commonjs/error/InvalidArgumentError.js.map +1 -0
- package/lib/commonjs/error/InvalidStateError.js +33 -0
- package/lib/commonjs/error/InvalidStateError.js.map +1 -0
- package/lib/commonjs/error/TwilioError.js +38 -0
- package/lib/commonjs/error/TwilioError.js.map +1 -0
- package/lib/commonjs/error/UnsupportedPlatformError.js +33 -0
- package/lib/commonjs/error/UnsupportedPlatformError.js.map +1 -0
- package/lib/commonjs/error/generated.js +2343 -0
- package/lib/commonjs/error/generated.js.map +1 -0
- package/lib/commonjs/error/index.js +112 -0
- package/lib/commonjs/error/index.js.map +1 -0
- package/lib/commonjs/error/utility.js +37 -0
- package/lib/commonjs/error/utility.js.map +1 -0
- package/lib/commonjs/index.js +95 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/type/AudioDevice.js +6 -0
- package/lib/commonjs/type/AudioDevice.js.map +1 -0
- package/lib/commonjs/type/Call.js +6 -0
- package/lib/commonjs/type/Call.js.map +1 -0
- package/lib/commonjs/type/CallInvite.js +6 -0
- package/lib/commonjs/type/CallInvite.js.map +1 -0
- package/lib/commonjs/type/CallKit.js +30 -0
- package/lib/commonjs/type/CallKit.js.map +1 -0
- package/lib/commonjs/type/CallMessage.js +6 -0
- package/lib/commonjs/type/CallMessage.js.map +1 -0
- package/lib/commonjs/type/Error.js +6 -0
- package/lib/commonjs/type/Error.js.map +1 -0
- package/lib/commonjs/type/NativeModule.js +6 -0
- package/lib/commonjs/type/NativeModule.js.map +1 -0
- package/lib/commonjs/type/RTCStats.js +29 -0
- package/lib/commonjs/type/RTCStats.js.map +1 -0
- package/lib/commonjs/type/Voice.js +6 -0
- package/lib/commonjs/type/Voice.js.map +1 -0
- package/lib/commonjs/type/common.js +2 -0
- package/lib/commonjs/type/common.js.map +1 -0
- package/lib/module/AudioDevice.js +97 -0
- package/lib/module/AudioDevice.js.map +1 -0
- package/lib/module/Call.js +766 -0
- package/lib/module/Call.js.map +1 -0
- package/lib/module/CallInvite.js +450 -0
- package/lib/module/CallInvite.js.map +1 -0
- package/lib/module/CallMessage/CallMessage.js +51 -0
- package/lib/module/CallMessage/CallMessage.js.map +1 -0
- package/lib/module/CallMessage/IncomingCallMessage.js +116 -0
- package/lib/module/CallMessage/IncomingCallMessage.js.map +1 -0
- package/lib/module/CallMessage/OutgoingCallMessage.js +154 -0
- package/lib/module/CallMessage/OutgoingCallMessage.js.map +1 -0
- package/lib/module/ExpoModule.js +58 -0
- package/lib/module/ExpoModule.js.map +1 -0
- package/lib/module/Voice.js +598 -0
- package/lib/module/Voice.js.map +1 -0
- package/lib/module/common.js +11 -0
- package/lib/module/common.js.map +1 -0
- package/lib/module/constants.js +151 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/error/InvalidArgumentError.js +23 -0
- package/lib/module/error/InvalidArgumentError.js.map +1 -0
- package/lib/module/error/InvalidStateError.js +24 -0
- package/lib/module/error/InvalidStateError.js.map +1 -0
- package/lib/module/error/TwilioError.js +29 -0
- package/lib/module/error/TwilioError.js.map +1 -0
- package/lib/module/error/UnsupportedPlatformError.js +24 -0
- package/lib/module/error/UnsupportedPlatformError.js.map +1 -0
- package/lib/module/error/generated.js +2315 -0
- package/lib/module/error/generated.js.map +1 -0
- package/lib/module/error/index.js +6 -0
- package/lib/module/error/index.js.map +1 -0
- package/lib/module/error/utility.js +27 -0
- package/lib/module/error/utility.js.map +1 -0
- package/lib/module/index.js +23 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/type/AudioDevice.js +2 -0
- package/lib/module/type/AudioDevice.js.map +1 -0
- package/lib/module/type/Call.js +2 -0
- package/lib/module/type/Call.js.map +1 -0
- package/lib/module/type/CallInvite.js +2 -0
- package/lib/module/type/CallInvite.js.map +1 -0
- package/lib/module/type/CallKit.js +22 -0
- package/lib/module/type/CallKit.js.map +1 -0
- package/lib/module/type/CallMessage.js +2 -0
- package/lib/module/type/CallMessage.js.map +1 -0
- package/lib/module/type/Error.js +2 -0
- package/lib/module/type/Error.js.map +1 -0
- package/lib/module/type/NativeModule.js +2 -0
- package/lib/module/type/NativeModule.js.map +1 -0
- package/lib/module/type/RTCStats.js +21 -0
- package/lib/module/type/RTCStats.js.map +1 -0
- package/lib/module/type/Voice.js +2 -0
- package/lib/module/type/Voice.js.map +1 -0
- package/lib/module/type/common.js +2 -0
- package/lib/module/type/common.js.map +1 -0
- package/lib/typescript/AudioDevice.d.ts +74 -0
- package/lib/typescript/Call.d.ts +874 -0
- package/lib/typescript/CallInvite.d.ts +484 -0
- package/lib/typescript/CallMessage/CallMessage.d.ts +53 -0
- package/lib/typescript/CallMessage/IncomingCallMessage.d.ts +75 -0
- package/lib/typescript/CallMessage/OutgoingCallMessage.d.ts +198 -0
- package/lib/typescript/ExpoModule.d.ts +13 -0
- package/lib/typescript/Voice.d.ts +620 -0
- package/lib/typescript/common.d.ts +11 -0
- package/lib/typescript/constants.d.ts +148 -0
- package/lib/typescript/error/InvalidArgumentError.d.ts +11 -0
- package/lib/typescript/error/InvalidStateError.d.ts +12 -0
- package/lib/typescript/error/TwilioError.d.ts +14 -0
- package/lib/typescript/error/UnsupportedPlatformError.d.ts +12 -0
- package/lib/typescript/error/generated.d.ts +1558 -0
- package/lib/typescript/error/index.d.ts +5 -0
- package/lib/typescript/error/utility.d.ts +12 -0
- package/lib/typescript/index.d.ts +18 -0
- package/lib/typescript/type/AudioDevice.d.ts +15 -0
- package/lib/typescript/type/Call.d.ts +59 -0
- package/lib/typescript/type/CallInvite.d.ts +40 -0
- package/lib/typescript/type/CallKit.d.ts +60 -0
- package/lib/typescript/type/CallMessage.d.ts +20 -0
- package/lib/typescript/type/Error.d.ts +9 -0
- package/lib/typescript/type/NativeModule.d.ts +59 -0
- package/lib/typescript/type/RTCStats.d.ts +91 -0
- package/lib/typescript/type/Voice.d.ts +16 -0
- package/lib/typescript/type/common.d.ts +15 -0
- package/package.json +167 -0
- package/src/AudioDevice.tsx +88 -0
- package/src/Call.tsx +1343 -0
- package/src/CallInvite.tsx +757 -0
- package/src/CallMessage/CallMessage.ts +83 -0
- package/src/CallMessage/IncomingCallMessage.ts +104 -0
- package/src/CallMessage/OutgoingCallMessage.ts +308 -0
- package/src/ExpoModule.ts +59 -0
- package/src/Voice.tsx +1010 -0
- package/src/common.ts +16 -0
- package/src/constants.ts +193 -0
- package/src/error/InvalidArgumentError.ts +19 -0
- package/src/error/InvalidStateError.ts +19 -0
- package/src/error/TwilioError.ts +22 -0
- package/src/error/UnsupportedPlatformError.ts +19 -0
- package/src/error/generated.ts +2277 -0
- package/src/error/index.ts +18 -0
- package/src/error/utility.ts +36 -0
- package/src/index.tsx +24 -0
- package/src/type/AudioDevice.ts +18 -0
- package/src/type/Call.ts +102 -0
- package/src/type/CallInvite.ts +59 -0
- package/src/type/CallKit.ts +61 -0
- package/src/type/CallMessage.ts +31 -0
- package/src/type/Error.ts +11 -0
- package/src/type/NativeModule.ts +93 -0
- package/src/type/RTCStats.ts +99 -0
- package/src/type/Voice.ts +31 -0
- package/src/type/common.ts +16 -0
- 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
|
+
}
|