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,363 @@
|
|
|
1
|
+
package com.twiliovoicereactnative;
|
|
2
|
+
|
|
3
|
+
import java.security.SecureRandom;
|
|
4
|
+
|
|
5
|
+
import java.util.Map;
|
|
6
|
+
import java.util.Objects;
|
|
7
|
+
|
|
8
|
+
import android.annotation.SuppressLint;
|
|
9
|
+
import android.app.Notification;
|
|
10
|
+
import android.app.PendingIntent;
|
|
11
|
+
import android.content.ContentResolver;
|
|
12
|
+
import android.content.Context;
|
|
13
|
+
import android.content.Intent;
|
|
14
|
+
import android.graphics.Color;
|
|
15
|
+
import android.media.AudioAttributes;
|
|
16
|
+
import android.net.Uri;
|
|
17
|
+
|
|
18
|
+
import androidx.annotation.NonNull;
|
|
19
|
+
import androidx.core.app.NotificationChannelCompat;
|
|
20
|
+
import androidx.core.app.NotificationChannelGroupCompat;
|
|
21
|
+
import androidx.core.app.NotificationCompat;
|
|
22
|
+
import androidx.core.app.NotificationManagerCompat;
|
|
23
|
+
import androidx.core.app.Person;
|
|
24
|
+
|
|
25
|
+
import com.twilio.voice.CallInvite;
|
|
26
|
+
|
|
27
|
+
import static com.twiliovoicereactnative.ConfigurationProperties.isFullScreenNotificationEnabled;
|
|
28
|
+
import static com.twiliovoicereactnative.Constants.VOICE_CHANNEL_DEFAULT_IMPORTANCE;
|
|
29
|
+
import static com.twiliovoicereactnative.Constants.VOICE_CHANNEL_HIGH_IMPORTANCE;
|
|
30
|
+
import static com.twiliovoicereactnative.Constants.VOICE_CHANNEL_LOW_IMPORTANCE;
|
|
31
|
+
import static com.twiliovoicereactnative.VoiceService.constructMessage;
|
|
32
|
+
|
|
33
|
+
import com.twiliovoicereactnative.CallRecordDatabase.CallRecord;
|
|
34
|
+
|
|
35
|
+
class NotificationUtility {
|
|
36
|
+
private static final SecureRandom secureRandom = new SecureRandom();
|
|
37
|
+
|
|
38
|
+
private static class NotificationResource {
|
|
39
|
+
enum Type { INCOMING, OUTGOING, ANSWERED }
|
|
40
|
+
|
|
41
|
+
private final Type type;
|
|
42
|
+
private final Context ctx;
|
|
43
|
+
private final CallRecord callRecord;
|
|
44
|
+
|
|
45
|
+
public NotificationResource(Context context, Type type, CallRecord callRecord) {
|
|
46
|
+
this.ctx = context;
|
|
47
|
+
this.type = type;
|
|
48
|
+
this.callRecord = callRecord;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private int getSmallIconId() {
|
|
52
|
+
switch (this.type) {
|
|
53
|
+
case INCOMING:
|
|
54
|
+
return this.getDrawableResourceId("incoming_call_small_icon");
|
|
55
|
+
case OUTGOING:
|
|
56
|
+
return this.getDrawableResourceId("outgoing_call_small_icon");
|
|
57
|
+
default:
|
|
58
|
+
return this.getDrawableResourceId("answered_call_small_icon");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private String getContentText() {
|
|
63
|
+
switch (this.type) {
|
|
64
|
+
case INCOMING:
|
|
65
|
+
return this.ctx.getString(this.getTextResourceId("incoming_call_caller_name_text"));
|
|
66
|
+
case OUTGOING:
|
|
67
|
+
return this.ctx.getString(this.getTextResourceId("outgoing_call_caller_name_text"));
|
|
68
|
+
default:
|
|
69
|
+
return this.ctx.getString(this.getTextResourceId("answered_call_caller_name_text"));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public String getName() {
|
|
74
|
+
if (this.callRecord.getDirection() == CallRecord.Direction.INCOMING) {
|
|
75
|
+
final String template = ConfigurationProperties.getIncomingCallContactHandleTemplate(ctx);
|
|
76
|
+
if (template != null) {
|
|
77
|
+
final String processedTemplate =
|
|
78
|
+
templateDisplayName(template, this.callRecord.getCustomParameters());
|
|
79
|
+
if (!processedTemplate.isEmpty()) {
|
|
80
|
+
return processedTemplate;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
final CallInvite callInvite = this.callRecord.getCallInvite();
|
|
85
|
+
final String from = null != callInvite ? getDisplayName(callInvite) : "";
|
|
86
|
+
return this.getContentText().replaceAll("\\$\\{from\\}", from);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// this.callRecord.Direction == CallRecord.Direction.OUTGOING
|
|
90
|
+
final String notificationDisplayName = this.callRecord.getNotificationDisplayName();
|
|
91
|
+
if (notificationDisplayName != null && !notificationDisplayName.isEmpty()) {
|
|
92
|
+
return notificationDisplayName;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
final String to = this.callRecord.getCallRecipient();
|
|
96
|
+
return this.getContentText().replaceAll("\\$\\{to\\}", to);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@SuppressLint("DiscouragedApi")
|
|
100
|
+
private int getDrawableResourceId(String id) {
|
|
101
|
+
return ctx.getResources().getIdentifier(id, "drawable", ctx.getPackageName());
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@SuppressLint("DiscouragedApi")
|
|
105
|
+
private int getTextResourceId(String id) {
|
|
106
|
+
return ctx.getResources().getIdentifier(id, "string", ctx.getPackageName());
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private static String getDisplayName(@NonNull CallInvite callInvite) {
|
|
110
|
+
final String title = callInvite.getFrom();
|
|
111
|
+
if (title.startsWith("client:")) {
|
|
112
|
+
return title.replaceFirst("client:", "");
|
|
113
|
+
}
|
|
114
|
+
return title;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private static String templateDisplayName(final String template, final Map<String, String> twimlParams) {
|
|
118
|
+
String processedTemplate = template;
|
|
119
|
+
|
|
120
|
+
for (Map.Entry<String, String> e : twimlParams.entrySet()) {
|
|
121
|
+
String paramKey = e.getKey();
|
|
122
|
+
String paramValue = e.getValue();
|
|
123
|
+
processedTemplate = processedTemplate.replaceAll(
|
|
124
|
+
String.format("\\$\\{%s\\}", paramKey),
|
|
125
|
+
paramValue);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return processedTemplate;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public static int createNotificationIdentifier() {
|
|
133
|
+
return (secureRandom.nextInt() & 0x7FFFFFFF) + 1; // prevent 0 as an id
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public static Notification createIncomingCallNotification(@NonNull Context context,
|
|
137
|
+
@NonNull final CallRecord callRecord,
|
|
138
|
+
@NonNull final String channelImportance) {
|
|
139
|
+
final NotificationResource notificationResource = new NotificationResource(
|
|
140
|
+
context,
|
|
141
|
+
NotificationResource.Type.INCOMING,
|
|
142
|
+
callRecord);
|
|
143
|
+
|
|
144
|
+
final Person incomingCaller = new Person.Builder()
|
|
145
|
+
.setName(notificationResource.getName())
|
|
146
|
+
.build();
|
|
147
|
+
|
|
148
|
+
Intent foregroundIntent = constructMessage(
|
|
149
|
+
context,
|
|
150
|
+
Constants.ACTION_FOREGROUND_AND_DEPRIORITIZE_INCOMING_CALL_NOTIFICATION,
|
|
151
|
+
Objects.requireNonNull(VoiceApplicationProxy.getMainActivityClass()),
|
|
152
|
+
callRecord.getUuid());
|
|
153
|
+
PendingIntent piForegroundIntent = constructPendingIntentForActivity(context, foregroundIntent);
|
|
154
|
+
|
|
155
|
+
Intent rejectIntent = constructMessage(
|
|
156
|
+
context,
|
|
157
|
+
Constants.ACTION_REJECT_CALL,
|
|
158
|
+
VoiceService.class,
|
|
159
|
+
callRecord.getUuid());
|
|
160
|
+
PendingIntent piRejectIntent = constructPendingIntentForService(context, rejectIntent);
|
|
161
|
+
|
|
162
|
+
Intent acceptIntent = constructMessage(
|
|
163
|
+
context,
|
|
164
|
+
Constants.ACTION_ACCEPT_CALL,
|
|
165
|
+
Objects.requireNonNull(VoiceApplicationProxy.getMainActivityClass()),
|
|
166
|
+
callRecord.getUuid());
|
|
167
|
+
PendingIntent piAcceptIntent = constructPendingIntentForActivity(context, acceptIntent);
|
|
168
|
+
|
|
169
|
+
NotificationCompat.Builder builder = constructNotificationBuilder(context, channelImportance)
|
|
170
|
+
.setSmallIcon(notificationResource.getSmallIconId())
|
|
171
|
+
.setCategory(Notification.CATEGORY_CALL)
|
|
172
|
+
.setAutoCancel(true)
|
|
173
|
+
.setContentIntent(piForegroundIntent)
|
|
174
|
+
.addPerson(incomingCaller)
|
|
175
|
+
.setStyle(NotificationCompat.CallStyle.forIncomingCall(
|
|
176
|
+
incomingCaller, piRejectIntent, piAcceptIntent));
|
|
177
|
+
if (isFullscreenIntentEnabled(context)) {
|
|
178
|
+
builder.setFullScreenIntent(piForegroundIntent, true);
|
|
179
|
+
}
|
|
180
|
+
return builder.build();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
public static Notification createCallAnsweredNotificationWithLowImportance(@NonNull Context context,
|
|
184
|
+
@NonNull final CallRecord callRecord) {
|
|
185
|
+
final NotificationResource notificationResource = new NotificationResource(
|
|
186
|
+
context,
|
|
187
|
+
NotificationResource.Type.ANSWERED,
|
|
188
|
+
callRecord);
|
|
189
|
+
|
|
190
|
+
final Person activeCaller = new Person.Builder()
|
|
191
|
+
.setName(notificationResource.getName())
|
|
192
|
+
.build();
|
|
193
|
+
|
|
194
|
+
Intent foregroundIntent = constructMessage(
|
|
195
|
+
context,
|
|
196
|
+
Constants.ACTION_PUSH_APP_TO_FOREGROUND,
|
|
197
|
+
Objects.requireNonNull(VoiceApplicationProxy.getMainActivityClass()),
|
|
198
|
+
callRecord.getUuid());
|
|
199
|
+
PendingIntent piForegroundIntent = constructPendingIntentForActivity(context, foregroundIntent);
|
|
200
|
+
|
|
201
|
+
Intent endCallIntent = constructMessage(
|
|
202
|
+
context,
|
|
203
|
+
Constants.ACTION_CALL_DISCONNECT,
|
|
204
|
+
VoiceService.class,
|
|
205
|
+
callRecord.getUuid());
|
|
206
|
+
PendingIntent piEndCallIntent = constructPendingIntentForService(context, endCallIntent);
|
|
207
|
+
|
|
208
|
+
NotificationCompat.Builder builder = constructNotificationBuilder(context, Constants.VOICE_CHANNEL_LOW_IMPORTANCE)
|
|
209
|
+
.setSmallIcon(notificationResource.getSmallIconId())
|
|
210
|
+
.setCategory(Notification.CATEGORY_CALL)
|
|
211
|
+
.setAutoCancel(false)
|
|
212
|
+
.setContentIntent(piForegroundIntent)
|
|
213
|
+
.setOngoing(true)
|
|
214
|
+
.addPerson(activeCaller)
|
|
215
|
+
.setStyle(NotificationCompat.CallStyle.forOngoingCall(activeCaller, piEndCallIntent));
|
|
216
|
+
if (isFullscreenIntentEnabled(context)) {
|
|
217
|
+
builder.setFullScreenIntent(piForegroundIntent, true);
|
|
218
|
+
}
|
|
219
|
+
return builder.build();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
public static Notification createOutgoingCallNotificationWithLowImportance(@NonNull Context context,
|
|
223
|
+
@NonNull final CallRecord callRecord) {
|
|
224
|
+
final NotificationResource notificationResource = new NotificationResource(
|
|
225
|
+
context,
|
|
226
|
+
NotificationResource.Type.OUTGOING,
|
|
227
|
+
callRecord);
|
|
228
|
+
|
|
229
|
+
final Person activeCaller = new Person.Builder()
|
|
230
|
+
.setName(notificationResource.getName())
|
|
231
|
+
.build();
|
|
232
|
+
|
|
233
|
+
Intent foregroundIntent = constructMessage(
|
|
234
|
+
context,
|
|
235
|
+
Constants.ACTION_PUSH_APP_TO_FOREGROUND,
|
|
236
|
+
Objects.requireNonNull(VoiceApplicationProxy.getMainActivityClass()),
|
|
237
|
+
callRecord.getUuid());
|
|
238
|
+
PendingIntent piForegroundIntent = constructPendingIntentForActivity(context, foregroundIntent);
|
|
239
|
+
|
|
240
|
+
Intent endCallIntent = constructMessage(
|
|
241
|
+
context,
|
|
242
|
+
Constants.ACTION_CALL_DISCONNECT,
|
|
243
|
+
VoiceService.class,
|
|
244
|
+
callRecord.getUuid());
|
|
245
|
+
PendingIntent piEndCallIntent = constructPendingIntentForService(context, endCallIntent);
|
|
246
|
+
|
|
247
|
+
NotificationCompat.Builder builder = constructNotificationBuilder(context, Constants.VOICE_CHANNEL_LOW_IMPORTANCE)
|
|
248
|
+
.setSmallIcon(notificationResource.getSmallIconId())
|
|
249
|
+
.setCategory(Notification.CATEGORY_CALL)
|
|
250
|
+
.setAutoCancel(false)
|
|
251
|
+
.setContentIntent(piForegroundIntent)
|
|
252
|
+
.setOngoing(true)
|
|
253
|
+
.addPerson(activeCaller)
|
|
254
|
+
.setStyle(NotificationCompat.CallStyle.forOngoingCall(activeCaller, piEndCallIntent));
|
|
255
|
+
if (isFullscreenIntentEnabled(context)) {
|
|
256
|
+
builder.setFullScreenIntent(piForegroundIntent, true);
|
|
257
|
+
}
|
|
258
|
+
return builder.build();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
public static void createNotificationChannels(@NonNull Context context) {
|
|
262
|
+
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
|
263
|
+
notificationManager.createNotificationChannelGroup(
|
|
264
|
+
new NotificationChannelGroupCompat.Builder(Constants.VOICE_CHANNEL_GROUP)
|
|
265
|
+
.setName("Twilio Voice").build());
|
|
266
|
+
|
|
267
|
+
for (String channelId:
|
|
268
|
+
new String[]{
|
|
269
|
+
VOICE_CHANNEL_HIGH_IMPORTANCE,
|
|
270
|
+
VOICE_CHANNEL_DEFAULT_IMPORTANCE,
|
|
271
|
+
VOICE_CHANNEL_LOW_IMPORTANCE}) {
|
|
272
|
+
notificationManager.createNotificationChannel(
|
|
273
|
+
createNotificationChannel(context, channelId));
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public static void destroyNotificationChannels(@NonNull Context context) {
|
|
278
|
+
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
|
279
|
+
notificationManager.deleteNotificationChannelGroup(Constants.VOICE_CHANNEL_GROUP);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
public static boolean isFullscreenIntentEnabled(Context context) {
|
|
283
|
+
return isFullScreenNotificationEnabled(context) &&
|
|
284
|
+
NotificationManagerCompat.from(context).canUseFullScreenIntent();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
private static NotificationChannelCompat createNotificationChannel(@NonNull Context context,
|
|
288
|
+
@NonNull final String voiceChannelId) {
|
|
289
|
+
final int notificationImportance = getChannelImportance(voiceChannelId);
|
|
290
|
+
NotificationChannelCompat.Builder voiceChannelBuilder =
|
|
291
|
+
new NotificationChannelCompat.Builder(voiceChannelId, notificationImportance)
|
|
292
|
+
.setName("Primary Voice Channel")
|
|
293
|
+
.setLightColor(Color.GREEN)
|
|
294
|
+
.setGroup(Constants.VOICE_CHANNEL_GROUP);
|
|
295
|
+
// low-importance notifications don't have sound
|
|
296
|
+
if (!Constants.VOICE_CHANNEL_LOW_IMPORTANCE.equals(voiceChannelId)) {
|
|
297
|
+
// set audio attributes for channel
|
|
298
|
+
Uri soundUri = provideResourceSilent_wav(context);
|
|
299
|
+
AudioAttributes audioAttributes = new AudioAttributes.Builder()
|
|
300
|
+
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
|
301
|
+
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
|
|
302
|
+
.build();
|
|
303
|
+
voiceChannelBuilder.setSound(soundUri, audioAttributes);
|
|
304
|
+
}
|
|
305
|
+
return voiceChannelBuilder.build();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
private static int getChannelImportance(@NonNull final String voiceChannel) {
|
|
309
|
+
final Map<String, Integer> importanceMapping = Map.of(
|
|
310
|
+
Constants.VOICE_CHANNEL_HIGH_IMPORTANCE, NotificationManagerCompat.IMPORTANCE_HIGH,
|
|
311
|
+
Constants.VOICE_CHANNEL_DEFAULT_IMPORTANCE, NotificationManagerCompat.IMPORTANCE_DEFAULT,
|
|
312
|
+
Constants.VOICE_CHANNEL_LOW_IMPORTANCE, NotificationManagerCompat.IMPORTANCE_LOW);
|
|
313
|
+
return Objects.requireNonNull(importanceMapping.get(voiceChannel));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
private static String getChannel(@NonNull Context context, @NonNull final String voiceChannelId) {
|
|
317
|
+
// construct channel if it has not been created
|
|
318
|
+
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
|
|
319
|
+
|
|
320
|
+
if (null == notificationManager.getNotificationChannel(voiceChannelId)) {
|
|
321
|
+
createNotificationChannels(context);
|
|
322
|
+
}
|
|
323
|
+
return voiceChannelId;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private static PendingIntent constructPendingIntentForActivity(@NonNull Context context,
|
|
327
|
+
@NonNull final Intent intent) {
|
|
328
|
+
return PendingIntent.getActivity(
|
|
329
|
+
context.getApplicationContext(),
|
|
330
|
+
0,
|
|
331
|
+
intent,
|
|
332
|
+
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
private static PendingIntent constructPendingIntentForService(@NonNull Context context,
|
|
336
|
+
@NonNull final Intent intent) {
|
|
337
|
+
return PendingIntent.getService(
|
|
338
|
+
context.getApplicationContext(),
|
|
339
|
+
0,
|
|
340
|
+
intent,
|
|
341
|
+
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private static NotificationCompat.Builder constructNotificationBuilder(
|
|
345
|
+
@NonNull Context context,
|
|
346
|
+
@NonNull final String channelImportance) {
|
|
347
|
+
return new NotificationCompat.Builder(context,
|
|
348
|
+
getChannel(context.getApplicationContext(),
|
|
349
|
+
channelImportance));
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
static Uri provideResourceSilent_wav(@NonNull Context context) {
|
|
353
|
+
return provideResource(context, R.raw.silent);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private static Uri provideResource(@NonNull Context context, int id) {
|
|
357
|
+
return (new Uri.Builder()
|
|
358
|
+
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
|
|
359
|
+
.authority(context.getResources().getResourcePackageName(id))
|
|
360
|
+
.appendPath(String.valueOf(id))
|
|
361
|
+
).build();
|
|
362
|
+
}
|
|
363
|
+
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
package com.twiliovoicereactnative;
|
|
2
|
+
|
|
3
|
+
import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeyAudioDevices;
|
|
4
|
+
import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeyName;
|
|
5
|
+
import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeySelectedDevice;
|
|
6
|
+
import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeyType;
|
|
7
|
+
import static com.twiliovoicereactnative.CommonConstants.AudioDeviceKeyUuid;
|
|
8
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoFrom;
|
|
9
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoInitialConnectedTimestamp;
|
|
10
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoSid;
|
|
11
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoTo;
|
|
12
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoUuid;
|
|
13
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoState;
|
|
14
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoIsMuted;
|
|
15
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInfoIsOnHold;
|
|
16
|
+
import static com.twiliovoicereactnative.CommonConstants.CallMessageContent;
|
|
17
|
+
import static com.twiliovoicereactnative.CommonConstants.CallMessageContentType;
|
|
18
|
+
import static com.twiliovoicereactnative.CommonConstants.CallMessageMessageType;
|
|
19
|
+
import static com.twiliovoicereactnative.CommonConstants.ScopeVoice;
|
|
20
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceEventError;
|
|
21
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceEventSid;
|
|
22
|
+
import static com.twiliovoicereactnative.CommonConstants.CallStateConnected;
|
|
23
|
+
import static com.twiliovoicereactnative.CommonConstants.CallStateConnecting;
|
|
24
|
+
import static com.twiliovoicereactnative.CommonConstants.CallStateDisconnected;
|
|
25
|
+
import static com.twiliovoicereactnative.CommonConstants.CallStateReconnecting;
|
|
26
|
+
import static com.twiliovoicereactnative.CommonConstants.CallStateRinging;
|
|
27
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteInfoCallSid;
|
|
28
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteInfoCustomParameters;
|
|
29
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteInfoFrom;
|
|
30
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteInfoTo;
|
|
31
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteInfoUuid;
|
|
32
|
+
import static com.twiliovoicereactnative.CommonConstants.CancelledCallInviteInfoCallSid;
|
|
33
|
+
import static com.twiliovoicereactnative.CommonConstants.CancelledCallInviteInfoFrom;
|
|
34
|
+
import static com.twiliovoicereactnative.CommonConstants.CancelledCallInviteInfoTo;
|
|
35
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceErrorKeyCode;
|
|
36
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceErrorKeyMessage;
|
|
37
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceEventType;
|
|
38
|
+
import static com.twiliovoicereactnative.JSEventEmitter.constructJSMap;
|
|
39
|
+
|
|
40
|
+
import java.text.SimpleDateFormat;
|
|
41
|
+
import android.util.Pair;
|
|
42
|
+
|
|
43
|
+
import androidx.annotation.NonNull;
|
|
44
|
+
import androidx.annotation.Nullable;
|
|
45
|
+
|
|
46
|
+
import com.twilio.voice.CallMessage;
|
|
47
|
+
import com.twilio.voice.CancelledCallInvite;
|
|
48
|
+
import com.twilio.voice.VoiceException;
|
|
49
|
+
import com.twiliovoicereactnative.CallRecordDatabase.CallRecord;
|
|
50
|
+
|
|
51
|
+
import com.facebook.react.bridge.Arguments;
|
|
52
|
+
import com.facebook.react.bridge.WritableArray;
|
|
53
|
+
import com.facebook.react.bridge.WritableMap;
|
|
54
|
+
import com.twilio.audioswitch.AudioDevice;
|
|
55
|
+
import com.twilio.voice.Call;
|
|
56
|
+
import com.twilio.voice.CallInvite;
|
|
57
|
+
|
|
58
|
+
import java.util.Date;
|
|
59
|
+
import java.util.Locale;
|
|
60
|
+
import java.util.Map;
|
|
61
|
+
import java.util.Map.Entry;
|
|
62
|
+
import java.util.Objects;
|
|
63
|
+
import java.util.Set;
|
|
64
|
+
import java.util.UUID;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* This class provides static helper functions that serializes native objects into
|
|
68
|
+
* React Native (RN) bridge objects emit-able to the JS layer.
|
|
69
|
+
*/
|
|
70
|
+
class ReactNativeArgumentsSerializer {
|
|
71
|
+
private static final SDKLog logger = new SDKLog(ReactNativeArgumentsSerializer.class);
|
|
72
|
+
/**
|
|
73
|
+
* Serializes the custom parameters of a CallInvite.
|
|
74
|
+
* @param callInvite A CallInvite object
|
|
75
|
+
* @return Serialized CallInvite custom parameters
|
|
76
|
+
*/
|
|
77
|
+
public static WritableMap serializeCallInviteCustomParameters(CallInvite callInvite) {
|
|
78
|
+
if (null != callInvite) {
|
|
79
|
+
WritableMap customParameters = Arguments.createMap();
|
|
80
|
+
for (Entry<String, String> entry : callInvite.getCustomParameters().entrySet()) {
|
|
81
|
+
String customParameterKey = entry.getKey();
|
|
82
|
+
String customParameterValue = entry.getValue();
|
|
83
|
+
|
|
84
|
+
customParameters.putString(customParameterKey, customParameterValue);
|
|
85
|
+
}
|
|
86
|
+
return customParameters;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Serializes a CallInvite.
|
|
93
|
+
* @param CallRecord the callRecord
|
|
94
|
+
* @return A serialized CallInvite
|
|
95
|
+
*/
|
|
96
|
+
public static WritableMap serializeCallInvite(@NonNull final CallRecord callRecord) {
|
|
97
|
+
// validate input
|
|
98
|
+
final UUID uuid = Objects.requireNonNull(callRecord.getUuid());
|
|
99
|
+
final CallInvite callInvite = Objects.requireNonNull(callRecord.getCallInvite());
|
|
100
|
+
|
|
101
|
+
// serialize
|
|
102
|
+
return constructJSMap(
|
|
103
|
+
new Pair<>(CallInviteInfoUuid, uuid.toString()),
|
|
104
|
+
new Pair<>(CallInviteInfoCallSid, callInvite.getCallSid()),
|
|
105
|
+
new Pair<>(CallInviteInfoFrom, callInvite.getFrom()),
|
|
106
|
+
new Pair<>(CallInviteInfoTo, callInvite.getTo()),
|
|
107
|
+
new Pair<>(CallInviteInfoCustomParameters, serializeCallInviteCustomParameters(callInvite)));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Serializes a CancelledCallInvite.
|
|
112
|
+
* @param CallRecord The callRecord
|
|
113
|
+
* @return A serialized CancelledCallInvite
|
|
114
|
+
*/
|
|
115
|
+
public static WritableMap serializeCancelledCallInvite(@NonNull final CallRecord callRecord) {
|
|
116
|
+
// validate input
|
|
117
|
+
final CancelledCallInvite callInvite = Objects.requireNonNull(callRecord.getCancelledCallInvite());
|
|
118
|
+
|
|
119
|
+
// serialize
|
|
120
|
+
return constructJSMap(
|
|
121
|
+
new Pair<>(CancelledCallInviteInfoCallSid, callInvite.getCallSid()),
|
|
122
|
+
new Pair<>(CancelledCallInviteInfoFrom, callInvite.getFrom()),
|
|
123
|
+
new Pair<>(CancelledCallInviteInfoTo, callInvite.getTo()));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Convert the call state enumeration to a string that the JS layer expects.
|
|
128
|
+
* @param state The call state
|
|
129
|
+
* @return A string representing the state
|
|
130
|
+
*/
|
|
131
|
+
public static String callStateToString(Call.State state) {
|
|
132
|
+
switch (state) {
|
|
133
|
+
case CONNECTED:
|
|
134
|
+
return CallStateConnected;
|
|
135
|
+
case CONNECTING:
|
|
136
|
+
return CallStateConnecting;
|
|
137
|
+
case DISCONNECTED:
|
|
138
|
+
return CallStateDisconnected;
|
|
139
|
+
case RECONNECTING:
|
|
140
|
+
return CallStateReconnecting;
|
|
141
|
+
case RINGING:
|
|
142
|
+
return CallStateRinging;
|
|
143
|
+
default:
|
|
144
|
+
logger.warning("Unknown call state: " + state);
|
|
145
|
+
return CallStateConnecting;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Serializes a Call.
|
|
151
|
+
* @param CallRecord the call record
|
|
152
|
+
* @return A serialized Call
|
|
153
|
+
*/
|
|
154
|
+
public static WritableMap serializeCall(@NonNull final CallRecord callRecord) {
|
|
155
|
+
// validate input
|
|
156
|
+
Objects.requireNonNull(callRecord.getUuid());
|
|
157
|
+
Objects.requireNonNull(callRecord.getVoiceCall());
|
|
158
|
+
|
|
159
|
+
// serialize
|
|
160
|
+
WritableMap callInfo = constructJSMap(
|
|
161
|
+
new Pair<>(CallInfoUuid, callRecord.getUuid().toString()),
|
|
162
|
+
new Pair<>(CallInfoSid, callRecord.getVoiceCall().getSid()),
|
|
163
|
+
new Pair<>(CallInfoFrom, callRecord.getVoiceCall().getFrom()),
|
|
164
|
+
new Pair<>(CallInfoTo, callRecord.getVoiceCall().getTo()),
|
|
165
|
+
new Pair<>(CallInfoState, callStateToString(callRecord.getVoiceCall().getState())),
|
|
166
|
+
new Pair<>(CallInfoIsMuted, callRecord.getVoiceCall().isMuted()),
|
|
167
|
+
new Pair<>(CallInfoIsOnHold, callRecord.getVoiceCall().isOnHold()),
|
|
168
|
+
new Pair<>(CallInviteInfoCustomParameters, serializeCallInviteCustomParameters(callRecord.getCallInvite())),
|
|
169
|
+
new Pair<>(CallInfoInitialConnectedTimestamp, simplifiedISO8601DateTimeFormat(callRecord.getTimestamp()))
|
|
170
|
+
);
|
|
171
|
+
return callInfo;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Serializes an AudioDevice.
|
|
176
|
+
* @param uuid The UUID of the AudioDevice
|
|
177
|
+
* @param audioDevice The AudioDevice
|
|
178
|
+
* @return A serialized AudioDevice
|
|
179
|
+
*/
|
|
180
|
+
public static WritableMap serializeAudioDevice(String uuid, @Nullable AudioDevice audioDevice) {
|
|
181
|
+
if (null != audioDevice) {
|
|
182
|
+
String type = audioDevice.getClass().getSimpleName();
|
|
183
|
+
return constructJSMap(
|
|
184
|
+
new Pair<>(AudioDeviceKeyUuid, uuid),
|
|
185
|
+
new Pair<>(AudioDeviceKeyName, audioDevice.getName()),
|
|
186
|
+
new Pair<>(AudioDeviceKeyType, AudioSwitchManager.AUDIO_DEVICE_TYPE.get(type)));
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Serializes a map of UUIDs to AudioDevices into a list of [key, value] tuples.
|
|
193
|
+
* @param audioDevices A map of UUIDs to AudioDevices
|
|
194
|
+
* @return A serialized list of UUID and AudioDevice tuples
|
|
195
|
+
*/
|
|
196
|
+
public static WritableArray serializeAudioDeviceMapIntoArray(Map<String, AudioDevice> audioDevices) {
|
|
197
|
+
WritableArray audioDeviceInfoArray = Arguments.createArray();
|
|
198
|
+
|
|
199
|
+
for (Entry<String, AudioDevice> entry : audioDevices.entrySet()) {
|
|
200
|
+
String uuid = entry.getKey();
|
|
201
|
+
AudioDevice audioDevice = entry.getValue();
|
|
202
|
+
|
|
203
|
+
WritableMap audioDeviceInfoMap = serializeAudioDevice(uuid, audioDevice);
|
|
204
|
+
audioDeviceInfoArray.pushMap(audioDeviceInfoMap);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return audioDeviceInfoArray;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Serializes all audio device information.
|
|
212
|
+
* @param audioDevices A map of UUIDs to AudioDevices
|
|
213
|
+
* @param selectedAudioDeviceUuid The UUID of the selected audio device
|
|
214
|
+
* @param selectedAudioDevice The selected audio device
|
|
215
|
+
* @return Serialized audio device information
|
|
216
|
+
*/
|
|
217
|
+
public static WritableMap serializeAudioDeviceInfo(
|
|
218
|
+
Map<String, AudioDevice> audioDevices,
|
|
219
|
+
String selectedAudioDeviceUuid,
|
|
220
|
+
AudioDevice selectedAudioDevice) {
|
|
221
|
+
return constructJSMap(
|
|
222
|
+
new Pair<>(AudioDeviceKeyAudioDevices, serializeAudioDeviceMapIntoArray(audioDevices)),
|
|
223
|
+
new Pair<>(AudioDeviceKeySelectedDevice, serializeAudioDevice(selectedAudioDeviceUuid, selectedAudioDevice)));
|
|
224
|
+
}
|
|
225
|
+
public static WritableMap serializeVoiceException(VoiceException exception) {
|
|
226
|
+
if (null != exception) {
|
|
227
|
+
return constructJSMap(
|
|
228
|
+
new Pair<>(VoiceErrorKeyCode, exception.getErrorCode()),
|
|
229
|
+
new Pair<>(VoiceErrorKeyMessage, exception.getMessage()));
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
public static WritableMap serializeCallException(@NonNull final CallRecord callRecord) {
|
|
234
|
+
return (null != callRecord.getCallException())
|
|
235
|
+
? serializeVoiceException(callRecord.getCallException())
|
|
236
|
+
: null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
public static WritableMap serializeError(int code, String message) {
|
|
240
|
+
if (null != message) {
|
|
241
|
+
return constructJSMap(
|
|
242
|
+
new Pair<>(VoiceErrorKeyCode, code),
|
|
243
|
+
new Pair<>(VoiceErrorKeyMessage, message)
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
public static WritableArray serializeCallQualityWarnings(@NonNull Set<Call.CallQualityWarning> warnings) {
|
|
250
|
+
WritableArray previousWarningsArray = Arguments.createArray();
|
|
251
|
+
for (Call.CallQualityWarning warning : warnings) {
|
|
252
|
+
previousWarningsArray.pushString(warning.toString());
|
|
253
|
+
}
|
|
254
|
+
return previousWarningsArray;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Serializes a Call Message
|
|
259
|
+
* @param CallMessage the call message
|
|
260
|
+
* @return A serialized Call
|
|
261
|
+
*/
|
|
262
|
+
public static WritableMap serializeCallMessage(@NonNull final CallMessage callMessage) {
|
|
263
|
+
return constructJSMap(
|
|
264
|
+
new Pair<>(VoiceEventSid, callMessage.getVoiceEventSID()),
|
|
265
|
+
new Pair<>(CallMessageContent, callMessage.getContent()),
|
|
266
|
+
new Pair<>(CallMessageContentType, callMessage.getMessageContentType()),
|
|
267
|
+
new Pair<>(CallMessageMessageType, callMessage.getMessageType())
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private static String simplifiedISO8601DateTimeFormat(final Date date) {
|
|
272
|
+
SimpleDateFormat simpleDateFormat =
|
|
273
|
+
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
|
|
274
|
+
return (null != date) ? simpleDateFormat.format(date) : null;
|
|
275
|
+
}
|
|
276
|
+
}
|