@qusaieilouti99/call-manager 0.1.24 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/qusaieilouti99/callmanager/CallActivity.kt +1 -0
- package/android/src/main/java/com/qusaieilouti99/callmanager/CallEngine.kt +133 -90
- package/android/src/main/java/com/qusaieilouti99/callmanager/CallEventType.kt +15 -0
- package/android/src/main/java/com/qusaieilouti99/callmanager/CallForegroundService.kt +1 -0
- package/android/src/main/java/com/qusaieilouti99/callmanager/CallManagerModule.kt +9 -8
- package/android/src/main/java/com/qusaieilouti99/callmanager/CallNotificationActionReceiver.kt +1 -0
- package/android/src/main/java/com/qusaieilouti99/callmanager/MyConnection.kt +30 -28
- package/android/src/main/java/com/qusaieilouti99/callmanager/MyConnectionService.kt +1 -0
- package/lib/module/NativeCallManager.js +1 -0
- package/lib/module/NativeCallManager.js.map +1 -1
- package/lib/module/index.js +9 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NativeCallManager.d.ts +1 -1
- package/lib/typescript/src/NativeCallManager.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +9 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativeCallManager.ts +2 -2
- package/src/index.tsx +11 -1
|
@@ -15,8 +15,9 @@ import android.app.Person
|
|
|
15
15
|
import java.util.concurrent.ConcurrentHashMap
|
|
16
16
|
import android.media.AudioDeviceInfo
|
|
17
17
|
import android.media.AudioManager
|
|
18
|
-
import android.
|
|
19
|
-
import
|
|
18
|
+
import android.os.PowerManager
|
|
19
|
+
import org.json.JSONArray
|
|
20
|
+
import org.json.JSONObject
|
|
20
21
|
|
|
21
22
|
object CallEngine {
|
|
22
23
|
private const val TAG = "CallEngine"
|
|
@@ -28,6 +29,7 @@ object CallEngine {
|
|
|
28
29
|
|
|
29
30
|
private var ringtone: android.media.Ringtone? = null
|
|
30
31
|
private var audioManager: AudioManager? = null
|
|
32
|
+
private var wakeLock: PowerManager.WakeLock? = null
|
|
31
33
|
|
|
32
34
|
// --- Multi-call state ---
|
|
33
35
|
private val activeCalls = ConcurrentHashMap<String, CallInfo>() // callId -> CallInfo
|
|
@@ -44,28 +46,48 @@ object CallEngine {
|
|
|
44
46
|
INCOMING, ACTIVE, HELD, ENDED
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
// --- Event handler for JS ---
|
|
50
|
+
private var eventHandler: ((CallEventType, String) -> Unit)? = null
|
|
51
|
+
|
|
52
|
+
fun setEventHandler(handler: ((CallEventType, String) -> Unit)?) {
|
|
53
|
+
eventHandler = handler
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun emitEvent(type: CallEventType, data: JSONObject) {
|
|
57
|
+
eventHandler?.invoke(type, data.toString())
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
// --- Public API ---
|
|
48
61
|
|
|
49
62
|
fun setCanMakeMultipleCalls(allow: Boolean) {
|
|
50
63
|
canMakeMultipleCalls = allow
|
|
51
64
|
}
|
|
52
65
|
|
|
66
|
+
fun getCurrentCallState(): String {
|
|
67
|
+
val calls = getActiveCalls()
|
|
68
|
+
if (calls.isEmpty()) return ""
|
|
69
|
+
val jsonArray = JSONArray()
|
|
70
|
+
calls.forEach {
|
|
71
|
+
val obj = JSONObject()
|
|
72
|
+
obj.put("callId", it.callId)
|
|
73
|
+
obj.put("callData", it.callData)
|
|
74
|
+
obj.put("state", it.state.name)
|
|
75
|
+
jsonArray.put(obj)
|
|
76
|
+
}
|
|
77
|
+
return jsonArray.toString()
|
|
78
|
+
}
|
|
79
|
+
|
|
53
80
|
fun reportIncomingCall(context: Context, callId: String, callData: String) {
|
|
54
81
|
Log.d(TAG, "reportIncomingCall: $callId, $callData")
|
|
55
82
|
val callerName = try {
|
|
56
|
-
val json =
|
|
83
|
+
val json = JSONObject(callData)
|
|
57
84
|
json.optString("name", "Unknown")
|
|
58
85
|
} catch (e: Exception) { "Unknown" }
|
|
59
86
|
|
|
60
|
-
// If not allowed, auto-hold or reject current call
|
|
61
87
|
if (!canMakeMultipleCalls && activeCalls.isNotEmpty()) {
|
|
62
|
-
// Option 1: Auto-hold current call
|
|
63
88
|
activeCalls.values.forEach { it.state = CallState.HELD }
|
|
64
|
-
// Option 2: Reject new call (uncomment to use)
|
|
65
|
-
// return
|
|
66
89
|
}
|
|
67
90
|
|
|
68
|
-
// Add to active calls
|
|
69
91
|
activeCalls[callId] = CallInfo(callId, callData, CallState.INCOMING)
|
|
70
92
|
currentCallId = callId
|
|
71
93
|
|
|
@@ -87,19 +109,35 @@ object CallEngine {
|
|
|
87
109
|
Log.d(TAG, "answerCall: $callId")
|
|
88
110
|
activeCalls[callId]?.state = CallState.ACTIVE
|
|
89
111
|
currentCallId = callId
|
|
90
|
-
// Optionally, auto-hold other calls
|
|
91
112
|
if (!canMakeMultipleCalls) {
|
|
92
113
|
activeCalls.filter { it.key != callId }.values.forEach { it.state = CallState.HELD }
|
|
93
114
|
}
|
|
115
|
+
emitEvent(CallEventType.CALL_ANSWERED, JSONObject().put("callId", callId))
|
|
94
116
|
notifyCallStateChanged(context)
|
|
95
117
|
}
|
|
96
118
|
|
|
97
119
|
fun holdCall(context: Context, callId: String) {
|
|
98
120
|
Log.d(TAG, "holdCall: $callId")
|
|
99
121
|
activeCalls[callId]?.state = CallState.HELD
|
|
122
|
+
emitEvent(CallEventType.CALL_HELD, JSONObject().put("callId", callId))
|
|
100
123
|
notifyCallStateChanged(context)
|
|
101
124
|
}
|
|
102
125
|
|
|
126
|
+
fun unholdCall(context: Context, callId: String) {
|
|
127
|
+
Log.d(TAG, "unholdCall: $callId")
|
|
128
|
+
activeCalls[callId]?.state = CallState.ACTIVE
|
|
129
|
+
emitEvent(CallEventType.CALL_UNHELD, JSONObject().put("callId", callId))
|
|
130
|
+
notifyCallStateChanged(context)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
fun muteCall(context: Context, callId: String) {
|
|
134
|
+
emitEvent(CallEventType.CALL_MUTED, JSONObject().put("callId", callId))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
fun unmuteCall(context: Context, callId: String) {
|
|
138
|
+
emitEvent(CallEventType.CALL_UNMUTED, JSONObject().put("callId", callId))
|
|
139
|
+
}
|
|
140
|
+
|
|
103
141
|
fun endCall(context: Context, callId: String) {
|
|
104
142
|
Log.d(TAG, "endCall: $callId")
|
|
105
143
|
activeCalls[callId]?.state = CallState.ENDED
|
|
@@ -110,6 +148,7 @@ object CallEngine {
|
|
|
110
148
|
cancelIncomingCallUI(context)
|
|
111
149
|
stopForegroundService(context)
|
|
112
150
|
disconnectTelecomCall(context, callId)
|
|
151
|
+
emitEvent(CallEventType.CALL_ENDED, JSONObject().put("callId", callId))
|
|
113
152
|
notifyCallStateChanged(context)
|
|
114
153
|
}
|
|
115
154
|
|
|
@@ -202,7 +241,6 @@ object CallEngine {
|
|
|
202
241
|
}
|
|
203
242
|
|
|
204
243
|
fun disconnectTelecomCall(context: Context, callId: String?) {
|
|
205
|
-
// You can extend this to track and disconnect specific calls if needed.
|
|
206
244
|
Log.d(TAG, "disconnectTelecomCall called for callId=$callId")
|
|
207
245
|
}
|
|
208
246
|
|
|
@@ -214,26 +252,95 @@ object CallEngine {
|
|
|
214
252
|
Log.d(TAG, "App brought to foreground via launchIntent")
|
|
215
253
|
}
|
|
216
254
|
|
|
217
|
-
// ---
|
|
255
|
+
// --- Audio Device Management ---
|
|
218
256
|
|
|
219
|
-
fun
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
257
|
+
fun getAudioDevices(context: Context): List<String> {
|
|
258
|
+
audioManager = audioManager ?: context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
259
|
+
val devices = mutableListOf<String>()
|
|
260
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
261
|
+
audioManager?.getDevices(AudioManager.GET_DEVICES_OUTPUTS)?.forEach { device ->
|
|
262
|
+
when (device.type) {
|
|
263
|
+
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> devices.add("Bluetooth")
|
|
264
|
+
AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_WIRED_HEADSET -> devices.add("Headset")
|
|
265
|
+
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> devices.add("Speaker")
|
|
266
|
+
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> devices.add("Earpiece")
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
devices.add("Speaker")
|
|
271
|
+
devices.add("Earpiece")
|
|
272
|
+
}
|
|
273
|
+
return devices.distinct()
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
fun setAudioRoute(context: Context, route: String) {
|
|
277
|
+
audioManager = audioManager ?: context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
278
|
+
when (route) {
|
|
279
|
+
"Speaker" -> audioManager?.isSpeakerphoneOn = true
|
|
280
|
+
"Earpiece" -> audioManager?.isSpeakerphoneOn = false
|
|
281
|
+
"Bluetooth" -> audioManager?.startBluetoothSco()
|
|
282
|
+
"Headset" -> { /* usually auto-selected */ }
|
|
231
283
|
}
|
|
284
|
+
emitEvent(CallEventType.AUDIO_ROUTE_CHANGED, JSONObject().put("route", route))
|
|
232
285
|
}
|
|
233
286
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
287
|
+
// --- Screen Awake Management ---
|
|
288
|
+
fun keepScreenAwake(context: Context, keepAwake: Boolean) {
|
|
289
|
+
val powerManager = context.getSystemService(Context.POWER_SERVICE) as android.os.PowerManager
|
|
290
|
+
if (keepAwake) {
|
|
291
|
+
if (wakeLock == null || !wakeLock!!.isHeld) {
|
|
292
|
+
wakeLock = powerManager.newWakeLock(
|
|
293
|
+
android.os.PowerManager.SCREEN_DIM_WAKE_LOCK or android.os.PowerManager.ACQUIRE_CAUSES_WAKEUP,
|
|
294
|
+
"CallEngine:WakeLock"
|
|
295
|
+
)
|
|
296
|
+
wakeLock?.acquire()
|
|
297
|
+
}
|
|
298
|
+
} else {
|
|
299
|
+
wakeLock?.let {
|
|
300
|
+
if (it.isHeld) it.release()
|
|
301
|
+
}
|
|
302
|
+
wakeLock = null
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// --- Audio Device Change Listener ---
|
|
307
|
+
private val audioDeviceCallback = object : AudioManager.AudioDeviceCallback() {
|
|
308
|
+
override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
|
|
309
|
+
emitAudioDevicesChanged()
|
|
310
|
+
}
|
|
311
|
+
override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
|
|
312
|
+
emitAudioDevicesChanged()
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
fun registerAudioDeviceCallback(context: Context) {
|
|
317
|
+
audioManager = audioManager ?: context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
318
|
+
audioManager?.registerAudioDeviceCallback(audioDeviceCallback, null)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
fun unregisterAudioDeviceCallback(context: Context) {
|
|
322
|
+
audioManager = audioManager ?: context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
323
|
+
audioManager?.unregisterAudioDeviceCallback(audioDeviceCallback)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
fun emitAudioDevicesChanged() {
|
|
327
|
+
val devices = getAudioDevices(audioManager!!.context)
|
|
328
|
+
val json = JSONObject().put("devices", JSONArray(devices))
|
|
329
|
+
emitEvent(CallEventType.AUDIO_DEVICES_CHANGED, json)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// --- Call State Change Notification ---
|
|
333
|
+
private fun notifyCallStateChanged(context: Context) {
|
|
334
|
+
val calls = getActiveCalls()
|
|
335
|
+
val jsonArray = JSONArray()
|
|
336
|
+
calls.forEach {
|
|
337
|
+
val obj = JSONObject()
|
|
338
|
+
obj.put("callId", it.callId)
|
|
339
|
+
obj.put("callData", it.callData)
|
|
340
|
+
obj.put("state", it.state.name)
|
|
341
|
+
jsonArray.put(obj)
|
|
342
|
+
}
|
|
343
|
+
emitEvent(CallEventType.CALL_STATE_CHANGED, JSONObject().put("calls", jsonArray))
|
|
237
344
|
}
|
|
238
345
|
|
|
239
346
|
private fun createNotificationChannel(context: Context) {
|
|
@@ -278,68 +385,4 @@ object CallEngine {
|
|
|
278
385
|
PHONE_ACCOUNT_ID
|
|
279
386
|
)
|
|
280
387
|
}
|
|
281
|
-
|
|
282
|
-
// --- JS/React Native Integration ---
|
|
283
|
-
|
|
284
|
-
private var callStateListener: ((List<CallInfo>) -> Unit)? = null
|
|
285
|
-
|
|
286
|
-
fun setCallStateListener(listener: ((List<CallInfo>) -> Unit)?) {
|
|
287
|
-
callStateListener = listener
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
private fun notifyCallStateChanged(context: Context) {
|
|
291
|
-
callStateListener?.invoke(getActiveCalls())
|
|
292
|
-
// Optionally, send a local broadcast or use DeviceEventEmitter for JS
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
fun getAudioDevices(context: Context): List<String> {
|
|
296
|
-
audioManager = audioManager ?: context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
297
|
-
val devices = mutableListOf<String>()
|
|
298
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
299
|
-
audioManager?.getDevices(AudioManager.GET_DEVICES_OUTPUTS)?.forEach { device ->
|
|
300
|
-
when (device.type) {
|
|
301
|
-
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> devices.add("Bluetooth")
|
|
302
|
-
AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_WIRED_HEADSET -> devices.add("Headset")
|
|
303
|
-
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> devices.add("Speaker")
|
|
304
|
-
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> devices.add("Earpiece")
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
} else {
|
|
308
|
-
// Fallback for older devices
|
|
309
|
-
devices.add("Speaker")
|
|
310
|
-
devices.add("Earpiece")
|
|
311
|
-
}
|
|
312
|
-
return devices.distinct()
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
fun setAudioRoute(context: Context, route: String) {
|
|
316
|
-
audioManager = audioManager ?: context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
317
|
-
when (route) {
|
|
318
|
-
"Speaker" -> audioManager?.isSpeakerphoneOn = true
|
|
319
|
-
"Earpiece" -> audioManager?.isSpeakerphoneOn = false
|
|
320
|
-
"Bluetooth" -> audioManager?.startBluetoothSco()
|
|
321
|
-
"Headset" -> { /* usually auto-selected */ }
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// --- Screen Awake Management ---
|
|
326
|
-
private var wakeLock: android.os.PowerManager.WakeLock? = null
|
|
327
|
-
|
|
328
|
-
fun keepScreenAwake(context: Context, keepAwake: Boolean) {
|
|
329
|
-
val powerManager = context.getSystemService(Context.POWER_SERVICE) as android.os.PowerManager
|
|
330
|
-
if (keepAwake) {
|
|
331
|
-
if (wakeLock == null || !wakeLock!!.isHeld) {
|
|
332
|
-
wakeLock = powerManager.newWakeLock(
|
|
333
|
-
android.os.PowerManager.SCREEN_DIM_WAKE_LOCK or android.os.PowerManager.ACQUIRE_CAUSES_WAKEUP,
|
|
334
|
-
"CallEngine:WakeLock"
|
|
335
|
-
)
|
|
336
|
-
wakeLock?.acquire()
|
|
337
|
-
}
|
|
338
|
-
} else {
|
|
339
|
-
wakeLock?.let {
|
|
340
|
-
if (it.isHeld) it.release()
|
|
341
|
-
}
|
|
342
|
-
wakeLock = null
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
388
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package com.qusaieilouti99.callmanager
|
|
2
|
+
|
|
3
|
+
enum class CallEventType {
|
|
4
|
+
INITIAL_CALL_STATE,
|
|
5
|
+
CALL_STATE_CHANGED,
|
|
6
|
+
AUDIO_DEVICES_CHANGED,
|
|
7
|
+
AUDIO_ROUTE_CHANGED,
|
|
8
|
+
CALL_HELD,
|
|
9
|
+
CALL_UNHELD,
|
|
10
|
+
CALL_MUTED,
|
|
11
|
+
CALL_UNMUTED,
|
|
12
|
+
CALL_ANSWERED,
|
|
13
|
+
CALL_REJECTED,
|
|
14
|
+
CALL_ENDED
|
|
15
|
+
}
|
|
@@ -14,26 +14,29 @@ class CallManagerModule(reactContext: ReactApplicationContext) :
|
|
|
14
14
|
const val TAG = "CallManagerModule"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
// JSI event handler (set from JS)
|
|
18
17
|
private var eventHandler: Callback? = null
|
|
19
18
|
|
|
20
19
|
override fun getName(): String = NAME
|
|
21
20
|
|
|
22
|
-
// JSI event handler registration
|
|
23
21
|
override fun setEventHandler(callback: Callback) {
|
|
24
22
|
Log.d(TAG, "setEventHandler called, registering JS callback")
|
|
25
23
|
eventHandler = callback
|
|
26
|
-
|
|
24
|
+
CallEngine.setEventHandler { eventType, data ->
|
|
25
|
+
eventHandler?.invoke(eventType.name, data)
|
|
26
|
+
}
|
|
27
|
+
// Send initial call state if there is an active call
|
|
28
|
+
val initialCallState = CallEngine.getCurrentCallState()
|
|
29
|
+
if (initialCallState.isNotEmpty()) {
|
|
30
|
+
Log.d(TAG, "Sending initial call state to JS: $initialCallState")
|
|
31
|
+
eventHandler?.invoke(CallEventType.INITIAL_CALL_STATE.name, initialCallState)
|
|
32
|
+
}
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
// JSI event emission (call from CallEngine or anywhere)
|
|
30
35
|
fun emitEvent(event: String, callData: String) {
|
|
31
36
|
Log.d(TAG, "emitEvent: event=$event, callData=$callData")
|
|
32
37
|
eventHandler?.invoke(event, callData)
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
// --- Call control (all JSI, no bridge) ---
|
|
36
|
-
|
|
37
40
|
override fun reportIncomingCall(callId: String, callData: String) {
|
|
38
41
|
Log.d(TAG, "reportIncomingCall called from JS with callId=$callId, callData=$callData")
|
|
39
42
|
CallEngine.reportIncomingCall(reactApplicationContext, callId, callData)
|
|
@@ -61,8 +64,6 @@ class CallManagerModule(reactContext: ReactApplicationContext) :
|
|
|
61
64
|
CallEngine.reportIncomingCall(reactApplicationContext, callId, callData)
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
// --- JSI-native audio/device/screen APIs ---
|
|
65
|
-
|
|
66
67
|
override fun getAudioDevices(): WritableArray {
|
|
67
68
|
val devices = CallEngine.getAudioDevices(reactApplicationContext)
|
|
68
69
|
val array = Arguments.createArray()
|
|
@@ -3,8 +3,8 @@ package com.qusaieilouti99.callmanager
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.telecom.Connection
|
|
5
5
|
import android.telecom.DisconnectCause
|
|
6
|
+
import android.telecom.CallAudioState
|
|
6
7
|
import android.util.Log
|
|
7
|
-
import com.facebook.react.ReactApplication
|
|
8
8
|
|
|
9
9
|
class MyConnection(
|
|
10
10
|
private val context: Context,
|
|
@@ -18,14 +18,7 @@ class MyConnection(
|
|
|
18
18
|
override fun onAnswer() {
|
|
19
19
|
Log.d(TAG, "Call answered")
|
|
20
20
|
setActive()
|
|
21
|
-
|
|
22
|
-
(context.applicationContext as? ReactApplication)?.let { app ->
|
|
23
|
-
val module = app.reactNativeHost.reactInstanceManager
|
|
24
|
-
.currentReactContext
|
|
25
|
-
?.getNativeModule(CallManagerModule::class.java)
|
|
26
|
-
module?.emitEvent("onCallAnswered", callData)
|
|
27
|
-
}
|
|
28
|
-
// Bring app to foreground
|
|
21
|
+
CallEngine.answerCall(context, callData)
|
|
29
22
|
CallEngine.bringAppToForeground(context)
|
|
30
23
|
}
|
|
31
24
|
|
|
@@ -33,31 +26,40 @@ class MyConnection(
|
|
|
33
26
|
Log.d(TAG, "Call rejected")
|
|
34
27
|
setDisconnected(DisconnectCause(DisconnectCause.REJECTED))
|
|
35
28
|
destroy()
|
|
36
|
-
(context
|
|
37
|
-
val module = app.reactNativeHost.reactInstanceManager
|
|
38
|
-
.currentReactContext
|
|
39
|
-
?.getNativeModule(CallManagerModule::class.java)
|
|
40
|
-
module?.emitEvent("onCallRejected", callData)
|
|
41
|
-
}
|
|
42
|
-
// Clean up
|
|
43
|
-
CallEngine.cancelIncomingCallUI(context)
|
|
44
|
-
CallEngine.stopForegroundService(context)
|
|
45
|
-
CallEngine.disconnectTelecomCall(context, "")
|
|
29
|
+
CallEngine.endCall(context, callData)
|
|
46
30
|
}
|
|
47
31
|
|
|
48
32
|
override fun onDisconnect() {
|
|
49
33
|
Log.d(TAG, "Call disconnected")
|
|
50
34
|
setDisconnected(DisconnectCause(DisconnectCause.LOCAL))
|
|
51
35
|
destroy()
|
|
52
|
-
(context
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
36
|
+
CallEngine.endCall(context, callData)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override fun onHold() {
|
|
40
|
+
super.onHold()
|
|
41
|
+
Log.d(TAG, "Call held")
|
|
42
|
+
CallEngine.holdCall(context, callData)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override fun onUnhold() {
|
|
46
|
+
super.onUnhold()
|
|
47
|
+
Log.d(TAG, "Call unheld")
|
|
48
|
+
CallEngine.unholdCall(context, callData)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override fun onCallAudioStateChanged(state: CallAudioState) {
|
|
52
|
+
super.onCallAudioStateChanged(state)
|
|
53
|
+
Log.d(TAG, "Audio state changed: muted=${state.isMuted}, route=${state.route}")
|
|
54
|
+
if (state.isMuted) {
|
|
55
|
+
CallEngine.muteCall(context, callData)
|
|
56
|
+
} else {
|
|
57
|
+
CallEngine.unmuteCall(context, callData)
|
|
57
58
|
}
|
|
58
|
-
//
|
|
59
|
-
CallEngine.
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
// Do NOT emit audio devices changed here; only emit route change
|
|
60
|
+
CallEngine.emitEvent(
|
|
61
|
+
CallEventType.AUDIO_ROUTE_CHANGED,
|
|
62
|
+
org.json.JSONObject().put("route", state.route)
|
|
63
|
+
)
|
|
62
64
|
}
|
|
63
65
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"..\\..\\src","sources":["NativeCallManager.ts"],"mappings":";;AACA,
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"..\\..\\src","sources":["NativeCallManager.ts"],"mappings":";;AAAA;AACA,SAA2BA,mBAAmB,QAAQ,cAAc;AAgBpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,aAAa,CAAC","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import CallManager from "./NativeCallManager.js";
|
|
4
|
-
export
|
|
4
|
+
export const reportIncomingCall = CallManager.reportIncomingCall;
|
|
5
|
+
export const endCall = CallManager.endCall;
|
|
6
|
+
export const answerCall = CallManager.answerCall;
|
|
7
|
+
export const silenceRingtone = CallManager.silenceRingtone;
|
|
8
|
+
export const rejectCurrentAndAnswerNew = CallManager.rejectCurrentAndAnswerNew;
|
|
9
|
+
export const setEventHandler = CallManager.setEventHandler;
|
|
10
|
+
export const getAudioDevices = CallManager.getAudioDevices;
|
|
11
|
+
export const setAudioRoute = CallManager.setAudioRoute;
|
|
12
|
+
export const keepScreenAwake = CallManager.keepScreenAwake;
|
|
5
13
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["CallManager"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,WAAW,MAAM,wBAAqB;
|
|
1
|
+
{"version":3,"names":["CallManager","reportIncomingCall","endCall","answerCall","silenceRingtone","rejectCurrentAndAnswerNew","setEventHandler","getAudioDevices","setAudioRoute","keepScreenAwake"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":";;AAAA,OAAOA,WAAW,MAAM,wBAAqB;AAG7C,OAAO,MAAMC,kBAAkB,GAAGD,WAAW,CAACC,kBAAkB;AAChE,OAAO,MAAMC,OAAO,GAAGF,WAAW,CAACE,OAAO;AAC1C,OAAO,MAAMC,UAAU,GAAGH,WAAW,CAACG,UAAU;AAChD,OAAO,MAAMC,eAAe,GAAGJ,WAAW,CAACI,eAAe;AAC1D,OAAO,MAAMC,yBAAyB,GAAGL,WAAW,CAACK,yBAAyB;AAC9E,OAAO,MAAMC,eAAe,GAAGN,WAAW,CAACM,eAAe;AAE1D,OAAO,MAAMC,eAAe,GAAGP,WAAW,CAACO,eAAe;AAC1D,OAAO,MAAMC,aAAa,GAAGR,WAAW,CAACQ,aAAa;AACtD,OAAO,MAAMC,eAAe,GAAGT,WAAW,CAACS,eAAe","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeCallManager.d.ts","sourceRoot":"","sources":["../../../src/NativeCallManager.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NativeCallManager.d.ts","sourceRoot":"","sources":["../../../src/NativeCallManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3D,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,IAAI,IAAI,CAAC;IACxB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAClE,eAAe,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAG3E,eAAe,IAAI,MAAM,EAAE,CAAC;IAC5B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3C;;AAED,wBAAqE"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
export declare const reportIncomingCall: (callId: string, callData: string) => void;
|
|
2
|
+
export declare const endCall: (callId: string) => void;
|
|
3
|
+
export declare const answerCall: (callId: string) => void;
|
|
4
|
+
export declare const silenceRingtone: () => void;
|
|
5
|
+
export declare const rejectCurrentAndAnswerNew: (callId: string, callData: string) => void;
|
|
6
|
+
export declare const setEventHandler: (callback: (event: string, callData: string) => void) => void;
|
|
7
|
+
export declare const getAudioDevices: () => string[];
|
|
8
|
+
export declare const setAudioRoute: (route: string) => void;
|
|
9
|
+
export declare const keepScreenAwake: (keepAwake: boolean) => void;
|
|
3
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB,4CAAiC,CAAC;AACjE,eAAO,MAAM,OAAO,0BAAsB,CAAC;AAC3C,eAAO,MAAM,UAAU,0BAAyB,CAAC;AACjD,eAAO,MAAM,eAAe,YAA8B,CAAC;AAC3D,eAAO,MAAM,yBAAyB,4CAAwC,CAAC;AAC/E,eAAO,MAAM,eAAe,+DAA8B,CAAC;AAE3D,eAAO,MAAM,eAAe,gBAA8B,CAAC;AAC3D,eAAO,MAAM,aAAa,yBAA4B,CAAC;AACvD,eAAO,MAAM,eAAe,8BAA8B,CAAC"}
|
package/package.json
CHANGED
package/src/NativeCallManager.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import { TurboModuleRegistry } from 'react-native';
|
|
1
|
+
// NativeCallManager.ts
|
|
2
|
+
import { type TurboModule, TurboModuleRegistry } from 'react-native';
|
|
3
3
|
|
|
4
4
|
export interface Spec extends TurboModule {
|
|
5
5
|
reportIncomingCall(callId: string, callData: string): void;
|
package/src/index.tsx
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
import CallManager from './NativeCallManager';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
export const reportIncomingCall = CallManager.reportIncomingCall;
|
|
5
|
+
export const endCall = CallManager.endCall;
|
|
6
|
+
export const answerCall = CallManager.answerCall;
|
|
7
|
+
export const silenceRingtone = CallManager.silenceRingtone;
|
|
8
|
+
export const rejectCurrentAndAnswerNew = CallManager.rejectCurrentAndAnswerNew;
|
|
9
|
+
export const setEventHandler = CallManager.setEventHandler;
|
|
10
|
+
|
|
11
|
+
export const getAudioDevices = CallManager.getAudioDevices;
|
|
12
|
+
export const setAudioRoute = CallManager.setAudioRoute;
|
|
13
|
+
export const keepScreenAwake = CallManager.keepScreenAwake;
|