edoctor-sendbird-calls 1.0.0

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 (71) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +33 -0
  3. package/android/build.gradle +82 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +34 -0
  6. package/android/src/main/AndroidManifestNew.xml +2 -0
  7. package/android/src/main/java/com/edoctorsendbirdcalls/ComingCallActivity.java +41 -0
  8. package/android/src/main/java/com/edoctorsendbirdcalls/RNSendBirdCallsModule.java +2068 -0
  9. package/android/src/main/java/com/edoctorsendbirdcalls/RNSendBirdCallsPackage.java +32 -0
  10. package/android/src/main/java/com/edoctorsendbirdcalls/RNVSendBirdCallsVideo.java +10 -0
  11. package/android/src/main/java/com/edoctorsendbirdcalls/RNVSendBirdCallsVideoManager.java +77 -0
  12. package/android/src/main/java/com/edoctorsendbirdcalls/RNVideoViewGroup.java +109 -0
  13. package/android/src/main/java/com/edoctorsendbirdcalls/SharedUtils.java +127 -0
  14. package/android/src/main/java/com/edoctorsendbirdcalls/VcCallReceiver.java +37 -0
  15. package/android/src/main/java/com/edoctorsendbirdcalls/VcHeadlessService.java +23 -0
  16. package/android/src/main/java/com/edoctorsendbirdcalls/VoIPBaseService.java +100 -0
  17. package/android/src/main/java/com/edoctorsendbirdcalls/VoIPService.java +164 -0
  18. package/android/src/main/java/com/edoctorsendbirdcalls/XiaomiUtilities.java +75 -0
  19. package/android/src/main/res/drawable/bar_selector_white.xml +18 -0
  20. package/android/src/main/res/drawable/button_answer.xml +8 -0
  21. package/android/src/main/res/drawable/button_reject.xml +8 -0
  22. package/android/src/main/res/drawable/call_notification_line.xml +8 -0
  23. package/android/src/main/res/drawable/ic_answer.xml +5 -0
  24. package/android/src/main/res/drawable/ic_call_notification_answer.xml +6 -0
  25. package/android/src/main/res/drawable/ic_call_notification_decline.xml +9 -0
  26. package/android/src/main/res/drawable/ic_reject.xml +5 -0
  27. package/android/src/main/res/drawable/rn_edit_text_material.xml +36 -0
  28. package/android/src/main/res/layout/call_notification.xml +124 -0
  29. package/edoctor-sendbird-calls.podspec +27 -0
  30. package/ios/CXCallManager.swift +211 -0
  31. package/ios/CXProvider.swift +38 -0
  32. package/ios/Extensions/UIKit/UIColor.swift +30 -0
  33. package/ios/Extensions/UIKit/UIView+Extension.swift +61 -0
  34. package/ios/Extensions/UIKit/UIViewController.swift +28 -0
  35. package/ios/PrivacyInfo.xcprivacy +47 -0
  36. package/ios/RNSendBirdCalls-Bridging-Header.h +3 -0
  37. package/ios/RNSendBirdCalls.mm +94 -0
  38. package/ios/RNSendBirdCalls.swift +549 -0
  39. package/ios/RNSendBirdCallsHelper.swift +28 -0
  40. package/ios/RNVSendBirdCallsVideo.swift +55 -0
  41. package/ios/RNVSendBirdCallsVideoManager.mm +6 -0
  42. package/ios/RNVSendBirdCallsVideoManager.swift +15 -0
  43. package/ios/SendBirdCallsExtentions.swift +46 -0
  44. package/lib/module/SendBirdCalls.js +377 -0
  45. package/lib/module/SendBirdCalls.js.map +1 -0
  46. package/lib/module/SendBirdCallsEvents.js +108 -0
  47. package/lib/module/SendBirdCallsEvents.js.map +1 -0
  48. package/lib/module/SendBirdCallsVideo.js +33 -0
  49. package/lib/module/SendBirdCallsVideo.js.map +1 -0
  50. package/lib/module/index.js +14 -0
  51. package/lib/module/index.js.map +1 -0
  52. package/lib/module/index.type.js +2 -0
  53. package/lib/module/index.type.js.map +1 -0
  54. package/lib/module/package.json +1 -0
  55. package/lib/typescript/package.json +1 -0
  56. package/lib/typescript/src/SendBirdCalls.d.ts +63 -0
  57. package/lib/typescript/src/SendBirdCalls.d.ts.map +1 -0
  58. package/lib/typescript/src/SendBirdCallsEvents.d.ts +36 -0
  59. package/lib/typescript/src/SendBirdCallsEvents.d.ts.map +1 -0
  60. package/lib/typescript/src/SendBirdCallsVideo.d.ts +18 -0
  61. package/lib/typescript/src/SendBirdCallsVideo.d.ts.map +1 -0
  62. package/lib/typescript/src/index.d.ts +5 -0
  63. package/lib/typescript/src/index.d.ts.map +1 -0
  64. package/lib/typescript/src/index.type.d.ts +14 -0
  65. package/lib/typescript/src/index.type.d.ts.map +1 -0
  66. package/package.json +154 -0
  67. package/src/SendBirdCalls.ts +472 -0
  68. package/src/SendBirdCallsEvents.ts +141 -0
  69. package/src/SendBirdCallsVideo.tsx +44 -0
  70. package/src/index.tsx +11 -0
  71. package/src/index.type.ts +20 -0
