voice-react-native-sdk 1.6.2-fork.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/LICENSE +206 -0
  2. package/README.md +179 -0
  3. package/android/build.gradle +113 -0
  4. package/android/gradle.properties +29 -0
  5. package/android/src/main/AndroidManifest.xml +30 -0
  6. package/android/src/main/java/com/twiliovoicereactnative/AudioSwitchManager.java +141 -0
  7. package/android/src/main/java/com/twiliovoicereactnative/CallListenerProxy.java +186 -0
  8. package/android/src/main/java/com/twiliovoicereactnative/CallMessageListenerProxy.java +103 -0
  9. package/android/src/main/java/com/twiliovoicereactnative/CallRecordDatabase.java +183 -0
  10. package/android/src/main/java/com/twiliovoicereactnative/CommonConstants.java +195 -0
  11. package/android/src/main/java/com/twiliovoicereactnative/ConfigurationProperties.java +41 -0
  12. package/android/src/main/java/com/twiliovoicereactnative/Constants.java +23 -0
  13. package/android/src/main/java/com/twiliovoicereactnative/ExpoActivityLifecycleListener.java +27 -0
  14. package/android/src/main/java/com/twiliovoicereactnative/ExpoApplicationLifecycleListener.java +14 -0
  15. package/android/src/main/java/com/twiliovoicereactnative/ExpoModule.kt +36 -0
  16. package/android/src/main/java/com/twiliovoicereactnative/ExpoPackage.java +20 -0
  17. package/android/src/main/java/com/twiliovoicereactnative/JSEventEmitter.java +98 -0
  18. package/android/src/main/java/com/twiliovoicereactnative/MediaPlayerManager.java +58 -0
  19. package/android/src/main/java/com/twiliovoicereactnative/NotificationUtility.java +363 -0
  20. package/android/src/main/java/com/twiliovoicereactnative/ReactNativeArgumentsSerializer.java +276 -0
  21. package/android/src/main/java/com/twiliovoicereactnative/SDKLog.java +74 -0
  22. package/android/src/main/java/com/twiliovoicereactnative/StatsListenerProxy.java +178 -0
  23. package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativeModule.java +778 -0
  24. package/android/src/main/java/com/twiliovoicereactnative/TwilioVoiceReactNativePackage.java +28 -0
  25. package/android/src/main/java/com/twiliovoicereactnative/VoiceActivityProxy.java +101 -0
  26. package/android/src/main/java/com/twiliovoicereactnative/VoiceApplicationProxy.java +133 -0
  27. package/android/src/main/java/com/twiliovoicereactnative/VoiceFirebaseMessagingService.java +88 -0
  28. package/android/src/main/java/com/twiliovoicereactnative/VoiceService.java +403 -0
  29. package/android/src/main/res/drawable/answered_call_small_icon.png +0 -0
  30. package/android/src/main/res/drawable/ic_launcher_round.png +0 -0
  31. package/android/src/main/res/drawable/ic_launcher_sdk.png +0 -0
  32. package/android/src/main/res/drawable/incoming_call_small_icon.png +0 -0
  33. package/android/src/main/res/drawable/outgoing_call_small_icon.png +0 -0
  34. package/android/src/main/res/raw/disconnect.wav +0 -0
  35. package/android/src/main/res/raw/incoming.wav +0 -0
  36. package/android/src/main/res/raw/outgoing.wav +0 -0
  37. package/android/src/main/res/raw/ringtone.wav +0 -0
  38. package/android/src/main/res/raw/silent.wav +0 -0
  39. package/android/src/main/res/values/colors.xml +11 -0
  40. package/android/src/main/res/values/config.xml +5 -0
  41. package/android/src/main/res/values/dimens.xml +7 -0
  42. package/android/src/main/res/values/strings.xml +25 -0
  43. package/android/src/main/res/values/styles.xml +10 -0
  44. package/android/src/main/res/values-night/colors.xml +11 -0
  45. package/expo-config-plugin/android.js +191 -0
  46. package/expo-config-plugin/ios.js +22 -0
  47. package/expo-module.config.json +6 -0
  48. package/ios/TwilioVoicePushRegistry.h +19 -0
  49. package/ios/TwilioVoicePushRegistry.m +72 -0
  50. package/ios/TwilioVoiceReactNative+CallInvite.m +56 -0
  51. package/ios/TwilioVoiceReactNative+CallKit.m +533 -0
  52. package/ios/TwilioVoiceReactNative+CallMessage.m +81 -0
  53. package/ios/TwilioVoiceReactNative.h +74 -0
  54. package/ios/TwilioVoiceReactNative.m +1046 -0
  55. package/ios/TwilioVoiceReactNative.xcodeproj/project.pbxproj +328 -0
  56. package/ios/TwilioVoiceReactNativeConstants.h +200 -0
  57. package/ios/Utilities/TwilioVoiceStatsReport.h +175 -0
  58. package/lib/commonjs/AudioDevice.js +101 -0
  59. package/lib/commonjs/AudioDevice.js.map +1 -0
  60. package/lib/commonjs/Call.js +765 -0
  61. package/lib/commonjs/Call.js.map +1 -0
  62. package/lib/commonjs/CallInvite.js +452 -0
  63. package/lib/commonjs/CallInvite.js.map +1 -0
  64. package/lib/commonjs/CallMessage/CallMessage.js +54 -0
  65. package/lib/commonjs/CallMessage/CallMessage.js.map +1 -0
  66. package/lib/commonjs/CallMessage/IncomingCallMessage.js +120 -0
  67. package/lib/commonjs/CallMessage/IncomingCallMessage.js.map +1 -0
  68. package/lib/commonjs/CallMessage/OutgoingCallMessage.js +148 -0
  69. package/lib/commonjs/CallMessage/OutgoingCallMessage.js.map +1 -0
  70. package/lib/commonjs/ExpoModule.js +69 -0
  71. package/lib/commonjs/ExpoModule.js.map +1 -0
  72. package/lib/commonjs/Voice.js +611 -0
  73. package/lib/commonjs/Voice.js.map +1 -0
  74. package/lib/commonjs/common.js +26 -0
  75. package/lib/commonjs/common.js.map +1 -0
  76. package/lib/commonjs/constants.js +158 -0
  77. package/lib/commonjs/constants.js.map +1 -0
  78. package/lib/commonjs/error/InvalidArgumentError.js +32 -0
  79. package/lib/commonjs/error/InvalidArgumentError.js.map +1 -0
  80. package/lib/commonjs/error/InvalidStateError.js +33 -0
  81. package/lib/commonjs/error/InvalidStateError.js.map +1 -0
  82. package/lib/commonjs/error/TwilioError.js +38 -0
  83. package/lib/commonjs/error/TwilioError.js.map +1 -0
  84. package/lib/commonjs/error/UnsupportedPlatformError.js +33 -0
  85. package/lib/commonjs/error/UnsupportedPlatformError.js.map +1 -0
  86. package/lib/commonjs/error/generated.js +2343 -0
  87. package/lib/commonjs/error/generated.js.map +1 -0
  88. package/lib/commonjs/error/index.js +112 -0
  89. package/lib/commonjs/error/index.js.map +1 -0
  90. package/lib/commonjs/error/utility.js +37 -0
  91. package/lib/commonjs/error/utility.js.map +1 -0
  92. package/lib/commonjs/index.js +95 -0
  93. package/lib/commonjs/index.js.map +1 -0
  94. package/lib/commonjs/type/AudioDevice.js +6 -0
  95. package/lib/commonjs/type/AudioDevice.js.map +1 -0
  96. package/lib/commonjs/type/Call.js +6 -0
  97. package/lib/commonjs/type/Call.js.map +1 -0
  98. package/lib/commonjs/type/CallInvite.js +6 -0
  99. package/lib/commonjs/type/CallInvite.js.map +1 -0
  100. package/lib/commonjs/type/CallKit.js +30 -0
  101. package/lib/commonjs/type/CallKit.js.map +1 -0
  102. package/lib/commonjs/type/CallMessage.js +6 -0
  103. package/lib/commonjs/type/CallMessage.js.map +1 -0
  104. package/lib/commonjs/type/Error.js +6 -0
  105. package/lib/commonjs/type/Error.js.map +1 -0
  106. package/lib/commonjs/type/NativeModule.js +6 -0
  107. package/lib/commonjs/type/NativeModule.js.map +1 -0
  108. package/lib/commonjs/type/RTCStats.js +29 -0
  109. package/lib/commonjs/type/RTCStats.js.map +1 -0
  110. package/lib/commonjs/type/Voice.js +6 -0
  111. package/lib/commonjs/type/Voice.js.map +1 -0
  112. package/lib/commonjs/type/common.js +2 -0
  113. package/lib/commonjs/type/common.js.map +1 -0
  114. package/lib/module/AudioDevice.js +97 -0
  115. package/lib/module/AudioDevice.js.map +1 -0
  116. package/lib/module/Call.js +766 -0
  117. package/lib/module/Call.js.map +1 -0
  118. package/lib/module/CallInvite.js +450 -0
  119. package/lib/module/CallInvite.js.map +1 -0
  120. package/lib/module/CallMessage/CallMessage.js +51 -0
  121. package/lib/module/CallMessage/CallMessage.js.map +1 -0
  122. package/lib/module/CallMessage/IncomingCallMessage.js +116 -0
  123. package/lib/module/CallMessage/IncomingCallMessage.js.map +1 -0
  124. package/lib/module/CallMessage/OutgoingCallMessage.js +154 -0
  125. package/lib/module/CallMessage/OutgoingCallMessage.js.map +1 -0
  126. package/lib/module/ExpoModule.js +58 -0
  127. package/lib/module/ExpoModule.js.map +1 -0
  128. package/lib/module/Voice.js +598 -0
  129. package/lib/module/Voice.js.map +1 -0
  130. package/lib/module/common.js +11 -0
  131. package/lib/module/common.js.map +1 -0
  132. package/lib/module/constants.js +151 -0
  133. package/lib/module/constants.js.map +1 -0
  134. package/lib/module/error/InvalidArgumentError.js +23 -0
  135. package/lib/module/error/InvalidArgumentError.js.map +1 -0
  136. package/lib/module/error/InvalidStateError.js +24 -0
  137. package/lib/module/error/InvalidStateError.js.map +1 -0
  138. package/lib/module/error/TwilioError.js +29 -0
  139. package/lib/module/error/TwilioError.js.map +1 -0
  140. package/lib/module/error/UnsupportedPlatformError.js +24 -0
  141. package/lib/module/error/UnsupportedPlatformError.js.map +1 -0
  142. package/lib/module/error/generated.js +2315 -0
  143. package/lib/module/error/generated.js.map +1 -0
  144. package/lib/module/error/index.js +6 -0
  145. package/lib/module/error/index.js.map +1 -0
  146. package/lib/module/error/utility.js +27 -0
  147. package/lib/module/error/utility.js.map +1 -0
  148. package/lib/module/index.js +23 -0
  149. package/lib/module/index.js.map +1 -0
  150. package/lib/module/type/AudioDevice.js +2 -0
  151. package/lib/module/type/AudioDevice.js.map +1 -0
  152. package/lib/module/type/Call.js +2 -0
  153. package/lib/module/type/Call.js.map +1 -0
  154. package/lib/module/type/CallInvite.js +2 -0
  155. package/lib/module/type/CallInvite.js.map +1 -0
  156. package/lib/module/type/CallKit.js +22 -0
  157. package/lib/module/type/CallKit.js.map +1 -0
  158. package/lib/module/type/CallMessage.js +2 -0
  159. package/lib/module/type/CallMessage.js.map +1 -0
  160. package/lib/module/type/Error.js +2 -0
  161. package/lib/module/type/Error.js.map +1 -0
  162. package/lib/module/type/NativeModule.js +2 -0
  163. package/lib/module/type/NativeModule.js.map +1 -0
  164. package/lib/module/type/RTCStats.js +21 -0
  165. package/lib/module/type/RTCStats.js.map +1 -0
  166. package/lib/module/type/Voice.js +2 -0
  167. package/lib/module/type/Voice.js.map +1 -0
  168. package/lib/module/type/common.js +2 -0
  169. package/lib/module/type/common.js.map +1 -0
  170. package/lib/typescript/AudioDevice.d.ts +74 -0
  171. package/lib/typescript/Call.d.ts +874 -0
  172. package/lib/typescript/CallInvite.d.ts +484 -0
  173. package/lib/typescript/CallMessage/CallMessage.d.ts +53 -0
  174. package/lib/typescript/CallMessage/IncomingCallMessage.d.ts +75 -0
  175. package/lib/typescript/CallMessage/OutgoingCallMessage.d.ts +198 -0
  176. package/lib/typescript/ExpoModule.d.ts +13 -0
  177. package/lib/typescript/Voice.d.ts +620 -0
  178. package/lib/typescript/common.d.ts +11 -0
  179. package/lib/typescript/constants.d.ts +148 -0
  180. package/lib/typescript/error/InvalidArgumentError.d.ts +11 -0
  181. package/lib/typescript/error/InvalidStateError.d.ts +12 -0
  182. package/lib/typescript/error/TwilioError.d.ts +14 -0
  183. package/lib/typescript/error/UnsupportedPlatformError.d.ts +12 -0
  184. package/lib/typescript/error/generated.d.ts +1558 -0
  185. package/lib/typescript/error/index.d.ts +5 -0
  186. package/lib/typescript/error/utility.d.ts +12 -0
  187. package/lib/typescript/index.d.ts +18 -0
  188. package/lib/typescript/type/AudioDevice.d.ts +15 -0
  189. package/lib/typescript/type/Call.d.ts +59 -0
  190. package/lib/typescript/type/CallInvite.d.ts +40 -0
  191. package/lib/typescript/type/CallKit.d.ts +60 -0
  192. package/lib/typescript/type/CallMessage.d.ts +20 -0
  193. package/lib/typescript/type/Error.d.ts +9 -0
  194. package/lib/typescript/type/NativeModule.d.ts +59 -0
  195. package/lib/typescript/type/RTCStats.d.ts +91 -0
  196. package/lib/typescript/type/Voice.d.ts +16 -0
  197. package/lib/typescript/type/common.d.ts +15 -0
  198. package/package.json +167 -0
  199. package/src/AudioDevice.tsx +88 -0
  200. package/src/Call.tsx +1343 -0
  201. package/src/CallInvite.tsx +757 -0
  202. package/src/CallMessage/CallMessage.ts +83 -0
  203. package/src/CallMessage/IncomingCallMessage.ts +104 -0
  204. package/src/CallMessage/OutgoingCallMessage.ts +308 -0
  205. package/src/ExpoModule.ts +59 -0
  206. package/src/Voice.tsx +1010 -0
  207. package/src/common.ts +16 -0
  208. package/src/constants.ts +193 -0
  209. package/src/error/InvalidArgumentError.ts +19 -0
  210. package/src/error/InvalidStateError.ts +19 -0
  211. package/src/error/TwilioError.ts +22 -0
  212. package/src/error/UnsupportedPlatformError.ts +19 -0
  213. package/src/error/generated.ts +2277 -0
  214. package/src/error/index.ts +18 -0
  215. package/src/error/utility.ts +36 -0
  216. package/src/index.tsx +24 -0
  217. package/src/type/AudioDevice.ts +18 -0
  218. package/src/type/Call.ts +102 -0
  219. package/src/type/CallInvite.ts +59 -0
  220. package/src/type/CallKit.ts +61 -0
  221. package/src/type/CallMessage.ts +31 -0
  222. package/src/type/Error.ts +11 -0
  223. package/src/type/NativeModule.ts +93 -0
  224. package/src/type/RTCStats.ts +99 -0
  225. package/src/type/Voice.ts +31 -0
  226. package/src/type/common.ts +16 -0
  227. package/twilio-voice-react-native.podspec +22 -0
@@ -0,0 +1,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
+ }
@@ -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,5 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <bool name="twiliovoicereactnative_firebasemessagingservice_enabled">true</bool>
4
+ <bool name="twiliovoicereactnative_fullscreennotification_enabled">true</bool>
5
+ </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>