@qusaieilouti99/call-manager 0.1.46 → 0.1.48

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.
@@ -1,67 +1,22 @@
1
- <manifest xmlns:android="http://schemas.android.com/apk/res/android">
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.margelo.nitro.qusaieilouti99.callmanager">
2
3
 
3
- <!-- REQUIRED FOR TELECOM API (Self-managed connections) -->
4
+ <!-- Essential permissions that the library requires -->
4
5
  <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
5
- <!-- Required for recording audio in calls -->
6
+ <uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
6
7
  <uses-permission android:name="android.permission.RECORD_AUDIO" />
7
- <!-- Required for changing audio routes like speakerphone -->
8
8
  <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
9
- <!-- For keeping screen awake during calls -->
10
9
  <uses-permission android:name="android.permission.WAKE_LOCK" />
11
- <!-- For vibrating the device (e.g., incoming call) -->
12
10
  <uses-permission android:name="android.permission.VIBRATE" />
11
+ <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
12
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
13
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
14
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
13
15
 
14
- <!-- Bluetooth permissions for audio routing -->
15
- <!-- For Android 11 (API 30) and lower -->
16
+ <!-- Bluetooth permissions -->
16
17
  <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
17
18
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
18
- <!-- For Android 12 (API 31) and higher -->
19
19
  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
20
20
 
21
- <!-- Required for foreground service on older devices (< Android P) -->
22
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
23
- <!-- Required for foreground service with phoneCall type on Android 12 (API 31) and higher -->
24
- <uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
25
-
26
- <application>
27
- <!-- Your CallActivity for full-screen incoming call UI -->
28
- <activity
29
- android:name=".CallActivity"
30
- android:exported="true"
31
- android:showOnLockScreen="true"
32
- android:turnScreenOn="true"
33
- android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
34
- android:screenOrientation="portrait"
35
- android:launchMode="singleTop"
36
- android:excludeFromRecents="true"
37
- android:taskAffinity=""
38
- android:windowSoftInputMode="adjustResize">
39
- <intent-filter>
40
- <action android:name="android.intent.action.VIEW"/>
41
- <category android:name="android.intent.category.DEFAULT"/>
42
- </intent-filter>
43
- </activity>
44
-
45
- <!-- The ConnectionService, crucial for Telecom API integration -->
46
- <service
47
- android:name=".MyConnectionService"
48
- android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
49
- android:exported="true">
50
- <intent-filter>
51
- <action android:name="android.telecom.ConnectionService" />
52
- </intent-filter>
53
- </service>
54
-
55
- <!-- The foreground service to keep the call alive in the background -->
56
- <service
57
- android:name=".CallForegroundService"
58
- android:enabled="true"
59
- android:exported="false"
60
- android:foregroundServiceType="phoneCall" />
61
-
62
- <!-- Receiver for notification actions (Answer/Decline) -->
63
- <receiver
64
- android:name=".CallNotificationActionReceiver"
65
- android:exported="false" />
66
- </application>
21
+ <!-- No components needed here - they're declared in app manifest -->
67
22
  </manifest>
@@ -24,6 +24,7 @@ import android.telecom.VideoProfile
24
24
  import android.util.Log
25
25
  import android.graphics.Color
26
26
  import android.app.Person
27
+ import android.view.WindowManager
27
28
  import org.json.JSONArray
28
29
  import org.json.JSONObject
29
30
  import java.util.UUID