@@ -0,0 +1,2068 @@
1
+ // // RNSendBirdCallsModule.java
2
+
3
+ // package com.rnsendbirdcalls;
4
+
5
+ // import android.annotation.SuppressLint;
6
+ // import android.content.Context;
7
+ // import android.content.Intent;
8
+ // import android.content.SharedPreferences;
9
+ // import android.os.Build;
10
+ // import android.os.Bundle;
11
+ // import android.os.Environment;
12
+ // import android.util.Log;
13
+
14
+ // import androidx.annotation.NonNull;
15
+ // import androidx.annotation.Nullable;
16
+
17
+ // import com.facebook.react.bridge.Arguments;
18
+ // import com.facebook.react.bridge.Promise;
19
+ // import com.facebook.react.bridge.ReactApplicationContext;
20
+ // import com.facebook.react.bridge.ReactContext;
21
+ // import com.facebook.react.bridge.ReactContextBaseJavaModule;
22
+ // import com.facebook.react.bridge.ReactMethod;
23
+ // import com.facebook.react.bridge.ReadableMap;
24
+ // import com.facebook.react.bridge.WritableArray;
25
+ // import com.facebook.react.bridge.WritableMap;
26
+ // import com.facebook.react.modules.core.DeviceEventManagerModule;
27
+ // import com.sendbird.calls.AcceptParams;
28
+ // import com.sendbird.calls.AuthenticateParams;
29
+ // import com.sendbird.calls.CallOptions;
30
+ // import com.sendbird.calls.DialParams;
31
+ // import com.sendbird.calls.DirectCall;
32
+ // import com.sendbird.calls.DirectCallUser;
33
+ // import com.sendbird.calls.RecordingOptions;
34
+ // import com.sendbird.calls.SendBirdCall;
35
+ // import com.sendbird.calls.SendBirdException;
36
+ // import com.sendbird.calls.handler.DirectCallListener;
37
+ // import com.sendbird.calls.handler.RecordingListener;
38
+ // import com.sendbird.calls.handler.SendBirdCallListener;
39
+
40
+ // import org.jetbrains.annotations.NotNull;
41
+
42
+ // import java.io.File;
43
+ // import java.util.ArrayList;
44
+ // import java.util.Arrays;
45
+ // import java.util.HashMap;
46
+ // import java.util.List;
47
+ // import java.util.Map;
48
+ // import java.util.Objects;
49
+ // import java.util.UUID;
50
+
51
+ // public class RNSendBirdCallsModule extends ReactContextBaseJavaModule {
52
+
53
+ // private static ReactApplicationContext mContext;
54
+ // private static String TAG = "RNSendBirdCalls";
55
+
56
+ // static Boolean IS_CALL_ACCEPTED = false;
57
+ // static Boolean IS_CALL_CONNECTED = false;
58
+ // private static Boolean IS_INITIAL = false;
59
+ // private static Boolean IS_SEND_EVENT_RINGING = false;
60
+ // private static ArrayList<String> JS_EVENTS = new ArrayList<String>();
61
+ // private static ArrayList<String> EVENTS = new ArrayList<String>(
62
+ // Arrays.asList(
63
+ // "onRinging",
64
+ // "onCallDidAccept",
65
+ // "onConnected",
66
+ // "onEnded",
67
+ // "onReconnected",
68
+ // "onReconnecting",
69
+ // "onRemoteAudioSettingsChanged",
70
+ // "onRemoteVideoSettingsChanged",
71
+ // "onRecordingSucceeded",
72
+ // "onRecordingFailed"
73
+ // )
74
+ // );
75
+
76
+ // static DirectCall CALL_ACTIVE = null;
77
+
78
+ // public RNSendBirdCallsModule(ReactApplicationContext reactContext) {
79
+ // super(reactContext);
80
+ // this.mContext = reactContext;
81
+ // }
82
+
83
+ // @Override
84
+ // public String getName() {
85
+ // return TAG;
86
+ // }
87
+
88
+ // private static WritableMap getParamDirectCall(@NotNull DirectCall directCall) {
89
+ // WritableMap params = Arguments.createMap();
90
+
91
+ // WritableMap callerMap = Arguments.createMap();
92
+ // WritableMap calleeMap = Arguments.createMap();
93
+ // WritableMap customItems = Arguments.createMap();
94
+
95
+ // if (directCall.getCustomItems().get("appointmentScheduleId") != null) {
96
+ // customItems.putString("appointmentScheduleId", directCall.getCustomItems().get("appointmentScheduleId"));
97
+ // }
98
+
99
+ // if (directCall.getCustomItems().get("eClinicId") != null) {
100
+ // customItems.putString("eClinicId", directCall.getCustomItems().get("eClinicId"));
101
+ // }
102
+
103
+ // DirectCallUser caller = directCall.getCaller();
104
+ // if (caller.getUserId() != null) callerMap.putString("userId", caller.getUserId());
105
+ // if (caller.getNickname() != null) callerMap.putString("nickname", caller.getNickname());
106
+ // if (caller.getProfileUrl() != null) callerMap.putString("profileUrl", caller.getProfileUrl());
107
+
108
+ // DirectCallUser callee = directCall.getCallee();
109
+ // if (callee.getUserId() != null) calleeMap.putString("userId", callee.getUserId());
110
+ // if (callee.getNickname() != null) calleeMap.putString("nickname", callee.getNickname());
111
+ // if (callee.getProfileUrl() != null) calleeMap.putString("profileUrl", callee.getProfileUrl());
112
+
113
+ // params.putMap("callee", calleeMap);
114
+ // params.putMap("caller", callerMap);
115
+ // params.putMap("customItems", customItems);
116
+
117
+ // String callId = directCall.getCallId();
118
+ // if (callId != null) params.putString("callId", callId);
119
+ // else params.putString("callId", "");
120
+
121
+ // float duration = directCall.getDuration();
122
+ // if (duration > 0) params.putDouble("duration", directCall.getDuration());
123
+ // else params.putDouble("duration", 0);
124
+
125
+ // Boolean isVideoCall = directCall.isVideoCall();
126
+ // Boolean isRemoteAudioEnabled = directCall.isRemoteAudioEnabled();
127
+ // Boolean isLocalAudioEnabled = directCall.isLocalAudioEnabled();
128
+
129
+ // Boolean isRemoteVideoEnabled = directCall.isRemoteVideoEnabled();
130
+ // Boolean isLocalVideoEnabled = directCall.isLocalVideoEnabled();
131
+
132
+ // if (isVideoCall != null) params.putBoolean("isVideoCall", isVideoCall);
133
+ // if (isRemoteAudioEnabled != null)
134
+ // params.putBoolean("isRemoteAudioEnabled", isRemoteAudioEnabled);
135
+ // if (isLocalAudioEnabled != null) params.putBoolean("isLocalAudioEnabled", isLocalAudioEnabled);
136
+ // if (isRemoteVideoEnabled != null)
137
+ // params.putBoolean("isRemoteVideoEnabled", isRemoteVideoEnabled);
138
+ // if (isLocalVideoEnabled != null) params.putBoolean("isLocalVideoEnabled", isLocalVideoEnabled);
139
+
140
+ // return params;
141
+ // }
142
+
143
+ // @SuppressLint("WrongConstant")
144
+ // public static void configureInNative(Context appContext, String appId) {
145
+ // Log.w(TAG, "SendBirdCall initial");
146
+ // if (IS_INITIAL) {
147
+ // Log.w(TAG, "SendBirdCall is initial ready");
148
+ // return;
149
+ // }
150
+
151
+ // if (SendBirdCall.init(appContext, appId)) {
152
+ // Log.d(TAG, "configureInNative: SUCCESS");
153
+ // SendBirdCall.removeAllListeners();
154
+ // SendBirdCall.removeAllRecordingListeners();
155
+ // String UNIQUE_HANDLER_ID = UUID.randomUUID().toString();
156
+ // SendBirdCall.addListener(UNIQUE_HANDLER_ID, new SendBirdCallListener() {
157
+ // @Override
158
+ // public void onRinging(@NotNull DirectCall call) {
159
+ // Log.i(TAG, "onRinging");
160
+
161
+ // int ongoingCallCount = SendBirdCall.getOngoingCallCount();
162
+ // if (ongoingCallCount >= 2) {
163
+ // call.end();
164
+ // return;
165
+ // }
166
+
167
+ // handleListenerSendBirdCall(call);
168
+ // if (JS_EVENTS.contains("onRinging")) {
169
+ // sendEvent(mContext, "onRinging", call);
170
+ // IS_SEND_EVENT_RINGING = true;
171
+ // }
172
+
173
+ // }
174
+ // });
175
+ // String UNIQUE_ID = UUID.randomUUID().toString();
176
+
177
+ // SendBirdCall.addRecordingListener(UNIQUE_ID, new RecordingListener() {
178
+ // @Override
179
+ // public void onRecordingSucceeded(@NotNull DirectCall directCall, @NotNull String recorderId, @NotNull RecordingOptions recordingOptions, @NotNull String outputFilePath) {
180
+ // if (!EVENTS.contains("onRecordingSucceeded")) return;
181
+ // WritableMap params = Arguments.createMap();
182
+ // params.putString("outputFilePath", outputFilePath);
183
+ // mContext
184
+ // .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
185
+ // .emit("onRecordingSucceeded", params);
186
+ // }
187
+
188
+ // @Override
189
+ // public void onRecordingFailed(@NotNull DirectCall directCall, @NotNull String recorderId, @NotNull SendBirdException e) {
190
+ // if (!EVENTS.contains("onRecordingFailed")) return;
191
+ // WritableMap params = Arguments.createMap();
192
+ // params.putString("errorCode", String.valueOf(e.getCode()));
193
+ // params.putString("errorMessage", String.valueOf(e.getMessage()));
194
+ // mContext
195
+ // .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
196
+ // .emit("onRecordingFailed", params);
197
+ // }
198
+ // });
199
+
200
+ // int ringing = appContext.getResources().getIdentifier("ringing", "raw", appContext.getPackageName());
201
+ // int connecting = appContext.getResources().getIdentifier("connecting", "raw", appContext.getPackageName());
202
+ // int connected = appContext.getResources().getIdentifier("connected", "raw", appContext.getPackageName());
203
+ // setUpSoundEffects(
204
+ // ringing,
205
+ // connecting,
206
+ // connected,
207
+ // connected
208
+ // );
209
+ // IS_INITIAL = true;
210
+ // }
211
+ // }
212
+
213
+ // @ReactMethod
214
+ // public void initSendBird(String appId, Promise promise) {
215
+ // IS_INITIAL = false;
216
+ // Context appContext = mContext.getApplicationContext();
217
+ // WritableMap result = Arguments.createMap();
218
+ // if (SendBirdCall.init(appContext, appId)) {
219
+ // Log.d(TAG, "configureInNative: SUCCESS");
220
+ // SendBirdCall.removeAllListeners();
221
+ // SendBirdCall.removeAllRecordingListeners();
222
+ // String UNIQUE_HANDLER_ID = UUID.randomUUID().toString();
223
+ // SendBirdCall.addListener(UNIQUE_HANDLER_ID, new SendBirdCallListener() {
224
+ // @Override
225
+ // public void onRinging(@NotNull DirectCall call) {
226
+ // Log.i(TAG, "onRinging");
227
+
228
+ // int ongoingCallCount = SendBirdCall.getOngoingCallCount();
229
+ // if (ongoingCallCount >= 2) {
230
+ // call.end();
231
+ // return;
232
+ // }
233
+
234
+ // handleListenerSendBirdCall(call);
235
+ // if (JS_EVENTS.contains("onRinging")) {
236
+ // sendEvent(mContext, "onRinging", call);
237
+ // IS_SEND_EVENT_RINGING = true;
238
+ // }
239
+
240
+ // }
241
+ // });
242
+ // String UNIQUE_ID = UUID.randomUUID().toString();
243
+
244
+ // SendBirdCall.addRecordingListener(UNIQUE_ID, new RecordingListener() {
245
+ // @Override
246
+ // public void onRecordingSucceeded(@NotNull DirectCall directCall, @NotNull String recorderId, @NotNull RecordingOptions recordingOptions, @NotNull String outputFilePath) {
247
+ // if (!EVENTS.contains("onRecordingSucceeded")) return;
248
+ // WritableMap params = Arguments.createMap();
249
+ // params.putString("outputFilePath", outputFilePath);
250
+ // mContext
251
+ // .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
252
+ // .emit("onRecordingSucceeded", params);
253
+ // }
254
+
255
+ // @Override
256
+ // public void onRecordingFailed(@NotNull DirectCall directCall, @NotNull String recorderId, @NotNull SendBirdException e) {
257
+ // if (!EVENTS.contains("onRecordingFailed")) return;
258
+ // WritableMap params = Arguments.createMap();
259
+ // params.putString("errorCode", String.valueOf(e.getCode()));
260
+ // params.putString("errorMessage", String.valueOf(e.getMessage()));
261
+ // mContext
262
+ // .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
263
+ // .emit("onRecordingFailed", params);
264
+ // }
265
+ // });
266
+
267
+ // int ringing = appContext.getResources().getIdentifier("ringing", "raw", appContext.getPackageName());
268
+ // int connecting = appContext.getResources().getIdentifier("connecting", "raw", appContext.getPackageName());
269
+ // int connected = appContext.getResources().getIdentifier("connected", "raw", appContext.getPackageName());
270
+ // setUpSoundEffects(
271
+ // ringing,
272
+ // connecting,
273
+ // connected,
274
+ // connected
275
+ // );
276
+ // IS_INITIAL = true;
277
+ // result.putBoolean("succeeded", true);
278
+ // } else {
279
+ // result.putBoolean("succeeded", false);
280
+ // }
281
+ // promise.resolve(result);
282
+ // }
283
+
284
+ // @ReactMethod
285
+ // public void authenticate(String userId, String accessToken, Promise promise) {
286
+ // try {
287
+ // AuthenticateParams params = new AuthenticateParams(userId).setAccessToken(accessToken);
288
+ // SendBirdCall.authenticate(params, (user, e) -> {
289
+ // WritableMap result = Arguments.createMap();
290
+ // if (e == null) {
291
+ // // The user has been authenticated successfully and is connected to Sendbird server
292
+ // result.putBoolean("succeeded", true);
293
+ // result.putString("userId", user.getUserId());
294
+ // result.putString("nickname", user.getNickname());
295
+ // Log.d(TAG, "authenticate: " + user.getNickname());
296
+ // } else {
297
+ // result.putBoolean("succeeded", false);
298
+ // result.putString("errorCode", String.valueOf(e.getCode()));
299
+ // result.putString("errorMessage", e.getMessage());
300
+ // Log.d(TAG, "authenticate: " + e.getMessage());
301
+ // }
302
+ // promise.resolve(result);
303
+ // });
304
+ // } catch (Exception e) {
305
+ // WritableMap result = Arguments.createMap();
306
+ // result.putBoolean("succeeded", false);
307
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
308
+ // promise.resolve(result);
309
+ // }
310
+ // }
311
+
312
+ // @ReactMethod
313
+ // public void deAuthenticate(Promise promise) {
314
+ // SendBirdCall.deauthenticate(e -> {
315
+ // Log.d(TAG, "deAuthen");
316
+ // WritableMap result = Arguments.createMap();
317
+ // if (e == null) {
318
+ // result.putBoolean("succeeded", true);
319
+ // } else {
320
+ // result.putBoolean("succeeded", false);
321
+ // result.putString("errorCode", String.valueOf(e.getCode()));
322
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
323
+ // }
324
+ // promise.resolve(result);
325
+ // });
326
+ // }
327
+
328
+ // @ReactMethod
329
+ // public void shareStorage(String appId) {
330
+ // if (appId.isEmpty()) {
331
+ // return;
332
+ // }
333
+ // SharedPreferences shareReference = mContext.getApplicationContext().getSharedPreferences("EDOCTOR_NATIVE", Context.MODE_PRIVATE);
334
+ // SharedPreferences.Editor editor = shareReference.edit();
335
+ // editor.putString("ANDROID_APP_ID", appId);
336
+ // editor.apply();
337
+ // }
338
+
339
+ // public static String getAppId(Context context) {
340
+ // SharedPreferences shareReference = context.getSharedPreferences("EDOCTOR_NATIVE", Context.MODE_PRIVATE);
341
+ // return shareReference.getString("ANDROID_APP_ID", "");
342
+ // }
343
+
344
+ // @ReactMethod
345
+ // public void getCall(String callId, Promise promise) {
346
+ // DirectCall mdirectCall = SendBirdCall.getCall(callId);
347
+ // if (mdirectCall != null) {
348
+ // WritableMap callInfo = getParamDirectCall(mdirectCall);
349
+ // callInfo.putBoolean("succeeded", true);
350
+ // promise.resolve(callInfo);
351
+ // } else {
352
+ // WritableMap result = Arguments.createMap();
353
+ // result.putBoolean("succeeded", false);
354
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
355
+ // promise.resolve(result);
356
+ // }
357
+ // }
358
+
359
+ // @ReactMethod
360
+ // public void registerPushToken(String token, Promise promise) {
361
+ // if (SendBirdCall.getCurrentUser() != null) {
362
+ // SendBirdCall.registerPushToken(token, false, e -> {
363
+ // if (e != null) {
364
+ // Log.i("RNSendBirdCalls", "registerPushToken => e: " + e.getMessage());
365
+ // WritableMap result = Arguments.createMap();
366
+ // result.putBoolean("succeeded", false);
367
+ // result.putString("errorCode", String.valueOf(e.getCode()));
368
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
369
+ // promise.resolve(result);
370
+ // } else {
371
+ // WritableMap result = Arguments.createMap();
372
+ // result.putBoolean("succeeded", true);
373
+ // promise.resolve(result);
374
+ // }
375
+ // });
376
+ // }
377
+ // }
378
+
379
+ // @ReactMethod
380
+ // public void unregisterPushToken(String token, Promise promise) {
381
+ // if (SendBirdCall.getCurrentUser() != null) {
382
+ // SendBirdCall.unregisterPushToken(token, e -> {
383
+ // WritableMap result = Arguments.createMap();
384
+ // if (e == null) {
385
+ // result.putBoolean("succeeded", true);
386
+ // } else {
387
+ // result.putBoolean("succeeded", false);
388
+ // result.putString("errorCode", String.valueOf(e.getCode()));
389
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
390
+ // }
391
+ // promise.resolve(result);
392
+ // });
393
+ // } else {
394
+ // WritableMap result = Arguments.createMap();
395
+ // result.putBoolean("succeeded", false);
396
+ // promise.resolve(result);
397
+ // }
398
+ // }
399
+
400
+ // @ReactMethod
401
+ // public void startRecording(String fileName, boolean isRemote, Promise promise) {
402
+ // try {
403
+ // File myDir = new File(mContext.getApplicationContext().getFilesDir().getAbsolutePath() + "/records");
404
+ // if (!myDir.exists()) {
405
+ // myDir.mkdirs();
406
+ // }
407
+ // RecordingOptions options;
408
+ // if (isRemote) {
409
+ // options = new RecordingOptions(RecordingOptions.RecordingType.LOCAL_AUDIO_REMOTE_AUDIO_AND_VIDEO, myDir.getAbsolutePath(), fileName);
410
+ // } else {
411
+ // options = new RecordingOptions(RecordingOptions.RecordingType.LOCAL_AUDIO_AND_VIDEO_REMOTE_AUDIO, myDir.getAbsolutePath(), fileName);
412
+ // }
413
+ // CALL_ACTIVE.startRecording(options, (recordingId, e) -> {
414
+ // WritableMap result = Arguments.createMap();
415
+ // if (e == null) {
416
+ // result.putBoolean("succeeded", true);
417
+ // result.putString("recordingId", recordingId);
418
+ // Log.d(TAG, "recordingId: " + recordingId);
419
+ // } else {
420
+ // result.putBoolean("succeeded", false);
421
+ // result.putString("errorCode", String.valueOf(e.getCode()));
422
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
423
+ // Log.d(TAG, "errorMessage: " + String.valueOf(e.getMessage()));
424
+
425
+ // }
426
+
427
+ // promise.resolve(result);
428
+ // });
429
+ // } catch (Exception e) {
430
+ // WritableMap result = Arguments.createMap();
431
+ // result.putBoolean("succeeded", false);
432
+ // result.putString("errorMessage", e.getMessage());
433
+ // promise.resolve(result);
434
+ // }
435
+ // }
436
+
437
+ // @ReactMethod
438
+ // public void stopRecording(String recordingId, Promise promise) {
439
+ // Log.d(TAG, "stopRecording: " + recordingId);
440
+ // if (CALL_ACTIVE == null) {
441
+ // WritableMap result = Arguments.createMap();
442
+ // result.putBoolean("succeeded", false);
443
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
444
+ // promise.resolve(result);
445
+ // }
446
+ // boolean succeeded = CALL_ACTIVE.stopRecording(recordingId);
447
+ // WritableMap result = Arguments.createMap();
448
+ // result.putBoolean("succeeded", succeeded);
449
+ // promise.resolve(result);
450
+ // }
451
+
452
+ // @ReactMethod
453
+ // public void dial(String calleeId, boolean isVideoCall, boolean isVideoEnable, boolean isAudioEnable, String appointmentScheduleId, String eClinicId, Promise promise) {
454
+ // Log.d(TAG, "dial");
455
+
456
+ // int ongoingCallCount = SendBirdCall.getOngoingCallCount();
457
+ // if (ongoingCallCount > 0) {
458
+ // return;
459
+ // }
460
+
461
+ // CallOptions callOptions = new CallOptions().setVideoEnabled(isVideoEnable).setAudioEnabled(isAudioEnable);
462
+ // Map<String, String> customItems = new HashMap<>();
463
+ // customItems.put("appointmentScheduleId", appointmentScheduleId);
464
+ // customItems.put("eClinicId", eClinicId);
465
+
466
+ // DialParams dialParams = new DialParams(calleeId);
467
+ // dialParams.setVideoCall(isVideoCall);
468
+ // dialParams.setCallOptions(callOptions);
469
+ // dialParams.setCustomItems(customItems);
470
+
471
+ // DirectCall mDirectCall = SendBirdCall.dial(dialParams, (call, e) -> {
472
+ // if (e != null) {
473
+ // Log.d(TAG, "dial: " + e.getMessage());
474
+ // WritableMap result = Arguments.createMap();
475
+ // result.putBoolean("succeeded", false);
476
+ // result.putString("errorCode", String.valueOf(e.getCode()));
477
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
478
+ // promise.resolve(result);
479
+ // return;
480
+ // }
481
+ // WritableMap params = Arguments.createMap();
482
+ // params.putBoolean("succeeded", true);
483
+ // params.putString("callId", call.getCallId());
484
+ // params.putString("caller", call.getCaller().getUserId());
485
+ // params.putString("callee", call.getCallee().getUserId());
486
+ // promise.resolve(params);
487
+ // });
488
+
489
+ // if (mDirectCall != null) {
490
+ // handleListenerSendBirdCall(mDirectCall);
491
+ // }
492
+ // }
493
+
494
+ // @ReactMethod
495
+ // public void muteMicrophone(Promise promise) {
496
+ // Log.i(TAG, "muteMicrophone");
497
+ // if (CALL_ACTIVE == null) {
498
+ // WritableMap result = Arguments.createMap();
499
+ // result.putBoolean("succeeded", false);
500
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
501
+ // promise.resolve(result);
502
+ // }
503
+ // ;
504
+ // boolean succeeded = CALL_ACTIVE.muteMicrophone();
505
+ // WritableMap result = Arguments.createMap();
506
+ // result.putBoolean("succeeded", succeeded);
507
+ // promise.resolve(result);
508
+ // }
509
+
510
+ // @ReactMethod
511
+ // public void unmuteMicrophone(Promise promise) {
512
+ // Log.i(TAG, "unmuteMicrophone");
513
+ // if (CALL_ACTIVE == null) {
514
+ // WritableMap result = Arguments.createMap();
515
+ // result.putBoolean("succeeded", false);
516
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
517
+ // promise.resolve(result);
518
+ // }
519
+ // ;
520
+ // boolean succeeded = CALL_ACTIVE.unmuteMicrophone();
521
+ // WritableMap result = Arguments.createMap();
522
+ // result.putBoolean("succeeded", succeeded);
523
+ // promise.resolve(result);
524
+ // }
525
+
526
+ // @ReactMethod
527
+ // public void startVideo(Promise promise) {
528
+ // Log.i(TAG, "startVideo");
529
+ // if (CALL_ACTIVE == null) {
530
+ // WritableMap result = Arguments.createMap();
531
+ // result.putBoolean("succeeded", false);
532
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
533
+ // promise.resolve(result);
534
+ // }
535
+ // ;
536
+ // try {
537
+ // CALL_ACTIVE.startVideo();
538
+ // WritableMap result = Arguments.createMap();
539
+ // result.putBoolean("succeeded", true);
540
+ // promise.resolve(result);
541
+ // } catch (Exception e) {
542
+ // WritableMap result = Arguments.createMap();
543
+ // result.putBoolean("succeeded", false);
544
+ // result.putString("errorMessage", e.getMessage());
545
+ // promise.resolve(result);
546
+ // }
547
+ // }
548
+
549
+ // @ReactMethod
550
+ // public void stopVideo(Promise promise) {
551
+ // Log.i(TAG, "stopVideo");
552
+ // if (CALL_ACTIVE == null) {
553
+ // WritableMap result = Arguments.createMap();
554
+ // result.putBoolean("succeeded", false);
555
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
556
+ // promise.resolve(result);
557
+ // }
558
+ // ;
559
+ // try {
560
+ // CALL_ACTIVE.stopVideo();
561
+ // WritableMap result = Arguments.createMap();
562
+ // result.putBoolean("succeeded", true);
563
+ // promise.resolve(result);
564
+ // } catch (Exception e) {
565
+ // WritableMap result = Arguments.createMap();
566
+ // result.putBoolean("succeeded", false);
567
+ // result.putString("errorMessage", e.getMessage());
568
+ // promise.resolve(result);
569
+ // }
570
+ // }
571
+
572
+ // @ReactMethod
573
+ // public void switchCamera(Promise promise) {
574
+ // Log.i(TAG, "switchCamera");
575
+ // if (CALL_ACTIVE == null) {
576
+ // WritableMap result = Arguments.createMap();
577
+ // result.putBoolean("succeeded", false);
578
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
579
+ // promise.resolve(result);
580
+ // }
581
+ // ;
582
+ // CALL_ACTIVE.switchCamera(e -> {
583
+ // WritableMap result = Arguments.createMap();
584
+ // if (e != null) {
585
+ // result.putBoolean("succeeded", false);
586
+ // result.putString("errorCode", String.valueOf(e.getCode()));
587
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
588
+ // } else {
589
+ // result.putBoolean("succeeded", true);
590
+ // }
591
+ // promise.resolve(result);
592
+ // });
593
+ // }
594
+
595
+ // @ReactMethod
596
+ // public void endCall(Promise promise) {
597
+ // Log.i(TAG, "endCall");
598
+ // if (CALL_ACTIVE != null) {
599
+ // IS_CALL_ACCEPTED = false;
600
+ // IS_CALL_CONNECTED = false;
601
+ // WritableMap params = Arguments.createMap();
602
+ // params.putString("callId", CALL_ACTIVE.getCallId());
603
+ // params.putString("caller", CALL_ACTIVE.getCaller().getUserId());
604
+ // params.putString("callee", CALL_ACTIVE.getCallee().getUserId());
605
+ // params.putString("duration", String.valueOf(CALL_ACTIVE.getDuration()));
606
+ // try {
607
+ // CALL_ACTIVE.end();
608
+ // promise.resolve(params);
609
+ // } catch (Exception e) {
610
+ // WritableMap result = Arguments.createMap();
611
+ // result.putBoolean("succeeded", false);
612
+ // result.putString("errorMessage", e.getMessage());
613
+ // promise.resolve(result);
614
+ // }
615
+ // } else {
616
+ // WritableMap result = Arguments.createMap();
617
+ // result.putBoolean("succeeded", false);
618
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
619
+ // promise.resolve(result);
620
+ // }
621
+ // }
622
+
623
+ // @ReactMethod
624
+ // public void acceptCall(String callId, boolean isVideoEnable, boolean isAudioEnable, Promise promise) {
625
+ // Log.i(TAG, "acceptCall");
626
+ // try {
627
+ // DirectCall mDirectCall = SendBirdCall.getCall(callId);
628
+ // if (mDirectCall != null) {
629
+ // handleListenerSendBirdCall(mDirectCall);
630
+ // CallOptions callOptions = new CallOptions().setVideoEnabled(isVideoEnable).setAudioEnabled(isAudioEnable);
631
+ // mDirectCall.accept(new AcceptParams().setCallOptions(callOptions));
632
+ // IS_CALL_ACCEPTED = true;
633
+ // WritableMap result = Arguments.createMap();
634
+ // result.putBoolean("succeeded", true);
635
+ // promise.resolve(result);
636
+ // }
637
+ // } catch (Exception e) {
638
+ // WritableMap result = Arguments.createMap();
639
+ // result.putBoolean("succeeded", false);
640
+ // result.putString("errorMessage", "Cuộc gọi không tồn tại");
641
+ // promise.resolve(result);
642
+ // }
643
+ // }
644
+
645
+ // @ReactMethod
646
+ // public void endIncomingCallNeedAuthentication(String callId, Promise promise) {
647
+ // Log.i(TAG, "endIncomingCallNeedAuthentication");
648
+ // try {
649
+ // DirectCall mDirectCall = SendBirdCall.getCall(callId);
650
+ // DirectCallUser callee = mDirectCall.getCallee();
651
+ // AuthenticateParams params = new AuthenticateParams(callee.getUserId());
652
+ // SendBirdCall.authenticate(params, (user, e) -> {
653
+ // if (e == null) {
654
+ // if (mDirectCall != null) {
655
+ // mDirectCall.end();
656
+ // IS_CALL_ACCEPTED = false;
657
+ // IS_CALL_CONNECTED = false;
658
+ // WritableMap result = Arguments.createMap();
659
+ // result.putBoolean("succeeded", true);
660
+ // promise.resolve(result);
661
+ // }
662
+ // } else {
663
+ // WritableMap result = Arguments.createMap();
664
+ // result.putBoolean("succeeded", false);
665
+ // result.putString("errorCode", String.valueOf(e.getCode()));
666
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
667
+ // promise.resolve(result);
668
+ // }
669
+ // });
670
+ // } catch (Exception e) {
671
+ // WritableMap result = Arguments.createMap();
672
+ // result.putBoolean("succeeded", false);
673
+ // result.putString("errorMessage", e.getMessage());
674
+ // promise.resolve(result);
675
+ // }
676
+ // }
677
+
678
+ // @ReactMethod
679
+ // public void acceptIncomingCallNeedAuthentication(String callId, boolean isVideoEnable, boolean isAudioEnable, Promise promise) {
680
+ // Log.i(TAG, "acceptIncomingCallNeedAuthentication");
681
+ // try {
682
+ // DirectCall mDirectCall = SendBirdCall.getCall(callId);
683
+ // DirectCallUser callee = mDirectCall.getCallee();
684
+ // AuthenticateParams params = new AuthenticateParams(callee.getUserId());
685
+ // SendBirdCall.authenticate(params, (user, e) -> {
686
+ // if (e == null) {
687
+ // if (mDirectCall != null) {
688
+ // handleListenerSendBirdCall(mDirectCall);
689
+ // CallOptions callOptions = new CallOptions().setVideoEnabled(isVideoEnable).setAudioEnabled(isAudioEnable);
690
+ // mDirectCall.accept(new AcceptParams().setCallOptions(callOptions));
691
+ // IS_CALL_ACCEPTED = true;
692
+ // WritableMap result = Arguments.createMap();
693
+ // result.putBoolean("succeeded", true);
694
+ // promise.resolve(result);
695
+ // }
696
+ // } else {
697
+ // WritableMap result = Arguments.createMap();
698
+ // result.putBoolean("succeeded", false);
699
+ // result.putString("errorCode", String.valueOf(e.getCode()));
700
+ // result.putString("errorMessage", String.valueOf(e.getMessage()));
701
+ // promise.resolve(result);
702
+ // }
703
+ // });
704
+ // } catch (Exception e) {
705
+ // WritableMap result = Arguments.createMap();
706
+ // result.putBoolean("succeeded", false);
707
+ // result.putString("errorMessage", e.getMessage());
708
+ // promise.resolve(result);
709
+ // }
710
+ // }
711
+
712
+ // @ReactMethod
713
+ // public void getOngoingCalls(Promise promise) {
714
+ // List<DirectCall> directCall = SendBirdCall.getOngoingCalls();
715
+ // WritableArray resultData = Arguments.createArray();
716
+ // if (directCall != null && directCall.isEmpty() == false) {
717
+ // for (int i = 0; i < directCall.size(); i++) {
718
+ // WritableMap item = getParamDirectCall(directCall.get(i));
719
+ // if (item != null) {
720
+ // resultData.pushMap(item);
721
+ // }
722
+ // }
723
+ // promise.resolve(resultData);
724
+ // } else {
725
+ // promise.resolve(null);
726
+ // }
727
+ // }
728
+
729
+ // @ReactMethod
730
+ // public void getCallInfo(Promise promise) {
731
+ // if (CALL_ACTIVE == null) {
732
+ // promise.resolve(null);
733
+ // } else {
734
+ // DirectCall mdirectCall = SendBirdCall.getCall(CALL_ACTIVE.getCallId());
735
+ // if (mdirectCall == null) promise.resolve(null);
736
+ // else {
737
+ // Log.d(TAG, "getCallInfo: " + mdirectCall);
738
+ // DirectCallUser callee = mdirectCall.getCallee();
739
+ // DirectCallUser caller = mdirectCall.getCaller();
740
+ // }
741
+ // }
742
+ // }
743
+
744
+ // @ReactMethod
745
+ // public void wakeAppIncomingCall(ReadableMap params) {
746
+ // Log.d(TAG, "wakeAppIncomingCall: ");
747
+ // Bundle bundle = Arguments.toBundle(params);
748
+ // Intent intent = new Intent(mContext.getApplicationContext(), VoIPService.class);
749
+ // intent.putExtras(bundle);
750
+ // if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
751
+ // mContext.getApplicationContext().startForegroundService(intent);
752
+ // } else {
753
+ // mContext.getApplicationContext().startService(intent);
754
+ // }
755
+ // }
756
+
757
+ // @ReactMethod
758
+ // public void navigateMainApp(ReadableMap params) {
759
+ // Log.d(TAG, "navigateMainApp: ");
760
+ // Bundle bundle = Arguments.toBundle(params);
761
+ // SharedUtils.navigateMainApp(mContext.getApplicationContext(), bundle);
762
+ // }
763
+
764
+ // @ReactMethod
765
+ // public void finishLockedScreenUI() {
766
+ // Objects.requireNonNull(mContext.getCurrentActivity()).finish();
767
+ // }
768
+
769
+ // @ReactMethod
770
+ // public void getDeviceLocked(Promise promise) {
771
+ // try {
772
+ // boolean isLocked = SharedUtils.getDeviceLocked(mContext.getApplicationContext());
773
+ // WritableMap result = Arguments.createMap();
774
+ // result.putBoolean("succeeded", true);
775
+ // result.putBoolean("isLocked", isLocked);
776
+ // promise.resolve(result);
777
+ // } catch (RuntimeException e) {
778
+ // WritableMap result = Arguments.createMap();
779
+ // result.putBoolean("succeeded", false);
780
+ // result.putString("errorMessage", e.getMessage());
781
+ // promise.resolve(result);
782
+ // }
783
+ // }
784
+
785
+ // @ReactMethod
786
+ // public void cancelComingCallNotification() {
787
+ // // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return;
788
+ // SharedUtils.cancelComingCallNotification();
789
+ // }
790
+
791
+ // @ReactMethod
792
+ // public void isAppInForeground(Promise promise) {
793
+ // try {
794
+ // boolean isInForeground = SharedUtils.isAppInForeground(mContext.getApplicationContext());
795
+ // WritableMap result = Arguments.createMap();
796
+ // result.putBoolean("succeeded", true);
797
+ // result.putBoolean("isInForeground", isInForeground);
798
+ // promise.resolve(result);
799
+ // } catch (RuntimeException e) {
800
+ // WritableMap result = Arguments.createMap();
801
+ // result.putBoolean("succeeded", false);
802
+ // result.putString("errorMessage", e.getMessage());
803
+ // promise.resolve(result);
804
+ // }
805
+ // }
806
+
807
+ // @ReactMethod
808
+ // public void setNativeEvent(String event) {
809
+ // JS_EVENTS.add(event);
810
+ // if (event.contains("onRinging")
811
+ // && IS_SEND_EVENT_RINGING == false
812
+ // && IS_CALL_ACCEPTED == false
813
+ // && IS_CALL_CONNECTED == false
814
+ // && CALL_ACTIVE != null) {
815
+ // sendEvent(mContext, "onRinging", CALL_ACTIVE);
816
+ // IS_SEND_EVENT_RINGING = true;
817
+ // }
818
+ // // if(event.contains("onCallDidAccept")
819
+ // // && IS_CALL_ACCEPTED == true
820
+ // // && IS_CALL_CONNECTED == false
821
+ // // && CALL_ACTIVE != null ){
822
+ // // sendEvent(mContext, "onConnected", CALL_ACTIVE);
823
+ // // IS_CALL_CONNECTED = true;
824
+ // // }
825
+ // }
826
+
827
+ // @ReactMethod
828
+ // public void removeNativeEvent(String event) {
829
+ // JS_EVENTS.remove(event);
830
+ // }
831
+
832
+ // @ReactMethod
833
+ // public void removeAllEvents() {
834
+ // SendBirdCall.removeAllListeners();
835
+ // SendBirdCall.removeAllRecordingListeners();
836
+ // }
837
+
838
+ // @ReactMethod
839
+ // public void endAllCalls(Promise promise) {
840
+ // try {
841
+ // List<DirectCall> directCall = SendBirdCall.getOngoingCalls();
842
+ // if (!directCall.isEmpty()) {
843
+ // for (int i = 0; i < directCall.size(); i++) {
844
+ // directCall.get(i).end();
845
+ // }
846
+ // }
847
+ // WritableMap result = Arguments.createMap();
848
+ // result.putBoolean("succeeded", true);
849
+ // promise.resolve(result);
850
+ // } catch (RuntimeException e) {
851
+ // WritableMap result = Arguments.createMap();
852
+ // result.putBoolean("succeeded", false);
853
+ // result.putString("errorMessage", e.getMessage());
854
+ // promise.resolve(result);
855
+ // }
856
+ // }
857
+
858
+ // public static void endCalls() {
859
+ // try {
860
+ // List<DirectCall> directCall = SendBirdCall.getOngoingCalls();
861
+ // if (!directCall.isEmpty()) {
862
+ // for (int i = 0; i < directCall.size(); i++) {
863
+ // directCall.get(i).end();
864
+ // }
865
+ // }
866
+ // } catch (RuntimeException e) {
867
+ // Log.d(TAG, "endCalls: " + e);
868
+ // }
869
+ // }
870
+
871
+ // private boolean contains(ArrayList array, String value) {
872
+ // for (int i = 0; i < array.size(); i++) {
873
+ // if (array.get(i).equals(value)) {
874
+ // return true;
875
+ // }
876
+ // }
877
+ // return false;
878
+ // }
879
+
880
+
881
+ // private static void handleListenerSendBirdCall(DirectCall mDirectCall) {
882
+ // if (mDirectCall == null) return;
883
+ // CALL_ACTIVE = mDirectCall;
884
+ // mDirectCall.setListener(new DirectCallListener() {
885
+ // @Override
886
+ // public void onEstablished(@NotNull DirectCall directCall) {
887
+ // //Remote user accepted the call.
888
+ // Log.i(TAG, "onEstablished");
889
+ // sendEvent(mContext, "onCallDidAccept", directCall);
890
+ // }
891
+
892
+ // @Override
893
+ // public void onConnected(@NotNull DirectCall directCall) {
894
+ // Log.i(TAG, "onConnected");
895
+ // WritableMap params = Arguments.createMap();
896
+ // sendEvent(mContext, "onConnected", directCall);
897
+ // }
898
+
899
+ // @Override
900
+ // public void onEnded(@NotNull DirectCall directCall) {
901
+ // Log.i(TAG, "onEnded");
902
+ // sendEvent(mContext, "onEnded", directCall);
903
+ // IS_CALL_ACCEPTED = false;
904
+ // IS_CALL_CONNECTED = false;
905
+ // CALL_ACTIVE = null;
906
+ // }
907
+
908
+ // @Override
909
+ // public void onReconnected(@NonNull DirectCall directCall) {
910
+ // Log.i(TAG, "onReconnected");
911
+ // sendEvent(mContext, "onReconnected", directCall);
912
+ // }
913
+
914
+ // @Override
915
+ // public void onReconnecting(@NonNull DirectCall directCall) {
916
+ // Log.i(TAG, "onReconnecting");
917
+ // sendEvent(mContext, "onReconnecting", directCall);
918
+ // }
919
+
920
+ // @Override
921
+ // public void onRemoteAudioSettingsChanged(DirectCall directCall) {
922
+ // Log.i(TAG, "onRemoteAudioSettingsChanged");
923
+ // sendEvent(mContext, "onRemoteAudioSettingsChanged", directCall);
924
+ // }
925
+
926
+ // @Override
927
+ // public void onRemoteVideoSettingsChanged(DirectCall directCall) {
928
+ // sendEvent(mContext, "onRemoteVideoSettingsChanged", directCall);
929
+ // }
930
+
931
+ // });
932
+ // }
933
+
934
+ // public static void sendEvent(ReactContext reactContext, String eventName, DirectCall directCall) {
935
+ // if (!EVENTS.contains(eventName)) return;
936
+ // WritableMap params = getParamDirectCall(directCall);
937
+ // reactContext
938
+ // .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
939
+ // .emit(eventName, params);
940
+ // }
941
+
942
+ // public static void onMessageReceived(Context context, Map<String, String> data) {
943
+ // int ringing = context.getResources().getIdentifier("ringing", "raw", context.getPackageName());
944
+ // int connecting = context.getResources().getIdentifier("connecting", "raw", context.getPackageName());
945
+ // int connected = context.getResources().getIdentifier("connected", "raw", context.getPackageName());
946
+ // setUpSoundEffects(
947
+ // ringing,
948
+ // connecting,
949
+ // connected,
950
+ // connected
951
+ // );
952
+ // SendBirdCall.handleFirebaseMessageData(data);
953
+ // }
954
+
955
+ // public static void onNewToken(String token) {
956
+ // if (SendBirdCall.getCurrentUser() != null) {
957
+ // SendBirdCall.registerPushToken(token, false, e -> {
958
+ // if (e != null) {
959
+ // Log.i("RNSendBirdCalls", "[FirebaseMessagingService] onNewToken() => e: " + e.getMessage());
960
+ // }
961
+ // });
962
+ // }
963
+ // }
964
+
965
+ // static public void setUpSoundEffects(
966
+ // @Nullable Integer ringingId,
967
+ // @Nullable Integer dialing,
968
+ // @Nullable Integer connectingId,
969
+ // @Nullable Integer connectedId
970
+ // ) {
971
+ // if (ringingId != null)
972
+ // SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RINGING, ringingId);
973
+ // if (dialing != null)
974
+ // SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.DIALING, dialing);
975
+ // if (connectingId != null)
976
+ // SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RECONNECTING, connectingId);
977
+ // if (connectedId != null)
978
+ // SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RECONNECTED, connectedId);
979
+ // SendBirdCall.Options.setDirectCallDialingSoundOnWhenSilentOrVibrateMode(true);
980
+ // }
981
+ // }
982
+
983
+
984
+ package com.rnsendbirdcalls;
985
+
986
+ import android.annotation.SuppressLint;
987
+ import android.content.Context;
988
+ import android.content.Intent;
989
+ import android.content.SharedPreferences;
990
+ import android.os.Build;
991
+ import android.os.Bundle;
992
+ import android.util.Log;
993
+
994
+ import androidx.annotation.NonNull;
995
+ import androidx.annotation.Nullable;
996
+
997
+ import com.facebook.react.bridge.Arguments;
998
+ import com.facebook.react.bridge.Promise;
999
+ import com.facebook.react.bridge.ReactApplicationContext;
1000
+ import com.facebook.react.bridge.ReactContext;
1001
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
1002
+ import com.facebook.react.bridge.ReactMethod;
1003
+ import com.facebook.react.bridge.ReadableMap;
1004
+ import com.facebook.react.bridge.WritableArray;
1005
+ import com.facebook.react.bridge.WritableMap;
1006
+ import com.facebook.react.modules.core.DeviceEventManagerModule;
1007
+ import com.sendbird.calls.AcceptParams;
1008
+ import com.sendbird.calls.AuthenticateParams;
1009
+ import com.sendbird.calls.CallOptions;
1010
+ import com.sendbird.calls.DialParams;
1011
+ import com.sendbird.calls.DirectCall;
1012
+ import com.sendbird.calls.DirectCallUser;
1013
+ import com.sendbird.calls.RecordingOptions;
1014
+ import com.sendbird.calls.SendBirdCall;
1015
+ import com.sendbird.calls.SendBirdException;
1016
+ import com.sendbird.calls.handler.DirectCallListener;
1017
+ import com.sendbird.calls.handler.RecordingListener;
1018
+ import com.sendbird.calls.handler.SendBirdCallListener;
1019
+
1020
+ import org.jetbrains.annotations.NotNull;
1021
+
1022
+ import java.io.File;
1023
+ import java.util.ArrayList;
1024
+ import java.util.Arrays;
1025
+ import java.util.HashMap;
1026
+ import java.util.List;
1027
+ import java.util.Map;
1028
+ import java.util.Objects;
1029
+ import java.util.UUID;
1030
+
1031
+ public class RNSendBirdCallsModule extends ReactContextBaseJavaModule {
1032
+
1033
+ private static ReactApplicationContext mContext;
1034
+ private static final String TAG = "RNSendBirdCalls";
1035
+
1036
+ private static Boolean IS_CALL_ACCEPTED = false;
1037
+ private static Boolean IS_CALL_CONNECTED = false;
1038
+ private static Boolean IS_INITIAL = false;
1039
+ private static Boolean IS_SEND_EVENT_RINGING = false;
1040
+ private static final ArrayList<String> JS_EVENTS = new ArrayList<>();
1041
+ private static final ArrayList<String> EVENTS = new ArrayList<>(
1042
+ Arrays.asList(
1043
+ "onRinging",
1044
+ "onCallDidAccept",
1045
+ "onConnected",
1046
+ "onEnded",
1047
+ "onReconnected",
1048
+ "onReconnecting",
1049
+ "onRemoteAudioSettingsChanged",
1050
+ "onRemoteVideoSettingsChanged",
1051
+ "onRecordingSucceeded",
1052
+ "onRecordingFailed"
1053
+ )
1054
+ );
1055
+
1056
+ private static DirectCall CALL_ACTIVE = null;
1057
+
1058
+ public RNSendBirdCallsModule(ReactApplicationContext reactContext) {
1059
+ super(reactContext);
1060
+ mContext = reactContext;
1061
+ }
1062
+
1063
+ @NonNull
1064
+ @Override
1065
+ public String getName() {
1066
+ return TAG;
1067
+ }
1068
+
1069
+ // MARK: - Helper Methods
1070
+ private static WritableMap getParamDirectCall(@NotNull DirectCall directCall) {
1071
+ WritableMap params = Arguments.createMap();
1072
+
1073
+ WritableMap callerMap = Arguments.createMap();
1074
+ WritableMap calleeMap = Arguments.createMap();
1075
+ WritableMap customItems = Arguments.createMap();
1076
+
1077
+ // Custom items
1078
+ Map<String, String> customItemsData = directCall.getCustomItems();
1079
+ if (customItemsData != null) {
1080
+ if (customItemsData.get("appointmentScheduleId") != null) {
1081
+ customItems.putString("appointmentScheduleId", customItemsData.get("appointmentScheduleId"));
1082
+ }
1083
+ if (customItemsData.get("eClinicId") != null) {
1084
+ customItems.putString("eClinicId", customItemsData.get("eClinicId"));
1085
+ }
1086
+ }
1087
+
1088
+ // Caller info
1089
+ DirectCallUser caller = directCall.getCaller();
1090
+ if (caller != null) {
1091
+ callerMap.putString("userId", caller.getUserId() != null ? caller.getUserId() : "");
1092
+ callerMap.putString("nickname", caller.getNickname() != null ? caller.getNickname() : "");
1093
+ callerMap.putString("profileUrl", caller.getProfileUrl() != null ? caller.getProfileUrl() : "");
1094
+ }
1095
+
1096
+ // Callee info
1097
+ DirectCallUser callee = directCall.getCallee();
1098
+ if (callee != null) {
1099
+ calleeMap.putString("userId", callee.getUserId() != null ? callee.getUserId() : "");
1100
+ calleeMap.putString("nickname", callee.getNickname() != null ? callee.getNickname() : "");
1101
+ calleeMap.putString("profileUrl", callee.getProfileUrl() != null ? callee.getProfileUrl() : "");
1102
+ }
1103
+
1104
+ params.putMap("callee", calleeMap);
1105
+ params.putMap("caller", callerMap);
1106
+ params.putMap("customItems", customItems);
1107
+
1108
+ // Call info
1109
+ params.putString("callId", directCall.getCallId() != null ? directCall.getCallId() : "");
1110
+ params.putDouble("duration", directCall.getDuration());
1111
+ params.putBoolean("isVideoCall", directCall.isVideoCall());
1112
+ params.putBoolean("isRemoteAudioEnabled", directCall.isRemoteAudioEnabled());
1113
+ params.putBoolean("isLocalAudioEnabled", directCall.isLocalAudioEnabled());
1114
+ params.putBoolean("isRemoteVideoEnabled", directCall.isRemoteVideoEnabled());
1115
+ params.putBoolean("isLocalVideoEnabled", directCall.isLocalVideoEnabled());
1116
+
1117
+ return params;
1118
+ }
1119
+
1120
+ @SuppressLint("WrongConstant")
1121
+ public static void configureInNative(Context appContext, String appId) {
1122
+ Log.w(TAG, "SendBirdCall initial");
1123
+ if (IS_INITIAL) {
1124
+ Log.w(TAG, "SendBirdCall is initial ready");
1125
+ return;
1126
+ }
1127
+
1128
+ if (SendBirdCall.init(appContext, appId)) {
1129
+ Log.d(TAG, "configureInNative: SUCCESS");
1130
+ setupSendBirdListeners();
1131
+ setupSoundEffects(appContext);
1132
+ IS_INITIAL = true;
1133
+ }
1134
+ }
1135
+
1136
+ private static void setupSendBirdListeners() {
1137
+ SendBirdCall.removeAllListeners();
1138
+ SendBirdCall.removeAllRecordingListeners();
1139
+
1140
+ String UNIQUE_HANDLER_ID = UUID.randomUUID().toString();
1141
+ SendBirdCall.addListener(UNIQUE_HANDLER_ID, new SendBirdCallListener() {
1142
+ @Override
1143
+ public void onRinging(@NotNull DirectCall call) {
1144
+ Log.i(TAG, "onRinging");
1145
+
1146
+ int ongoingCallCount = SendBirdCall.getOngoingCallCount();
1147
+ if (ongoingCallCount >= 2) {
1148
+ call.end();
1149
+ return;
1150
+ }
1151
+
1152
+ handleListenerSendBirdCall(call);
1153
+ if (JS_EVENTS.contains("onRinging")) {
1154
+ sendEvent(mContext, "onRinging", call);
1155
+ IS_SEND_EVENT_RINGING = true;
1156
+ }
1157
+ }
1158
+ });
1159
+
1160
+ String UNIQUE_ID = UUID.randomUUID().toString();
1161
+ SendBirdCall.addRecordingListener(UNIQUE_ID, new RecordingListener() {
1162
+ @Override
1163
+ public void onRecordingSucceeded(@NotNull DirectCall directCall, @NotNull String recorderId, @NotNull RecordingOptions recordingOptions, @NotNull String outputFilePath) {
1164
+ if (!JS_EVENTS.contains("onRecordingSucceeded")) return;
1165
+ WritableMap params = Arguments.createMap();
1166
+ params.putString("outputFilePath", outputFilePath);
1167
+ if (mContext != null) {
1168
+ mContext
1169
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
1170
+ .emit("onRecordingSucceeded", params);
1171
+ }
1172
+ }
1173
+
1174
+ @Override
1175
+ public void onRecordingFailed(@NotNull DirectCall directCall, @NotNull String recorderId, @NotNull SendBirdException e) {
1176
+ if (!JS_EVENTS.contains("onRecordingFailed")) return;
1177
+ WritableMap params = Arguments.createMap();
1178
+ params.putString("errorCode", String.valueOf(e.getCode()));
1179
+ params.putString("errorMessage", String.valueOf(e.getMessage()));
1180
+ if (mContext != null) {
1181
+ mContext
1182
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
1183
+ .emit("onRecordingFailed", params);
1184
+ }
1185
+ }
1186
+ });
1187
+ }
1188
+
1189
+ private static void setupSoundEffects(Context context) {
1190
+ int ringing = context.getResources().getIdentifier("ringing", "raw", context.getPackageName());
1191
+ int connecting = context.getResources().getIdentifier("connecting", "raw", context.getPackageName());
1192
+ int connected = context.getResources().getIdentifier("connected", "raw", context.getPackageName());
1193
+ setUpSoundEffects(ringing, connecting, connected, connected);
1194
+ }
1195
+
1196
+ // MARK: - React Methods
1197
+ @ReactMethod
1198
+ public void initSendBird(String appId, Promise promise) {
1199
+ try {
1200
+ IS_INITIAL = false;
1201
+ Context appContext = mContext.getApplicationContext();
1202
+ WritableMap result = Arguments.createMap();
1203
+
1204
+ if (SendBirdCall.init(appContext, appId)) {
1205
+ Log.d(TAG, "initSendBird: SUCCESS");
1206
+ setupSendBirdListeners();
1207
+ setupSoundEffects(appContext);
1208
+ IS_INITIAL = true;
1209
+ result.putBoolean("succeeded", true);
1210
+ } else {
1211
+ result.putBoolean("succeeded", false);
1212
+ }
1213
+ promise.resolve(result);
1214
+ } catch (Exception e) {
1215
+ WritableMap result = Arguments.createMap();
1216
+ result.putBoolean("succeeded", false);
1217
+ result.putString("errorMessage", e.getMessage());
1218
+ promise.resolve(result);
1219
+ }
1220
+ }
1221
+
1222
+ @ReactMethod
1223
+ public void authenticate(String userId, String accessToken, Promise promise) {
1224
+ try {
1225
+ AuthenticateParams params = new AuthenticateParams(userId).setAccessToken(accessToken);
1226
+ SendBirdCall.authenticate(params, (user, e) -> {
1227
+ WritableMap result = Arguments.createMap();
1228
+ if (e == null) {
1229
+ result.putBoolean("succeeded", true);
1230
+ result.putString("userId", user.getUserId());
1231
+ result.putString("nickname", user.getNickname() != null ? user.getNickname() : "");
1232
+ Log.d(TAG, "authenticate: " + user.getNickname());
1233
+ } else {
1234
+ result.putBoolean("succeeded", false);
1235
+ result.putString("errorCode", String.valueOf(e.getCode()));
1236
+ result.putString("errorMessage", e.getMessage());
1237
+ Log.d(TAG, "authenticate error: " + e.getMessage());
1238
+ }
1239
+ promise.resolve(result);
1240
+ });
1241
+ } catch (Exception e) {
1242
+ WritableMap result = Arguments.createMap();
1243
+ result.putBoolean("succeeded", false);
1244
+ result.putString("errorMessage", e.getMessage());
1245
+ promise.resolve(result);
1246
+ }
1247
+ }
1248
+
1249
+ @ReactMethod
1250
+ public void deAuthenticate(Promise promise) {
1251
+ SendBirdCall.deauthenticate(e -> {
1252
+ Log.d(TAG, "deAuthenticate");
1253
+ WritableMap result = Arguments.createMap();
1254
+ if (e == null) {
1255
+ result.putBoolean("succeeded", true);
1256
+ } else {
1257
+ result.putBoolean("succeeded", false);
1258
+ result.putString("errorCode", String.valueOf(e.getCode()));
1259
+ result.putString("errorMessage", e.getMessage());
1260
+ }
1261
+ promise.resolve(result);
1262
+ });
1263
+ }
1264
+
1265
+ @ReactMethod
1266
+ public void shareStorage(String appId) {
1267
+ if (appId == null || appId.isEmpty()) {
1268
+ return;
1269
+ }
1270
+ SharedPreferences shareReference = mContext.getApplicationContext()
1271
+ .getSharedPreferences("EDOCTOR_NATIVE", Context.MODE_PRIVATE);
1272
+ SharedPreferences.Editor editor = shareReference.edit();
1273
+ editor.putString("ANDROID_APP_ID", appId);
1274
+ editor.apply();
1275
+ }
1276
+
1277
+ @ReactMethod
1278
+ public void dial(String calleeId, boolean isVideoCall, boolean isVideoEnable, boolean isAudioEnable,
1279
+ String appointmentScheduleId, String eClinicId, Promise promise) {
1280
+ Log.d(TAG, "dial");
1281
+
1282
+ try {
1283
+ int ongoingCallCount = SendBirdCall.getOngoingCallCount();
1284
+ if (ongoingCallCount > 0) {
1285
+ WritableMap result = Arguments.createMap();
1286
+ result.putBoolean("succeeded", false);
1287
+ result.putString("errorMessage", "Đã có cuộc gọi đang diễn ra");
1288
+ promise.resolve(result);
1289
+ return;
1290
+ }
1291
+
1292
+ CallOptions callOptions = new CallOptions()
1293
+ .setVideoEnabled(isVideoEnable)
1294
+ .setAudioEnabled(isAudioEnable);
1295
+
1296
+ Map<String, String> customItems = new HashMap<>();
1297
+ customItems.put("appointmentScheduleId", appointmentScheduleId);
1298
+ customItems.put("eClinicId", eClinicId);
1299
+
1300
+ DialParams dialParams = new DialParams(calleeId)
1301
+ .setVideoCall(isVideoCall)
1302
+ .setCallOptions(callOptions)
1303
+ .setCustomItems(customItems);
1304
+
1305
+ DirectCall mDirectCall = SendBirdCall.dial(dialParams, (call, e) -> {
1306
+ WritableMap result = Arguments.createMap();
1307
+ if (e != null) {
1308
+ Log.d(TAG, "dial error: " + e.getMessage());
1309
+ result.putBoolean("succeeded", false);
1310
+ result.putString("errorCode", String.valueOf(e.getCode()));
1311
+ result.putString("errorMessage", e.getMessage());
1312
+ } else {
1313
+ result.putBoolean("succeeded", true);
1314
+ result.putString("callId", call.getCallId());
1315
+ result.putString("caller", call.getCaller().getUserId());
1316
+ result.putString("callee", call.getCallee().getUserId());
1317
+ }
1318
+ promise.resolve(result);
1319
+ });
1320
+
1321
+ if (mDirectCall != null) {
1322
+ handleListenerSendBirdCall(mDirectCall);
1323
+ }
1324
+ } catch (Exception e) {
1325
+ WritableMap result = Arguments.createMap();
1326
+ result.putBoolean("succeeded", false);
1327
+ result.putString("errorMessage", e.getMessage());
1328
+ promise.resolve(result);
1329
+ }
1330
+ }
1331
+
1332
+ @ReactMethod
1333
+ public void acceptCall(String callId, boolean isVideoEnable, boolean isAudioEnable, Promise promise) {
1334
+ Log.i(TAG, "acceptCall");
1335
+ try {
1336
+ DirectCall mDirectCall = SendBirdCall.getCall(callId);
1337
+ if (mDirectCall != null) {
1338
+ handleListenerSendBirdCall(mDirectCall);
1339
+ CallOptions callOptions = new CallOptions()
1340
+ .setVideoEnabled(isVideoEnable)
1341
+ .setAudioEnabled(isAudioEnable);
1342
+ mDirectCall.accept(new AcceptParams().setCallOptions(callOptions));
1343
+ IS_CALL_ACCEPTED = true;
1344
+
1345
+ WritableMap result = Arguments.createMap();
1346
+ result.putBoolean("succeeded", true);
1347
+ promise.resolve(result);
1348
+ } else {
1349
+ WritableMap result = Arguments.createMap();
1350
+ result.putBoolean("succeeded", false);
1351
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1352
+ promise.resolve(result);
1353
+ }
1354
+ } catch (Exception e) {
1355
+ WritableMap result = Arguments.createMap();
1356
+ result.putBoolean("succeeded", false);
1357
+ result.putString("errorMessage", e.getMessage());
1358
+ promise.resolve(result);
1359
+ }
1360
+ }
1361
+
1362
+ @ReactMethod
1363
+ public void endCall(Promise promise) {
1364
+ Log.i(TAG, "endCall");
1365
+ if (CALL_ACTIVE != null) {
1366
+ try {
1367
+ WritableMap params = getParamDirectCall(CALL_ACTIVE);
1368
+ params.putBoolean("succeeded", true);
1369
+
1370
+ IS_CALL_ACCEPTED = false;
1371
+ IS_CALL_CONNECTED = false;
1372
+ CALL_ACTIVE.end();
1373
+
1374
+ promise.resolve(params);
1375
+ } catch (Exception e) {
1376
+ WritableMap result = Arguments.createMap();
1377
+ result.putBoolean("succeeded", false);
1378
+ result.putString("errorMessage", e.getMessage());
1379
+ promise.resolve(result);
1380
+ }
1381
+ } else {
1382
+ WritableMap result = Arguments.createMap();
1383
+ result.putBoolean("succeeded", false);
1384
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1385
+ promise.resolve(result);
1386
+ }
1387
+ }
1388
+
1389
+ @ReactMethod
1390
+ public void endAllCalls(Promise promise) {
1391
+ try {
1392
+ List<DirectCall> directCalls = SendBirdCall.getOngoingCalls();
1393
+ if (directCalls != null && !directCalls.isEmpty()) {
1394
+ for (DirectCall call : directCalls) {
1395
+ call.end();
1396
+ }
1397
+ }
1398
+ WritableMap result = Arguments.createMap();
1399
+ result.putBoolean("succeeded", true);
1400
+ promise.resolve(result);
1401
+ } catch (Exception e) {
1402
+ WritableMap result = Arguments.createMap();
1403
+ result.putBoolean("succeeded", false);
1404
+ result.putString("errorMessage", e.getMessage());
1405
+ promise.resolve(result);
1406
+ }
1407
+ }
1408
+
1409
+ @ReactMethod
1410
+ public void getOngoingCalls(Promise promise) {
1411
+ try {
1412
+ List<DirectCall> directCalls = SendBirdCall.getOngoingCalls();
1413
+ WritableArray resultData = Arguments.createArray();
1414
+
1415
+ if (directCalls != null && !directCalls.isEmpty()) {
1416
+ for (DirectCall call : directCalls) {
1417
+ WritableMap item = getParamDirectCall(call);
1418
+ if (item != null) {
1419
+ resultData.pushMap(item);
1420
+ }
1421
+ }
1422
+ }
1423
+ promise.resolve(resultData);
1424
+ } catch (Exception e) {
1425
+ promise.resolve(Arguments.createArray()); // Return empty array on error
1426
+ }
1427
+ }
1428
+
1429
+ // MARK: - Audio/Video Controls
1430
+ @ReactMethod
1431
+ public void muteMicrophone(Promise promise) {
1432
+ Log.i(TAG, "muteMicrophone");
1433
+ if (CALL_ACTIVE == null) {
1434
+ WritableMap result = Arguments.createMap();
1435
+ result.putBoolean("succeeded", false);
1436
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1437
+ promise.resolve(result);
1438
+ return;
1439
+ }
1440
+
1441
+ try {
1442
+ boolean succeeded = CALL_ACTIVE.muteMicrophone();
1443
+ WritableMap result = Arguments.createMap();
1444
+ result.putBoolean("succeeded", succeeded);
1445
+ promise.resolve(result);
1446
+ } catch (Exception e) {
1447
+ WritableMap result = Arguments.createMap();
1448
+ result.putBoolean("succeeded", false);
1449
+ result.putString("errorMessage", e.getMessage());
1450
+ promise.resolve(result);
1451
+ }
1452
+ }
1453
+
1454
+ @ReactMethod
1455
+ public void unmuteMicrophone(Promise promise) {
1456
+ Log.i(TAG, "unmuteMicrophone");
1457
+ if (CALL_ACTIVE == null) {
1458
+ WritableMap result = Arguments.createMap();
1459
+ result.putBoolean("succeeded", false);
1460
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1461
+ promise.resolve(result);
1462
+ return;
1463
+ }
1464
+
1465
+ try {
1466
+ boolean succeeded = CALL_ACTIVE.unmuteMicrophone();
1467
+ WritableMap result = Arguments.createMap();
1468
+ result.putBoolean("succeeded", succeeded);
1469
+ promise.resolve(result);
1470
+ } catch (Exception e) {
1471
+ WritableMap result = Arguments.createMap();
1472
+ result.putBoolean("succeeded", false);
1473
+ result.putString("errorMessage", e.getMessage());
1474
+ promise.resolve(result);
1475
+ }
1476
+ }
1477
+
1478
+ @ReactMethod
1479
+ public void startVideo(Promise promise) {
1480
+ Log.i(TAG, "startVideo");
1481
+ if (CALL_ACTIVE == null) {
1482
+ WritableMap result = Arguments.createMap();
1483
+ result.putBoolean("succeeded", false);
1484
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1485
+ promise.resolve(result);
1486
+ return;
1487
+ }
1488
+
1489
+ try {
1490
+ CALL_ACTIVE.startVideo();
1491
+ WritableMap result = Arguments.createMap();
1492
+ result.putBoolean("succeeded", true);
1493
+ promise.resolve(result);
1494
+ } catch (Exception e) {
1495
+ WritableMap result = Arguments.createMap();
1496
+ result.putBoolean("succeeded", false);
1497
+ result.putString("errorMessage", e.getMessage());
1498
+ promise.resolve(result);
1499
+ }
1500
+ }
1501
+
1502
+ @ReactMethod
1503
+ public void stopVideo(Promise promise) {
1504
+ Log.i(TAG, "stopVideo");
1505
+ if (CALL_ACTIVE == null) {
1506
+ WritableMap result = Arguments.createMap();
1507
+ result.putBoolean("succeeded", false);
1508
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1509
+ promise.resolve(result);
1510
+ return;
1511
+ }
1512
+
1513
+ try {
1514
+ CALL_ACTIVE.stopVideo();
1515
+ WritableMap result = Arguments.createMap();
1516
+ result.putBoolean("succeeded", true);
1517
+ promise.resolve(result);
1518
+ } catch (Exception e) {
1519
+ WritableMap result = Arguments.createMap();
1520
+ result.putBoolean("succeeded", false);
1521
+ result.putString("errorMessage", e.getMessage());
1522
+ promise.resolve(result);
1523
+ }
1524
+ }
1525
+
1526
+ @ReactMethod
1527
+ public void switchCamera(Promise promise) {
1528
+ Log.i(TAG, "switchCamera");
1529
+ if (CALL_ACTIVE == null) {
1530
+ WritableMap result = Arguments.createMap();
1531
+ result.putBoolean("succeeded", false);
1532
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1533
+ promise.resolve(result);
1534
+ return;
1535
+ }
1536
+
1537
+ CALL_ACTIVE.switchCamera(e -> {
1538
+ WritableMap result = Arguments.createMap();
1539
+ if (e != null) {
1540
+ result.putBoolean("succeeded", false);
1541
+ result.putString("errorCode", String.valueOf(e.getCode()));
1542
+ result.putString("errorMessage", e.getMessage());
1543
+ } else {
1544
+ result.putBoolean("succeeded", true);
1545
+ }
1546
+ promise.resolve(result);
1547
+ });
1548
+ }
1549
+
1550
+ // MARK: - Recording
1551
+ @ReactMethod
1552
+ public void startRecording(String fileName, boolean isRemote, Promise promise) {
1553
+ Log.d(TAG, "startRecording");
1554
+ if (CALL_ACTIVE == null) {
1555
+ WritableMap result = Arguments.createMap();
1556
+ result.putBoolean("succeeded", false);
1557
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1558
+ promise.resolve(result);
1559
+ return;
1560
+ }
1561
+
1562
+ try {
1563
+ File myDir = new File(mContext.getApplicationContext().getFilesDir().getAbsolutePath() + "/records");
1564
+ if (!myDir.exists()) {
1565
+ myDir.mkdirs();
1566
+ }
1567
+
1568
+ RecordingOptions options = isRemote
1569
+ ? new RecordingOptions(RecordingOptions.RecordingType.LOCAL_AUDIO_REMOTE_AUDIO_AND_VIDEO, myDir.getAbsolutePath(), fileName)
1570
+ : new RecordingOptions(RecordingOptions.RecordingType.LOCAL_AUDIO_AND_VIDEO_REMOTE_AUDIO, myDir.getAbsolutePath(), fileName);
1571
+
1572
+ CALL_ACTIVE.startRecording(options, (recordingId, e) -> {
1573
+ WritableMap result = Arguments.createMap();
1574
+ if (e == null) {
1575
+ result.putBoolean("succeeded", true);
1576
+ result.putString("recordingId", recordingId);
1577
+ result.putString("filePath", myDir.getAbsolutePath());
1578
+ Log.d(TAG, "recordingId: " + recordingId);
1579
+ } else {
1580
+ result.putBoolean("succeeded", false);
1581
+ result.putString("errorCode", String.valueOf(e.getCode()));
1582
+ result.putString("errorMessage", e.getMessage());
1583
+ Log.d(TAG, "recording error: " + e.getMessage());
1584
+ }
1585
+ promise.resolve(result);
1586
+ });
1587
+ } catch (Exception e) {
1588
+ WritableMap result = Arguments.createMap();
1589
+ result.putBoolean("succeeded", false);
1590
+ result.putString("errorMessage", e.getMessage());
1591
+ promise.resolve(result);
1592
+ }
1593
+ }
1594
+
1595
+ @ReactMethod
1596
+ public void stopRecording(String recordingId, Promise promise) {
1597
+ Log.d(TAG, "stopRecording: " + recordingId);
1598
+ if (CALL_ACTIVE == null) {
1599
+ WritableMap result = Arguments.createMap();
1600
+ result.putBoolean("succeeded", false);
1601
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1602
+ promise.resolve(result);
1603
+ return;
1604
+ }
1605
+
1606
+ try {
1607
+ boolean succeeded = CALL_ACTIVE.stopRecording(recordingId);
1608
+ WritableMap result = Arguments.createMap();
1609
+ result.putBoolean("succeeded", succeeded);
1610
+ promise.resolve(result);
1611
+ } catch (Exception e) {
1612
+ WritableMap result = Arguments.createMap();
1613
+ result.putBoolean("succeeded", false);
1614
+ result.putString("errorMessage", e.getMessage());
1615
+ promise.resolve(result);
1616
+ }
1617
+ }
1618
+
1619
+ // MARK: - Push Token Management
1620
+ @ReactMethod
1621
+ public void registerPushToken(String token, Promise promise) {
1622
+ if (SendBirdCall.getCurrentUser() != null) {
1623
+ SendBirdCall.registerPushToken(token, false, e -> {
1624
+ WritableMap result = Arguments.createMap();
1625
+ if (e != null) {
1626
+ Log.i(TAG, "registerPushToken error: " + e.getMessage());
1627
+ result.putBoolean("succeeded", false);
1628
+ result.putString("errorCode", String.valueOf(e.getCode()));
1629
+ result.putString("errorMessage", e.getMessage());
1630
+ } else {
1631
+ result.putBoolean("succeeded", true);
1632
+ }
1633
+ promise.resolve(result);
1634
+ });
1635
+ } else {
1636
+ WritableMap result = Arguments.createMap();
1637
+ result.putBoolean("succeeded", false);
1638
+ result.putString("errorMessage", "User chưa được authenticate");
1639
+ promise.resolve(result);
1640
+ }
1641
+ }
1642
+
1643
+ @ReactMethod
1644
+ public void unregisterPushToken(String token, Promise promise) {
1645
+ if (SendBirdCall.getCurrentUser() != null) {
1646
+ SendBirdCall.unregisterPushToken(token, e -> {
1647
+ WritableMap result = Arguments.createMap();
1648
+ if (e == null) {
1649
+ result.putBoolean("succeeded", true);
1650
+ } else {
1651
+ result.putBoolean("succeeded", false);
1652
+ result.putString("errorCode", String.valueOf(e.getCode()));
1653
+ result.putString("errorMessage", e.getMessage());
1654
+ }
1655
+ promise.resolve(result);
1656
+ });
1657
+ } else {
1658
+ WritableMap result = Arguments.createMap();
1659
+ result.putBoolean("succeeded", false);
1660
+ result.putString("errorMessage", "User chưa được authenticate");
1661
+ promise.resolve(result);
1662
+ }
1663
+ }
1664
+
1665
+ // MARK: - Sound Configuration
1666
+ @ReactMethod
1667
+ public void setDirectCallDialingSoundOnWhenSilentMode(boolean isEnabled, Promise promise) {
1668
+ try {
1669
+ SendBirdCall.Options.setDirectCallDialingSoundOnWhenSilentOrVibrateMode(isEnabled);
1670
+ WritableMap result = Arguments.createMap();
1671
+ result.putBoolean("succeeded", true);
1672
+ promise.resolve(result);
1673
+ } catch (Exception e) {
1674
+ WritableMap result = Arguments.createMap();
1675
+ result.putBoolean("succeeded", false);
1676
+ result.putString("errorMessage", e.getMessage());
1677
+ promise.resolve(result);
1678
+ }
1679
+ }
1680
+
1681
+ @ReactMethod
1682
+ public void addDirectCallSound(String soundType, String filename) {
1683
+ try {
1684
+ Context context = mContext.getApplicationContext();
1685
+ int resourceId = context.getResources().getIdentifier(filename, "raw", context.getPackageName());
1686
+
1687
+ if (resourceId != 0) {
1688
+ switch (soundType) {
1689
+ case "DIALING":
1690
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.DIALING, resourceId);
1691
+ break;
1692
+ case "RINGING":
1693
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RINGING, resourceId);
1694
+ break;
1695
+ case "RECONNECTING":
1696
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RECONNECTING, resourceId);
1697
+ break;
1698
+ case "RECONNECTED":
1699
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RECONNECTED, resourceId);
1700
+ break;
1701
+ }
1702
+ }
1703
+ } catch (Exception e) {
1704
+ Log.e(TAG, "addDirectCallSound error: " + e.getMessage());
1705
+ }
1706
+ }
1707
+
1708
+ // MARK: - Event Management
1709
+ @ReactMethod
1710
+ public void setNativeEvent(String event) {
1711
+ if (!JS_EVENTS.contains(event)) {
1712
+ JS_EVENTS.add(event);
1713
+ }
1714
+
1715
+ // Handle pending events
1716
+ if ("onRinging".equals(event)
1717
+ && !IS_SEND_EVENT_RINGING
1718
+ && !IS_CALL_ACCEPTED
1719
+ && !IS_CALL_CONNECTED
1720
+ && CALL_ACTIVE != null) {
1721
+ sendEvent(mContext, "onRinging", CALL_ACTIVE);
1722
+ IS_SEND_EVENT_RINGING = true;
1723
+ }
1724
+ }
1725
+
1726
+ @ReactMethod
1727
+ public void removeNativeEvent(String event) {
1728
+ JS_EVENTS.remove(event);
1729
+ }
1730
+
1731
+ @ReactMethod
1732
+ public void removeAllEvents() {
1733
+ JS_EVENTS.clear();
1734
+ SendBirdCall.removeAllListeners();
1735
+ SendBirdCall.removeAllRecordingListeners();
1736
+ }
1737
+
1738
+ // MARK: - Utility Methods
1739
+ public static String getAppId(Context context) {
1740
+ SharedPreferences shareReference = context.getSharedPreferences("EDOCTOR_NATIVE", Context.MODE_PRIVATE);
1741
+ return shareReference.getString("ANDROID_APP_ID", "");
1742
+ }
1743
+
1744
+ public static void endCalls() {
1745
+ try {
1746
+ List<DirectCall> directCalls = SendBirdCall.getOngoingCalls();
1747
+ if (directCalls != null && !directCalls.isEmpty()) {
1748
+ for (DirectCall call : directCalls) {
1749
+ call.end();
1750
+ }
1751
+ }
1752
+ } catch (Exception e) {
1753
+ Log.d(TAG, "endCalls error: " + e.getMessage());
1754
+ }
1755
+ }
1756
+
1757
+ // MARK: - Call Listener Setup
1758
+ private static void handleListenerSendBirdCall(DirectCall mDirectCall) {
1759
+ if (mDirectCall == null) return;
1760
+ CALL_ACTIVE = mDirectCall;
1761
+
1762
+ mDirectCall.setListener(new DirectCallListener() {
1763
+ @Override
1764
+ public void onEstablished(@NotNull DirectCall directCall) {
1765
+ Log.i(TAG, "onEstablished");
1766
+ IS_CALL_ACCEPTED = true;
1767
+ sendEvent(mContext, "onCallDidAccept", directCall);
1768
+ }
1769
+
1770
+ @Override
1771
+ public void onConnected(@NotNull DirectCall directCall) {
1772
+ Log.i(TAG, "onConnected");
1773
+ IS_CALL_CONNECTED = true;
1774
+ sendEvent(mContext, "onConnected", directCall);
1775
+ }
1776
+
1777
+ @Override
1778
+ public void onEnded(@NotNull DirectCall directCall) {
1779
+ Log.i(TAG, "onEnded");
1780
+ sendEvent(mContext, "onEnded", directCall);
1781
+ IS_CALL_ACCEPTED = false;
1782
+ IS_CALL_CONNECTED = false;
1783
+ IS_SEND_EVENT_RINGING = false;
1784
+ CALL_ACTIVE = null;
1785
+ }
1786
+
1787
+ @Override
1788
+ public void onReconnected(@NonNull DirectCall directCall) {
1789
+ Log.i(TAG, "onReconnected");
1790
+ sendEvent(mContext, "onReconnected", directCall);
1791
+ }
1792
+
1793
+ @Override
1794
+ public void onReconnecting(@NonNull DirectCall directCall) {
1795
+ Log.i(TAG, "onReconnecting");
1796
+ sendEvent(mContext, "onReconnecting", directCall);
1797
+ }
1798
+
1799
+ @Override
1800
+ public void onRemoteAudioSettingsChanged(DirectCall directCall) {
1801
+ Log.i(TAG, "onRemoteAudioSettingsChanged");
1802
+ sendEvent(mContext, "onRemoteAudioSettingsChanged", directCall);
1803
+ }
1804
+
1805
+ @Override
1806
+ public void onRemoteVideoSettingsChanged(DirectCall directCall) {
1807
+ Log.i(TAG, "onRemoteVideoSettingsChanged");
1808
+ sendEvent(mContext, "onRemoteVideoSettingsChanged", directCall);
1809
+ }
1810
+ });
1811
+ }
1812
+
1813
+ // MARK: - Event Emission
1814
+ public static void sendEvent(ReactContext reactContext, String eventName, DirectCall directCall) {
1815
+ if (!JS_EVENTS.contains(eventName) || reactContext == null) return;
1816
+
1817
+ try {
1818
+ WritableMap params = getParamDirectCall(directCall);
1819
+ reactContext
1820
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
1821
+ .emit(eventName, params);
1822
+ } catch (Exception e) {
1823
+ Log.e(TAG, "Error sending event " + eventName + ": " + e.getMessage());
1824
+ }
1825
+ }
1826
+
1827
+ // MARK: - Firebase Integration
1828
+ public static void onMessageReceived(Context context, Map<String, String> data) {
1829
+ setupSoundEffects(context);
1830
+ SendBirdCall.handleFirebaseMessageData(data);
1831
+ }
1832
+
1833
+ public static void onNewToken(String token) {
1834
+ if (SendBirdCall.getCurrentUser() != null) {
1835
+ SendBirdCall.registerPushToken(token, false, e -> {
1836
+ if (e != null) {
1837
+ Log.i(TAG, "[FirebaseMessagingService] onNewToken() error: " + e.getMessage());
1838
+ }
1839
+ });
1840
+ }
1841
+ }
1842
+
1843
+ // MARK: - Sound Effects Setup
1844
+ static public void setUpSoundEffects(
1845
+ @Nullable Integer ringingId,
1846
+ @Nullable Integer dialingId,
1847
+ @Nullable Integer connectingId,
1848
+ @Nullable Integer connectedId
1849
+ ) {
1850
+ try {
1851
+ if (ringingId != null && ringingId != 0)
1852
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RINGING, ringingId);
1853
+ if (dialingId != null && dialingId != 0)
1854
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.DIALING, dialingId);
1855
+ if (connectingId != null && connectingId != 0)
1856
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RECONNECTING, connectingId);
1857
+ if (connectedId != null && connectedId != 0)
1858
+ SendBirdCall.Options.addDirectCallSound(SendBirdCall.SoundType.RECONNECTED, connectedId);
1859
+
1860
+ SendBirdCall.Options.setDirectCallDialingSoundOnWhenSilentOrVibrateMode(true);
1861
+ } catch (Exception e) {
1862
+ Log.e(TAG, "setUpSoundEffects error: " + e.getMessage());
1863
+ }
1864
+ }
1865
+
1866
+ // MARK: - Legacy Methods (for backward compatibility)
1867
+ @ReactMethod
1868
+ public void getCall(String callId, Promise promise) {
1869
+ try {
1870
+ DirectCall directCall = SendBirdCall.getCall(callId);
1871
+ if (directCall != null) {
1872
+ WritableMap callInfo = getParamDirectCall(directCall);
1873
+ callInfo.putBoolean("succeeded", true);
1874
+ promise.resolve(callInfo);
1875
+ } else {
1876
+ WritableMap result = Arguments.createMap();
1877
+ result.putBoolean("succeeded", false);
1878
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1879
+ promise.resolve(result);
1880
+ }
1881
+ } catch (Exception e) {
1882
+ WritableMap result = Arguments.createMap();
1883
+ result.putBoolean("succeeded", false);
1884
+ result.putString("errorMessage", e.getMessage());
1885
+ promise.resolve(result);
1886
+ }
1887
+ }
1888
+
1889
+ @ReactMethod
1890
+ public void endIncomingCallNeedAuthentication(String callId, Promise promise) {
1891
+ Log.i(TAG, "endIncomingCallNeedAuthentication");
1892
+ try {
1893
+ DirectCall mDirectCall = SendBirdCall.getCall(callId);
1894
+ if (mDirectCall != null) {
1895
+ DirectCallUser callee = mDirectCall.getCallee();
1896
+ AuthenticateParams params = new AuthenticateParams(callee.getUserId());
1897
+ SendBirdCall.authenticate(params, (user, e) -> {
1898
+ WritableMap result = Arguments.createMap();
1899
+ if (e == null) {
1900
+ mDirectCall.end();
1901
+ IS_CALL_ACCEPTED = false;
1902
+ IS_CALL_CONNECTED = false;
1903
+ result.putBoolean("succeeded", true);
1904
+ } else {
1905
+ result.putBoolean("succeeded", false);
1906
+ result.putString("errorCode", String.valueOf(e.getCode()));
1907
+ result.putString("errorMessage", e.getMessage());
1908
+ }
1909
+ promise.resolve(result);
1910
+ });
1911
+ } else {
1912
+ WritableMap result = Arguments.createMap();
1913
+ result.putBoolean("succeeded", false);
1914
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1915
+ promise.resolve(result);
1916
+ }
1917
+ } catch (Exception e) {
1918
+ WritableMap result = Arguments.createMap();
1919
+ result.putBoolean("succeeded", false);
1920
+ result.putString("errorMessage", e.getMessage());
1921
+ promise.resolve(result);
1922
+ }
1923
+ }
1924
+
1925
+ @ReactMethod
1926
+ public void acceptIncomingCallNeedAuthentication(String callId, boolean isVideoEnable, boolean isAudioEnable, Promise promise) {
1927
+ Log.i(TAG, "acceptIncomingCallNeedAuthentication");
1928
+ try {
1929
+ DirectCall mDirectCall = SendBirdCall.getCall(callId);
1930
+ if (mDirectCall != null) {
1931
+ DirectCallUser callee = mDirectCall.getCallee();
1932
+ AuthenticateParams params = new AuthenticateParams(callee.getUserId());
1933
+ SendBirdCall.authenticate(params, (user, e) -> {
1934
+ WritableMap result = Arguments.createMap();
1935
+ if (e == null) {
1936
+ handleListenerSendBirdCall(mDirectCall);
1937
+ CallOptions callOptions = new CallOptions()
1938
+ .setVideoEnabled(isVideoEnable)
1939
+ .setAudioEnabled(isAudioEnable);
1940
+ mDirectCall.accept(new AcceptParams().setCallOptions(callOptions));
1941
+ IS_CALL_ACCEPTED = true;
1942
+ result.putBoolean("succeeded", true);
1943
+ } else {
1944
+ result.putBoolean("succeeded", false);
1945
+ result.putString("errorCode", String.valueOf(e.getCode()));
1946
+ result.putString("errorMessage", e.getMessage());
1947
+ }
1948
+ promise.resolve(result);
1949
+ });
1950
+ } else {
1951
+ WritableMap result = Arguments.createMap();
1952
+ result.putBoolean("succeeded", false);
1953
+ result.putString("errorMessage", "Cuộc gọi không tồn tại");
1954
+ promise.resolve(result);
1955
+ }
1956
+ } catch (Exception e) {
1957
+ WritableMap result = Arguments.createMap();
1958
+ result.putBoolean("succeeded", false);
1959
+ result.putString("errorMessage", e.getMessage());
1960
+ promise.resolve(result);
1961
+ }
1962
+ }
1963
+
1964
+ @ReactMethod
1965
+ public void wakeAppIncomingCall(ReadableMap params) {
1966
+ Log.d(TAG, "wakeAppIncomingCall");
1967
+ try {
1968
+ Bundle bundle = Arguments.toBundle(params);
1969
+ Intent intent = new Intent(mContext.getApplicationContext(), VoIPService.class);
1970
+ intent.putExtras(bundle);
1971
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
1972
+ mContext.getApplicationContext().startForegroundService(intent);
1973
+ } else {
1974
+ mContext.getApplicationContext().startService(intent);
1975
+ }
1976
+ } catch (Exception e) {
1977
+ Log.e(TAG, "wakeAppIncomingCall error: " + e.getMessage());
1978
+ }
1979
+ }
1980
+
1981
+ @ReactMethod
1982
+ public void navigateMainApp(ReadableMap params) {
1983
+ Log.d(TAG, "navigateMainApp");
1984
+ try {
1985
+ Bundle bundle = Arguments.toBundle(params);
1986
+ SharedUtils.navigateMainApp(mContext.getApplicationContext(), bundle);
1987
+ } catch (Exception e) {
1988
+ Log.e(TAG, "navigateMainApp error: " + e.getMessage());
1989
+ }
1990
+ }
1991
+
1992
+ @ReactMethod
1993
+ public void finishLockedScreenUI() {
1994
+ try {
1995
+ if (mContext.getCurrentActivity() != null) {
1996
+ mContext.getCurrentActivity().finish();
1997
+ }
1998
+ } catch (Exception e) {
1999
+ Log.e(TAG, "finishLockedScreenUI error: " + e.getMessage());
2000
+ }
2001
+ }
2002
+
2003
+ @ReactMethod
2004
+ public void getDeviceLocked(Promise promise) {
2005
+ try {
2006
+ boolean isLocked = SharedUtils.getDeviceLocked(mContext.getApplicationContext());
2007
+ WritableMap result = Arguments.createMap();
2008
+ result.putBoolean("succeeded", true);
2009
+ result.putBoolean("isLocked", isLocked);
2010
+ promise.resolve(result);
2011
+ } catch (Exception e) {
2012
+ WritableMap result = Arguments.createMap();
2013
+ result.putBoolean("succeeded", false);
2014
+ result.putString("errorMessage", e.getMessage());
2015
+ promise.resolve(result);
2016
+ }
2017
+ }
2018
+
2019
+ @ReactMethod
2020
+ public void cancelComingCallNotification() {
2021
+ try {
2022
+ SharedUtils.cancelComingCallNotification();
2023
+ } catch (Exception e) {
2024
+ Log.e(TAG, "cancelComingCallNotification error: " + e.getMessage());
2025
+ }
2026
+ }
2027
+
2028
+ @ReactMethod
2029
+ public void isAppInForeground(Promise promise) {
2030
+ try {
2031
+ boolean isInForeground = SharedUtils.isAppInForeground(mContext.getApplicationContext());
2032
+ WritableMap result = Arguments.createMap();
2033
+ result.putBoolean("succeeded", true);
2034
+ result.putBoolean("isInForeground", isInForeground);
2035
+ promise.resolve(result);
2036
+ } catch (Exception e) {
2037
+ WritableMap result = Arguments.createMap();
2038
+ result.putBoolean("succeeded", false);
2039
+ result.putString("errorMessage", e.getMessage());
2040
+ promise.resolve(result);
2041
+ }
2042
+ }
2043
+
2044
+ @ReactMethod
2045
+ public void getCallInfo(Promise promise) {
2046
+ try {
2047
+ if (CALL_ACTIVE == null) {
2048
+ promise.resolve(null);
2049
+ return;
2050
+ }
2051
+
2052
+ DirectCall directCall = SendBirdCall.getCall(CALL_ACTIVE.getCallId());
2053
+ if (directCall == null) {
2054
+ promise.resolve(null);
2055
+ } else {
2056
+ Log.d(TAG, "getCallInfo: " + directCall.getCallId());
2057
+ WritableMap callInfo = getParamDirectCall(directCall);
2058
+ callInfo.putBoolean("succeeded", true);
2059
+ promise.resolve(callInfo);
2060
+ }
2061
+ } catch (Exception e) {
2062
+ WritableMap result = Arguments.createMap();
2063
+ result.putBoolean("succeeded", false);
2064
+ result.putString("errorMessage", e.getMessage());
2065
+ promise.resolve(result);
2066
+ }
2067
+ }
2068
+ }