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,403 @@
|
|
|
1
|
+
package com.twiliovoicereactnative;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteEventKeyCallSid;
|
|
5
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteEventKeyType;
|
|
6
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteEventTypeValueAccepted;
|
|
7
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteEventTypeValueCancelled;
|
|
8
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteEventTypeValueNotificationTapped;
|
|
9
|
+
import static com.twiliovoicereactnative.CommonConstants.CallInviteEventTypeValueRejected;
|
|
10
|
+
import static com.twiliovoicereactnative.CommonConstants.ScopeCallInvite;
|
|
11
|
+
import static com.twiliovoicereactnative.CommonConstants.ScopeVoice;
|
|
12
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceErrorKeyError;
|
|
13
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceEventError;
|
|
14
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceEventType;
|
|
15
|
+
import static com.twiliovoicereactnative.CommonConstants.VoiceEventTypeValueIncomingCallInvite;
|
|
16
|
+
import static com.twiliovoicereactnative.Constants.ACTION_ACCEPT_CALL;
|
|
17
|
+
import static com.twiliovoicereactnative.Constants.ACTION_CALL_DISCONNECT;
|
|
18
|
+
import static com.twiliovoicereactnative.Constants.ACTION_CANCEL_CALL;
|
|
19
|
+
import static com.twiliovoicereactnative.Constants.ACTION_CANCEL_ACTIVE_CALL_NOTIFICATION;
|
|
20
|
+
import static com.twiliovoicereactnative.Constants.ACTION_FOREGROUND_AND_DEPRIORITIZE_INCOMING_CALL_NOTIFICATION;
|
|
21
|
+
import static com.twiliovoicereactnative.Constants.ACTION_INCOMING_CALL;
|
|
22
|
+
import static com.twiliovoicereactnative.Constants.ACTION_PUSH_APP_TO_FOREGROUND;
|
|
23
|
+
import static com.twiliovoicereactnative.Constants.ACTION_RAISE_OUTGOING_CALL_NOTIFICATION;
|
|
24
|
+
import static com.twiliovoicereactnative.Constants.ACTION_REJECT_CALL;
|
|
25
|
+
import static com.twiliovoicereactnative.Constants.JS_EVENT_KEY_CALL_INVITE_INFO;
|
|
26
|
+
import static com.twiliovoicereactnative.Constants.JS_EVENT_KEY_CANCELLED_CALL_INVITE_INFO;
|
|
27
|
+
import static com.twiliovoicereactnative.Constants.VOICE_CHANNEL_DEFAULT_IMPORTANCE;
|
|
28
|
+
import static com.twiliovoicereactnative.Constants.VOICE_CHANNEL_HIGH_IMPORTANCE;
|
|
29
|
+
import static com.twiliovoicereactnative.JSEventEmitter.constructJSMap;
|
|
30
|
+
import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeCall;
|
|
31
|
+
import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeCallException;
|
|
32
|
+
import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeCallInvite;
|
|
33
|
+
import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeCancelledCallInvite;
|
|
34
|
+
import static com.twiliovoicereactnative.ReactNativeArgumentsSerializer.serializeError;
|
|
35
|
+
import static com.twiliovoicereactnative.VoiceApplicationProxy.getCallRecordDatabase;
|
|
36
|
+
import static com.twiliovoicereactnative.VoiceApplicationProxy.getJSEventEmitter;
|
|
37
|
+
|
|
38
|
+
import android.Manifest;
|
|
39
|
+
import android.app.Notification;
|
|
40
|
+
import android.app.NotificationManager;
|
|
41
|
+
import android.app.Service;
|
|
42
|
+
import android.content.Context;
|
|
43
|
+
import android.content.Intent;
|
|
44
|
+
import android.content.pm.PackageManager;
|
|
45
|
+
import android.content.pm.ServiceInfo;
|
|
46
|
+
import android.os.Binder;
|
|
47
|
+
import android.os.Build;
|
|
48
|
+
import android.os.IBinder;
|
|
49
|
+
import android.util.Pair;
|
|
50
|
+
|
|
51
|
+
import androidx.annotation.NonNull;
|
|
52
|
+
import androidx.core.app.ActivityCompat;
|
|
53
|
+
import androidx.core.app.ServiceCompat;
|
|
54
|
+
|
|
55
|
+
import com.facebook.react.bridge.WritableMap;
|
|
56
|
+
import com.twilio.voice.AcceptOptions;
|
|
57
|
+
import com.twilio.voice.Call;
|
|
58
|
+
import com.twilio.voice.ConnectOptions;
|
|
59
|
+
import com.twilio.voice.Voice;
|
|
60
|
+
|
|
61
|
+
import java.util.Objects;
|
|
62
|
+
import java.util.UUID;
|
|
63
|
+
|
|
64
|
+
public class VoiceService extends Service {
|
|
65
|
+
private static final SDKLog logger = new SDKLog(VoiceService.class);
|
|
66
|
+
public class VoiceServiceAPI extends Binder {
|
|
67
|
+
public Call connect(@NonNull ConnectOptions cxnOptions,
|
|
68
|
+
@NonNull Call.Listener listener) {
|
|
69
|
+
logger.debug("connect");
|
|
70
|
+
return Voice.connect(VoiceService.this, cxnOptions, listener);
|
|
71
|
+
}
|
|
72
|
+
public void disconnect(final CallRecordDatabase.CallRecord callRecord) {
|
|
73
|
+
VoiceService.this.disconnect(callRecord);
|
|
74
|
+
}
|
|
75
|
+
public void incomingCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
76
|
+
VoiceService.this.incomingCall(callRecord);
|
|
77
|
+
}
|
|
78
|
+
public void acceptCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
79
|
+
VoiceService.this.acceptCall(callRecord);
|
|
80
|
+
}
|
|
81
|
+
public void rejectCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
82
|
+
VoiceService.this.rejectCall(callRecord);
|
|
83
|
+
}
|
|
84
|
+
public void cancelCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
85
|
+
VoiceService.this.cancelCall(callRecord);
|
|
86
|
+
}
|
|
87
|
+
public void raiseOutgoingCallNotification(final CallRecordDatabase.CallRecord callRecord) {
|
|
88
|
+
VoiceService.this.raiseOutgoingCallNotification(callRecord);
|
|
89
|
+
}
|
|
90
|
+
public void cancelActiveCallNotification(final CallRecordDatabase.CallRecord callRecord) {
|
|
91
|
+
VoiceService.this.cancelActiveCallNotification(callRecord);
|
|
92
|
+
}
|
|
93
|
+
public void foregroundAndDeprioritizeIncomingCallNotification(final CallRecordDatabase.CallRecord callRecord) {
|
|
94
|
+
VoiceService.this.foregroundAndDeprioritizeIncomingCallNotification(callRecord);
|
|
95
|
+
}
|
|
96
|
+
public Context getServiceContext() {
|
|
97
|
+
return VoiceService.this;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@Override
|
|
102
|
+
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
103
|
+
// apparently the system can recreate the service without sending it an intent so protect
|
|
104
|
+
// against that case (GH-430).
|
|
105
|
+
if (null != intent) {
|
|
106
|
+
switch (Objects.requireNonNull(intent.getAction())) {
|
|
107
|
+
case ACTION_INCOMING_CALL:
|
|
108
|
+
incomingCall(getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
109
|
+
break;
|
|
110
|
+
case ACTION_ACCEPT_CALL:
|
|
111
|
+
try {
|
|
112
|
+
acceptCall(getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
113
|
+
} catch (SecurityException e) {
|
|
114
|
+
sendPermissionsError();
|
|
115
|
+
logger.warning(e, "Cannot accept call, lacking necessary permissions");
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
case ACTION_REJECT_CALL:
|
|
119
|
+
rejectCall(getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
120
|
+
break;
|
|
121
|
+
case ACTION_CANCEL_CALL:
|
|
122
|
+
cancelCall(getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
123
|
+
break;
|
|
124
|
+
case ACTION_CALL_DISCONNECT:
|
|
125
|
+
disconnect(getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
126
|
+
break;
|
|
127
|
+
case ACTION_RAISE_OUTGOING_CALL_NOTIFICATION:
|
|
128
|
+
raiseOutgoingCallNotification(getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
129
|
+
break;
|
|
130
|
+
case ACTION_CANCEL_ACTIVE_CALL_NOTIFICATION:
|
|
131
|
+
cancelActiveCallNotification(getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
132
|
+
break;
|
|
133
|
+
case ACTION_FOREGROUND_AND_DEPRIORITIZE_INCOMING_CALL_NOTIFICATION:
|
|
134
|
+
foregroundAndDeprioritizeIncomingCallNotification(
|
|
135
|
+
getCallRecord(Objects.requireNonNull(getMessageUUID(intent))));
|
|
136
|
+
break;
|
|
137
|
+
case ACTION_PUSH_APP_TO_FOREGROUND:
|
|
138
|
+
logger.warning("VoiceService received foreground request, ignoring");
|
|
139
|
+
break;
|
|
140
|
+
default:
|
|
141
|
+
logger.log("Unknown notification, ignoring");
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return START_NOT_STICKY;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@Override
|
|
149
|
+
public IBinder onBind(Intent intent) {
|
|
150
|
+
return new VoiceServiceAPI();
|
|
151
|
+
}
|
|
152
|
+
public static Intent constructMessage(@NonNull Context context,
|
|
153
|
+
@NonNull final String action,
|
|
154
|
+
@NonNull final Class<?> target,
|
|
155
|
+
@NonNull final UUID uuid) {
|
|
156
|
+
Intent intent = new Intent(context.getApplicationContext(), target);
|
|
157
|
+
intent.setAction(action);
|
|
158
|
+
intent.putExtra(Constants.MSG_KEY_UUID, uuid);
|
|
159
|
+
return intent;
|
|
160
|
+
}
|
|
161
|
+
private void disconnect(final CallRecordDatabase.CallRecord callRecord) {
|
|
162
|
+
logger.debug("disconnect");
|
|
163
|
+
if (null != callRecord) {
|
|
164
|
+
Objects.requireNonNull(callRecord.getVoiceCall()).disconnect();
|
|
165
|
+
} else {
|
|
166
|
+
logger.warning("No call record found");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
private void incomingCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
170
|
+
logger.debug("incomingCall: " + callRecord.getUuid());
|
|
171
|
+
|
|
172
|
+
// verify that mic permissions have been granted and if not, throw a error
|
|
173
|
+
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) &&
|
|
174
|
+
ActivityCompat.checkSelfPermission(VoiceService.this,
|
|
175
|
+
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
|
176
|
+
|
|
177
|
+
// report to js layer lack of permissions issue
|
|
178
|
+
sendPermissionsError();
|
|
179
|
+
|
|
180
|
+
// report an error to logger
|
|
181
|
+
logger.warning("WARNING: Incoming call cannot be handled, microphone permission not granted");
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// put up notification
|
|
186
|
+
callRecord.setNotificationId(NotificationUtility.createNotificationIdentifier());
|
|
187
|
+
Notification notification = NotificationUtility.createIncomingCallNotification(
|
|
188
|
+
VoiceService.this,
|
|
189
|
+
callRecord,
|
|
190
|
+
VOICE_CHANNEL_HIGH_IMPORTANCE);
|
|
191
|
+
createOrReplaceNotification(callRecord.getNotificationId(), notification);
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
// play ringer sound
|
|
196
|
+
VoiceApplicationProxy.getAudioSwitchManager().getAudioSwitch().activate();
|
|
197
|
+
VoiceApplicationProxy.getMediaPlayerManager().play(MediaPlayerManager.SoundTable.INCOMING);
|
|
198
|
+
|
|
199
|
+
// trigger JS layer
|
|
200
|
+
sendJSEvent(
|
|
201
|
+
ScopeVoice,
|
|
202
|
+
constructJSMap(
|
|
203
|
+
new Pair<>(VoiceEventType, VoiceEventTypeValueIncomingCallInvite),
|
|
204
|
+
new Pair<>(JS_EVENT_KEY_CALL_INVITE_INFO, serializeCallInvite(callRecord))));
|
|
205
|
+
}
|
|
206
|
+
private void acceptCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
207
|
+
logger.debug("acceptCall: " + callRecord.getUuid());
|
|
208
|
+
|
|
209
|
+
// verify that mic permissions have been granted and if not, throw a error
|
|
210
|
+
if (ActivityCompat.checkSelfPermission(VoiceService.this,
|
|
211
|
+
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
|
212
|
+
// cancel incoming call notification
|
|
213
|
+
removeNotification(callRecord.getNotificationId());
|
|
214
|
+
|
|
215
|
+
// stop ringer sound
|
|
216
|
+
VoiceApplicationProxy.getMediaPlayerManager().stop();
|
|
217
|
+
VoiceApplicationProxy.getAudioSwitchManager().getAudioSwitch().deactivate();
|
|
218
|
+
|
|
219
|
+
// report an error to JS layer
|
|
220
|
+
sendPermissionsError();
|
|
221
|
+
|
|
222
|
+
// report an error to logger
|
|
223
|
+
logger.warning("WARNING: Call not accepted, microphone permission not granted");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// cancel existing notification & put up in call
|
|
228
|
+
Notification notification = NotificationUtility.createCallAnsweredNotificationWithLowImportance(
|
|
229
|
+
VoiceService.this,
|
|
230
|
+
callRecord);
|
|
231
|
+
createOrReplaceForegroundNotification(callRecord.getNotificationId(), notification);
|
|
232
|
+
|
|
233
|
+
// stop ringer sound
|
|
234
|
+
VoiceApplicationProxy.getMediaPlayerManager().stop();
|
|
235
|
+
|
|
236
|
+
// accept call
|
|
237
|
+
AcceptOptions acceptOptions = new AcceptOptions.Builder()
|
|
238
|
+
.enableDscp(true)
|
|
239
|
+
.callMessageListener(new CallMessageListenerProxy())
|
|
240
|
+
.build();
|
|
241
|
+
|
|
242
|
+
callRecord.setCall(
|
|
243
|
+
callRecord.getCallInvite().accept(
|
|
244
|
+
VoiceService.this,
|
|
245
|
+
acceptOptions,
|
|
246
|
+
new CallListenerProxy(callRecord.getUuid(), VoiceService.this)));
|
|
247
|
+
callRecord.setCallInviteUsedState();
|
|
248
|
+
|
|
249
|
+
// handle if event spawned from JS
|
|
250
|
+
if (null != callRecord.getCallAcceptedPromise()) {
|
|
251
|
+
callRecord.getCallAcceptedPromise().resolve(serializeCall(callRecord));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// notify JS layer
|
|
255
|
+
sendJSEvent(
|
|
256
|
+
ScopeCallInvite,
|
|
257
|
+
constructJSMap(
|
|
258
|
+
new Pair<>(CallInviteEventKeyType, CallInviteEventTypeValueAccepted),
|
|
259
|
+
new Pair<>(CallInviteEventKeyCallSid, callRecord.getCallSid()),
|
|
260
|
+
new Pair<>(JS_EVENT_KEY_CALL_INVITE_INFO, serializeCallInvite(callRecord))));
|
|
261
|
+
}
|
|
262
|
+
private void rejectCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
263
|
+
logger.debug("rejectCall: " + callRecord.getUuid());
|
|
264
|
+
|
|
265
|
+
// remove call record
|
|
266
|
+
getCallRecordDatabase().remove(callRecord);
|
|
267
|
+
|
|
268
|
+
// take down notification
|
|
269
|
+
removeNotification(callRecord.getNotificationId());
|
|
270
|
+
|
|
271
|
+
// stop ringer sound
|
|
272
|
+
VoiceApplicationProxy.getMediaPlayerManager().stop();
|
|
273
|
+
VoiceApplicationProxy.getAudioSwitchManager().getAudioSwitch().deactivate();
|
|
274
|
+
|
|
275
|
+
// reject call
|
|
276
|
+
callRecord.getCallInvite().reject(VoiceService.this);
|
|
277
|
+
callRecord.setCallInviteUsedState();
|
|
278
|
+
|
|
279
|
+
// handle if event spawned from JS
|
|
280
|
+
if (null != callRecord.getCallRejectedPromise()) {
|
|
281
|
+
callRecord.getCallRejectedPromise().resolve(callRecord.getUuid().toString());
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// notify JS layer
|
|
285
|
+
sendJSEvent(
|
|
286
|
+
ScopeCallInvite,
|
|
287
|
+
constructJSMap(
|
|
288
|
+
new Pair<>(CallInviteEventKeyType, CallInviteEventTypeValueRejected),
|
|
289
|
+
new Pair<>(CallInviteEventKeyCallSid, callRecord.getCallSid()),
|
|
290
|
+
new Pair<>(JS_EVENT_KEY_CALL_INVITE_INFO, serializeCallInvite(callRecord))));
|
|
291
|
+
}
|
|
292
|
+
private void cancelCall(final CallRecordDatabase.CallRecord callRecord) {
|
|
293
|
+
logger.debug("CancelCall: " + callRecord.getUuid());
|
|
294
|
+
|
|
295
|
+
// take down notification
|
|
296
|
+
removeNotification(callRecord.getNotificationId());
|
|
297
|
+
|
|
298
|
+
// stop ringer sound
|
|
299
|
+
VoiceApplicationProxy.getMediaPlayerManager().stop();
|
|
300
|
+
VoiceApplicationProxy.getAudioSwitchManager().getAudioSwitch().deactivate();
|
|
301
|
+
|
|
302
|
+
// notify JS layer
|
|
303
|
+
sendJSEvent(
|
|
304
|
+
ScopeCallInvite,
|
|
305
|
+
constructJSMap(
|
|
306
|
+
new Pair<>(CallInviteEventKeyType, CallInviteEventTypeValueCancelled),
|
|
307
|
+
new Pair<>(CallInviteEventKeyCallSid, callRecord.getCallSid()),
|
|
308
|
+
new Pair<>(JS_EVENT_KEY_CANCELLED_CALL_INVITE_INFO, serializeCancelledCallInvite(callRecord)),
|
|
309
|
+
new Pair<>(VoiceErrorKeyError, serializeCallException(callRecord))));
|
|
310
|
+
}
|
|
311
|
+
private void raiseOutgoingCallNotification(final CallRecordDatabase.CallRecord callRecord) {
|
|
312
|
+
logger.debug("raiseOutgoingCallNotification: " + callRecord.getUuid());
|
|
313
|
+
|
|
314
|
+
// put up outgoing call notification
|
|
315
|
+
Notification notification =
|
|
316
|
+
NotificationUtility.createOutgoingCallNotificationWithLowImportance(
|
|
317
|
+
VoiceService.this,
|
|
318
|
+
callRecord);
|
|
319
|
+
createOrReplaceForegroundNotification(callRecord.getNotificationId(), notification);
|
|
320
|
+
}
|
|
321
|
+
private void foregroundAndDeprioritizeIncomingCallNotification(final CallRecordDatabase.CallRecord callRecord) {
|
|
322
|
+
logger.debug("foregroundAndDeprioritizeIncomingCallNotification: " + callRecord.getUuid());
|
|
323
|
+
|
|
324
|
+
// cancel existing notification & put up in call
|
|
325
|
+
Notification notification = NotificationUtility.createIncomingCallNotification(
|
|
326
|
+
VoiceService.this,
|
|
327
|
+
callRecord,
|
|
328
|
+
VOICE_CHANNEL_DEFAULT_IMPORTANCE);
|
|
329
|
+
createOrReplaceNotification(callRecord.getNotificationId(), notification);
|
|
330
|
+
|
|
331
|
+
// stop active sound (if any)
|
|
332
|
+
VoiceApplicationProxy.getMediaPlayerManager().stop();
|
|
333
|
+
|
|
334
|
+
// notify JS layer
|
|
335
|
+
sendJSEvent(
|
|
336
|
+
ScopeCallInvite,
|
|
337
|
+
constructJSMap(
|
|
338
|
+
new Pair<>(CallInviteEventKeyType, CallInviteEventTypeValueNotificationTapped),
|
|
339
|
+
new Pair<>(CallInviteEventKeyCallSid, callRecord.getCallSid())));
|
|
340
|
+
}
|
|
341
|
+
private void cancelActiveCallNotification(final CallRecordDatabase.CallRecord callRecord) {
|
|
342
|
+
logger.debug("cancelNotification");
|
|
343
|
+
// only take down notification & stop any active sounds if one is active
|
|
344
|
+
if (null != callRecord) {
|
|
345
|
+
VoiceApplicationProxy.getMediaPlayerManager().stop();
|
|
346
|
+
removeForegroundNotification();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
private void createOrReplaceNotification(final int notificationId,
|
|
350
|
+
final Notification notification) {
|
|
351
|
+
NotificationManager mNotificationManager =
|
|
352
|
+
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
353
|
+
mNotificationManager.notify(notificationId, notification);
|
|
354
|
+
}
|
|
355
|
+
private void createOrReplaceForegroundNotification(final int notificationId,
|
|
356
|
+
final Notification notification) {
|
|
357
|
+
if (ActivityCompat.checkSelfPermission(VoiceService.this, Manifest.permission.POST_NOTIFICATIONS)
|
|
358
|
+
== PackageManager.PERMISSION_GRANTED) {
|
|
359
|
+
foregroundNotification(notificationId, notification);
|
|
360
|
+
} else {
|
|
361
|
+
logger.warning("WARNING: Notification not posted, permission not granted");
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
private void removeNotification(final int notificationId) {
|
|
365
|
+
logger.debug("removeNotification");
|
|
366
|
+
NotificationManager mNotificationManager =
|
|
367
|
+
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
368
|
+
mNotificationManager.cancel(notificationId);
|
|
369
|
+
}
|
|
370
|
+
private void removeForegroundNotification() {
|
|
371
|
+
logger.debug("removeForegroundNotification");
|
|
372
|
+
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE);
|
|
373
|
+
}
|
|
374
|
+
private void foregroundNotification(int id, Notification notification) {
|
|
375
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
376
|
+
try {
|
|
377
|
+
startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
|
|
378
|
+
} catch (Exception e) {
|
|
379
|
+
sendPermissionsError();
|
|
380
|
+
logger.warning(e, "Failed to place notification due to lack of permissions");
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
startForeground(id, notification);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
private static UUID getMessageUUID(@NonNull final Intent intent) {
|
|
387
|
+
return (UUID)intent.getSerializableExtra(Constants.MSG_KEY_UUID);
|
|
388
|
+
}
|
|
389
|
+
private static CallRecordDatabase.CallRecord getCallRecord(final UUID uuid) {
|
|
390
|
+
return Objects.requireNonNull(getCallRecordDatabase().get(new CallRecordDatabase.CallRecord(uuid)));
|
|
391
|
+
}
|
|
392
|
+
private static void sendJSEvent(@NonNull String scope, @NonNull WritableMap event) {
|
|
393
|
+
getJSEventEmitter().sendEvent(scope, event);
|
|
394
|
+
}
|
|
395
|
+
private static void sendPermissionsError() {
|
|
396
|
+
final String errorMessage = "Missing permissions.";
|
|
397
|
+
final int errorCode = 31401;
|
|
398
|
+
getJSEventEmitter().sendEvent(ScopeVoice, constructJSMap(
|
|
399
|
+
new Pair<>(VoiceEventType, VoiceEventError),
|
|
400
|
+
new Pair<>(VoiceErrorKeyError, serializeError(errorCode, errorMessage))
|
|
401
|
+
));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<resources>
|
|
3
|
+
<color name="colorPrimary">#f10028</color>
|
|
4
|
+
<color name="colorPrimaryDark">#a3090e</color>
|
|
5
|
+
<color name="colorAccent">#b0bec5</color>
|
|
6
|
+
<color name="colorGreen">#4ECE23</color>
|
|
7
|
+
<color name="colorRed">#EE3E27</color>
|
|
8
|
+
<color name="colorContentTitle">#000000</color>
|
|
9
|
+
<color name="colorContent">#505050</color>
|
|
10
|
+
<color name="colorButtonText">#FFFFFF</color>
|
|
11
|
+
</resources>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<resources>
|
|
2
|
+
<!-- Default screen margins, per the Android Design guidelines. -->
|
|
3
|
+
<dimen name="activity_horizontal_margin">16dp</dimen>
|
|
4
|
+
<dimen name="activity_vertical_margin">16dp</dimen>
|
|
5
|
+
<dimen name="notification_small_window_size">20dp</dimen>
|
|
6
|
+
<dimen name="notification_window_size">140dp</dimen>
|
|
7
|
+
</resources>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<resources>
|
|
2
|
+
<string name="app_name">Twilio Voice React Native</string>
|
|
3
|
+
<string name="audio_device">Audio Device</string>
|
|
4
|
+
<string name="callee">client identity or phone number</string>
|
|
5
|
+
<string name="answer">ANSWER</string>
|
|
6
|
+
<string name="decline">DECLINE</string>
|
|
7
|
+
<string name="tapToApp">Tap to return to call</string>
|
|
8
|
+
<string name="end_call">End Call</string>
|
|
9
|
+
<string name="callHint">Dial a client name or phone number. Leaving the field empty results in an automated response.</string>
|
|
10
|
+
<string name="digitHint">A string of digits to be sent. Valid values are "0" - "9", "*", "#", and "w". Each "w" will cause a 500 ms pause between digits sent. </string>
|
|
11
|
+
<string name="select_device">Select Audio Device</string>
|
|
12
|
+
<string name="registration_error">Registration Error: %d, %s</string>
|
|
13
|
+
<string name="unregistration_error">Unregistration Error: %d, %s</string>
|
|
14
|
+
<string name="fcm_token_registration_fail">Fetching FCM registration token failed %s</string>
|
|
15
|
+
<string name="fcm_token_null">FCM token is "null"</string>
|
|
16
|
+
<string name="missing_audiodevice_uuid">No such "audioDevice" object exists with UUID %s</string>
|
|
17
|
+
<string name="missing_call_uuid">No such "call" object exists with UUID %s</string>
|
|
18
|
+
<string name="missing_callinvite_uuid">No such "callInvite" object exists with UUID %s</string>
|
|
19
|
+
<string name="invalid_notification_type">Invalid notificaiton type %s</string>
|
|
20
|
+
<string name="unknown_call_recipient">Unknown</string>
|
|
21
|
+
<string name="incoming_call_caller_name_text">${from}</string>
|
|
22
|
+
<string name="outgoing_call_caller_name_text">${to}</string>
|
|
23
|
+
<string name="answered_call_caller_name_text">${from}</string>
|
|
24
|
+
<string name="method_invocation_invalid">Method invocation invalid</string>
|
|
25
|
+
</resources>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<resources>
|
|
2
|
+
|
|
3
|
+
<!-- Base application theme. -->
|
|
4
|
+
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
|
5
|
+
<!-- Customize your theme here. -->
|
|
6
|
+
<item name="colorPrimary">@color/colorPrimary</item>
|
|
7
|
+
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
|
8
|
+
<item name="colorAccent">@color/colorAccent</item>
|
|
9
|
+
</style>
|
|
10
|
+
</resources>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<resources>
|
|
3
|
+
<color name="colorPrimary">#f10028</color>
|
|
4
|
+
<color name="colorPrimaryDark">#a3090e</color>
|
|
5
|
+
<color name="colorAccent">#b0bec5</color>
|
|
6
|
+
<color name="colorGreen">#4ECE23</color>
|
|
7
|
+
<color name="colorRed">#EE3E27</color>
|
|
8
|
+
<color name="colorContentTitle">#000000</color>
|
|
9
|
+
<color name="colorContent">#505050</color>
|
|
10
|
+
<color name="colorButtonText">#FFFFFF</color>
|
|
11
|
+
</resources>
|