@qusaieilouti99/call-manager 0.1.36 → 0.1.38

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.
@@ -12,16 +12,16 @@ import android.media.MediaPlayer
12
12
  import android.media.RingtoneManager
13
13
  import android.net.Uri
14
14
  import android.os.Build
15
- import android.os.Bundle // Explicit import
15
+ import android.os.Bundle
16
16
  import android.os.PowerManager
17
- import android.telecom.CallAudioState // Explicit import
18
- import android.telecom.Connection // Explicit import
19
- import android.telecom.DisconnectCause // Explicit import
20
- import android.telecom.PhoneAccount // Explicit import
21
- import android.telecom.PhoneAccountHandle // Explicit import
22
- import android.telecom.TelecomManager // Explicit import
23
- import android.telecom.VideoProfile // Explicit import
24
- import android.util.Log // Explicit import
17
+ import android.telecom.CallAudioState
18
+ import android.telecom.Connection
19
+ import android.telecom.DisconnectCause
20
+ import android.telecom.PhoneAccount
21
+ import android.telecom.PhoneAccountHandle
22
+ import android.telecom.TelecomManager
23
+ import android.telecom.VideoProfile
24
+ import android.util.Log
25
25
  import android.graphics.Color
26
26
  import android.app.Person
27
27
  import org.json.JSONArray
