@capgo/capacitor-stream-call 0.0.81 → 0.0.83

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.
@@ -20,15 +20,14 @@ import android.os.Bundle
20
20
  import android.os.Handler
21
21
  import android.os.Looper
22
22
  import android.provider.Settings
23
+ import android.util.Log
23
24
  import android.view.View
24
25
  import android.view.ViewGroup
25
26
  import android.view.WindowManager
26
27
  import android.widget.FrameLayout
27
28
  import androidx.compose.foundation.layout.fillMaxSize
28
29
  import androidx.compose.runtime.collectAsState
29
- import androidx.compose.runtime.derivedStateOf
30
30
  import androidx.compose.runtime.getValue
31
- import androidx.compose.runtime.remember
32
31
  import androidx.compose.ui.Modifier
33
32
  import androidx.compose.ui.draw.clip
34
33
  import androidx.compose.ui.platform.ComposeView
@@ -87,11 +86,13 @@ import kotlinx.coroutines.launch
87
86
  import kotlinx.coroutines.tasks.await
88
87
  import androidx.core.net.toUri
89
88
  import org.json.JSONObject
89
+ import androidx.core.graphics.toColorInt
90
+ import androidx.core.content.edit
90
91
 
91
92
  // I am not a religious pearson, but at this point, I am not sure even god himself would understand this code
92
93
  // It's a spaghetti-like, tangled, unreadable mess and frankly, I am deeply sorry for the code crimes commited in the Android impl
93
94
  @CapacitorPlugin(name = "StreamCall")
