@qusaieilouti99/call-manager 0.1.75 → 0.1.77

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.
@@ -28,18 +28,27 @@ class CallActivity : Activity() {
28
28
  private val timeoutRunnable = Runnable {
29
29
  Log.d(TAG, "CallActivity timeout triggered for callId: $callId")
30
30
  finishReason = FinishReason.TIMEOUT
31
+ CallEngine.stopRingtone()
32
+ CallEngine.cancelIncomingCallUI()
31
33
  CallEngine.endCall(callId)
32
34
  finishCallActivity()
33
35
  }
34
36
 
35
- // NEW: Broadcast receiver to listen for close events
36
37
  private val closeReceiver = object : BroadcastReceiver() {
37
38
  override fun onReceive(context: Context?, intent: Intent?) {
38
39
  val receivedCallId = intent?.getStringExtra("callId")
39
- if (receivedCallId == callId) {
40
+ Log.d(TAG, "Broadcast received for callId: $receivedCallId, current callId: $callId")
41
+
42
+ if (receivedCallId == callId || receivedCallId.isNullOrEmpty()) {
40
43
  Log.d(TAG, "Received close broadcast for $callId")
41
44
  finishReason = FinishReason.EXTERNAL_END
42
- finishCallActivity()
45
+
46
+ // Ensure we're on main thread and activity isn't finishing
47
+ runOnUiThread {
48
+ if (!isFinishing) {
49
+ finishCallActivity()
50
+ }
51
+ }
43
52
  }
44
53
  }
45
54
  }
@@ -67,8 +76,8 @@ class CallActivity : Activity() {
67
76
  callType = intent.getStringExtra("callType") ?: "Audio"
68
77
  Log.d(TAG, "CallActivity received callId: $callId, callType: $callType")
69
78
 
70
- // FIXED: Immediate cleanup of notifications when CallActivity is shown
71
- CallEngine.cancelIncomingCallUI()
79
+ // FIXED: Don't immediately cancel ringtone and notification - let them play
80
+ // CallEngine.cancelIncomingCallUI() // REMOVED
72
81
 
73
82
  val callerName = intent.getStringExtra("callerName") ?: "Unknown"
74
83
  val nameView = findViewById<TextView>(R.id.caller_name)
@@ -80,6 +89,9 @@ class CallActivity : Activity() {
80
89
  answerBtn.setOnClickListener {
81
90
  Log.d(TAG, "CallActivity: Answer button clicked for callId: $callId")
82
91
  finishReason = FinishReason.ANSWER
92
+ // Stop ringtone and notification when user answers
93
+ CallEngine.stopRingtone()
94
+ CallEngine.cancelIncomingCallUI()
83
95
  CallEngine.answerCall(callId)
84
96
  finishCallActivity()
85
97
  }
@@ -87,47 +99,71 @@ class CallActivity : Activity() {
87
99
  declineBtn.setOnClickListener {
88
100
  Log.d(TAG, "CallActivity: Decline button clicked for callId: $callId")
89
101
  finishReason = FinishReason.DECLINE
102
+ // Stop ringtone and notification when user declines
103
+ CallEngine.stopRingtone()
104
+ CallEngine.cancelIncomingCallUI()
90
105
  CallEngine.endCall(callId)
91
106
  finishCallActivity()
92
107
  }
93
108
 
94
- // NEW: Register broadcast receiver
109
+ // Enhanced broadcast receiver registration
95
110
  val filter = IntentFilter("com.qusaieilouti99.callmanager.CLOSE_CALL_ACTIVITY")
96
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
97
- registerReceiver(closeReceiver, filter, Context.RECEIVER_NOT_EXPORTED)
98
- } else {
99
- registerReceiver(closeReceiver, filter)
111
+ try {
112
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
113
+ registerReceiver(closeReceiver, filter, Context.RECEIVER_NOT_EXPORTED)
114
+ } else {
115
+ registerReceiver(closeReceiver, filter)
116
+ }
117
+ Log.d(TAG, "Broadcast receiver registered successfully for callId: $callId")
118
+ } catch (e: Exception) {
119
+ Log.e(TAG, "Failed to register broadcast receiver: ${e.message}", e)
100
120
  }
101
121
 
122
+ // Set timeout for incoming call
102
123
  timeoutHandler.postDelayed(timeoutRunnable, 60_000)
124
+ Log.d(TAG, "CallActivity onCreate - END")
103
125
  }
104
126
 
105
127
  override fun onDestroy() {
106
128
  super.onDestroy()
107
129
  Log.d(TAG, "CallActivity onDestroy for callId: $callId. Reason: $finishReason")
130
+
131
+ // Clean up timeout handler
108
132
  timeoutHandler.removeCallbacks(timeoutRunnable)
109
133
 
110
- // NEW: Unregister broadcast receiver
134
+ // Unregister broadcast receiver with better error handling
111
135
  try {
112
136
  unregisterReceiver(closeReceiver)
137
+ Log.d(TAG, "Broadcast receiver unregistered for callId: $callId")
138
+ } catch (e: IllegalArgumentException) {
139
+ Log.w(TAG, "Receiver was not registered: ${e.message}")
113
140
  } catch (e: Exception) {
114
- Log.w(TAG, "Receiver already unregistered: ${e.message}")
141
+ Log.e(TAG, "Error unregistering receiver: ${e.message}", e)
115
142
  }
116
143
 
117
- // FIXED: Ensure cleanup happens regardless of how activity ends
118
- CallEngine.stopRingtone()
119
- CallEngine.cancelIncomingCallUI()
144
+ // Clean up ringtone and notification if call wasn't answered
145
+ if (finishReason != FinishReason.ANSWER) {
146
+ CallEngine.stopRingtone()
147
+ CallEngine.cancelIncomingCallUI()
148
+ }
120
149
  }
121
150
 
122
151
  override fun onBackPressed() {
123
152
  Log.d(TAG, "CallActivity onBackPressed for callId: $callId. Treating as decline/dismiss.")
124
153
  finishReason = FinishReason.MANUAL_DISMISS
154
+ CallEngine.stopRingtone()
155
+ CallEngine.cancelIncomingCallUI()
125
156
  CallEngine.endCall(callId)
126
157
  finishCallActivity()
127
158
  }
128
159
 
129
160
  private fun finishCallActivity() {
130
- Log.d(TAG, "Finishing CallActivity.")
161
+ if (isFinishing) {
162
+ Log.d(TAG, "Activity is already finishing, skipping finishCallActivity")
163
+ return
164
+ }
165
+
166
+ Log.d(TAG, "Finishing CallActivity for callId: $callId")
131
167
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
132
168
  finishAndRemoveTask()
133
169
  } else {
@@ -602,13 +602,35 @@ object CallEngine {
602
602
  currentCallId = activeCalls.filter { it.value.state != CallState.ENDED }.keys.firstOrNull()
603
603
  }
604
604
 
605
- // NEW: Send broadcast to close CallActivity
605
+ // ENHANCED: Multiple broadcast attempts with delays for better reliability
606
606
  val context = requireContext()
607
607
  val closeActivityIntent = Intent("com.qusaieilouti99.callmanager.CLOSE_CALL_ACTIVITY")
608
608
  closeActivityIntent.putExtra("callId", callId)
609
+
609
610
  try {
611
+ // Send immediate broadcast
610
612
  context.sendBroadcast(closeActivityIntent)
611
613
  Log.d(TAG, "Sent close broadcast for CallActivity: $callId")
614
+
615
+ // Send additional broadcasts with delays to handle timing issues
616
+ Handler(Looper.getMainLooper()).postDelayed({
617
+ try {
618
+ context.sendBroadcast(closeActivityIntent)
619
+ Log.d(TAG, "Sent delayed close broadcast (100ms) for CallActivity: $callId")
620
+ } catch (e: Exception) {
621
+ Log.w(TAG, "Failed to send delayed close broadcast (100ms): ${e.message}")
622
+ }
623
+ }, 100L)
624
+
625
+ Handler(Looper.getMainLooper()).postDelayed({
626
+ try {
627
+ context.sendBroadcast(closeActivityIntent)
628
+ Log.d(TAG, "Sent delayed close broadcast (500ms) for CallActivity: $callId")
629
+ } catch (e: Exception) {
630
+ Log.w(TAG, "Failed to send delayed close broadcast (500ms): ${e.message}")
631
+ }
632
+ }, 500L)
633
+
612
634
  } catch (e: Exception) {
613
635
  Log.w(TAG, "Failed to send close broadcast: ${e.message}")
614
636
  }
@@ -1091,25 +1113,31 @@ object CallEngine {
1091
1113
  )
1092
1114
  }
1093
1115
 
1094
- // --- Media Management ---
1116
+ // --- Media Management (SIMPLIFIED - NO AUDIO FOCUS) ---
1095
1117
  private fun playRingtone() {
1096
1118
  val context = requireContext()
1097
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
1098
- return // System handles it
1099
- }
1119
+ Log.d(TAG, "playRingtone() called")
1100
1120
 
1101
1121
  try {
1102
1122
  val uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
1123
+ Log.d(TAG, "Ringtone URI: $uri")
1124
+
1103
1125
  ringtone = RingtoneManager.getRingtone(context, uri)
1104
- ringtone?.play()
1126
+ if (ringtone != null) {
1127
+ ringtone?.play()
1128
+ Log.d(TAG, "Ringtone started playing successfully (system handles audio focus)")
1129
+ } else {
1130
+ Log.w(TAG, "Ringtone is null, cannot play")
1131
+ }
1105
1132
  } catch (e: Exception) {
1106
- Log.e(TAG, "Failed to play ringtone: ${e.message}")
1133
+ Log.e(TAG, "Failed to play ringtone: ${e.message}", e)
1107
1134
  }
1108
1135
  }
1109
1136
 
1110
1137
  fun stopRingtone() {
1111
1138
  try {
1112
1139
  ringtone?.stop()
1140
+ Log.d(TAG, "Ringtone stopped")
1113
1141
  } catch (e: Exception) {
1114
1142
  Log.e(TAG, "Error stopping ringtone: ${e.message}")
1115
1143
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.75",
3
+ "version": "0.1.77",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",