@@ -49,6 +50,14 @@ object CallEngine {
49
50
  private var currentCallId: String? = null
50
51
  private var canMakeMultipleCalls: Boolean = true
51
52
 
53
+ // --- Lock Screen Bypass State Management ---
54
+ private var lockScreenBypassActive = false
55
+ private val lockScreenBypassCallbacks = mutableSetOf<LockScreenBypassCallback>()
56
+
57
+ interface LockScreenBypassCallback {
58
+ fun onLockScreenBypassChanged(shouldBypass: Boolean)
59
+ }
60
+
52
61
  data class CallInfo(
53
62
  val callId: String,
54
63
  val callData: String,
@@ -89,6 +98,34 @@ object CallEngine {
89
98
 
90
99
  fun getAppContext(): Context? = appContext
91
100
 
101
+ // --- Lock Screen Bypass Management (Single Source of Truth) ---
102
+ fun registerLockScreenBypassCallback(callback: LockScreenBypassCallback) {
103
+ lockScreenBypassCallbacks.add(callback)
104
+ }
105
+
106
+ fun unregisterLockScreenBypassCallback(callback: LockScreenBypassCallback) {
107
+ lockScreenBypassCallbacks.remove(callback)
108
+ }
109
+
110
+ private fun updateLockScreenBypass() {
111
+ val shouldBypass = isCallActive()
112
+ if (lockScreenBypassActive != shouldBypass) {
113
+ lockScreenBypassActive = shouldBypass
114
+ Log.d(TAG, "Lock screen bypass state changed: $lockScreenBypassActive")
115
+
116
+ // Notify all registered callbacks
117
+ lockScreenBypassCallbacks.forEach { callback ->
118
+ try {
119
+ callback.onLockScreenBypassChanged(shouldBypass)
120
+ } catch (e: Exception) {
121
+ Log.w(TAG, "Error notifying lock screen bypass callback", e)
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ fun isLockScreenBypassActive(): Boolean = lockScreenBypassActive
128
+
92
129
  // --- Telecom Connection Management ---
93
130
  fun addTelecomConnection(callId: String, connection: Connection) {
94
131
  telecomConnections[callId] = connection
@@ -163,7 +200,6 @@ object CallEngine {
163
200
  telecomManager.addNewIncomingCall(phoneAccountHandle, extras)
164
201
  startForegroundService(context)
165
202
  Log.d(TAG, "Successfully reported incoming call to TelecomManager for $callId")
166
- // REMOVED: Don't bring app to foreground for incoming calls - only when answered
167
203
  } catch (e: SecurityException) {
168
204
  Log.e(TAG, "SecurityException: Failed to report incoming call. Check MANAGE_OWN_CALLS permission: ${e.message}", e)
169
205
  endCall(context, callId)
@@ -171,6 +207,7 @@ object CallEngine {
171
207
  Log.e(TAG, "Failed to report incoming call: ${e.message}", e)
172
208
  endCall(context, callId)
173
209
  }
210
+ updateLockScreenBypass()
174
211
  notifyCallStateChanged(context)
175
212
  }
176
213
 
@@ -217,7 +254,6 @@ object CallEngine {
217
254
  startForegroundService(context)
218
255
  Log.d(TAG, "Successfully reported outgoing call to TelecomManager via placeCall for $callId")
219
256
  startRingback()
220
- // CHANGED: Bring app to foreground for outgoing calls
221
257
  bringAppToForeground(context)
222
258
  keepScreenAwake(context, true)
223
259
  if (parsedCallType == "Video") {
@@ -232,6 +268,7 @@ object CallEngine {
232
268
  Log.e(TAG, "Failed to start outgoing call via placeCall: ${e.message}", e)
233
269
  endCall(context, callId)
234
270
  }
271
+ updateLockScreenBypass()
235
272
  notifyCallStateChanged(context)
236
273
  }
237
274
 
@@ -270,6 +307,8 @@ object CallEngine {
270
307
  keepScreenAwake(context, true)
271
308
  resetAudioMode(context)
272
309
 
310
+ updateLockScreenBypass()
311
+
273
312
  // Emit event
274
313
  emitEvent(CallEventType.CALL_ANSWERED, JSONObject().put("callId", callId))
275
314
  notifyCallStateChanged(context)
@@ -279,9 +318,11 @@ object CallEngine {
279
318
 
280
319
  fun holdCall(context: Context, callId: String) {
281
320
  Log.d(TAG, "holdCall: $callId")
321
+ activeCalls[callId]?.state = CallState.HELD
282
322
  val connection = telecomConnections[callId]
283
323
  connection?.setOnHold()
284
324
  emitEvent(CallEventType.CALL_HELD, JSONObject().put("callId", callId))
325
+ updateLockScreenBypass()
285
326
  notifyCallStateChanged(context)
286
327
  }
287
328
 
@@ -291,6 +332,7 @@ object CallEngine {
291
332
  val connection = telecomConnections[callId]
292
333
  connection?.setActive()
293
334
  emitEvent(CallEventType.CALL_UNHELD, JSONObject().put("callId", callId))
335
+ updateLockScreenBypass()
294
336
  notifyCallStateChanged(context)
295
337
  }
296
338
 
@@ -332,6 +374,7 @@ object CallEngine {
332
374
 
333
375
  // Final cleanup
334
376
  finalCleanup(context)
377
+ updateLockScreenBypass()
335
378
  notifyCallStateChanged(context)
336
379
  }
337
380
 
@@ -369,6 +412,7 @@ object CallEngine {
369
412
  finalCleanup(context)
370
413
  }
371
414
 
415
+ updateLockScreenBypass()
372
416
  emitEvent(CallEventType.CALL_ENDED, JSONObject().put("callId", callId))
373
417
  notifyCallStateChanged(context)
374
418
  }
@@ -380,30 +424,6 @@ object CallEngine {
380
424
  stopForegroundService(context)
381
425
  keepScreenAwake(context, false)
382
426
  resetAudioMode(context)
383
-
384
- // FIXED: Clear lock screen bypass when calls end
385
- clearLockScreenBypass(context)
386
- }
387
-
388
- // NEW: Function to clear lock screen bypass
389
- private fun clearLockScreenBypass(context: Context) {
390
- try {
391
- if (context is Activity) {
392
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
393
- context.setShowWhenLocked(false)
394
- context.setTurnScreenOn(false)
395
- } else {
396
- context.window.clearFlags(
397
- android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
398
- android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
399
- android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
400
- )
401
- }
402
- Log.d(TAG, "Lock screen bypass flags cleared for Activity")
403
- }
404
- } catch (e: Exception) {
405
- Log.w(TAG, "Could not clear lock screen bypass flags: ${e.message}")
406
- }
407
427
  }
408
428
 
409
429
  fun getActiveCalls(): List<CallInfo> = activeCalls.values.toList()
@@ -491,25 +511,34 @@ object CallEngine {
491
511
  context.stopService(intent)
492
512
  }
493
513
 
514
+ // FIXED: Corrected bringAppToForeground method
494
515
  fun bringAppToForeground(context: Context) {
495
516
  val packageName = context.packageName
496
517
  val launchIntent = context.packageManager.getLaunchIntentForPackage(packageName)
497
- launchIntent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
518
+ launchIntent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
498
519
 
499
520
  // Handle lock screen bypass for active calls
500
521
  if (isCallActive()) {
501
- // Only set lock screen bypass when bringing to foreground during active calls
502
522
  launchIntent?.putExtra("BYPASS_LOCK_SCREEN", true)
503
- Log.d(TAG, "App brought to foreground with lock screen bypass for active call")
523
+ launchIntent?.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
524
+ Log.d(TAG, "App brought to foreground with lock screen bypass request for active call")
504
525
  } else {
526
+ launchIntent?.removeExtra("BYPASS_LOCK_SCREEN")
505
527
  Log.d(TAG, "App brought to foreground without lock screen bypass")
506
528
  }
507
529
 
508
- context.startActivity(launchIntent)
509
- }
530
+ try {
531
+ context.startActivity(launchIntent)
532
+
533
+ // Small delay to ensure activity is created before updating bypass
534
+ android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({
535
+ updateLockScreenBypass()
536
+ }, 100)
510
537
 
511
- // Rest of the methods remain the same...
512
- // (getAudioDevices, setAudioRoute, keepScreenAwake, etc. - keeping them unchanged for brevity)
538
+ } catch (e: Exception) {
539
+ Log.e(TAG, "Failed to bring app to foreground: ${e.message}")
540
+ }
541
+ }
513
542
 
514
543
  // --- Audio Device Management ---
515
544
  fun getAudioDevices(): AudioRoutesInfo {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.46",
3
+ "version": "0.1.48",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",