94
- public class StreamCallPlugin : Plugin() {
95
+ class StreamCallPlugin : Plugin() {
95
96
  private var streamVideoClient: StreamVideo? = null
96
97
  private var state: State = State.NOT_INITIALIZED
97
98
  private var overlayView: ComposeView? = null
@@ -108,6 +109,7 @@ public class StreamCallPlugin : Plugin() {
108
109
  private var activeCallStateJob: Job? = null
109
110
  private var cameraStatusJob: Job? = null
110
111
  private var microphoneStatusJob: Job? = null
112
+ private var lastEventSent: String? = null
111
113
 
112
114
  // Store current call info
113
115
  private var currentCallId: String = ""
@@ -116,7 +118,6 @@ public class StreamCallPlugin : Plugin() {
116
118
 
117
119
  // Add a field for the fragment
118
120
  private var callFragment: StreamCallFragment? = null
119
- private var streamVideo: StreamVideo? = null
120
121
  private var touchInterceptWrapper: TouchInterceptWrapper? = null
121
122
 
122
123
  // Track permission request timing and attempts
@@ -138,7 +139,7 @@ public class StreamCallPlugin : Plugin() {
138
139
  INITIALIZED
139
140
  }
140
141
 
141
- public fun incomingOnlyRingingConfig(): RingingConfig = object : RingingConfig {
142
+ fun incomingOnlyRingingConfig(): RingingConfig = object : RingingConfig {
142
143
  override val incomingCallSoundUri: Uri? = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
143
144
  override val outgoingCallSoundUri: Uri? = null
144
145
  }
@@ -154,41 +155,41 @@ public class StreamCallPlugin : Plugin() {
154
155
  override fun handleOnResume() {
155
156
  super.handleOnResume()
156
157
 
157
- android.util.Log.d("StreamCallPlugin", "handleOnResume: App resumed, checking permissions and pending operations")
158
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Have pendingCall: ${pendingCall != null}")
159
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Have pendingCallUserIds: ${pendingCallUserIds != null}")
160
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Have pendingAcceptCall: ${pendingAcceptCall != null}")
161
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Permission attempt count: $permissionAttemptCount")
158
+ Log.d("StreamCallPlugin", "handleOnResume: App resumed, checking permissions and pending operations")
159
+ Log.d("StreamCallPlugin", "handleOnResume: Have pendingCall: ${pendingCall != null}")
160
+ Log.d("StreamCallPlugin", "handleOnResume: Have pendingCallUserIds: ${pendingCallUserIds != null}")
161
+ Log.d("StreamCallPlugin", "handleOnResume: Have pendingAcceptCall: ${pendingAcceptCall != null}")
162
+ Log.d("StreamCallPlugin", "handleOnResume: Permission attempt count: $permissionAttemptCount")
162
163
 
163
164
  // Check if permissions were granted after returning from settings or permission dialog
164
165
  if (checkPermissions()) {
165
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Permissions are now granted")
166
+ Log.d("StreamCallPlugin", "handleOnResume: Permissions are now granted")
166
167
  // Handle any pending calls that were waiting for permissions
167
168
  handlePermissionGranted()
168
169
  } else if (pendingCall != null || pendingAcceptCall != null) {
169
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Permissions still not granted, but have pending operations")
170
+ Log.d("StreamCallPlugin", "handleOnResume: Permissions still not granted, but have pending operations")
170
171
  // If we have pending operations but permissions are still not granted,
171
172
  // it means the permission dialog was dismissed without granting
172
173
  // We should trigger our retry logic if we haven't exhausted attempts
173
174
  if (permissionAttemptCount > 0) {
174
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Permission dialog was dismissed, treating as denial (attempt: $permissionAttemptCount)")
175
+ Log.d("StreamCallPlugin", "handleOnResume: Permission dialog was dismissed, treating as denial (attempt: $permissionAttemptCount)")
175
176
  val timeSinceRequest = System.currentTimeMillis() - permissionRequestStartTime
176
177
  handlePermissionDenied(timeSinceRequest)
177
178
  } else {
178
- android.util.Log.d("StreamCallPlugin", "handleOnResume: No permission attempts yet, starting permission request")
179
+ Log.d("StreamCallPlugin", "handleOnResume: No permission attempts yet, starting permission request")
179
180
  // If we have pending operations but no attempts yet, start the permission flow
180
181
  if (pendingAcceptCall != null) {
181
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Have active call waiting for permissions, requesting now")
182
+ Log.d("StreamCallPlugin", "handleOnResume: Have active call waiting for permissions, requesting now")
182
183
  permissionAttemptCount = 0
183
184
  requestPermissions()
184
185
  } else if (pendingCall != null && pendingCallUserIds != null) {
185
- android.util.Log.d("StreamCallPlugin", "handleOnResume: Have outgoing call waiting for permissions, requesting now")
186
+ Log.d("StreamCallPlugin", "handleOnResume: Have outgoing call waiting for permissions, requesting now")
186
187
  permissionAttemptCount = 0
187
188
  requestPermissions()
188
189
  }
189
190
  }
190
191
  } else {
191
- android.util.Log.d("StreamCallPlugin", "handleOnResume: No pending operations, nothing to handle")
192
+ Log.d("StreamCallPlugin", "handleOnResume: No pending operations, nothing to handle")
192
193
  }
193
194
  }
194
195
 
@@ -201,36 +202,36 @@ public class StreamCallPlugin : Plugin() {
201
202
  // Register broadcast receiver for ACCEPT_CALL action with high priority
202
203
  val filter = IntentFilter("io.getstream.video.android.action.ACCEPT_CALL")
203
204
  filter.priority = 999 // Set high priority to ensure it captures the intent
204
- androidx.core.content.ContextCompat.registerReceiver(activity, acceptCallReceiver, filter, androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED)
205
- android.util.Log.d("StreamCallPlugin", "Registered broadcast receiver for ACCEPT_CALL action with high priority")
205
+ ContextCompat.registerReceiver(activity, acceptCallReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED)
206
+ Log.d("StreamCallPlugin", "Registered broadcast receiver for ACCEPT_CALL action with high priority")
206
207
 
207
208
  // Start the background service to keep the app alive
208
209
  val serviceIntent = Intent(activity, StreamCallBackgroundService::class.java)
209
210
  activity.startService(serviceIntent)
210
- android.util.Log.d("StreamCallPlugin", "Started StreamCallBackgroundService to keep app alive")
211
+ Log.d("StreamCallPlugin", "Started StreamCallBackgroundService to keep app alive")
211
212
  }
212
213
 
213
214
  @OptIn(DelicateCoroutinesApi::class)
214
- override fun handleOnNewIntent(intent: android.content.Intent) {
215
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent called: action=${intent.action}, data=${intent.data}, extras=${intent.extras}")
215
+ override fun handleOnNewIntent(intent: Intent) {
216
+ Log.d("StreamCallPlugin", "handleOnNewIntent called: action=${intent.action}, data=${intent.data}, extras=${intent.extras}")
216
217
  super.handleOnNewIntent(intent)
217
218
 
218
219
  val action = intent.action
219
220
  val data = intent.data
220
221
  val extras = intent.extras
221
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: Parsed action: $action")
222
+ Log.d("StreamCallPlugin", "handleOnNewIntent: Parsed action: $action")
222
223
 
223
224
  if (action === "io.getstream.video.android.action.INCOMING_CALL") {
224
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: Matched INCOMING_CALL action")
225
+ Log.d("StreamCallPlugin", "handleOnNewIntent: Matched INCOMING_CALL action")
225
226
  // We need to make sure the activity is visible on locked screen in such case
226
227
  changeActivityAsVisibleOnLockScreen(this@StreamCallPlugin.activity, true)
227
228
  activity?.runOnUiThread {
228
229
  val cid = intent.streamCallId(NotificationHandler.INTENT_EXTRA_CALL_CID)
229
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - Extracted cid: $cid")
230
+ Log.d("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - Extracted cid: $cid")
230
231
  if (cid != null) {
231
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - cid is not null, processing.")
232
+ Log.d("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - cid is not null, processing.")
232
233
  val call = streamVideoClient?.call(id = cid.id, type = cid.type)
233
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - Got call object: ${call?.id}")
234
+ Log.d("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - Got call object: ${call?.id}")
234
235
 
235
236
  // Try to get caller information from the call
236
237
  kotlinx.coroutines.GlobalScope.launch {
@@ -239,15 +240,15 @@ public class StreamCallPlugin : Plugin() {
239
240
  val callerInfo = callInfo?.getOrNull()?.call?.createdBy
240
241
  val custom = callInfo?.getOrNull()?.call?.custom
241
242
 
242
- val payload = com.getcapacitor.JSObject().apply {
243
+ val payload = JSObject().apply {
243
244
  put("cid", cid.cid)
244
245
  put("type", "incoming")
245
246
  if (callerInfo != null) {
246
- val caller = com.getcapacitor.JSObject().apply {
247
+ val caller = JSObject().apply {
247
248
  put("userId", callerInfo.id)
248
249
  put("name", callerInfo.name ?: "")
249
250
  put("imageURL", callerInfo.image ?: "")
250
- put("role", callerInfo.role ?: "")
251
+ put("role", callerInfo.role)
251
252
  }
252
253
  put("caller", caller)
253
254
  }
@@ -263,9 +264,9 @@ public class StreamCallPlugin : Plugin() {
263
264
  kotlinx.coroutines.delay(500) // 500ms delay
264
265
  bringAppToForeground()
265
266
  } catch (e: Exception) {
266
- android.util.Log.e("StreamCallPlugin", "Error getting call info for incoming call", e)
267
+ Log.e("StreamCallPlugin", "Error getting call info for incoming call", e)
267
268
  // Fallback to basic payload without caller info
268
- val payload = com.getcapacitor.JSObject().apply {
269
+ val payload = JSObject().apply {
269
270
  put("cid", cid.cid)
270
271
  put("type", "incoming")
271
272
  }
@@ -277,41 +278,41 @@ public class StreamCallPlugin : Plugin() {
277
278
  }
278
279
  }
279
280
  } else {
280
- android.util.Log.w("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - cid is null. Cannot process.")
281
+ Log.w("StreamCallPlugin", "handleOnNewIntent: INCOMING_CALL - cid is null. Cannot process.")
281
282
  }
282
283
  }
283
284
  } else if (action === "io.getstream.video.android.action.ACCEPT_CALL") {
284
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: Matched ACCEPT_CALL action")
285
+ Log.d("StreamCallPlugin", "handleOnNewIntent: Matched ACCEPT_CALL action")
285
286
  val cid = intent.streamCallId(NotificationHandler.INTENT_EXTRA_CALL_CID)
286
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: ACCEPT_CALL - Extracted cid: $cid")
287
+ Log.d("StreamCallPlugin", "handleOnNewIntent: ACCEPT_CALL - Extracted cid: $cid")
287
288
  if (cid != null) {
288
- android.util.Log.d("StreamCallPlugin", "handleOnNewIntent: ACCEPT_CALL - Accepting call with cid: $cid")
289
+ Log.d("StreamCallPlugin", "handleOnNewIntent: ACCEPT_CALL - Accepting call with cid: $cid")
289
290
  val call = streamVideoClient?.call(id = cid.id, type = cid.type)
290
291
  if (call != null) {
291
292
  // Log the full stack trace to see exactly where this is called from
292
293
  val stackTrace = Thread.currentThread().stackTrace
293
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall STACK TRACE:")
294
+ Log.d("StreamCallPlugin", "internalAcceptCall STACK TRACE:")
294
295
  stackTrace.forEachIndexed { index, element ->
295
- android.util.Log.d("StreamCallPlugin", " [$index] ${element.className}.${element.methodName}(${element.fileName}:${element.lineNumber})")
296
+ Log.d("StreamCallPlugin", " [$index] ${element.className}.${element.methodName}(${element.fileName}:${element.lineNumber})")
296
297
  }
297
298
  kotlinx.coroutines.GlobalScope.launch {
298
299
  internalAcceptCall(call, requestPermissionsAfter = !checkPermissions())
299
300
  }
300
301
  bringAppToForeground()
301
302
  } else {
302
- android.util.Log.e("StreamCallPlugin", "handleOnNewIntent: ACCEPT_CALL - Call object is null for cid: $cid")
303
+ Log.e("StreamCallPlugin", "handleOnNewIntent: ACCEPT_CALL - Call object is null for cid: $cid")
303
304
  }
304
305
  }
305
306
  }
306
307
  // Log the intent information
307
- android.util.Log.d("StreamCallPlugin", "New Intent - Action: $action")
308
- android.util.Log.d("StreamCallPlugin", "New Intent - Data: $data")
309
- android.util.Log.d("StreamCallPlugin", "New Intent - Extras: $extras")
308
+ Log.d("StreamCallPlugin", "New Intent - Action: $action")
309
+ Log.d("StreamCallPlugin", "New Intent - Data: $data")
310
+ Log.d("StreamCallPlugin", "New Intent - Extras: $extras")
310
311
  }
311
312
 
312
313
  @OptIn(DelicateCoroutinesApi::class)
313
314
  private fun declineCall(call: Call) {
314
- android.util.Log.d("StreamCallPlugin", "declineCall called for call: ${call.id}")
315
+ Log.d("StreamCallPlugin", "declineCall called for call: ${call.id}")
315
316
  kotlinx.coroutines.GlobalScope.launch {
316
317
  try {
317
318
  call.reject()
@@ -322,7 +323,7 @@ public class StreamCallPlugin : Plugin() {
322
323
 
323
324
  hideIncomingCall()
324
325
  } catch (e: Exception) {
325
- android.util.Log.e("StreamCallPlugin", "Error declining call: ${e.message}")
326
+ Log.e("StreamCallPlugin", "Error declining call: ${e.message}")
326
327
  }
327
328
  }
328
329
  }
@@ -333,18 +334,6 @@ public class StreamCallPlugin : Plugin() {
333
334
  }
334
335
  }
335
336
 
336
- private fun showBarrier() {
337
- activity?.runOnUiThread {
338
- barrierView?.isVisible = true
339
- }
340
- }
341
-
342
- private fun hideBarrier() {
343
- activity?.runOnUiThread {
344
- barrierView?.isVisible = false
345
- }
346
- }
347
-
348
337
  @OptIn(InternalStreamVideoApi::class)
349
338
  private fun setupViews() {
350
339
  val context = context
@@ -356,7 +345,7 @@ public class StreamCallPlugin : Plugin() {
356
345
  if (rootParent != null && indexInRoot >= 0) {
357
346
  rootParent.removeViewAt(indexInRoot)
358
347
  touchInterceptWrapper = TouchInterceptWrapper(originalParent).apply {
359
- setBackgroundColor(android.graphics.Color.TRANSPARENT)
348
+ setBackgroundColor(Color.TRANSPARENT)
360
349
  }
361
350
  rootParent.addView(touchInterceptWrapper, indexInRoot)
362
351
  }
@@ -386,7 +375,7 @@ public class StreamCallPlugin : Plugin() {
386
375
  ViewGroup.LayoutParams.MATCH_PARENT,
387
376
  ViewGroup.LayoutParams.MATCH_PARENT
388
377
  )
389
- setBackgroundColor(Color.parseColor("#1a242c"))
378
+ setBackgroundColor("#1a242c".toColorInt())
390
379
  }
391
380
  parent.addView(barrierView, parent.indexOfChild(bridge?.webView) + 1) // Add above WebView
392
381
  }
@@ -400,17 +389,6 @@ public class StreamCallPlugin : Plugin() {
400
389
  VideoTheme {
401
390
  val activeCall = call ?: streamVideoClient?.state?.activeCall?.collectAsState()?.value
402
391
  if (activeCall != null) {
403
- val participants by activeCall.state.participants.collectAsStateWithLifecycle()
404
- val sortedParticipants by activeCall.state.sortedParticipants.collectAsStateWithLifecycle(emptyList())
405
- val callParticipants by remember(participants) {
406
- derivedStateOf {
407
- if (sortedParticipants.size > 6) {
408
- sortedParticipants
409
- } else {
410
- participants
411
- }
412
- }
413
- }
414
392
 
415
393
  val currentLocal by activeCall.state.me.collectAsStateWithLifecycle()
416
394
 
@@ -489,7 +467,7 @@ public class StreamCallPlugin : Plugin() {
489
467
  SecureUserRepository.getInstance(context).save(credentials)
490
468
 
491
469
  // Initialize Stream Video with new credentials
492
- if (!hadSavedCredentials || (savedCredentials!!.user.id != userId)) {
470
+ if (!hadSavedCredentials || (savedCredentials.user.id != userId)) {
493
471
  initializeStreamVideo()
494
472
  }
495
473
 
@@ -532,10 +510,10 @@ public class StreamCallPlugin : Plugin() {
532
510
  }
533
511
 
534
512
  @OptIn(DelicateCoroutinesApi::class)
535
- public fun initializeStreamVideo(passedContext: Context? = null, passedApplication: Application? = null) {
536
- android.util.Log.d("StreamCallPlugin", "initializeStreamVideo called")
513
+ fun initializeStreamVideo(passedContext: Context? = null, passedApplication: Application? = null) {
514
+ Log.d("StreamCallPlugin", "initializeStreamVideo called")
537
515
  if (state == State.INITIALIZING) {
538
- android.util.Log.v("StreamCallPlugin", "Returning, already in the process of initializing")
516
+ Log.v("StreamCallPlugin", "Returning, already in the process of initializing")
539
517
  return
540
518
  }
541
519
  state = State.INITIALIZING
@@ -548,7 +526,7 @@ public class StreamCallPlugin : Plugin() {
548
526
  // Try to get user credentials from repository
549
527
  val savedCredentials = SecureUserRepository.getInstance(contextToUse).loadCurrentUser()
550
528
  if (savedCredentials == null) {
551
- android.util.Log.v("StreamCallPlugin", "Saved credentials are null")
529
+ Log.v("StreamCallPlugin", "Saved credentials are null")
552
530
  state = State.NOT_INITIALIZED
553
531
  return
554
532
  }
@@ -556,14 +534,14 @@ public class StreamCallPlugin : Plugin() {
556
534
  try {
557
535
  // Check if we can reuse existing StreamVideo singleton client
558
536
  if (StreamVideo.isInstalled) {
559
- android.util.Log.v("StreamCallPlugin", "Found existing StreamVideo singleton client")
537
+ Log.v("StreamCallPlugin", "Found existing StreamVideo singleton client")
560
538
  if (streamVideoClient == null) {
561
- android.util.Log.v("StreamCallPlugin", "Plugin's streamVideoClient is null, reusing singleton and registering event handlers")
539
+ Log.v("StreamCallPlugin", "Plugin's streamVideoClient is null, reusing singleton and registering event handlers")
562
540
  streamVideoClient = StreamVideo.instance()
563
541
  // Register event handlers since streamVideoClient was null
564
542
  registerEventHandlers()
565
543
  } else {
566
- android.util.Log.v("StreamCallPlugin", "Plugin already has streamVideoClient, skipping event handler registration")
544
+ Log.v("StreamCallPlugin", "Plugin already has streamVideoClient, skipping event handler registration")
567
545
  }
568
546
  state = State.INITIALIZED
569
547
  initializationTime = System.currentTimeMillis()
@@ -571,11 +549,11 @@ public class StreamCallPlugin : Plugin() {
571
549
  }
572
550
 
573
551
  // If we reach here, we need to create a new client
574
- android.util.Log.v("StreamCallPlugin", "No existing StreamVideo singleton client, creating new one")
552
+ Log.v("StreamCallPlugin", "No existing StreamVideo singleton client, creating new one")
575
553
 
576
554
  // unsafe cast, add better handling
577
555
  val application = contextToUse.applicationContext as Application
578
- android.util.Log.d("StreamCallPlugin", "No existing StreamVideo singleton client, creating new one")
556
+ Log.d("StreamCallPlugin", "No existing StreamVideo singleton client, creating new one")
579
557
  val notificationHandler = CustomNotificationHandler(
580
558
  application = application,
581
559
  endCall = { callId ->
@@ -583,13 +561,13 @@ public class StreamCallPlugin : Plugin() {
583
561
 
584
562
  kotlinx.coroutines.GlobalScope.launch {
585
563
  try {
586
- android.util.Log.i(
564
+ Log.i(
587
565
  "StreamCallPlugin",
588
566
  "Attempt to endCallRaw, activeCall == null: ${activeCall == null}",
589
567
  )
590
568
  activeCall?.let { endCallRaw(it) }
591
569
  } catch (e: Exception) {
592
- android.util.Log.e(
570
+ Log.e(
593
571
  "StreamCallPlugin",
594
572
  "Error ending after missed call notif action",
595
573
  e
@@ -603,12 +581,12 @@ public class StreamCallPlugin : Plugin() {
603
581
  val now = System.currentTimeMillis()
604
582
  val isWithinOneSecond = (now - contextCreatedAt) <= 1000L
605
583
 
606
- android.util.Log.i(
584
+ Log.i(
607
585
  "StreamCallPlugin",
608
586
  "Time between context creation and activity created (incoming call notif): ${now - contextCreatedAt}"
609
587
  )
610
588
  if (isWithinOneSecond && !bootedToHandleCall) {
611
- android.util.Log.i(
589
+ Log.i(
612
590
  "StreamCallPlugin",
613
591
  "Notification incomingCall received less than 1 second after the creation of streamVideoSDK. Booted FOR SURE in order to handle the notification"
614
592
  )
@@ -644,7 +622,7 @@ public class StreamCallPlugin : Plugin() {
644
622
 
645
623
  // don't do event handler registration when activity may be null
646
624
  if (passedContext != null) {
647
- android.util.Log.w("StreamCallPlugin", "Ignoring event listeners for initializeStreamVideo")
625
+ Log.w("StreamCallPlugin", "Ignoring event listeners for initializeStreamVideo")
648
626
  passedApplication?.let {
649
627
  registerActivityEventListener(it)
650
628
  }
@@ -655,7 +633,7 @@ public class StreamCallPlugin : Plugin() {
655
633
 
656
634
  registerEventHandlers()
657
635
 
658
- android.util.Log.v("StreamCallPlugin", "Initialization finished")
636
+ Log.v("StreamCallPlugin", "Initialization finished")
659
637
  initializationTime = System.currentTimeMillis()
660
638
  state = State.INITIALIZED
661
639
  } catch (e: Exception) {
@@ -667,7 +645,7 @@ public class StreamCallPlugin : Plugin() {
667
645
  private fun moveAllActivitiesToBackgroundOrKill(context: Context, allowKill: Boolean = false) {
668
646
  try {
669
647
  if (allowKill && bootedToHandleCall && savedActivity != null) {
670
- android.util.Log.d("StreamCallPlugin", "App was booted to handle call and allowKill is true, killing app")
648
+ Log.d("StreamCallPlugin", "App was booted to handle call and allowKill is true, killing app")
671
649
  savedActivity?.let { act ->
672
650
  try {
673
651
  // Get the ActivityManager
@@ -687,7 +665,7 @@ public class StreamCallPlugin : Plugin() {
687
665
  android.os.Process.killProcess(android.os.Process.myPid())
688
666
  }, 100)
689
667
  } catch (e: Exception) {
690
- android.util.Log.e("StreamCallPlugin", "Error during aggressive cleanup", e)
668
+ Log.e("StreamCallPlugin", "Error during aggressive cleanup", e)
691
669
  // Fallback to direct process kill
692
670
  android.os.Process.killProcess(android.os.Process.myPid())
693
671
  }
@@ -695,19 +673,20 @@ public class StreamCallPlugin : Plugin() {
695
673
  return
696
674
  }
697
675
 
698
- val intent = android.content.Intent(android.content.Intent.ACTION_MAIN).apply {
699
- addCategory(android.content.Intent.CATEGORY_HOME)
676
+ val intent = Intent(Intent.ACTION_MAIN).apply {
677
+ addCategory(Intent.CATEGORY_HOME)
700
678
  flags = Intent.FLAG_ACTIVITY_NEW_TASK
701
679
  }
702
680
  context.startActivity(intent)
703
- android.util.Log.d("StreamCallPlugin", "Moving app to background using HOME intent")
681
+ Log.d("StreamCallPlugin", "Moving app to background using HOME intent")
704
682
  } catch (e: Exception) {
705
- android.util.Log.e("StreamCallPlugin", "Failed to move app to background", e)
683
+ Log.e("StreamCallPlugin", "Failed to move app to background", e)
706
684
  }
707
685
  }
708
686
 
709
687
  @OptIn(DelicateCoroutinesApi::class)
710
688
  private fun registerEventHandlers() {
689
+ Log.d("StreamCallPlugin", "registerEventHandlers called")
711
690
  eventSubscription?.dispose()
712
691
  activeCallStateJob?.cancel()
713
692
  cameraStatusJob?.cancel()
@@ -715,7 +694,7 @@ public class StreamCallPlugin : Plugin() {
715
694
  // Subscribe to call events
716
695
  streamVideoClient?.let { client ->
717
696
  eventSubscription = client.subscribe { event: VideoEvent ->
718
- android.util.Log.v("StreamCallPlugin", "Received an event ${event.getEventType()} $event")
697
+ Log.v("StreamCallPlugin", "Received an event ${event.getEventType()} $event")
719
698
  when (event) {
720
699
  is CallRingEvent -> {
721
700
  // Extract caller information from the ringing call
@@ -736,7 +715,7 @@ public class StreamCallPlugin : Plugin() {
736
715
  "userId" to callerInfo.id,
737
716
  "name" to (callerInfo.name ?: ""),
738
717
  "imageURL" to (callerInfo.image ?: ""),
739
- "role" to (callerInfo.role ?: "")
718
+ "role" to (callerInfo.role)
740
719
  )
741
720
  updateCallStatusAndNotify(event.callCid, "ringing", null, null, null, caller)
742
721
  } else {
@@ -746,7 +725,7 @@ public class StreamCallPlugin : Plugin() {
746
725
  updateCallStatusAndNotify(event.callCid, "ringing")
747
726
  }
748
727
  } catch (e: Exception) {
749
- android.util.Log.e("StreamCallPlugin", "Error getting caller info for ringing event", e)
728
+ Log.e("StreamCallPlugin", "Error getting caller info for ringing event", e)
750
729
  updateCallStatusAndNotify(event.callCid, "ringing")
751
730
  }
752
731
  }
@@ -754,9 +733,9 @@ public class StreamCallPlugin : Plugin() {
754
733
  // Handle CallCreatedEvent differently - only log it but don't try to access members yet
755
734
  is CallCreatedEvent -> {
756
735
  val callCid = event.callCid
757
- android.util.Log.d("StreamCallPlugin", "CallCreatedEvent: Received for $callCid")
758
- android.util.Log.d("StreamCallPlugin", "CallCreatedEvent: All members from event: ${event.members.joinToString { it.user.id + " (role: " + it.user.role + ")" }}")
759
- android.util.Log.d("StreamCallPlugin", "CallCreatedEvent: Self user ID from SDK: ${this@StreamCallPlugin.streamVideoClient?.userId}")
736
+ Log.d("StreamCallPlugin", "CallCreatedEvent: Received for $callCid")
737
+ Log.d("StreamCallPlugin", "CallCreatedEvent: All members from event: ${event.members.joinToString { it.user.id + " (role: " + it.user.role + ")" }}")
738
+ Log.d("StreamCallPlugin", "CallCreatedEvent: Self user ID from SDK: ${this@StreamCallPlugin.streamVideoClient?.userId}")
760
739
 
761
740
  // Only send "created" event for outgoing calls (calls created by current user)
762
741
  // For incoming calls, we'll only send "ringing" event in CallRingEvent handler
@@ -771,21 +750,21 @@ public class StreamCallPlugin : Plugin() {
771
750
  val createdBy = callInfo?.getOrNull()?.call?.createdBy
772
751
  val currentUserId = streamVideoClient?.userId
773
752
 
774
- android.util.Log.d("StreamCallPlugin", "CallCreatedEvent: Call created by: ${createdBy?.id}, Current user: $currentUserId")
753
+ Log.d("StreamCallPlugin", "CallCreatedEvent: Call created by: ${createdBy?.id}, Current user: $currentUserId")
775
754
 
776
755
  // Only notify for outgoing calls (where current user is the creator)
777
756
  if (createdBy?.id == currentUserId) {
778
- android.util.Log.d("StreamCallPlugin", "CallCreatedEvent: This is an outgoing call, sending created event")
757
+ Log.d("StreamCallPlugin", "CallCreatedEvent: This is an outgoing call, sending created event")
779
758
 
780
759
  val callParticipants = event.members.filter {
781
760
  val selfId = this@StreamCallPlugin.streamVideoClient?.userId
782
761
  val memberId = it.user.id
783
762
  val isSelf = memberId == selfId
784
- android.util.Log.d("StreamCallPlugin", "CallCreatedEvent: Filtering member $memberId. Self ID: $selfId. Is self: $isSelf")
763
+ Log.d("StreamCallPlugin", "CallCreatedEvent: Filtering member $memberId. Self ID: $selfId. Is self: $isSelf")
785
764
  !isSelf
786
765
  }.map { it.user.id }
787
766
 
788
- android.util.Log.d("StreamCallPlugin", "Call created for $callCid with ${callParticipants.size} remote participants: ${callParticipants.joinToString()}.")
767
+ Log.d("StreamCallPlugin", "Call created for $callCid with ${callParticipants.size} remote participants: ${callParticipants.joinToString()}.")
789
768
 
790
769
  // Start tracking this call now that we have the member list
791
770
  startCallTimeoutMonitor(callCid, callParticipants)
@@ -796,19 +775,19 @@ public class StreamCallPlugin : Plugin() {
796
775
  "userId" to member.user.id,
797
776
  "name" to (member.user.name ?: ""),
798
777
  "imageURL" to (member.user.image ?: ""),
799
- "role" to (member.user.role ?: "")
778
+ "role" to (member.user.role)
800
779
  )
801
780
  }
802
781
 
803
782
  updateCallStatusAndNotify(callCid, "created", null, null, allMembers)
804
783
  } else {
805
- android.util.Log.d("StreamCallPlugin", "CallCreatedEvent: This is an incoming call (created by ${createdBy?.id}), not sending created event")
784
+ Log.d("StreamCallPlugin", "CallCreatedEvent: This is an incoming call (created by ${createdBy?.id}), not sending created event")
806
785
  }
807
786
  } else {
808
- android.util.Log.w("StreamCallPlugin", "CallCreatedEvent: Invalid call CID format: $callCid")
787
+ Log.w("StreamCallPlugin", "CallCreatedEvent: Invalid call CID format: $callCid")
809
788
  }
810
789
  } catch (e: Exception) {
811
- android.util.Log.e("StreamCallPlugin", "Error processing CallCreatedEvent", e)
790
+ Log.e("StreamCallPlugin", "Error processing CallCreatedEvent", e)
812
791
  }
813
792
  }
814
793
  }
@@ -844,7 +823,7 @@ public class StreamCallPlugin : Plugin() {
844
823
 
845
824
  val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
846
825
  if (keyguardManager.isKeyguardLocked) {
847
- android.util.Log.d("StreamCallPlugin", "Stop ringing and move to background")
826
+ Log.d("StreamCallPlugin", "Stop ringing and move to background")
848
827
  moveAllActivitiesToBackgroundOrKill(context)
849
828
  }
850
829
 
@@ -863,7 +842,7 @@ public class StreamCallPlugin : Plugin() {
863
842
  callState.participantResponses[userId] = "accepted"
864
843
 
865
844
  // Since someone accepted, cancel the timeout timer
866
- android.util.Log.d("StreamCallPlugin", "Call accepted by $userId, canceling timeout timer for $callCid")
845
+ Log.d("StreamCallPlugin", "Call accepted by $userId, canceling timeout timer for $callCid")
867
846
  callState.timer?.removeCallbacksAndMessages(null)
868
847
  callState.timer = null
869
848
  }
@@ -873,7 +852,7 @@ public class StreamCallPlugin : Plugin() {
873
852
 
874
853
  is CallEndedEvent -> {
875
854
  runOnMainThread {
876
- android.util.Log.d("StreamCallPlugin", "Setting overlay invisible due to CallEndedEvent for call ${event.callCid}")
855
+ Log.d("StreamCallPlugin", "Setting overlay invisible due to CallEndedEvent for call ${event.callCid}")
877
856
  // Clean up call resources
878
857
  val callCid = event.callCid
879
858
  cleanupCall(callCid)
@@ -883,7 +862,7 @@ public class StreamCallPlugin : Plugin() {
883
862
 
884
863
  is CallSessionEndedEvent -> {
885
864
  runOnMainThread {
886
- android.util.Log.d("StreamCallPlugin", "Setting overlay invisible due to CallSessionEndedEvent for call ${event.callCid}. Test session: ${event.call.session?.endedAt}")
865
+ Log.d("StreamCallPlugin", "Setting overlay invisible due to CallSessionEndedEvent for call ${event.callCid}. Test session: ${event.call.session?.endedAt}")
887
866
  // Clean up call resources
888
867
  val callCid = event.callCid
889
868
  cleanupCall(callCid)
@@ -907,23 +886,23 @@ public class StreamCallPlugin : Plugin() {
907
886
  }
908
887
  }
909
888
 
910
- android.util.Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: Received for call $callId. Active call: ${activeCall?.cid}")
889
+ Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: Received for call $callId. Active call: ${activeCall?.cid}")
911
890
 
912
891
 
913
892
  if (activeCall != null && activeCall.cid == callId) {
914
893
  val connectionState = activeCall.state.connection.value
915
894
  if (connectionState != RealtimeConnection.Disconnected) {
916
895
  val total = activeCall.state.participantCounts.value?.total
917
- android.util.Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: Participant left, remaining: $total");
896
+ Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: Participant left, remaining: $total")
918
897
  if (total != null && total <= 1) {
919
- android.util.Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: All remote participants have left call ${activeCall.cid}. Ending call.")
898
+ Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: All remote participants have left call ${activeCall.cid}. Ending call.")
920
899
  kotlinx.coroutines.GlobalScope.launch(Dispatchers.IO) {
921
900
  endCallRaw(activeCall)
922
901
  }
923
902
  }
924
903
  }
925
904
  } else {
926
- android.util.Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: Conditions not met (activeCall null, or cid mismatch, or local user not joined). ActiveCall CID: ${activeCall?.cid}")
905
+ Log.d("StreamCallPlugin", "CallSessionParticipantLeftEvent: Conditions not met (activeCall null, or cid mismatch, or local user not joined). ActiveCall CID: ${activeCall?.cid}")
927
906
  }
928
907
  }
929
908
 
@@ -940,13 +919,13 @@ public class StreamCallPlugin : Plugin() {
940
919
  // used so that it follows the same patterns as iOS
941
920
  activeCallStateJob = kotlinx.coroutines.GlobalScope.launch {
942
921
  client.state.activeCall.collect { call ->
943
- android.util.Log.d("StreamCallPlugin", "Call State Update:")
944
- android.util.Log.d("StreamCallPlugin", "- Call is null: ${call == null}")
922
+ Log.d("StreamCallPlugin", "Call State Update:")
923
+ Log.d("StreamCallPlugin", "- Call is null: ${call == null}")
945
924
 
946
925
  call?.state?.let { state ->
947
- android.util.Log.d("StreamCallPlugin", "- Session ID: ${state.session.value?.id}")
948
- android.util.Log.d("StreamCallPlugin", "- All participants: ${state.participants}")
949
- android.util.Log.d("StreamCallPlugin", "- Remote participants: ${state.remoteParticipants}")
926
+ Log.d("StreamCallPlugin", "- Session ID: ${state.session.value?.id}")
927
+ Log.d("StreamCallPlugin", "- All participants: ${state.participants}")
928
+ Log.d("StreamCallPlugin", "- Remote participants: ${state.remoteParticipants}")
950
929
 
951
930
  // Notify that a call has started or state updated (e.g., participants changed but still active)
952
931
  // The actual check for "last participant" is now handled by CallSessionParticipantLeftEvent
@@ -960,7 +939,7 @@ public class StreamCallPlugin : Plugin() {
960
939
  // Listen to camera status changes
961
940
  cameraStatusJob = kotlinx.coroutines.GlobalScope.launch {
962
941
  call.camera.isEnabled.collect { isEnabled ->
963
- android.util.Log.d("StreamCallPlugin", "Camera status changed for call ${call.id}: enabled=$isEnabled")
942
+ Log.d("StreamCallPlugin", "Camera status changed for call ${call.id}: enabled=$isEnabled")
964
943
  updateCallStatusAndNotify(call.cid, if (isEnabled) "camera_enabled" else "camera_disabled")
965
944
  }
966
945
  }
@@ -968,7 +947,7 @@ public class StreamCallPlugin : Plugin() {
968
947
  // Listen to microphone status changes
969
948
  microphoneStatusJob = kotlinx.coroutines.GlobalScope.launch {
970
949
  call.microphone.isEnabled.collect { isEnabled ->
971
- android.util.Log.d("StreamCallPlugin", "Microphone status changed for call ${call.id}: enabled=$isEnabled")
950
+ Log.d("StreamCallPlugin", "Microphone status changed for call ${call.id}: enabled=$isEnabled")
972
951
  updateCallStatusAndNotify(call.cid, if (isEnabled) "microphone_enabled" else "microphone_disabled")
973
952
  }
974
953
  }
@@ -985,18 +964,18 @@ public class StreamCallPlugin : Plugin() {
985
964
  }
986
965
 
987
966
  private fun registerActivityEventListener(application: Application) {
988
- android.util.Log.i("StreamCallPlugin", "Registering activity event listener")
967
+ Log.i("StreamCallPlugin", "Registering activity event listener")
989
968
  application.registerActivityLifecycleCallbacks(object: ActivityLifecycleCallbacks() {
990
969
  override fun onActivityCreated(activity: Activity, bunlde: Bundle?) {
991
- android.util.Log.d("StreamCallPlugin", "onActivityCreated called")
970
+ Log.d("StreamCallPlugin", "onActivityCreated called")
992
971
  savedContext?.let {
993
972
  if (this@StreamCallPlugin.savedActivity != null && activity is BridgeActivity) {
994
- android.util.Log.d("StreamCallPlugin", "Activity created before, but got re-created. saving and returning")
995
- this@StreamCallPlugin.savedActivity = activity;
973
+ Log.d("StreamCallPlugin", "Activity created before, but got re-created. saving and returning")
974
+ this@StreamCallPlugin.savedActivity = activity
996
975
  return
997
976
  }
998
977
  if (initializationTime == 0L) {
999
- android.util.Log.w("StreamCallPlugin", "initializationTime is zero. Not continuing with onActivityCreated")
978
+ Log.w("StreamCallPlugin", "initializationTime is zero. Not continuing with onActivityCreated")
1000
979
  return
1001
980
  }
1002
981
 
@@ -1004,8 +983,8 @@ public class StreamCallPlugin : Plugin() {
1004
983
  val isLocked = keyguardManager.isKeyguardLocked
1005
984
 
1006
985
  if (isLocked) {
1007
- this@StreamCallPlugin.bootedToHandleCall = true;
1008
- android.util.Log.d("StreamCallPlugin", "Detected that the app booted an activity while locked. We will kill after the call fails")
986
+ this@StreamCallPlugin.bootedToHandleCall = true
987
+ Log.d("StreamCallPlugin", "Detected that the app booted an activity while locked. We will kill after the call fails")
1009
988
  }
1010
989
 
1011
990
  if (this@StreamCallPlugin.bridge == null && activity is BridgeActivity) {
@@ -1027,7 +1006,7 @@ public class StreamCallPlugin : Plugin() {
1027
1006
  this@StreamCallPlugin.savedActivityPaused = false
1028
1007
  }
1029
1008
  for (call in this@StreamCallPlugin.savedCallsToEndOnResume) {
1030
- android.util.Log.d("StreamCallPlugin", "Trying to end call with ID ${call.id} on resume")
1009
+ Log.d("StreamCallPlugin", "Trying to end call with ID ${call.id} on resume")
1031
1010
  transEndCallRaw(call)
1032
1011
  }
1033
1012
  super.onActivityResumed(activity)
@@ -1036,8 +1015,8 @@ public class StreamCallPlugin : Plugin() {
1036
1015
  }
1037
1016
 
1038
1017
  @PluginMethod
1039
- public fun acceptCall(call: PluginCall) {
1040
- android.util.Log.d("StreamCallPlugin", "acceptCall called")
1018
+ fun acceptCall(call: PluginCall) {
1019
+ Log.d("StreamCallPlugin", "acceptCall called")
1041
1020
  try {
1042
1021
  val streamVideoCall = streamVideoClient?.state?.ringingCall?.value
1043
1022
  if (streamVideoCall == null) {
@@ -1045,7 +1024,7 @@ public class StreamCallPlugin : Plugin() {
1045
1024
  return
1046
1025
  }
1047
1026
 
1048
- android.util.Log.d("StreamCallPlugin", "acceptCall: Accepting call immediately, will handle permissions after")
1027
+ Log.d("StreamCallPlugin", "acceptCall: Accepting call immediately, will handle permissions after")
1049
1028
 
1050
1029
  // Accept call immediately regardless of permissions - time is critical!
1051
1030
  kotlinx.coroutines.GlobalScope.launch {
@@ -1055,19 +1034,19 @@ public class StreamCallPlugin : Plugin() {
1055
1034
  put("success", true)
1056
1035
  })
1057
1036
  } catch (e: Exception) {
1058
- android.util.Log.e("StreamCallPlugin", "Error accepting call", e)
1037
+ Log.e("StreamCallPlugin", "Error accepting call", e)
1059
1038
  call.reject("Failed to accept call: ${e.message}")
1060
1039
  }
1061
1040
  }
1062
1041
  } catch (t: Throwable) {
1063
- android.util.Log.d("StreamCallPlugin", "JS -> acceptCall fail", t);
1042
+ Log.d("StreamCallPlugin", "JS -> acceptCall fail", t)
1064
1043
  call.reject("Cannot acceptCall")
1065
1044
  }
1066
1045
  }
1067
1046
 
1068
1047
  @PluginMethod
1069
- public fun rejectCall(call: PluginCall) {
1070
- android.util.Log.d("StreamCallPlugin", "rejectCall called")
1048
+ fun rejectCall(call: PluginCall) {
1049
+ Log.d("StreamCallPlugin", "rejectCall called")
1071
1050
  try {
1072
1051
  val streamVideoCall = streamVideoClient?.state?.ringingCall?.value
1073
1052
  if (streamVideoCall == null) {
@@ -1078,103 +1057,103 @@ public class StreamCallPlugin : Plugin() {
1078
1057
  declineCall(streamVideoCall)
1079
1058
  }
1080
1059
  } catch (t: Throwable) {
1081
- android.util.Log.d("StreamCallPlugin", "JS -> rejectCall fail", t);
1060
+ Log.d("StreamCallPlugin", "JS -> rejectCall fail", t)
1082
1061
  call.reject("Cannot rejectCall")
1083
1062
  }
1084
1063
  }
1085
1064
 
1086
1065
  @OptIn(DelicateCoroutinesApi::class, InternalStreamVideoApi::class)
1087
1066
  internal fun internalAcceptCall(call: Call, requestPermissionsAfter: Boolean = false) {
1088
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Entered for call: ${call.id}, requestPermissionsAfter: $requestPermissionsAfter")
1067
+ Log.d("StreamCallPlugin", "internalAcceptCall: Entered for call: ${call.id}, requestPermissionsAfter: $requestPermissionsAfter")
1089
1068
 
1090
1069
  kotlinx.coroutines.GlobalScope.launch {
1091
1070
  try {
1092
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Coroutine started for call ${call.id}")
1071
+ Log.d("StreamCallPlugin", "internalAcceptCall: Coroutine started for call ${call.id}")
1093
1072
 
1094
1073
  // Hide incoming call view first
1095
1074
  runOnMainThread {
1096
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Hiding incoming call view for call ${call.id}")
1075
+ Log.d("StreamCallPlugin", "internalAcceptCall: Hiding incoming call view for call ${call.id}")
1097
1076
  // No dedicated incoming-call native view anymore; UI handled by web layer
1098
1077
  }
1099
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Incoming call view hidden for call ${call.id}")
1078
+ Log.d("StreamCallPlugin", "internalAcceptCall: Incoming call view hidden for call ${call.id}")
1100
1079
 
1101
1080
  // Accept and join call immediately - don't wait for permissions!
1102
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Accepting call immediately for ${call.id}")
1081
+ Log.d("StreamCallPlugin", "internalAcceptCall: Accepting call immediately for ${call.id}")
1103
1082
  call.accept()
1104
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: call.accept() completed for call ${call.id}")
1083
+ Log.d("StreamCallPlugin", "internalAcceptCall: call.accept() completed for call ${call.id}")
1105
1084
  call.join()
1106
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: call.join() completed for call ${call.id}")
1085
+ Log.d("StreamCallPlugin", "internalAcceptCall: call.join() completed for call ${call.id}")
1107
1086
  streamVideoClient?.state?.setActiveCall(call)
1108
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: setActiveCall completed for call ${call.id}")
1087
+ Log.d("StreamCallPlugin", "internalAcceptCall: setActiveCall completed for call ${call.id}")
1109
1088
 
1110
1089
  // Notify that call has started using helper
1111
1090
  updateCallStatusAndNotify(call.id, "joined")
1112
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: updateCallStatusAndNotify(joined) called for ${call.id}")
1091
+ Log.d("StreamCallPlugin", "internalAcceptCall: updateCallStatusAndNotify(joined) called for ${call.id}")
1113
1092
 
1114
1093
  // Show overlay view with the active call and make webview transparent
1115
1094
  runOnMainThread {
1116
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Updating UI for active call ${call.id} - setting overlay visible.")
1095
+ Log.d("StreamCallPlugin", "internalAcceptCall: Updating UI for active call ${call.id} - setting overlay visible.")
1117
1096
  bridge?.webView?.setBackgroundColor(Color.TRANSPARENT) // Make webview transparent
1118
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: WebView background set to transparent for call ${call.id}")
1097
+ Log.d("StreamCallPlugin", "internalAcceptCall: WebView background set to transparent for call ${call.id}")
1119
1098
  bridge?.webView?.bringToFront() // Ensure WebView is on top and transparent
1120
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: WebView brought to front for call ${call.id}")
1099
+ Log.d("StreamCallPlugin", "internalAcceptCall: WebView brought to front for call ${call.id}")
1121
1100
 
1122
1101
  // Enable camera/microphone based on permissions
1123
1102
  val hasPermissions = checkPermissions()
1124
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Has permissions: $hasPermissions for call ${call.id}")
1103
+ Log.d("StreamCallPlugin", "internalAcceptCall: Has permissions: $hasPermissions for call ${call.id}")
1125
1104
 
1126
- call.microphone?.setEnabled(hasPermissions)
1127
- call.camera?.setEnabled(hasPermissions)
1128
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Microphone and camera set to $hasPermissions for call ${call.id}")
1105
+ call.microphone.setEnabled(hasPermissions)
1106
+ call.camera.setEnabled(hasPermissions)
1107
+ Log.d("StreamCallPlugin", "internalAcceptCall: Microphone and camera set to $hasPermissions for call ${call.id}")
1129
1108
 
1130
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Setting CallContent with active call ${call.id}")
1109
+ Log.d("StreamCallPlugin", "internalAcceptCall: Setting CallContent with active call ${call.id}")
1131
1110
  setOverlayContent(call)
1132
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Content set for overlayView for call ${call.id}")
1111
+ Log.d("StreamCallPlugin", "internalAcceptCall: Content set for overlayView for call ${call.id}")
1133
1112
  overlayView?.isVisible = true
1134
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: OverlayView set to visible for call ${call.id}, isVisible: ${overlayView?.isVisible}")
1113
+ Log.d("StreamCallPlugin", "internalAcceptCall: OverlayView set to visible for call ${call.id}, isVisible: ${overlayView?.isVisible}")
1135
1114
 
1136
1115
  // Ensure overlay is behind WebView by adjusting its position in the parent
1137
1116
  val parent = overlayView?.parent as? ViewGroup
1138
1117
  parent?.removeView(overlayView)
1139
1118
  parent?.addView(overlayView, 0) // Add at index 0 to ensure it's behind other views
1140
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: OverlayView re-added to parent at index 0 for call ${call.id}")
1119
+ Log.d("StreamCallPlugin", "internalAcceptCall: OverlayView re-added to parent at index 0 for call ${call.id}")
1141
1120
 
1142
1121
  // Add a small delay to ensure UI refresh
1143
1122
  mainHandler.postDelayed({
1144
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Delayed UI check, overlay visible: ${overlayView?.isVisible} for call ${call.id}")
1123
+ Log.d("StreamCallPlugin", "internalAcceptCall: Delayed UI check, overlay visible: ${overlayView?.isVisible} for call ${call.id}")
1145
1124
  if (overlayView?.isVisible == true) {
1146
1125
  overlayView?.invalidate()
1147
1126
  overlayView?.requestLayout()
1148
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: UI invalidated and layout requested for call ${call.id}")
1127
+ Log.d("StreamCallPlugin", "internalAcceptCall: UI invalidated and layout requested for call ${call.id}")
1149
1128
  // Force refresh with active call from client
1150
1129
  val activeCall = streamVideoClient?.state?.activeCall?.value
1151
1130
  if (activeCall != null) {
1152
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Force refreshing CallContent with active call ${activeCall.id}")
1131
+ Log.d("StreamCallPlugin", "internalAcceptCall: Force refreshing CallContent with active call ${activeCall.id}")
1153
1132
  setOverlayContent(activeCall)
1154
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Content force refreshed for call ${activeCall.id}")
1133
+ Log.d("StreamCallPlugin", "internalAcceptCall: Content force refreshed for call ${activeCall.id}")
1155
1134
  } else {
1156
- android.util.Log.w("StreamCallPlugin", "internalAcceptCall: Active call is null during force refresh for call ${call.id}")
1135
+ Log.w("StreamCallPlugin", "internalAcceptCall: Active call is null during force refresh for call ${call.id}")
1157
1136
  }
1158
1137
  } else {
1159
- android.util.Log.w("StreamCallPlugin", "internalAcceptCall: overlayView not visible after delay for call ${call.id}")
1138
+ Log.w("StreamCallPlugin", "internalAcceptCall: overlayView not visible after delay for call ${call.id}")
1160
1139
  }
1161
1140
  }, 1000) // Increased delay to ensure all events are processed
1162
1141
  }
1163
1142
 
1164
1143
  // Request permissions after joining if needed
1165
1144
  if (requestPermissionsAfter) {
1166
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Requesting permissions after call acceptance for ${call.id}")
1145
+ Log.d("StreamCallPlugin", "internalAcceptCall: Requesting permissions after call acceptance for ${call.id}")
1167
1146
  runOnMainThread {
1168
1147
  // Store reference to the active call for enabling camera/mic later
1169
1148
  pendingAcceptCall = call
1170
- android.util.Log.d("StreamCallPlugin", "internalAcceptCall: Set pendingAcceptCall to ${call.id}, resetting attempt count")
1149
+ Log.d("StreamCallPlugin", "internalAcceptCall: Set pendingAcceptCall to ${call.id}, resetting attempt count")
1171
1150
  permissionAttemptCount = 0
1172
1151
  requestPermissions()
1173
1152
  }
1174
1153
  }
1175
1154
 
1176
1155
  } catch (e: Exception) {
1177
- android.util.Log.e("StreamCallPlugin", "internalAcceptCall: Error accepting call ${call.id}: ${e.message}", e)
1156
+ Log.e("StreamCallPlugin", "internalAcceptCall: Error accepting call ${call.id}: ${e.message}", e)
1178
1157
  runOnMainThread {
1179
1158
  android.widget.Toast.makeText(
1180
1159
  context,
@@ -1188,54 +1167,54 @@ public class StreamCallPlugin : Plugin() {
1188
1167
 
1189
1168
  // Function to check required permissions
1190
1169
  private fun checkPermissions(): Boolean {
1191
- android.util.Log.d("StreamCallPlugin", "checkPermissions: Entered")
1170
+ Log.d("StreamCallPlugin", "checkPermissions: Entered")
1192
1171
  val audioPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO)
1193
- android.util.Log.d("StreamCallPlugin", "checkPermissions: RECORD_AUDIO permission status: $audioPermission (Granted=${PackageManager.PERMISSION_GRANTED})")
1172
+ Log.d("StreamCallPlugin", "checkPermissions: RECORD_AUDIO permission status: $audioPermission (Granted=${PackageManager.PERMISSION_GRANTED})")
1194
1173
  val cameraPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA)
1195
- android.util.Log.d("StreamCallPlugin", "checkPermissions: CAMERA permission status: $cameraPermission (Granted=${PackageManager.PERMISSION_GRANTED})")
1174
+ Log.d("StreamCallPlugin", "checkPermissions: CAMERA permission status: $cameraPermission (Granted=${PackageManager.PERMISSION_GRANTED})")
1196
1175
  val allGranted = audioPermission == PackageManager.PERMISSION_GRANTED && cameraPermission == PackageManager.PERMISSION_GRANTED
1197
- android.util.Log.d("StreamCallPlugin", "checkPermissions: All permissions granted: $allGranted")
1176
+ Log.d("StreamCallPlugin", "checkPermissions: All permissions granted: $allGranted")
1198
1177
  return allGranted
1199
1178
  }
1200
1179
 
1201
1180
  // Override to handle permission results
1202
1181
  override fun handleRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
1203
1182
  super.handleRequestPermissionsResult(requestCode, permissions, grantResults)
1204
- android.util.Log.d("StreamCallPlugin", "handleRequestPermissionsResult: Entered. RequestCode: $requestCode, Attempt: $permissionAttemptCount")
1205
- android.util.Log.d("StreamCallPlugin", "handleRequestPermissionsResult: Expected requestCode: 9001")
1183
+ Log.d("StreamCallPlugin", "handleRequestPermissionsResult: Entered. RequestCode: $requestCode, Attempt: $permissionAttemptCount")
1184
+ Log.d("StreamCallPlugin", "handleRequestPermissionsResult: Expected requestCode: 9001")
1206
1185
 
1207
1186
  if (requestCode == 9001) {
1208
1187
  val responseTime = System.currentTimeMillis() - permissionRequestStartTime
1209
- android.util.Log.d("StreamCallPlugin", "handleRequestPermissionsResult: Response time: ${responseTime}ms")
1188
+ Log.d("StreamCallPlugin", "handleRequestPermissionsResult: Response time: ${responseTime}ms")
1210
1189
 
1211
1190
  logPermissionResults(permissions, grantResults)
1212
1191
 
1213
1192
  if (grantResults.isNotEmpty() && grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
1214
- android.util.Log.i("StreamCallPlugin", "handleRequestPermissionsResult: All permissions GRANTED.")
1193
+ Log.i("StreamCallPlugin", "handleRequestPermissionsResult: All permissions GRANTED.")
1215
1194
  // Reset attempt count on success
1216
1195
  permissionAttemptCount = 0
1217
1196
  handlePermissionGranted()
1218
1197
  } else {
1219
- android.util.Log.e("StreamCallPlugin", "handleRequestPermissionsResult: Permissions DENIED. Attempt: $permissionAttemptCount")
1198
+ Log.e("StreamCallPlugin", "handleRequestPermissionsResult: Permissions DENIED. Attempt: $permissionAttemptCount")
1220
1199
  handlePermissionDenied(responseTime)
1221
1200
  }
1222
1201
  } else {
1223
- android.util.Log.w("StreamCallPlugin", "handleRequestPermissionsResult: Received unknown requestCode: $requestCode")
1202
+ Log.w("StreamCallPlugin", "handleRequestPermissionsResult: Received unknown requestCode: $requestCode")
1224
1203
  }
1225
1204
  }
1226
1205
 
1227
1206
  private fun logPermissionResults(permissions: Array<out String>, grantResults: IntArray) {
1228
- android.util.Log.d("StreamCallPlugin", "logPermissionResults: Logging permission results:")
1207
+ Log.d("StreamCallPlugin", "logPermissionResults: Logging permission results:")
1229
1208
  for (i in permissions.indices) {
1230
1209
  val permission = permissions[i]
1231
1210
  val grantResult = if (grantResults.size > i) grantResults[i] else -999 // -999 for safety if arrays mismatch
1232
1211
  val resultString = if (grantResult == PackageManager.PERMISSION_GRANTED) "GRANTED" else "DENIED ($grantResult)"
1233
- android.util.Log.d("StreamCallPlugin", " Permission: $permission, Result: $resultString")
1212
+ Log.d("StreamCallPlugin", " Permission: $permission, Result: $resultString")
1234
1213
  }
1235
1214
  }
1236
1215
 
1237
1216
  private fun handlePermissionGranted() {
1238
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Processing granted permissions")
1217
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Processing granted permissions")
1239
1218
 
1240
1219
  // Reset attempt count since permissions are now granted
1241
1220
  permissionAttemptCount = 0
@@ -1244,12 +1223,12 @@ public class StreamCallPlugin : Plugin() {
1244
1223
  val hasOutgoingCall = pendingCall != null && pendingCallUserIds != null
1245
1224
  val hasActiveCallNeedingPermissions = pendingAcceptCall != null
1246
1225
 
1247
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: hasOutgoingCall=$hasOutgoingCall, hasActiveCallNeedingPermissions=$hasActiveCallNeedingPermissions")
1226
+ Log.d("StreamCallPlugin", "handlePermissionGranted: hasOutgoingCall=$hasOutgoingCall, hasActiveCallNeedingPermissions=$hasActiveCallNeedingPermissions")
1248
1227
 
1249
1228
  when {
1250
1229
  hasOutgoingCall -> {
1251
1230
  // Outgoing call creation was waiting for permissions
1252
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Executing pending outgoing call with ${pendingCallUserIds?.size} users")
1231
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Executing pending outgoing call with ${pendingCallUserIds?.size} users")
1253
1232
  executePendingCall()
1254
1233
  }
1255
1234
 
@@ -1258,17 +1237,17 @@ public class StreamCallPlugin : Plugin() {
1258
1237
  val callToHandle = pendingAcceptCall!!
1259
1238
  val activeCall = streamVideoClient?.state?.activeCall?.value
1260
1239
 
1261
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Processing call ${callToHandle.id}")
1262
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Active call in state: ${activeCall?.id}")
1240
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Processing call ${callToHandle.id}")
1241
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Active call in state: ${activeCall?.id}")
1263
1242
 
1264
1243
  if (activeCall != null && activeCall.id == callToHandle.id) {
1265
1244
  // Call is already active - enable camera/microphone
1266
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Enabling camera/microphone for active call ${callToHandle.id}")
1245
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Enabling camera/microphone for active call ${callToHandle.id}")
1267
1246
  runOnMainThread {
1268
1247
  try {
1269
- callToHandle.microphone?.setEnabled(true)
1270
- callToHandle.camera?.setEnabled(true)
1271
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Camera and microphone enabled for call ${callToHandle.id}")
1248
+ callToHandle.microphone.setEnabled(true)
1249
+ callToHandle.camera.setEnabled(true)
1250
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Camera and microphone enabled for call ${callToHandle.id}")
1272
1251
 
1273
1252
  // Show success message
1274
1253
  android.widget.Toast.makeText(
@@ -1277,13 +1256,13 @@ public class StreamCallPlugin : Plugin() {
1277
1256
  android.widget.Toast.LENGTH_SHORT
1278
1257
  ).show()
1279
1258
  } catch (e: Exception) {
1280
- android.util.Log.e("StreamCallPlugin", "Error enabling camera/microphone", e)
1259
+ Log.e("StreamCallPlugin", "Error enabling camera/microphone", e)
1281
1260
  }
1282
1261
  clearPendingCall()
1283
1262
  }
1284
1263
  } else if (pendingCall != null) {
1285
1264
  // Call not active yet - accept it (old flow, shouldn't happen with new flow)
1286
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Accepting pending incoming call ${callToHandle.id}")
1265
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Accepting pending incoming call ${callToHandle.id}")
1287
1266
  kotlinx.coroutines.GlobalScope.launch {
1288
1267
  try {
1289
1268
  internalAcceptCall(callToHandle)
@@ -1291,7 +1270,7 @@ public class StreamCallPlugin : Plugin() {
1291
1270
  put("success", true)
1292
1271
  })
1293
1272
  } catch (e: Exception) {
1294
- android.util.Log.e("StreamCallPlugin", "Error accepting call after permission grant", e)
1273
+ Log.e("StreamCallPlugin", "Error accepting call after permission grant", e)
1295
1274
  pendingCall?.reject("Failed to accept call: ${e.message}")
1296
1275
  } finally {
1297
1276
  clearPendingCall()
@@ -1299,12 +1278,12 @@ public class StreamCallPlugin : Plugin() {
1299
1278
  }
1300
1279
  } else {
1301
1280
  // Just enable camera/mic for the stored call even if not currently active
1302
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Enabling camera/microphone for stored call ${callToHandle.id}")
1281
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Enabling camera/microphone for stored call ${callToHandle.id}")
1303
1282
  runOnMainThread {
1304
1283
  try {
1305
- callToHandle.microphone?.setEnabled(true)
1306
- callToHandle.camera?.setEnabled(true)
1307
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Camera and microphone enabled for stored call ${callToHandle.id}")
1284
+ callToHandle.microphone.setEnabled(true)
1285
+ callToHandle.camera.setEnabled(true)
1286
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Camera and microphone enabled for stored call ${callToHandle.id}")
1308
1287
 
1309
1288
  android.widget.Toast.makeText(
1310
1289
  context,
@@ -1312,7 +1291,7 @@ public class StreamCallPlugin : Plugin() {
1312
1291
  android.widget.Toast.LENGTH_SHORT
1313
1292
  ).show()
1314
1293
  } catch (e: Exception) {
1315
- android.util.Log.e("StreamCallPlugin", "Error enabling camera/microphone for stored call", e)
1294
+ Log.e("StreamCallPlugin", "Error enabling camera/microphone for stored call", e)
1316
1295
  }
1317
1296
  clearPendingCall()
1318
1297
  }
@@ -1321,14 +1300,14 @@ public class StreamCallPlugin : Plugin() {
1321
1300
 
1322
1301
  pendingCall != null -> {
1323
1302
  // We have a pending call but unclear what type - fallback handling
1324
- android.util.Log.w("StreamCallPlugin", "handlePermissionGranted: Have pendingCall but unclear operation type")
1325
- android.util.Log.w("StreamCallPlugin", " - pendingCallUserIds: ${pendingCallUserIds != null}")
1326
- android.util.Log.w("StreamCallPlugin", " - pendingAcceptCall: ${pendingAcceptCall != null}")
1303
+ Log.w("StreamCallPlugin", "handlePermissionGranted: Have pendingCall but unclear operation type")
1304
+ Log.w("StreamCallPlugin", " - pendingCallUserIds: ${pendingCallUserIds != null}")
1305
+ Log.w("StreamCallPlugin", " - pendingAcceptCall: ${pendingAcceptCall != null}")
1327
1306
 
1328
1307
  // Try fallback to current ringing call for acceptance
1329
1308
  val ringingCall = streamVideoClient?.state?.ringingCall?.value
1330
1309
  if (ringingCall != null) {
1331
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: Fallback - accepting current ringing call ${ringingCall.id}")
1310
+ Log.d("StreamCallPlugin", "handlePermissionGranted: Fallback - accepting current ringing call ${ringingCall.id}")
1332
1311
  kotlinx.coroutines.GlobalScope.launch {
1333
1312
  try {
1334
1313
  internalAcceptCall(ringingCall)
@@ -1336,43 +1315,43 @@ public class StreamCallPlugin : Plugin() {
1336
1315
  put("success", true)
1337
1316
  })
1338
1317
  } catch (e: Exception) {
1339
- android.util.Log.e("StreamCallPlugin", "Error accepting fallback call after permission grant", e)
1318
+ Log.e("StreamCallPlugin", "Error accepting fallback call after permission grant", e)
1340
1319
  pendingCall?.reject("Failed to accept call: ${e.message}")
1341
1320
  } finally {
1342
1321
  clearPendingCall()
1343
1322
  }
1344
1323
  }
1345
1324
  } else {
1346
- android.util.Log.w("StreamCallPlugin", "handlePermissionGranted: No ringing call found for fallback")
1325
+ Log.w("StreamCallPlugin", "handlePermissionGranted: No ringing call found for fallback")
1347
1326
  pendingCall?.reject("Unable to determine pending operation")
1348
1327
  clearPendingCall()
1349
1328
  }
1350
1329
  }
1351
1330
 
1352
1331
  else -> {
1353
- android.util.Log.d("StreamCallPlugin", "handlePermissionGranted: No pending operations to handle")
1332
+ Log.d("StreamCallPlugin", "handlePermissionGranted: No pending operations to handle")
1354
1333
  }
1355
1334
  }
1356
1335
  }
1357
1336
 
1358
1337
  private fun handlePermissionDenied(responseTime: Long) {
1359
- android.util.Log.d("StreamCallPlugin", "handlePermissionDenied: Response time: ${responseTime}ms, Attempt: $permissionAttemptCount")
1338
+ Log.d("StreamCallPlugin", "handlePermissionDenied: Response time: ${responseTime}ms, Attempt: $permissionAttemptCount")
1360
1339
 
1361
1340
  // Check if the response was instant (< 500ms) indicating "don't ask again"
1362
1341
  val instantDenial = responseTime < 500
1363
- android.util.Log.d("StreamCallPlugin", "handlePermissionDenied: Instant denial detected: $instantDenial")
1342
+ Log.d("StreamCallPlugin", "handlePermissionDenied: Instant denial detected: $instantDenial")
1364
1343
 
1365
1344
  if (instantDenial) {
1366
1345
  // If it's an instant denial (don't ask again), go straight to settings dialog
1367
- android.util.Log.d("StreamCallPlugin", "handlePermissionDenied: Instant denial, showing settings dialog")
1346
+ Log.d("StreamCallPlugin", "handlePermissionDenied: Instant denial, showing settings dialog")
1368
1347
  showPermissionSettingsDialog()
1369
1348
  } else if (permissionAttemptCount < 2) {
1370
1349
  // Try asking again immediately if this is the first denial
1371
- android.util.Log.d("StreamCallPlugin", "handlePermissionDenied: First denial (attempt $permissionAttemptCount), asking again immediately")
1350
+ Log.d("StreamCallPlugin", "handlePermissionDenied: First denial (attempt $permissionAttemptCount), asking again immediately")
1372
1351
  requestPermissions() // This will increment the attempt count
1373
1352
  } else {
1374
1353
  // Second denial - show settings dialog (final ask)
1375
- android.util.Log.d("StreamCallPlugin", "handlePermissionDenied: Second denial (attempt $permissionAttemptCount), showing settings dialog (final ask)")
1354
+ Log.d("StreamCallPlugin", "handlePermissionDenied: Second denial (attempt $permissionAttemptCount), showing settings dialog (final ask)")
1376
1355
  showPermissionSettingsDialog()
1377
1356
  }
1378
1357
  }
@@ -1386,7 +1365,7 @@ public class StreamCallPlugin : Plugin() {
1386
1365
  val custom = pendingCustomObject
1387
1366
 
1388
1367
  if (call != null && userIds != null && callType != null && shouldRing != null) {
1389
- android.util.Log.d("StreamCallPlugin", "executePendingCall: Executing call with ${userIds.size} users")
1368
+ Log.d("StreamCallPlugin", "executePendingCall: Executing call with ${userIds.size} users")
1390
1369
 
1391
1370
  // Clear pending call data
1392
1371
  clearPendingCall()
@@ -1394,7 +1373,7 @@ public class StreamCallPlugin : Plugin() {
1394
1373
  // Execute the call creation logic
1395
1374
  createAndStartCall(call, userIds, callType, shouldRing, team, custom)
1396
1375
  } else {
1397
- android.util.Log.w("StreamCallPlugin", "executePendingCall: Missing pending call data")
1376
+ Log.w("StreamCallPlugin", "executePendingCall: Missing pending call data")
1398
1377
  call?.reject("Internal error: missing call parameters")
1399
1378
  clearPendingCall()
1400
1379
  }
@@ -1433,7 +1412,7 @@ public class StreamCallPlugin : Plugin() {
1433
1412
  // instead, which contains the actual participant list
1434
1413
 
1435
1414
 
1436
- android.util.Log.d("StreamCallPlugin", "Creating call with members...")
1415
+ Log.d("StreamCallPlugin", "Creating call with members...")
1437
1416
  // Create the call with all members
1438
1417
  val createResult = streamCall?.create(
1439
1418
  memberIds = userIds + selfUserId,
@@ -1446,7 +1425,7 @@ public class StreamCallPlugin : Plugin() {
1446
1425
  throw (createResult.errorOrNull() ?: RuntimeException("Unknown error creating call")) as Throwable
1447
1426
  }
1448
1427
 
1449
- android.util.Log.d("StreamCallPlugin", "Setting overlay visible for outgoing call $callId")
1428
+ Log.d("StreamCallPlugin", "Setting overlay visible for outgoing call $callId")
1450
1429
  // Show overlay view
1451
1430
  activity?.runOnUiThread {
1452
1431
  streamCall?.microphone?.setEnabled(true)
@@ -1467,7 +1446,7 @@ public class StreamCallPlugin : Plugin() {
1467
1446
  put("success", true)
1468
1447
  })
1469
1448
  } catch (e: Exception) {
1470
- android.util.Log.e("StreamCallPlugin", "Error making call: ${e.message}")
1449
+ Log.e("StreamCallPlugin", "Error making call: ${e.message}")
1471
1450
  call.reject("Failed to make call: ${e.message}")
1472
1451
  }
1473
1452
  }
@@ -1476,11 +1455,11 @@ public class StreamCallPlugin : Plugin() {
1476
1455
  // Function to request required permissions
1477
1456
  private fun requestPermissions() {
1478
1457
  permissionAttemptCount++
1479
- android.util.Log.d("StreamCallPlugin", "requestPermissions: Attempt #$permissionAttemptCount - Requesting RECORD_AUDIO and CAMERA permissions.")
1458
+ Log.d("StreamCallPlugin", "requestPermissions: Attempt #$permissionAttemptCount - Requesting RECORD_AUDIO and CAMERA permissions.")
1480
1459
 
1481
1460
  // Record timing for instant denial detection
1482
1461
  permissionRequestStartTime = System.currentTimeMillis()
1483
- android.util.Log.d("StreamCallPlugin", "requestPermissions: Starting permission request at $permissionRequestStartTime")
1462
+ Log.d("StreamCallPlugin", "requestPermissions: Starting permission request at $permissionRequestStartTime")
1484
1463
 
1485
1464
  ActivityCompat.requestPermissions(
1486
1465
  activity,
@@ -1488,7 +1467,7 @@ public class StreamCallPlugin : Plugin() {
1488
1467
  9001 // Use high request code to avoid Capacitor conflicts
1489
1468
  )
1490
1469
 
1491
- android.util.Log.d("StreamCallPlugin", "requestPermissions: Permission request initiated with code 9001")
1470
+ Log.d("StreamCallPlugin", "requestPermissions: Permission request initiated with code 9001")
1492
1471
  }
1493
1472
 
1494
1473
  private fun showPermissionSettingsDialog() {
@@ -1502,19 +1481,19 @@ public class StreamCallPlugin : Plugin() {
1502
1481
  if (hasActiveCall) {
1503
1482
  builder.setMessage("Your call is active but camera and microphone are disabled.\n\nWould you like to open Settings to enable video and audio?")
1504
1483
  builder.setNegativeButton("Continue without") { _, _ ->
1505
- android.util.Log.d("StreamCallPlugin", "User chose to continue call without permissions")
1484
+ Log.d("StreamCallPlugin", "User chose to continue call without permissions")
1506
1485
  showPermissionRequiredMessage()
1507
1486
  }
1508
1487
  } else {
1509
1488
  builder.setMessage("To make video calls, this app needs Camera and Microphone permissions.\n\nWould you like to open Settings to enable them?")
1510
1489
  builder.setNegativeButton("Cancel") { _, _ ->
1511
- android.util.Log.d("StreamCallPlugin", "User declined to grant permissions - final rejection")
1490
+ Log.d("StreamCallPlugin", "User declined to grant permissions - final rejection")
1512
1491
  showPermissionRequiredMessage()
1513
1492
  }
1514
1493
  }
1515
1494
 
1516
1495
  builder.setPositiveButton("Open Settings") { _, _ ->
1517
- android.util.Log.d("StreamCallPlugin", "User chose to open app settings")
1496
+ Log.d("StreamCallPlugin", "User chose to open app settings")
1518
1497
  openAppSettings()
1519
1498
  // Don't reject the call yet - let them go to settings and come back
1520
1499
  }
@@ -1548,7 +1527,7 @@ public class StreamCallPlugin : Plugin() {
1548
1527
  }
1549
1528
 
1550
1529
  private fun handleFinalPermissionDenial() {
1551
- android.util.Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Processing final permission denial")
1530
+ Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Processing final permission denial")
1552
1531
 
1553
1532
  val hasOutgoingCall = pendingCall != null && pendingCallUserIds != null
1554
1533
  val hasIncomingCall = pendingCall != null && pendingAcceptCall != null
@@ -1557,22 +1536,22 @@ public class StreamCallPlugin : Plugin() {
1557
1536
  when {
1558
1537
  hasOutgoingCall -> {
1559
1538
  // Outgoing call that couldn't be created due to permissions
1560
- android.util.Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Rejecting outgoing call creation")
1539
+ Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Rejecting outgoing call creation")
1561
1540
  pendingCall?.reject("Permissions required for call. Please grant them.")
1562
1541
  clearPendingCall()
1563
1542
  }
1564
1543
 
1565
1544
  hasIncomingCall && activeCall != null && activeCall.id == pendingAcceptCall?.id -> {
1566
1545
  // Incoming call that's already active - DON'T end the call, just keep it without camera/mic
1567
- android.util.Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Incoming call already active, keeping call without camera/mic")
1546
+ Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Incoming call already active, keeping call without camera/mic")
1568
1547
 
1569
1548
  // Ensure camera and microphone are disabled since no permissions
1570
1549
  try {
1571
- activeCall.microphone?.setEnabled(false)
1572
- activeCall.camera?.setEnabled(false)
1573
- android.util.Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Disabled camera/microphone for call ${activeCall.id}")
1550
+ activeCall.microphone.setEnabled(false)
1551
+ activeCall.camera.setEnabled(false)
1552
+ Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Disabled camera/microphone for call ${activeCall.id}")
1574
1553
  } catch (e: Exception) {
1575
- android.util.Log.w("StreamCallPlugin", "handleFinalPermissionDenial: Error disabling camera/mic", e)
1554
+ Log.w("StreamCallPlugin", "handleFinalPermissionDenial: Error disabling camera/mic", e)
1576
1555
  }
1577
1556
 
1578
1557
  android.widget.Toast.makeText(
@@ -1591,13 +1570,13 @@ public class StreamCallPlugin : Plugin() {
1591
1570
 
1592
1571
  hasIncomingCall -> {
1593
1572
  // Incoming call that wasn't accepted yet (old flow)
1594
- android.util.Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Rejecting incoming call acceptance")
1573
+ Log.d("StreamCallPlugin", "handleFinalPermissionDenial: Rejecting incoming call acceptance")
1595
1574
  pendingCall?.reject("Permissions required for call. Please grant them.")
1596
1575
  clearPendingCall()
1597
1576
  }
1598
1577
 
1599
1578
  else -> {
1600
- android.util.Log.d("StreamCallPlugin", "handleFinalPermissionDenial: No pending operations to handle")
1579
+ Log.d("StreamCallPlugin", "handleFinalPermissionDenial: No pending operations to handle")
1601
1580
  clearPendingCall()
1602
1581
  }
1603
1582
  }
@@ -1610,10 +1589,10 @@ public class StreamCallPlugin : Plugin() {
1610
1589
  try {
1611
1590
  val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
1612
1591
  ("package:" + activity.packageName).toUri())
1613
- intent.addCategory(Intent.CATEGORY_DEFAULT);
1614
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1592
+ intent.addCategory(Intent.CATEGORY_DEFAULT)
1593
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
1615
1594
  context.startActivity(intent)
1616
- android.util.Log.d("StreamCallPlugin", "Opened app details settings (Android 11+)")
1595
+ Log.d("StreamCallPlugin", "Opened app details settings (Android 11+)")
1617
1596
 
1618
1597
  // Show toast with specific instructions
1619
1598
  runOnMainThread {
@@ -1625,17 +1604,17 @@ public class StreamCallPlugin : Plugin() {
1625
1604
  }
1626
1605
  return
1627
1606
  } catch (e: Exception) {
1628
- android.util.Log.w("StreamCallPlugin", "Failed to open app details, falling back", e)
1607
+ Log.w("StreamCallPlugin", "Failed to open app details, falling back", e)
1629
1608
  }
1630
1609
  }
1631
1610
 
1632
1611
  // Fallback for older Android versions or if the above fails
1633
- val intent = android.content.Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
1612
+ val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
1634
1613
  data = Uri.fromParts("package", context.packageName, null)
1635
1614
  addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
1636
1615
  }
1637
1616
  context.startActivity(intent)
1638
- android.util.Log.d("StreamCallPlugin", "Opened app settings via fallback")
1617
+ Log.d("StreamCallPlugin", "Opened app settings via fallback")
1639
1618
 
1640
1619
  // Show more specific instructions for older versions
1641
1620
  runOnMainThread {
@@ -1647,15 +1626,15 @@ public class StreamCallPlugin : Plugin() {
1647
1626
  }
1648
1627
 
1649
1628
  } catch (e: Exception) {
1650
- android.util.Log.e("StreamCallPlugin", "Error opening app settings", e)
1629
+ Log.e("StreamCallPlugin", "Error opening app settings", e)
1651
1630
 
1652
1631
  // Final fallback - open general settings
1653
1632
  try {
1654
- val intent = android.content.Intent(android.provider.Settings.ACTION_SETTINGS).apply {
1633
+ val intent = Intent(Settings.ACTION_SETTINGS).apply {
1655
1634
  addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
1656
1635
  }
1657
1636
  context.startActivity(intent)
1658
- android.util.Log.d("StreamCallPlugin", "Opened general settings as final fallback")
1637
+ Log.d("StreamCallPlugin", "Opened general settings as final fallback")
1659
1638
 
1660
1639
  runOnMainThread {
1661
1640
  android.widget.Toast.makeText(
@@ -1665,7 +1644,7 @@ public class StreamCallPlugin : Plugin() {
1665
1644
  ).show()
1666
1645
  }
1667
1646
  } catch (finalException: Exception) {
1668
- android.util.Log.e("StreamCallPlugin", "All settings intents failed", finalException)
1647
+ Log.e("StreamCallPlugin", "All settings intents failed", finalException)
1669
1648
  runOnMainThread {
1670
1649
  android.widget.Toast.makeText(
1671
1650
  context,
@@ -1701,11 +1680,12 @@ public class StreamCallPlugin : Plugin() {
1701
1680
  put("success", true)
1702
1681
  })
1703
1682
  } catch (e: Exception) {
1704
- android.util.Log.e("StreamCallPlugin", "Error setting microphone: ${e.message}")
1683
+ Log.e("StreamCallPlugin", "Error setting microphone: ${e.message}")
1705
1684
  call.reject("Failed to set microphone: ${e.message}")
1706
1685
  }
1707
1686
  }
1708
1687
  } catch (e: Exception) {
1688
+ Log.e("StreamCallPlugin", "Error setting microphone: ${e.message}")
1709
1689
  call.reject("StreamVideo not initialized")
1710
1690
  }
1711
1691
  }
@@ -1731,11 +1711,12 @@ public class StreamCallPlugin : Plugin() {
1731
1711
  put("enabled", enabled)
1732
1712
  })
1733
1713
  } catch (e: Exception) {
1734
- android.util.Log.e("StreamCallPlugin", "Error checking the camera status: ${e.message}")
1714
+ Log.e("StreamCallPlugin", "Error checking the camera status: ${e.message}")
1735
1715
  call.reject("Failed to check if camera is enabled: ${e.message}")
1736
1716
  }
1737
1717
  }
1738
1718
  } catch (e: Exception) {
1719
+ Log.e("StreamCallPlugin", "Error checking camera status: ${e.message}")
1739
1720
  call.reject("StreamVideo not initialized")
1740
1721
  }
1741
1722
  }
@@ -1762,11 +1743,12 @@ public class StreamCallPlugin : Plugin() {
1762
1743
  put("success", true)
1763
1744
  })
1764
1745
  } catch (e: Exception) {
1765
- android.util.Log.e("StreamCallPlugin", "Error setting camera: ${e.message}")
1746
+ Log.e("StreamCallPlugin", "Error setting camera: ${e.message}")
1766
1747
  call.reject("Failed to set camera: ${e.message}")
1767
1748
  }
1768
1749
  }
1769
1750
  } catch (e: Exception) {
1751
+ Log.e("StreamCallPlugin", "Error setting camera: ${e.message}")
1770
1752
  call.reject("StreamVideo not initialized")
1771
1753
  }
1772
1754
  }
@@ -1774,29 +1756,29 @@ public class StreamCallPlugin : Plugin() {
1774
1756
  @OptIn(InternalStreamVideoApi::class)
1775
1757
  private suspend fun endCallRaw(call: Call) {
1776
1758
  val callId = call.id
1777
- android.util.Log.d("StreamCallPlugin", "Attempting to end call $callId")
1759
+ Log.d("StreamCallPlugin", "Attempting to end call $callId")
1778
1760
 
1779
1761
  try {
1780
1762
  // Get call information to make the decision
1781
1763
  val callInfo = call.get()
1782
- val callData = callInfo?.getOrNull()?.call
1764
+ val callData = callInfo.getOrNull()?.call
1783
1765
  val currentUserId = streamVideoClient?.userId
1784
1766
  val createdBy = callData?.createdBy?.id
1785
1767
  val isCreator = createdBy == currentUserId
1786
1768
 
1787
1769
  // Use call.state.totalParticipants to get participant count (as per StreamVideo Android SDK docs)
1788
- val totalParticipants = call.state.totalParticipants.value ?: 0
1770
+ val totalParticipants = call.state.totalParticipants.value
1789
1771
  val shouldEndCall = isCreator || totalParticipants <= 1
1790
1772
 
1791
- android.util.Log.d("StreamCallPlugin", "Call $callId - Creator: $createdBy, CurrentUser: $currentUserId, IsCreator: $isCreator, TotalParticipants: $totalParticipants, ShouldEnd: $shouldEndCall")
1773
+ Log.d("StreamCallPlugin", "Call $callId - Creator: $createdBy, CurrentUser: $currentUserId, IsCreator: $isCreator, TotalParticipants: $totalParticipants, ShouldEnd: $shouldEndCall")
1792
1774
 
1793
1775
  if (shouldEndCall) {
1794
1776
  // End the call for everyone if I'm the creator or only 1 person
1795
- android.util.Log.d("StreamCallPlugin", "Ending call $callId for all participants (creator: $isCreator, participants: $totalParticipants)")
1777
+ Log.d("StreamCallPlugin", "Ending call $callId for all participants (creator: $isCreator, participants: $totalParticipants)")
1796
1778
  call.end()
1797
1779
  } else {
1798
1780
  // Just leave the call if there are more than 1 person and I'm not the creator
1799
- android.util.Log.d("StreamCallPlugin", "Leaving call $callId (not creator, >1 participants)")
1781
+ Log.d("StreamCallPlugin", "Leaving call $callId (not creator, >1 participants)")
1800
1782
  call.leave()
1801
1783
  }
1802
1784
 
@@ -1806,7 +1788,7 @@ public class StreamCallPlugin : Plugin() {
1806
1788
  }
1807
1789
 
1808
1790
  } catch (e: Exception) {
1809
- android.util.Log.e("StreamCallPlugin", "Error getting call info for $callId, defaulting to leave()", e)
1791
+ Log.e("StreamCallPlugin", "Error getting call info for $callId, defaulting to leave()", e)
1810
1792
  // Fallback to leave if we can't determine the call info
1811
1793
  call.leave()
1812
1794
  }
@@ -1814,12 +1796,12 @@ public class StreamCallPlugin : Plugin() {
1814
1796
  // Capture context from the overlayView
1815
1797
  val currentContext = overlayView?.context ?: this.savedContext
1816
1798
  if (currentContext == null) {
1817
- android.util.Log.w("StreamCallPlugin", "Cannot end call $callId because context is null")
1799
+ Log.w("StreamCallPlugin", "Cannot end call $callId because context is null")
1818
1800
  return
1819
1801
  }
1820
1802
 
1821
1803
  runOnMainThread {
1822
- android.util.Log.d("StreamCallPlugin", "Setting overlay invisible after ending call $callId")
1804
+ Log.d("StreamCallPlugin", "Setting overlay invisible after ending call $callId")
1823
1805
 
1824
1806
 
1825
1807
  currentContext.let { ctx ->
@@ -1838,7 +1820,7 @@ public class StreamCallPlugin : Plugin() {
1838
1820
  if (savedCapacitorActivity != null) {
1839
1821
 
1840
1822
  if (savedActivityPaused) {
1841
- android.util.Log.d("StreamCallPlugin", "Activity is paused. Adding call ${call.id} to savedCallsToEndOnResume")
1823
+ Log.d("StreamCallPlugin", "Activity is paused. Adding call ${call.id} to savedCallsToEndOnResume")
1842
1824
  savedCallsToEndOnResume.add(call)
1843
1825
  } else {
1844
1826
  transEndCallRaw(call)
@@ -1852,7 +1834,7 @@ public class StreamCallPlugin : Plugin() {
1852
1834
  bridge?.webView?.setBackgroundColor(Color.WHITE) // Restore webview opacity
1853
1835
 
1854
1836
  // Also hide incoming call view if visible
1855
- android.util.Log.d("StreamCallPlugin", "Hiding incoming call view for call $callId")
1837
+ Log.d("StreamCallPlugin", "Hiding incoming call view for call $callId")
1856
1838
  // No dedicated incoming-call native view anymore; UI handled by web layer
1857
1839
  }
1858
1840
 
@@ -1863,21 +1845,21 @@ public class StreamCallPlugin : Plugin() {
1863
1845
  private fun changeActivityAsVisibleOnLockScreen(activity: Activity, visible: Boolean) {
1864
1846
  if (visible) {
1865
1847
  // Ensure the activity is visible over the lock screen when launched via full-screen intent
1866
- android.util.Log.d("StreamCallPlugin", "Mark the mainActivity as visible on the lockscreen")
1848
+ Log.d("StreamCallPlugin", "Mark the mainActivity as visible on the lockscreen")
1867
1849
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
1868
1850
  activity.setShowWhenLocked(true)
1869
1851
  activity.setTurnScreenOn(true)
1870
1852
  } else {
1871
- activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
1853
+ activity.window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
1872
1854
  }
1873
1855
  } else {
1874
1856
  // Ensure the activity is NOT visible over the lock screen when launched via full-screen intent
1875
- android.util.Log.d("StreamCallPlugin", "Clear the flag for the mainActivity for visible on the lockscreen")
1857
+ Log.d("StreamCallPlugin", "Clear the flag for the mainActivity for visible on the lockscreen")
1876
1858
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
1877
1859
  activity.setShowWhenLocked(false)
1878
1860
  activity.setTurnScreenOn(false)
1879
1861
  } else {
1880
- activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
1862
+ activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
1881
1863
  }
1882
1864
  }
1883
1865
 
@@ -1888,21 +1870,21 @@ public class StreamCallPlugin : Plugin() {
1888
1870
  val callId = call.id
1889
1871
  val savedCapacitorActivity = savedActivity
1890
1872
  if (savedCapacitorActivity == null) {
1891
- android.util.Log.d("StreamCallPlugin", "Cannot perform transEndCallRaw for call $callId. savedCapacitorActivity is null")
1873
+ Log.d("StreamCallPlugin", "Cannot perform transEndCallRaw for call $callId. savedCapacitorActivity is null")
1892
1874
  return
1893
1875
  }
1894
- android.util.Log.d("StreamCallPlugin", "Performing a trans-instance call to end call with id $callId")
1876
+ Log.d("StreamCallPlugin", "Performing a trans-instance call to end call with id $callId")
1895
1877
  if (savedCapacitorActivity !is BridgeActivity) {
1896
- android.util.Log.e("StreamCallPlugin", "Saved activity is NOT a Capactor activity. Saved activity class: ${savedCapacitorActivity.javaClass.canonicalName}")
1878
+ Log.e("StreamCallPlugin", "Saved activity is NOT a Capactor activity. Saved activity class: ${savedCapacitorActivity.javaClass.canonicalName}")
1897
1879
  return
1898
1880
  }
1899
1881
  val plugin = savedCapacitorActivity.bridge.getPlugin("StreamCall")
1900
1882
  if (plugin == null) {
1901
- android.util.Log.e("StreamCallPlugin", "Plugin with name StreamCall not found?????")
1883
+ Log.e("StreamCallPlugin", "Plugin with name StreamCall not found?????")
1902
1884
  return
1903
1885
  }
1904
1886
  if (plugin.instance !is StreamCallPlugin) {
1905
- android.util.Log.e("StreamCallPlugin", "Plugin found, but invalid instance")
1887
+ Log.e("StreamCallPlugin", "Plugin found, but invalid instance")
1906
1888
  return
1907
1889
  }
1908
1890
 
@@ -1910,7 +1892,7 @@ public class StreamCallPlugin : Plugin() {
1910
1892
  try {
1911
1893
  (plugin.instance as StreamCallPlugin).endCallRaw(call)
1912
1894
  } catch (e: Exception) {
1913
- android.util.Log.e("StreamCallPlugin", "Error ending call on remote instance", e)
1895
+ Log.e("StreamCallPlugin", "Error ending call on remote instance", e)
1914
1896
  }
1915
1897
  }
1916
1898
  }
@@ -1925,12 +1907,12 @@ public class StreamCallPlugin : Plugin() {
1925
1907
  val callToEnd = activeCall ?: ringingCall
1926
1908
 
1927
1909
  if (callToEnd == null) {
1928
- android.util.Log.w("StreamCallPlugin", "Attempted to end call but no active or ringing call found")
1910
+ Log.w("StreamCallPlugin", "Attempted to end call but no active or ringing call found")
1929
1911
  call.reject("No active call to end")
1930
1912
  return
1931
1913
  }
1932
1914
 
1933
- android.util.Log.d("StreamCallPlugin", "Ending call: activeCall=${activeCall?.id}, ringingCall=${ringingCall?.id}, callToEnd=${callToEnd.id}")
1915
+ Log.d("StreamCallPlugin", "Ending call: activeCall=${activeCall?.id}, ringingCall=${ringingCall?.id}, callToEnd=${callToEnd.id}")
1934
1916
 
1935
1917
  kotlinx.coroutines.GlobalScope.launch {
1936
1918
  try {
@@ -1939,11 +1921,12 @@ public class StreamCallPlugin : Plugin() {
1939
1921
  put("success", true)
1940
1922
  })
1941
1923
  } catch (e: Exception) {
1942
- android.util.Log.e("StreamCallPlugin", "Error ending call: ${e.message}")
1924
+ Log.e("StreamCallPlugin", "Error ending call: ${e.message}")
1943
1925
  call.reject("Failed to end call: ${e.message}")
1944
1926
  }
1945
1927
  }
1946
1928
  } catch (e: Exception) {
1929
+ Log.e("StreamCallPlugin", "Error ending call: ${e.message}")
1947
1930
  call.reject("StreamVideo not initialized")
1948
1931
  }
1949
1932
  }
@@ -1974,20 +1957,20 @@ public class StreamCallPlugin : Plugin() {
1974
1957
  val callType = call.getString("type") ?: "default"
1975
1958
  val shouldRing = call.getBoolean("ring") ?: true
1976
1959
  val callId = java.util.UUID.randomUUID().toString()
1977
- val team = call.getString("team");
1960
+ val team = call.getString("team")
1978
1961
 
1979
- android.util.Log.d("StreamCallPlugin", "Creating call:")
1980
- android.util.Log.d("StreamCallPlugin", "- Call ID: $callId")
1981
- android.util.Log.d("StreamCallPlugin", "- Call Type: $callType")
1982
- android.util.Log.d("StreamCallPlugin", "- Users: $userIds")
1983
- android.util.Log.d("StreamCallPlugin", "- Should Ring: $shouldRing")
1962
+ Log.d("StreamCallPlugin", "Creating call:")
1963
+ Log.d("StreamCallPlugin", "- Call ID: $callId")
1964
+ Log.d("StreamCallPlugin", "- Call Type: $callType")
1965
+ Log.d("StreamCallPlugin", "- Users: $userIds")
1966
+ Log.d("StreamCallPlugin", "- Should Ring: $shouldRing")
1984
1967
  if (custom != null) {
1985
- android.util.Log.d("StreamCallPlugin", "- Custom data: $custom")
1968
+ Log.d("StreamCallPlugin", "- Custom data: $custom")
1986
1969
  }
1987
1970
 
1988
1971
  // Check permissions before creating the call
1989
1972
  if (!checkPermissions()) {
1990
- android.util.Log.d("StreamCallPlugin", "Permissions not granted, storing call parameters and requesting permissions")
1973
+ Log.d("StreamCallPlugin", "Permissions not granted, storing call parameters and requesting permissions")
1991
1974
  // Store call parameters for later execution
1992
1975
  pendingCall = call
1993
1976
  pendingCallUserIds = userIds
@@ -2026,7 +2009,7 @@ public class StreamCallPlugin : Plugin() {
2026
2009
 
2027
2010
  callStates[callCid] = callState
2028
2011
 
2029
- android.util.Log.d("StreamCallPlugin", "Started timeout monitor for call $callCid with ${memberIds.size} members")
2012
+ Log.d("StreamCallPlugin", "Started timeout monitor for call $callCid with ${memberIds.size} members")
2030
2013
  }
2031
2014
 
2032
2015
  private fun checkCallTimeout(callCid: String) {
@@ -2036,12 +2019,12 @@ public class StreamCallPlugin : Plugin() {
2036
2019
  val elapsedSeconds = (now - callState.createdAt) / 1000
2037
2020
 
2038
2021
  if (elapsedSeconds >= 30) {
2039
- android.util.Log.d("StreamCallPlugin", "Call $callCid has timed out after $elapsedSeconds seconds")
2022
+ Log.d("StreamCallPlugin", "Call $callCid has timed out after $elapsedSeconds seconds")
2040
2023
 
2041
2024
  val hasAccepted = callState.participantResponses.values.any { it == "accepted" }
2042
2025
 
2043
2026
  if (!hasAccepted) {
2044
- android.util.Log.d("StreamCallPlugin", "No one accepted call $callCid, marking all non-responders as missed")
2027
+ Log.d("StreamCallPlugin", "No one accepted call $callCid, marking all non-responders as missed")
2045
2028
 
2046
2029
  // First, remove the timer to prevent further callbacks
2047
2030
  callState.timer?.removeCallbacksAndMessages(null)
@@ -2072,7 +2055,7 @@ public class StreamCallPlugin : Plugin() {
2072
2055
  // Notify that call has ended using helper
2073
2056
  updateCallStatusAndNotify(callCid, "ended", null, "timeout")
2074
2057
  } catch (e: Exception) {
2075
- android.util.Log.e("StreamCallPlugin", "Error ending timed out call", e)
2058
+ Log.e("StreamCallPlugin", "Error ending timed out call", e)
2076
2059
  }
2077
2060
  }
2078
2061
  }
@@ -2087,7 +2070,7 @@ public class StreamCallPlugin : Plugin() {
2087
2070
 
2088
2071
  if (callState != null) {
2089
2072
  // Ensure timer is properly canceled
2090
- android.util.Log.d("StreamCallPlugin", "Stopping timer for call: $callCid")
2073
+ Log.d("StreamCallPlugin", "Stopping timer for call: $callCid")
2091
2074
  callState.timer?.removeCallbacksAndMessages(null)
2092
2075
  callState.timer = null
2093
2076
  }
@@ -2097,13 +2080,13 @@ public class StreamCallPlugin : Plugin() {
2097
2080
 
2098
2081
  // Hide UI elements directly without setting content
2099
2082
  runOnMainThread {
2100
- android.util.Log.d("StreamCallPlugin", "Hiding UI elements for call $callCid (one-time cleanup)")
2083
+ Log.d("StreamCallPlugin", "Hiding UI elements for call $callCid (one-time cleanup)")
2101
2084
  overlayView?.isVisible = false
2102
2085
  // here we will also make sure we don't show on lock screen
2103
2086
  changeActivityAsVisibleOnLockScreen(this.activity, false)
2104
2087
  }
2105
2088
 
2106
- android.util.Log.d("StreamCallPlugin", "Cleaned up resources for ended call: $callCid")
2089
+ Log.d("StreamCallPlugin", "Cleaned up resources for ended call: $callCid")
2107
2090
  }
2108
2091
 
2109
2092
  private fun checkAllParticipantsResponded(callCid: String) {
@@ -2112,14 +2095,14 @@ public class StreamCallPlugin : Plugin() {
2112
2095
  val totalParticipants = callState.members.size
2113
2096
  val responseCount = callState.participantResponses.size
2114
2097
 
2115
- android.util.Log.d("StreamCallPlugin", "Checking responses for call $callCid: $responseCount / $totalParticipants")
2098
+ Log.d("StreamCallPlugin", "Checking responses for call $callCid: $responseCount / $totalParticipants")
2116
2099
 
2117
2100
  val allResponded = responseCount >= totalParticipants
2118
2101
  val allRejectedOrMissed = allResponded &&
2119
2102
  callState.participantResponses.values.all { it == "rejected" || it == "missed" }
2120
2103
 
2121
2104
  if (allResponded && allRejectedOrMissed) {
2122
- android.util.Log.d("StreamCallPlugin", "All participants have rejected or missed the call $callCid")
2105
+ Log.d("StreamCallPlugin", "All participants have rejected or missed the call $callCid")
2123
2106
 
2124
2107
  // Cancel the timer immediately to prevent further callbacks
2125
2108
  callState.timer?.removeCallbacksAndMessages(null)
@@ -2143,7 +2126,7 @@ public class StreamCallPlugin : Plugin() {
2143
2126
  // Notify that call has ended using helper
2144
2127
  updateCallStatusAndNotify(callCid, "ended", null, "all_rejected_or_missed")
2145
2128
  } catch (e: Exception) {
2146
- android.util.Log.e("StreamCallPlugin", "Error ending call after all rejected/missed", e)
2129
+ Log.e("StreamCallPlugin", "Error ending call after all rejected/missed", e)
2147
2130
  }
2148
2131
  }
2149
2132
  }
@@ -2153,10 +2136,10 @@ public class StreamCallPlugin : Plugin() {
2153
2136
 
2154
2137
  private suspend fun magicDeviceDelete(streamVideoClient: StreamVideo) {
2155
2138
  try {
2156
- android.util.Log.d("StreamCallPlugin", "Starting magicDeviceDelete operation")
2139
+ Log.d("StreamCallPlugin", "Starting magicDeviceDelete operation")
2157
2140
 
2158
2141
  FirebaseMessaging.getInstance().token.await()?.let {
2159
- android.util.Log.d("StreamCallPlugin", "Found firebase token")
2142
+ Log.d("StreamCallPlugin", "Found firebase token")
2160
2143
  val device = Device(
2161
2144
  id = it,
2162
2145
  pushProvider = PushProvider.FIREBASE.key,
@@ -2166,7 +2149,7 @@ public class StreamCallPlugin : Plugin() {
2166
2149
  streamVideoClient.deleteDevice(device)
2167
2150
  }
2168
2151
  } catch (e: Exception) {
2169
- android.util.Log.e("StreamCallPlugin", "Error in magicDeviceDelete", e)
2152
+ Log.e("StreamCallPlugin", "Error in magicDeviceDelete", e)
2170
2153
  }
2171
2154
  }
2172
2155
 
@@ -2231,12 +2214,12 @@ public class StreamCallPlugin : Plugin() {
2231
2214
 
2232
2215
  try {
2233
2216
  saveDynamicApiKey(apiKey)
2234
- android.util.Log.d("StreamCallPlugin", "Dynamic API key saved successfully")
2217
+ Log.d("StreamCallPlugin", "Dynamic API key saved successfully")
2235
2218
  call.resolve(JSObject().apply {
2236
2219
  put("success", true)
2237
2220
  })
2238
2221
  } catch (e: Exception) {
2239
- android.util.Log.e("StreamCallPlugin", "Error saving dynamic API key", e)
2222
+ Log.e("StreamCallPlugin", "Error saving dynamic API key", e)
2240
2223
  call.reject("Failed to save API key: ${e.message}")
2241
2224
  }
2242
2225
  }
@@ -2255,7 +2238,7 @@ public class StreamCallPlugin : Plugin() {
2255
2238
  }
2256
2239
  })
2257
2240
  } catch (e: Exception) {
2258
- android.util.Log.e("StreamCallPlugin", "Error getting dynamic API key", e)
2241
+ Log.e("StreamCallPlugin", "Error getting dynamic API key", e)
2259
2242
  call.reject("Failed to get API key: ${e.message}")
2260
2243
  }
2261
2244
  }
@@ -2263,17 +2246,9 @@ public class StreamCallPlugin : Plugin() {
2263
2246
  // Helper functions for managing dynamic API key in SharedPreferences
2264
2247
  private fun saveDynamicApiKey(apiKey: String) {
2265
2248
  val sharedPrefs = getApiKeyPreferences()
2266
- sharedPrefs.edit()
2267
- .putString(DYNAMIC_API_KEY_PREF, apiKey)
2268
- .apply()
2269
- }
2270
-
2271
- // Helper functions for managing dynamic API key in SharedPreferences
2272
- private fun clearDynamicApiKey() {
2273
- val sharedPrefs = getApiKeyPreferences()
2274
- sharedPrefs.edit()
2275
- .remove(DYNAMIC_API_KEY_PREF)
2276
- .apply()
2249
+ sharedPrefs.edit {
2250
+ putString(DYNAMIC_API_KEY_PREF, apiKey)
2251
+ }
2277
2252
  }
2278
2253
 
2279
2254
  private fun getDynamicApiKey(): String? {
@@ -2298,18 +2273,18 @@ public class StreamCallPlugin : Plugin() {
2298
2273
  // A) Check if the key exists in the custom preference
2299
2274
  val dynamicApiKey = getDynamicApiKey(context)
2300
2275
  return if (!dynamicApiKey.isNullOrEmpty() && dynamicApiKey.trim().isNotEmpty()) {
2301
- android.util.Log.d("StreamCallPlugin", "Using dynamic API key")
2276
+ Log.d("StreamCallPlugin", "Using dynamic API key")
2302
2277
  dynamicApiKey
2303
2278
  } else {
2304
2279
  // B) If not, use R.string.CAPACITOR_STREAM_VIDEO_APIKEY
2305
- android.util.Log.d("StreamCallPlugin", "Using static API key from resources")
2280
+ Log.d("StreamCallPlugin", "Using static API key from resources")
2306
2281
  context.getString(R.string.CAPACITOR_STREAM_VIDEO_APIKEY)
2307
2282
  }
2308
2283
  }
2309
2284
 
2310
2285
  // Helper method to update call status and notify listeners
2311
2286
  private fun updateCallStatusAndNotify(callId: String, state: String, userId: String? = null, reason: String? = null, members: List<Map<String, Any>>? = null, caller: Map<String, Any>? = null) {
2312
- android.util.Log.d("StreamCallPlugin", "updateCallStatusAndNotify called: callId=$callId, state=$state, userId=$userId, reason=$reason")
2287
+ Log.d("StreamCallPlugin", "updateCallStatusAndNotify called: callId=$callId, state=$state, userId=$userId, reason=$reason")
2313
2288
  // Update stored call info
2314
2289
  currentCallId = callId
2315
2290
  currentCallState = state
@@ -2351,6 +2326,13 @@ public class StreamCallPlugin : Plugin() {
2351
2326
  }
2352
2327
  }
2353
2328
 
2329
+ val eventString = data.toString()
2330
+ if (lastEventSent == eventString) {
2331
+ Log.d("StreamCallPlugin", "Duplicate event detected, not sending: $eventString")
2332
+ return
2333
+ }
2334
+ lastEventSent = eventString
2335
+
2354
2336
  // Notify listeners
2355
2337
  notifyListeners("callEvent", data)
2356
2338
  }
@@ -2396,19 +2378,19 @@ public class StreamCallPlugin : Plugin() {
2396
2378
  private val acceptCallReceiver = object : BroadcastReceiver() {
2397
2379
  override fun onReceive(context: Context?, intent: Intent?) {
2398
2380
  if (intent?.action == "io.getstream.video.android.action.ACCEPT_CALL") {
2399
- android.util.Log.d("StreamCallPlugin", "BroadcastReceiver: Received broadcast with action: ${intent.action}")
2381
+ Log.d("StreamCallPlugin", "BroadcastReceiver: Received broadcast with action: ${intent.action}")
2400
2382
  val cid = intent.streamCallId(NotificationHandler.INTENT_EXTRA_CALL_CID)
2401
2383
  if (cid != null) {
2402
- android.util.Log.d("StreamCallPlugin", "BroadcastReceiver: ACCEPT_CALL broadcast received with cid: $cid")
2384
+ Log.d("StreamCallPlugin", "BroadcastReceiver: ACCEPT_CALL broadcast received with cid: $cid")
2403
2385
  val call = streamVideoClient?.call(id = cid.id, type = cid.type)
2404
2386
  if (call != null) {
2405
- android.util.Log.d("StreamCallPlugin", "BroadcastReceiver: Accepting call with cid: $cid")
2387
+ Log.d("StreamCallPlugin", "BroadcastReceiver: Accepting call with cid: $cid")
2406
2388
  kotlinx.coroutines.GlobalScope.launch {
2407
2389
  internalAcceptCall(call, requestPermissionsAfter = !checkPermissions())
2408
2390
  }
2409
2391
  bringAppToForeground()
2410
2392
  } else {
2411
- android.util.Log.e("StreamCallPlugin", "BroadcastReceiver: Call object is null for cid: $cid")
2393
+ Log.e("StreamCallPlugin", "BroadcastReceiver: Call object is null for cid: $cid")
2412
2394
  }
2413
2395
  }
2414
2396
  }
@@ -2422,12 +2404,12 @@ public class StreamCallPlugin : Plugin() {
2422
2404
  launchIntent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
2423
2405
  if (launchIntent != null) {
2424
2406
  ctx.startActivity(launchIntent)
2425
- android.util.Log.d("StreamCallPlugin", "bringAppToForeground: Launch intent executed to foreground app")
2407
+ Log.d("StreamCallPlugin", "bringAppToForeground: Launch intent executed to foreground app")
2426
2408
  } else {
2427
- android.util.Log.w("StreamCallPlugin", "bringAppToForeground: launchIntent is null")
2409
+ Log.w("StreamCallPlugin", "bringAppToForeground: launchIntent is null")
2428
2410
  }
2429
2411
  } catch (e: Exception) {
2430
- android.util.Log.e("StreamCallPlugin", "bringAppToForeground error", e)
2412
+ Log.e("StreamCallPlugin", "bringAppToForeground error", e)
2431
2413
  }
2432
2414
  }
2433
2415