@qusaieilouti99/call-manager 0.1.89 → 0.1.91

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.
@@ -14,7 +14,9 @@ import android.widget.Button
14
14
  import android.widget.TextView
15
15
 
16
16
  /**
17
- * Enhanced CallActivity with better lock screen bypass for Samsung devices
17
+ * Full‐screen incoming‐call UI. Implements CallEndListener
18
+ * so it always auto‐finishes when the engine ends the call.
19
+ * **SAMSUNG FIX**: Enhanced lock screen bypass for Samsung devices
18
20
  */
19
21
  class CallActivity : Activity(), CallEngine.CallEndListener {
20
22
 
@@ -40,57 +42,21 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
40
42
  super.onCreate(savedInstanceState)
41
43
  Log.d(TAG, "CallActivity onCreate")
42
44
 
43
- // Enhanced lock screen bypass for Samsung devices
44
- setupLockScreenBypass()
45
+ // **SAMSUNG FIX**: Enhanced lock screen bypass
46
+ val isSamsungLockScreenBypass = intent.getBooleanExtra("SAMSUNG_LOCK_SCREEN_BYPASS", false)
47
+ setupLockScreenBypass(isSamsungLockScreenBypass)
45
48
 
46
49
  setContentView(R.layout.activity_call)
47
50
 
48
- // Read incoming call params
51
+ // Read incomingcall params
49
52
  callId = intent.getStringExtra("callId") ?: ""
50
53
  callType = intent.getStringExtra("callType") ?: "Audio"
51
54
  Log.d(TAG, "CallActivity received callId: $callId, callType: $callType")
52
55
 
53
- // Register for call-end callbacks
56
+ // Register for callend callbacks BEFORE timeout or user can dismiss
54
57
  CallEngine.registerCallEndListener(this)
55
58
 
56
59
  // Bind UI
57
- setupUI()
58
-
59
- // Start auto-timeout
60
- timeoutHandler.postDelayed(timeoutRunnable, 60_000)
61
- Log.d(TAG, "CallActivity setup complete")
62
- }
63
-
64
- private fun setupLockScreenBypass() {
65
- // For Android O_MR1 and above
66
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
67
- setShowWhenLocked(true)
68
- setTurnScreenOn(true)
69
-
70
- // Additional Samsung-specific setup
71
- val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
72
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
73
- keyguardManager.requestDismissKeyguard(this, null)
74
- }
75
- } else {
76
- // For older versions
77
- window.addFlags(
78
- WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
79
- WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
80
- WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
81
- WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
82
- )
83
- }
84
-
85
- // Additional flags for better compatibility
86
- window.addFlags(
87
- WindowManager.LayoutParams.FLAG_FULLSCREEN or
88
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
89
- WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
90
- )
91
- }
92
-
93
- private fun setupUI() {
94
60
  val callerName = intent.getStringExtra("callerName") ?: "Unknown"
95
61
  findViewById<TextView>(R.id.caller_name).text = callerName
96
62
 
@@ -111,15 +77,64 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
111
77
  CallEngine.endCall(callId)
112
78
  finishCallActivity()
113
79
  }
80
+
81
+ // Start auto‐timeout
82
+ timeoutHandler.postDelayed(timeoutRunnable, 60_000)
83
+ Log.d(TAG, "CallActivity setup complete")
84
+ }
85
+
86
+ // **SAMSUNG FIX**: Enhanced lock screen bypass method
87
+ private fun setupLockScreenBypass(isSamsungSpecific: Boolean) {
88
+ // Standard lock screen bypass
89
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
90
+ setShowWhenLocked(true)
91
+ setTurnScreenOn(true)
92
+ } else {
93
+ window.addFlags(
94
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
95
+ WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
96
+ WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
97
+ )
98
+ }
99
+
100
+ // **SAMSUNG SPECIFIC**: Additional fixes for Samsung One UI 7
101
+ if (isSamsungSpecific) {
102
+ Log.d(TAG, "Applying Samsung-specific lock screen bypass")
103
+
104
+ // **CRITICAL**: Samsung requires BOTH new and old methods
105
+ window.addFlags(
106
+ WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
107
+ WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
108
+ WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
109
+ WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
110
+ )
111
+
112
+ // **SAMSUNG SPECIFIC**: Request keyguard dismissal
113
+ val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
114
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
115
+ keyguardManager.requestDismissKeyguard(this, object : KeyguardManager.KeyguardDismissCallback() {
116
+ override fun onDismissSucceeded() {
117
+ Log.d(TAG, "Samsung keyguard dismissed successfully")
118
+ }
119
+ override fun onDismissError() {
120
+ Log.w(TAG, "Samsung keyguard dismissal failed")
121
+ }
122
+ })
123
+ }
124
+ }
114
125
  }
115
126
 