@@ -38,15 +38,15 @@ object CallEngine {
38
38
  private const val FOREGROUND_NOTIF_ID = 1001
39
39
 
40
40
  private var ringtone: android.media.Ringtone? = null
41
- private var ringbackPlayer: MediaPlayer? = null // For outgoing call ringback
41
+ private var ringbackPlayer: MediaPlayer? = null
42
42
  private var audioManager: AudioManager? = null
43
43
  private var wakeLock: PowerManager.WakeLock? = null
44
44
  private var appContext: Context? = null
45
45
 
46
46
  // --- Multi-call state ---
47
- private val activeCalls = ConcurrentHashMap<String, CallInfo>() // callId -> CallInfo
48
- private val telecomConnections = ConcurrentHashMap<String, Connection>() // callId -> Telecom Connection
49
- private var currentCallId: String? = null // The call currently in foreground (active/ringing/dialing)
47
+ private val activeCalls = ConcurrentHashMap<String, CallInfo>()
48
+ private val telecomConnections = ConcurrentHashMap<String, Connection>()
49
+ private var currentCallId: String? = null
50
50
  private var canMakeMultipleCalls: Boolean = true
51
51
 
52
52
  data class CallInfo(
@@ -61,14 +61,12 @@ object CallEngine {
61
61
  }
62
62
 
63
63
  // --- Event handler for JS ---
64
- // Changed listener type to generated Func_void_CallEventType_std__string
65
64
  private var eventHandler: ((CallEventType, String) -> Unit)? = null
66
- private val cachedEvents = mutableListOf<Pair<CallEventType, String>>() // For caching events
65
+ private val cachedEvents = mutableListOf<Pair<CallEventType, String>>()
67
66
 
68
67
  fun setEventHandler(handler: ((CallEventType, String) -> Unit)?) {
69
68
  Log.d(TAG, "setEventHandler called. Handler present: ${handler != null}")
70
69
  eventHandler = handler
71
- // Emit cached events if a handler is now available
72
70
  handler?.let { h ->
73
71
  if (cachedEvents.isNotEmpty()) {
74
72
  Log.d(TAG, "Emitting ${cachedEvents.size} cached events.")
@@ -78,7 +76,6 @@ object CallEngine {
78
76
  }
79
77
  }
80
78
 
81
- // Emit event uses the generated CallEventType enum directly
82
79
  fun emitEvent(type: CallEventType, data: JSONObject) {
83
80
  Log.d(TAG, "Emitting event: $type, data: $data")
84
81
  val dataString = data.toString()
@@ -126,7 +123,7 @@ object CallEngine {
126
123
  return result
127
124
  }
128
125
 
129
- // Removed callType param, now extracted from callData
126
+ // This is for INCOMING calls using TelecomManager.addNewIncomingCall
130
127
  fun reportIncomingCall(context: Context, callId: String, callData: String) {
131
128
  appContext = context.applicationContext
132
129
  Log.d(TAG, "reportIncomingCall: $callId, $callData")
@@ -136,12 +133,12 @@ object CallEngine {
136
133
  json.optString("name", "Unknown")
137
134
  } catch (e: Exception) { "Unknown" }
138
135
 
139
- val parsedCallType = try { // Extract callType from callData
136
+ val parsedCallType = try {
140
137
  val json = JSONObject(callData)
141
138
  json.optString("callType", "Audio")
142
139
  } catch (e: Exception) { "Audio" }
143
140
 
144
- val isVideoCallBoolean = parsedCallType == "Video" // Convert to boolean for Telecom API
141
+ val isVideoCallBoolean = parsedCallType == "Video"
145
142
 
146
143
  if (!canMakeMultipleCalls && activeCalls.isNotEmpty()) {
147
144
  Log.d(TAG, "Can't make multiple calls, holding existing calls.")
@@ -153,14 +150,15 @@ object CallEngine {
153
150
  Log.d(TAG, "Call $callId added to activeCalls. State: INCOMING, callType: $parsedCallType")
154
151
 
155
152
  showIncomingCallUI(context, callId, callerName, parsedCallType)
156
- registerPhoneAccount(context)
153
+ registerPhoneAccount(context) // Register phone account so Telecom can handle incoming
157
154
  val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
158
155
  val phoneAccountHandle = getPhoneAccountHandle(context)
159
156
  val extras = Bundle().apply {
160
- putString(MyConnectionService.EXTRA_CALL_DATA, callData) // Pass raw callData
161
- putBoolean(MyConnectionService.EXTRA_IS_VIDEO_CALL_BOOLEAN, isVideoCallBoolean) // Pass boolean for Telecom
157
+ putString(MyConnectionService.EXTRA_CALL_DATA, callData)
158
+ putBoolean(MyConnectionService.EXTRA_IS_VIDEO_CALL_BOOLEAN, isVideoCallBoolean)
162
159
  }
163
160
  try {
161
+ // This API is fundamental for INCOMING call integration with Telecom.
164
162
  telecomManager.addNewIncomingCall(phoneAccountHandle, extras)
165
163
  startForegroundService(context)
166
164
  Log.d(TAG, "Successfully reported incoming call to TelecomManager for $callId")
@@ -174,7 +172,7 @@ object CallEngine {
174
172
  notifyCallStateChanged(context)
175
173
  }
176
174
 
177
- // Removed callType param, now extracted from callData
175
+ // CORRECTED: Uses TelecomManager.placeCall for outgoing calls.
178
176
  fun startOutgoingCall(context: Context, callId: String, callData: String) {
179
177
  appContext = context.applicationContext
180
178
  Log.d(TAG, "startOutgoingCall: $callId, $callData")
@@ -184,12 +182,12 @@ object CallEngine {
184
182
  json.optString("name", "Unknown")
185
183
  } catch (e: Exception) { "Unknown" }
186
184
 
187
- val parsedCallType = try { // Extract callType from callData
185
+ val parsedCallType = try {
188
186
  val json = JSONObject(callData)
189
187
  json.optString("callType", "Audio")
190
188
  } catch (e: Exception) { "Audio" }
191
189
 
192
- val isVideoCallBoolean = parsedCallType == "Video" // Convert to boolean for Telecom API
190
+ val isVideoCallBoolean = parsedCallType == "Video"
193
191
 
194
192
  if (!canMakeMultipleCalls && activeCalls.isNotEmpty()) {
195
193
  Log.d(TAG, "Can't make multiple calls, holding existing calls before outgoing.")
@@ -200,33 +198,41 @@ object CallEngine {
200
198
  currentCallId = callId
201
199
  Log.d(TAG, "Call $callId added to activeCalls. State: DIALING, callType: $parsedCallType")
202
200
 
203
- registerPhoneAccount(context)
201
+ registerPhoneAccount(context) // Ensure PhoneAccount is registered for Telecom to recognize it
204
202
  val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
205
203
  val phoneAccountHandle = getPhoneAccountHandle(context)
204
+
205
+ // For `placeCall`, the address URI is usually required. Use a generic "tel:" scheme with callId or number.
206
+ val addressUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, callId, null) // Using callId as a unique identifier for URI
207
+
206
208
  val extras = Bundle().apply {
207
- putString(MyConnectionService.EXTRA_CALL_DATA, callData) // Pass raw callData
208
- putBoolean(MyConnectionService.EXTRA_IS_VIDEO_CALL_BOOLEAN, isVideoCallBoolean) // Pass boolean for Telecom
209
- // Set speaker for video calls initially in Telecom's extras
209
+ // Essential for self-managed apps using placeCall
210
+ putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle)
211
+ // Pass additional data for your ConnectionService to retrieve
212
+ putString(MyConnectionService.EXTRA_CALL_DATA, callData)
213
+ putBoolean(MyConnectionService.EXTRA_IS_VIDEO_CALL_BOOLEAN, isVideoCallBoolean)
214
+ // Hint for initial speakerphone state
210
215
  putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, isVideoCallBoolean)
211
216
  }
212
217
 
213
218
  try {
214
- telecomManager.addNewOutgoingCall(phoneAccountHandle, extras)
219
+ // CORRECT API for self-managed outgoing calls that interact with Telecom
220
+ telecomManager.placeCall(addressUri, extras)
215
221
  startForegroundService(context)
216
- Log.d(TAG, "Successfully reported outgoing call to TelecomManager for $callId")
222
+ Log.d(TAG, "Successfully reported outgoing call to TelecomManager via placeCall for $callId")
217
223
  startRingback()
218
224
  bringAppToForeground(context)
219
225
  keepScreenAwake(context, true)
220
- if (parsedCallType == "Video") { // Initial audio route for video calls
226
+ if (parsedCallType == "Video") {
221
227
  setAudioRoute(context, "Speaker")
222
228
  } else {
223
- setAudioRoute(context, "Earpiece") // Initial audio route for audio calls
229
+ setAudioRoute(context, "Earpiece")
224
230
  }
225
231
  } catch (e: SecurityException) {
226
- Log.e(TAG, "SecurityException: Failed to start outgoing call. Check MANAGE_OWN_CALLS permission: ${e.message}", e)
232
+ Log.e(TAG, "SecurityException: Failed to start outgoing call via placeCall. Check MANAGE_OWN_CALLS permission: ${e.message}", e)
227
233
  endCall(context, callId)
228
234
  } catch (e: Exception) {
229
- Log.e(TAG, "Failed to start outgoing call: ${e.message}", e)
235
+ Log.e(TAG, "Failed to start outgoing call via placeCall: ${e.message}", e)
230
236
  endCall(context, callId)
231
237
  }
232
238
  notifyCallStateChanged(context)
@@ -263,7 +269,7 @@ object CallEngine {
263
269
 
264
270
  fun holdCall(context: Context, callId: String) {
265
271
  Log.d(TAG, "holdCall: $callId")
266
- activeCalls[callId]?.state = CallState.HELD
272
+ // Always attempt to inform Telecom if a Connection object exists for this callId
267
273
  val connection = telecomConnections[callId]
268
274
  connection?.setOnHold()
269
275
  emitEvent(CallEventType.CALL_HELD, JSONObject().put("callId", callId))
@@ -273,6 +279,7 @@ object CallEngine {
273
279
  fun unholdCall(context: Context, callId: String) {
274
280
  Log.d(TAG, "unholdCall: $callId")
275
281
  activeCalls[callId]?.state = CallState.ACTIVE
282
+ // Always attempt to inform Telecom if a Connection object exists for this callId
276
283
  val connection = telecomConnections[callId]
277
284
  connection?.setActive()
278
285
  emitEvent(CallEventType.CALL_UNHELD, JSONObject().put("callId", callId))
@@ -310,6 +317,7 @@ object CallEngine {
310
317
 
311
318
  cancelIncomingCallUI(context)
312
319
 
320
+ // Only disconnect from Telecom if a Connection object exists for this callId
313
321
  val connection = telecomConnections[callId]
314
322
  if (connection != null) {
315
323
  connection.setDisconnected(DisconnectCause(DisconnectCause.LOCAL))
@@ -317,7 +325,7 @@ object CallEngine {
317
325
  removeTelecomConnection(callId)
318
326
  Log.d(TAG, "Telecom Connection for $callId disconnected and destroyed.")
319
327
  } else {
320
- Log.w(TAG, "No Telecom Connection found for callId=$callId. It might have already been handled by Telecom.")
328
+ Log.d(TAG, "No Telecom Connection found for callId=$callId. Likely an outgoing call not initially handled by Telecom.")
321
329
  }
322
330
 
323
331
  if (activeCalls.isEmpty()) {
@@ -446,11 +454,10 @@ object CallEngine {
446
454
 
447
455
  // --- Audio Device Management ---
448
456
 
449
- // Returns the generated AudioRoutesInfo data class
450
457
  fun getAudioDevices(): AudioRoutesInfo {
451
- audioManager = audioManager ?: appContext?.getSystemService(Context.AUDIO_SERVICE) as? AudioManager ?: run {
458
+ audioManager = appContext?.getSystemService(Context.AUDIO_SERVICE) as? AudioManager ?: run {
452
459
  Log.e(TAG, "getAudioDevices: AudioManager is null or appContext is not set. Returning default.")
453
- return AudioRoutesInfo(emptyArray(), "Unknown") // Return default empty info
460
+ return AudioRoutesInfo(emptyArray(), "Unknown")
454
461
  }
455
462
  val devices = mutableListOf<String>()
456
463
  var currentRoute: String = "Unknown"
@@ -461,7 +468,7 @@ object CallEngine {
461
468
  when (device.type) {
462
469
  AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> {
463
470
  devices.add("Bluetooth")
464
- if (audioManager?.isBluetoothScoOn == true && !device.isSource) currentRoute = "Bluetooth" // check if output device
471
+ if (audioManager?.isBluetoothScoOn == true && !device.isSource) currentRoute = "Bluetooth"
465
472
  }
466
473
  AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_WIRED_HEADSET -> {
467
474
  devices.add("Headset")
@@ -473,10 +480,7 @@ object CallEngine {
473
480
  }
474
481
  AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> {
475
482
  devices.add("Earpiece")
476
- // Earpiece is active if speaker, bluetooth, and headset are off
477
- // This heuristic is tricky, relies on other routes being off
478
483
  if (audioManager?.isSpeakerphoneOn == false && audioManager?.isWiredHeadsetOn == false && audioManager?.isBluetoothScoOn == false && !device.isSource) {
479
- // This heuristic is tricky, relies on other routes being off
480
484
  currentRoute = "Earpiece"
481
485
  }
482
486
  }
@@ -484,17 +488,15 @@ object CallEngine {
484
488
  }
485
489
  }
486
490
  } else {
487
- // Fallback for older APIs. Detection is less reliable.
488
491
  devices.add("Speaker")
489
492
  devices.add("Earpiece")
490
493
  if (audioManager?.isSpeakerphoneOn == true) currentRoute = "Speaker"
491
- else currentRoute = "Earpiece" // Best guess for older API
494
+ else currentRoute = "Earpiece"
492
495
  }
493
496
 
494
497
  val distinctDevices = devices.distinct().toTypedArray()
495
498
 
496
- // Final check/refinement for currentRoute based on AudioManager flags
497
- if (currentRoute == "Unknown" || currentRoute == "Earpiece") { // If still unknown or defaulted to earpiece
499
+ if (currentRoute == "Unknown" || currentRoute == "Earpiece") {
498
500
  if (audioManager?.isBluetoothScoOn == true) {
499
501
  currentRoute = "Bluetooth"
500
502
  } else if (audioManager?.isSpeakerphoneOn == true) {
@@ -502,7 +504,7 @@ object CallEngine {
502
504
  } else if (audioManager?.isWiredHeadsetOn == true) {
503
505
  currentRoute = "Headset"
504
506
  } else {
505
- currentRoute = "Earpiece" // Assume earpiece as last resort
507
+ currentRoute = "Earpiece"
506
508
  }
507
509
  }
508
510
 
@@ -544,8 +546,6 @@ object CallEngine {
544
546
  Log.w(TAG, "Unknown audio route: $route. No action taken.")
545
547
  }
546
548
  }
547
- // Emit event immediately with the requested route.
548
- // The actual route change will be confirmed by onCallAudioStateChanged callback.
549
549
  emitEvent(CallEventType.AUDIO_ROUTE_CHANGED, JSONObject().put("route", route))
550
550
  }
551
551
 
@@ -617,12 +617,12 @@ object CallEngine {
617
617
  Log.w(TAG, "Cannot emit AudioDevicesChanged: appContext is null.")
618
618
  return
619
619
  }
620
- val audioInfo = getAudioDevices() // Get AudioRoutesInfo data class
621
- val jsonPayload = JSONObject().apply { // Convert to JSONObject for emitEvent
620
+ val audioInfo = getAudioDevices()
621
+ val jsonPayload = JSONObject().apply {
622
622
  put("devices", JSONArray(audioInfo.devices.toList()))
623
623
  put("currentRoute", audioInfo.currentRoute)
624
624
  }
625
- emitEvent(CallEventType.AUDIO_DEVICES_CHANGED, jsonPayload) // Emit the full JSON object
625
+ emitEvent(CallEventType.AUDIO_DEVICES_CHANGED, jsonPayload)
626
626
  }
627
627
 
628
628
  // --- Call State Change Notification ---
@@ -671,6 +671,7 @@ object CallEngine {
671
671
  }
672
672
  }
673
673
 
674
+ // PhoneAccount registration is used for both INCOMING and OUTGOING calls when interacting with Telecom
674
675
  private fun registerPhoneAccount(context: Context) {
675
676
  val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
676
677
  val phoneAccountHandle = getPhoneAccountHandle(context)
@@ -699,7 +700,6 @@ object CallEngine {
699
700
  }
700
701
 
701
702
  // --- Ringtone Management (for incoming calls, pre-Android S) ---
702
- // Can rely on default ringtone without adding custom file for incoming calls.
703
703
  fun playRingtone(context: Context) {
704
704
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
705
705
  Log.d(TAG, "playRingtone: Android S+ detected, system will handle ringtone via Telecom.")
@@ -732,15 +732,12 @@ object CallEngine {
732
732
  }
733
733
 
734
734
  // --- Ringback Tone Management (for outgoing calls) ---
735
- // Requires `res/raw/ringback_tone.mp3` for custom outgoing ringback.
736
735
  private fun startRingback() {
737
736
  if (ringbackPlayer != null && ringbackPlayer!!.isPlaying) {
738
737
  Log.d(TAG, "Ringback tone already playing.")
739
738
  return
740
739
  }
741
740
  try {
742
- // Ensure you have `res/raw/ringback_tone.mp3` in your project for this to work.
743
- // If you don't want a custom ringback, you can play a silent audio file or do nothing here.
744
741
  val ringbackUri = Uri.parse("android.resource://${appContext?.packageName}/raw/ringback_tone")
745
742
  ringbackPlayer = MediaPlayer.create(appContext, ringbackUri)
746
743
  if (ringbackPlayer == null) {
@@ -6,9 +6,9 @@ import android.app.Service
6
6
  import android.content.Context
7
7
  import android.content.Intent
8
8
  import android.os.Build
9
- import android.util.Log // Explicit import
9
+ import android.util.Log
10
10
  import android.os.IBinder
11
- import android.app.NotificationManager // Explicit import
11
+ import android.app.NotificationManager
12
12
 
13
13
  class CallForegroundService : Service() {
14
14
 
@@ -61,7 +61,7 @@ class CallForegroundService : Service() {
61
61
  NotificationManager.IMPORTANCE_LOW
62
62
  )
63
63
  channel.description = "Notification for ongoing calls"
64
- val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Corrected usage
64
+ val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
65
65
  manager.createNotificationChannel(channel)
66
66
  Log.d(TAG, "Foreground notification channel '$CHANNEL_ID' created/updated.")
67
67
  }
@@ -1,7 +1,7 @@
1
1
  package com.margelo.nitro.qusaieilouti99.callmanager
2
2
 
3
3
  import com.facebook.proguard.annotations.DoNotStrip
4
- import android.util.Log // Explicit import
4
+ import android.util.Log
5
5
  import org.json.JSONArray
6
6
  import org.json.JSONObject
7
7
 
@@ -10,8 +10,6 @@ class CallManager : HybridCallManagerSpec() {
10
10
 
11
11
  private val TAG = "CallManager"
12
12
 
13
- // Listener type now directly matches the generated Func_void_CallEventType_std__string
14
- // This is the correct type from your Nitro codegen output.
15
13
  private var currentListener: Func_void_CallEventType_std__string? = null
16
14
 
17
15
  override fun endCall(callId: String) {
@@ -28,14 +26,13 @@ class CallManager : HybridCallManagerSpec() {
28
26
  } ?: Log.e(TAG, "App context not set for silenceRingtone.")
29
27
  }
30
28
 
31
- // Return type changed to AudioRoutesInfo from String
32
29
  override fun getAudioDevices(): AudioRoutesInfo {
33
30
  Log.d(TAG, "getAudioDevices requested.")
34
31
  return CallEngine.getAppContext()?.let {
35
- CallEngine.getAudioDevices() // This now directly returns AudioRoutesInfo
32
+ CallEngine.getAudioDevices()
36
33
  } ?: run {
37
34
  Log.e(TAG, "App context not set for getAudioDevices. Returning empty AudioRoutesInfo.")
38
- AudioRoutesInfo(emptyArray(), "Unknown") // Return default empty data class
35
+ AudioRoutesInfo(emptyArray(), "Unknown")
39
36
  }
40
37
  }
41
38
 
@@ -50,23 +47,18 @@ class CallManager : HybridCallManagerSpec() {
50
47
  Log.d(TAG, "keepScreenAwake requested: $keepAwake")
51
48
  CallEngine.getAppContext()?.let {
52
49
  CallEngine.keepScreenAwake(it, keepAwake)
53
- } ?: Log.e(TAG, "App context not set for keepScreenAwake.")
50
+ } ?: Log.e(TAG, "App context not set for keepAwake.")
54
51
  }
55
52
 
56
- // Corrected addListener signature to match generated HybridCallManagerSpec
57
- // This is the primary fix for the `addListener overrides nothing` error.
58
53
  override fun addListener(
59
- listener: Func_void_CallEventType_std__string // Use generated type directly
60
- ): Func_void { // Return generated type
54
+ listener: Func_void_CallEventType_std__string
55
+ ): Func_void {
61
56
  Log.d(TAG, "addListener called with listener: $listener")
62
- // Store the incoming Nitro-generated listener.
63
- // It already implements the (CallEventType, String) -> Unit interface.
64
57
  currentListener = listener
65
- CallEngine.setEventHandler(listener) // Pass it directly to CallEngine
58
+ CallEngine.setEventHandler(listener)
66
59
 
67
- // Return a Nitro-generated Func_void for the remove function
68
60
  return Func_void_java {
69
- if (currentListener === listener) { // Compare against the original listener passed
61
+ if (currentListener === listener) {
70
62
  CallEngine.setEventHandler(null)
71
63
  currentListener = null
72
64
  Log.d(TAG, "Listener removed.")
@@ -76,7 +68,6 @@ class CallManager : HybridCallManagerSpec() {
76
68
  }
77
69
  }
78
70
 
79
- // Removed callType param, now extracted from callData
80
71
  override fun startOutgoingCall(callId: String, callData: String) {
81
72
  Log.d(TAG, "startOutgoingCall requested: callId=$callId, callData=$callData")
82
73
  CallEngine.getAppContext()?.let {
@@ -121,8 +121,8 @@ class MyConnection(
121
121
  Log.d(TAG, "Stopping DTMF tone for callId: $callId")
122
122
  }
123
123
 
124
- override fun onConnectionEvent(event: String, extras: Bundle?) { // Resolved - signature is correct
125
- super.onConnectionEvent(event, extras)
124
+ override fun onConnectionEvent(event: String, extras: Bundle?) { // Resolved
125
+ super.onConnectionEvent(event, extras) // Correct super call
126
126
  Log.d(TAG, "Connection event: $event, extras: $extras for callId: $callId")
127
127
  }
128
128
 
@@ -31,7 +31,7 @@ class MyConnectionService : ConnectionService() {
31
31
  val videoState = if (isVideoCallBoolean) VideoProfile.STATE_BIDIRECTIONAL else VideoProfile.STATE_AUDIO_ONLY
32
32
  connection.setVideoState(videoState)
33
33
  connection.setRinging()
34
- Log.d(TAG, "Created incoming connection for callId: ${connection.callId}. Status: RINGING, VideoState: $videoState")
34
+ Log.d(TAG, "Created incoming connection for callId: ${connection.callId}. Status: RINGING, VideoState: $videoState") // Accesses internal callId
35
35
  return connection
36
36
  }
37
37
 
@@ -49,7 +49,7 @@ class MyConnectionService : ConnectionService() {
49
49
  val videoState = if (isVideoCallBoolean) VideoProfile.STATE_BIDIRECTIONAL else VideoProfile.STATE_AUDIO_ONLY
50
50
  connection.setVideoState(videoState)
51
51
  connection.setDialing()
52
- Log.d(TAG, "Created outgoing connection for callId: ${connection.callId}. Status: DIALING, VideoState: $videoState")
52
+ Log.d(TAG, "Created outgoing connection for callId: ${connection.callId}. Status: DIALING, VideoState: $videoState") // Accesses internal callId
53
53
 
54
54
  if (request.extras?.getBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false) == true) {
55
55
  Log.d(TAG, "Hinting Telecom to start outgoing call with speakerphone as per request extras.")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.36",
3
+ "version": "0.1.38",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",