116
127
  override fun onDestroy() {
117
128
  super.onDestroy()
118
129
  Log.d(TAG, "CallActivity onDestroy for callId: $callId. Reason: $finishReason")
119
130
 
131
+ // Unregister listener
120
132
  CallEngine.unregisterCallEndListener(this)
133
+
134
+ // Cancel timeout
121
135
  timeoutHandler.removeCallbacks(timeoutRunnable)
122
136
 
137
+ // If user never answered, clean up ringtone/UI
123
138
  if (finishReason != FinishReason.ANSWER) {
124
139
  CallEngine.stopRingtone()
125
140
  CallEngine.cancelIncomingCallUI()
@@ -135,6 +150,10 @@ class CallActivity : Activity(), CallEngine.CallEndListener {
135
150
  finishCallActivity()
136
151
  }
137
152
 
153
+ /**
154
+ * Called by CallEngine whenever ANY call ends.
155
+ * We only care about our own callId.
156
+ */
138
157
  override fun onCallEnded(endedCallId: String) {
139
158
  if (endedCallId == callId && !isFinishing) {
140
159
  Log.d(TAG, "CallActivity onCallEnded callback for callId: $callId")
@@ -880,6 +880,7 @@ object CallEngine {
880
880
  }
881
881
 
882
882
  // --- Notification Management ---
883
+ // **SAMSUNG FIX**: Enhanced notification channel creation
883
884
  private fun createNotificationChannel() {
884
885
  val context = requireContext()
885
886
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -893,6 +894,10 @@ object CallEngine {
893
894
  channel.lightColor = Color.GREEN
894
895
  channel.enableVibration(true)
895
896
 
897
+ // **SAMSUNG FIX**: Set bypass DND and lock screen visibility
898
+ channel.setBypassDnd(true)
899
+ channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
900
+
896
901
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
897
902
  channel.setSound(
898
903
  RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE),
@@ -911,6 +916,7 @@ object CallEngine {
911
916
  }
912
917
  }
913
918
 
919
+ // **SAMSUNG FIX**: Enhanced showIncomingCallUI method
914
920
  private fun showIncomingCallUI(callId: String, callerName: String, callType: String) {
915
921
  val context = requireContext()
916
922
  Log.d(TAG, "Showing incoming call UI for $callId")
@@ -918,34 +924,12 @@ object CallEngine {
918
924
  val notificationManager =
919
925
  context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
920
926
 
921
- // Enhanced full screen intent
922
- val fullScreenIntent = Intent(context, CallActivity::class.java).apply {
923
- addFlags(
924
- Intent.FLAG_ACTIVITY_NEW_TASK or
925
- Intent.FLAG_ACTIVITY_CLEAR_TASK or
926
- Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS or
927
- Intent.FLAG_ACTIVITY_NO_ANIMATION or
928
- Intent.FLAG_ACTIVITY_SINGLE_TOP
929
- )
930
- putExtra("callId", callId)
931
- putExtra("callerName", callerName)
932
- putExtra("callType", callType)
933
- }
934
-
935
- val fullScreenPendingIntent = PendingIntent.getActivity(
936
- context,
937
- callId.hashCode(), // Use unique request code
938
- fullScreenIntent,
939
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
940
- )
941
-
942
- // Answer and decline intents
943
927
  val answerIntent = Intent(context, CallNotificationActionReceiver::class.java).apply {
944
928
  action = "com.qusaieilouti99.callmanager.ANSWER_CALL"
945
929
  putExtra("callId", callId)
946
930
  }
947
931
  val answerPendingIntent = PendingIntent.getBroadcast(
948
- context, callId.hashCode() + 1, answerIntent,
932
+ context, 0, answerIntent,
949
933
  PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
950
934
  )
951
935
 
@@ -954,10 +938,33 @@ object CallEngine {
954
938
  putExtra("callId", callId)
955
939
  }
956
940
  val declinePendingIntent = PendingIntent.getBroadcast(
957
- context, callId.hashCode() + 2, declineIntent,
941
+ context, 1, declineIntent,
958
942
  PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
959
943
  )
960
944
 
945
+ // **SAMSUNG FIX**: Enhanced full-screen intent
946
+
947
+ // First, wake up the screen using PowerManager
948
+ val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
949
+ val wakeLock = powerManager.newWakeLock(
950
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP,
951
+ "CallEngine:IncomingCallWake"
952
+ )
953
+ wakeLock.acquire(5000) // 5 sec
954
+ val fullScreenIntent = Intent(context, CallActivity::class.java).apply {
955
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
956
+ putExtra("callId", callId)
957
+ putExtra("callerName", callerName)
958
+ putExtra("callType", callType)
959
+ // **SAMSUNG SPECIFIC**: Add Samsung lock screen bypass flag
960
+ putExtra("SAMSUNG_LOCK_SCREEN_BYPASS", true)
961
+ }
962
+ val fullScreenPendingIntent = PendingIntent.getActivity(
963
+ context, 2, fullScreenIntent,
964
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
965
+ )
966
+
967
+ // **SAMSUNG FIX**: Enhanced notification
961
968
  val notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
962
969
  val person = android.app.Person.Builder()
963
970
  .setName(callerName)
@@ -977,19 +984,24 @@ object CallEngine {
977
984
  .setAutoCancel(false)
978
985
  .setCategory(Notification.CATEGORY_CALL)
979
986
  .setPriority(Notification.PRIORITY_MAX)
987
+ // **SAMSUNG SPECIFIC**: Add lock screen visibility
988
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
989
+ .setPublicVersion(null)
980
990
  .build()
981
991
  } else {
982
992
  Notification.Builder(context, NOTIF_CHANNEL_ID)
983
993
  .setSmallIcon(android.R.drawable.sym_call_incoming)
984
994
  .setContentTitle("Incoming Call")
985
995
  .setContentText(callerName)
986
- .setPriority(Notification.PRIORITY_MAX)
996
+ .setPriority(Notification.PRIORITY_HIGH)
987
997
  .setCategory(Notification.CATEGORY_CALL)
988
998
  .setFullScreenIntent(fullScreenPendingIntent, true)
989
999
  .addAction(android.R.drawable.sym_action_call, "Answer", answerPendingIntent)
990
1000
  .addAction(android.R.drawable.ic_menu_close_clear_cancel, "Decline", declinePendingIntent)
991
1001
  .setOngoing(true)
992
1002
  .setAutoCancel(false)
1003
+ // **SAMSUNG SPECIFIC**: Add lock screen visibility
1004
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
993
1005
  .build()
994
1006
  }
995
1007
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.89",
3
+ "version": "0.1.91",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",