@qusaieilouti99/call-manager 0.1.81 → 0.1.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.
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallActivity.kt +145 -145
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallData.kt +31 -31
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallEngine.kt +1201 -1201
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallForegroundService.kt +171 -171
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallNotificationActionReceiver.kt +49 -49
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/MyConnection.kt +133 -133
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/MyConnectionService.kt +77 -77
- package/android/src/main/res/drawable/action_button_secondary.xml +12 -12
- package/android/src/main/res/drawable/answer_button.xml +15 -15
- package/android/src/main/res/drawable/answer_button_shadow.xml +10 -10
- package/android/src/main/res/drawable/avatar_bg.xml +8 -8
- package/android/src/main/res/drawable/avatar_glow.xml +10 -10
- package/android/src/main/res/drawable/call_background.xml +24 -24
- package/android/src/main/res/drawable/decline_button.xml +15 -15
- package/android/src/main/res/drawable/decline_button_shadow.xml +10 -10
- package/android/src/main/res/drawable/overlay_gradient.xml +8 -8
- package/android/src/main/res/layout/activity_call.xml +166 -166
- package/ios/AudioManager.swift +279 -279
- package/ios/CallEngine.swift +670 -670
- package/ios/CallInfo.swift +70 -70
- package/ios/CallKitManager.swift +302 -302
- package/ios/CallManager.swift +149 -149
- package/ios/VoIPTokenManager.swift +175 -175
- package/lib/module/CallEventType.js.map +1 -1
- package/lib/module/CallManager.nitro.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/nitrogen/generated/android/c++/JFunc_void_CallEventType_std__string.hpp +1 -1
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +1 -1
- package/nitrogen/generated/android/c++/JHybridCallManagerSpec.cpp +6 -1
- package/nitrogen/generated/android/c++/JHybridCallManagerSpec.hpp +1 -0
- package/nitrogen/generated/ios/c++/HybridCallManagerSpecSwift.hpp +3 -1
- package/nitrogen/generated/ios/swift/HybridCallManagerSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridCallManagerSpec_cxx.swift +10 -1
- package/nitrogen/generated/shared/c++/AudioRoutesInfo.hpp +1 -1
- package/package.json +168 -168
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
// File: CallActivity.kt
|
|
2
|
-
package com.margelo.nitro.qusaieilouti99.callmanager
|
|
3
|
-
|
|
4
|
-
import android.app.Activity
|
|
5
|
-
import android.os.Build
|
|
6
|
-
import android.os.Bundle
|
|
7
|
-
import android.os.Handler
|
|
8
|
-
import android.os.Looper
|
|
9
|
-
import android.util.Log
|
|
10
|
-
import android.view.WindowManager
|
|
11
|
-
import android.widget.Button
|
|
12
|
-
import android.widget.TextView
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Full‐screen incoming‐call UI. Implements CallEndListener
|
|
16
|
-
* so it always auto‐finishes when the engine ends the call.
|
|
17
|
-
*/
|
|
18
|
-
class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
19
|
-
|
|
20
|
-
private enum class FinishReason {
|
|
21
|
-
ANSWER, DECLINE, TIMEOUT, MANUAL_DISMISS, EXTERNAL_END
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
private var finishReason: FinishReason? = null
|
|
25
|
-
private var callId: String = ""
|
|
26
|
-
private var callType: String = "Audio"
|
|
27
|
-
|
|
28
|
-
private val timeoutHandler = Handler(Looper.getMainLooper())
|
|
29
|
-
private val timeoutRunnable = Runnable {
|
|
30
|
-
Log.d(TAG, "CallActivity timeout triggered for callId: $callId")
|
|
31
|
-
finishReason = FinishReason.TIMEOUT
|
|
32
|
-
CallEngine.stopRingtone()
|
|
33
|
-
CallEngine.cancelIncomingCallUI()
|
|
34
|
-
CallEngine.endCall(callId)
|
|
35
|
-
finishCallActivity()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
override fun onCreate(savedInstanceState: Bundle?) {
|
|
39
|
-
super.onCreate(savedInstanceState)
|
|
40
|
-
Log.d(TAG, "CallActivity onCreate")
|
|
41
|
-
|
|
42
|
-
// Lock‐screen bypass
|
|
43
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
44
|
-
setShowWhenLocked(true)
|
|
45
|
-
setTurnScreenOn(true)
|
|
46
|
-
} else {
|
|
47
|
-
window.addFlags(
|
|
48
|
-
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
49
|
-
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
50
|
-
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
setContentView(R.layout.activity_call)
|
|
55
|
-
|
|
56
|
-
// Read incoming‐call params
|
|
57
|
-
callId = intent.getStringExtra("callId") ?: ""
|
|
58
|
-
callType = intent.getStringExtra("callType") ?: "Audio"
|
|
59
|
-
Log.d(TAG, "CallActivity received callId: $callId, callType: $callType")
|
|
60
|
-
|
|
61
|
-
// Register for call‐end callbacks BEFORE timeout or user can dismiss
|
|
62
|
-
CallEngine.registerCallEndListener(this)
|
|
63
|
-
|
|
64
|
-
// Bind UI
|
|
65
|
-
val callerName = intent.getStringExtra("callerName") ?: "Unknown"
|
|
66
|
-
findViewById<TextView>(R.id.caller_name).text = callerName
|
|
67
|
-
|
|
68
|
-
findViewById<Button>(R.id.answer_btn).setOnClickListener {
|
|
69
|
-
Log.d(TAG, "Answer clicked for callId: $callId")
|
|
70
|
-
finishReason = FinishReason.ANSWER
|
|
71
|
-
CallEngine.stopRingtone()
|
|
72
|
-
CallEngine.cancelIncomingCallUI()
|
|
73
|
-
CallEngine.answerCall(callId)
|
|
74
|
-
finishCallActivity()
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
findViewById<Button>(R.id.decline_btn).setOnClickListener {
|
|
78
|
-
Log.d(TAG, "Decline clicked for callId: $callId")
|
|
79
|
-
finishReason = FinishReason.DECLINE
|
|
80
|
-
CallEngine.stopRingtone()
|
|
81
|
-
CallEngine.cancelIncomingCallUI()
|
|
82
|
-
CallEngine.endCall(callId)
|
|
83
|
-
finishCallActivity()
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Start auto‐timeout
|
|
87
|
-
timeoutHandler.postDelayed(timeoutRunnable, 60_000)
|
|
88
|
-
Log.d(TAG, "CallActivity setup complete")
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
override fun onDestroy() {
|
|
92
|
-
super.onDestroy()
|
|
93
|
-
Log.d(TAG, "CallActivity onDestroy for callId: $callId. Reason: $finishReason")
|
|
94
|
-
|
|
95
|
-
// Unregister listener
|
|
96
|
-
CallEngine.unregisterCallEndListener(this)
|
|
97
|
-
|
|
98
|
-
// Cancel timeout
|
|
99
|
-
timeoutHandler.removeCallbacks(timeoutRunnable)
|
|
100
|
-
|
|
101
|
-
// If user never answered, clean up ringtone/UI
|
|
102
|
-
if (finishReason != FinishReason.ANSWER) {
|
|
103
|
-
CallEngine.stopRingtone()
|
|
104
|
-
CallEngine.cancelIncomingCallUI()
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
override fun onBackPressed() {
|
|
109
|
-
Log.d(TAG, "onBackPressed for callId: $callId → treat as decline")
|
|
110
|
-
finishReason = FinishReason.MANUAL_DISMISS
|
|
111
|
-
CallEngine.stopRingtone()
|
|
112
|
-
CallEngine.cancelIncomingCallUI()
|
|
113
|
-
CallEngine.endCall(callId)
|
|
114
|
-
finishCallActivity()
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Called by CallEngine whenever ANY call ends.
|
|
119
|
-
* We only care about our own callId.
|
|
120
|
-
*/
|
|
121
|
-
override fun onCallEnded(endedCallId: String) {
|
|
122
|
-
if (endedCallId == callId && !isFinishing) {
|
|
123
|
-
Log.d(TAG, "CallActivity onCallEnded callback for callId: $callId")
|
|
124
|
-
finishReason = FinishReason.EXTERNAL_END
|
|
125
|
-
runOnUiThread { finishCallActivity() }
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private fun finishCallActivity() {
|
|
130
|
-
if (isFinishing) {
|
|
131
|
-
Log.d(TAG, "Already finishing, skip.")
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
Log.d(TAG, "Finishing CallActivity for callId: $callId")
|
|
135
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
136
|
-
finishAndRemoveTask()
|
|
137
|
-
} else {
|
|
138
|
-
finish()
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
companion object {
|
|
143
|
-
private const val TAG = "CallActivity"
|
|
144
|
-
}
|
|
145
|
-
}
|
|
1
|
+
// File: CallActivity.kt
|
|
2
|
+
package com.margelo.nitro.qusaieilouti99.callmanager
|
|
3
|
+
|
|
4
|
+
import android.app.Activity
|
|
5
|
+
import android.os.Build
|
|
6
|
+
import android.os.Bundle
|
|
7
|
+
import android.os.Handler
|
|
8
|
+
import android.os.Looper
|
|
9
|
+
import android.util.Log
|
|
10
|
+
import android.view.WindowManager
|
|
11
|
+
import android.widget.Button
|
|
12
|
+
import android.widget.TextView
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Full‐screen incoming‐call UI. Implements CallEndListener
|
|
16
|
+
* so it always auto‐finishes when the engine ends the call.
|
|
17
|
+
*/
|
|
18
|
+
class CallActivity : Activity(), CallEngine.CallEndListener {
|
|
19
|
+
|
|
20
|
+
private enum class FinishReason {
|
|
21
|
+
ANSWER, DECLINE, TIMEOUT, MANUAL_DISMISS, EXTERNAL_END
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private var finishReason: FinishReason? = null
|
|
25
|
+
private var callId: String = ""
|
|
26
|
+
private var callType: String = "Audio"
|
|
27
|
+
|
|
28
|
+
private val timeoutHandler = Handler(Looper.getMainLooper())
|
|
29
|
+
private val timeoutRunnable = Runnable {
|
|
30
|
+
Log.d(TAG, "CallActivity timeout triggered for callId: $callId")
|
|
31
|
+
finishReason = FinishReason.TIMEOUT
|
|
32
|
+
CallEngine.stopRingtone()
|
|
33
|
+
CallEngine.cancelIncomingCallUI()
|
|
34
|
+
CallEngine.endCall(callId)
|
|
35
|
+
finishCallActivity()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
39
|
+
super.onCreate(savedInstanceState)
|
|
40
|
+
Log.d(TAG, "CallActivity onCreate")
|
|
41
|
+
|
|
42
|
+
// Lock‐screen bypass
|
|
43
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
44
|
+
setShowWhenLocked(true)
|
|
45
|
+
setTurnScreenOn(true)
|
|
46
|
+
} else {
|
|
47
|
+
window.addFlags(
|
|
48
|
+
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
49
|
+
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
50
|
+
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setContentView(R.layout.activity_call)
|
|
55
|
+
|
|
56
|
+
// Read incoming‐call params
|
|
57
|
+
callId = intent.getStringExtra("callId") ?: ""
|
|
58
|
+
callType = intent.getStringExtra("callType") ?: "Audio"
|
|
59
|
+
Log.d(TAG, "CallActivity received callId: $callId, callType: $callType")
|
|
60
|
+
|
|
61
|
+
// Register for call‐end callbacks BEFORE timeout or user can dismiss
|
|
62
|
+
CallEngine.registerCallEndListener(this)
|
|
63
|
+
|
|
64
|
+
// Bind UI
|
|
65
|
+
val callerName = intent.getStringExtra("callerName") ?: "Unknown"
|
|
66
|
+
findViewById<TextView>(R.id.caller_name).text = callerName
|
|
67
|
+
|
|
68
|
+
findViewById<Button>(R.id.answer_btn).setOnClickListener {
|
|
69
|
+
Log.d(TAG, "Answer clicked for callId: $callId")
|
|
70
|
+
finishReason = FinishReason.ANSWER
|
|
71
|
+
CallEngine.stopRingtone()
|
|
72
|
+
CallEngine.cancelIncomingCallUI()
|
|
73
|
+
CallEngine.answerCall(callId)
|
|
74
|
+
finishCallActivity()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
findViewById<Button>(R.id.decline_btn).setOnClickListener {
|
|
78
|
+
Log.d(TAG, "Decline clicked for callId: $callId")
|
|
79
|
+
finishReason = FinishReason.DECLINE
|
|
80
|
+
CallEngine.stopRingtone()
|
|
81
|
+
CallEngine.cancelIncomingCallUI()
|
|
82
|
+
CallEngine.endCall(callId)
|
|
83
|
+
finishCallActivity()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Start auto‐timeout
|
|
87
|
+
timeoutHandler.postDelayed(timeoutRunnable, 60_000)
|
|
88
|
+
Log.d(TAG, "CallActivity setup complete")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
override fun onDestroy() {
|
|
92
|
+
super.onDestroy()
|
|
93
|
+
Log.d(TAG, "CallActivity onDestroy for callId: $callId. Reason: $finishReason")
|
|
94
|
+
|
|
95
|
+
// Unregister listener
|
|
96
|
+
CallEngine.unregisterCallEndListener(this)
|
|
97
|
+
|
|
98
|
+
// Cancel timeout
|
|
99
|
+
timeoutHandler.removeCallbacks(timeoutRunnable)
|
|
100
|
+
|
|
101
|
+
// If user never answered, clean up ringtone/UI
|
|
102
|
+
if (finishReason != FinishReason.ANSWER) {
|
|
103
|
+
CallEngine.stopRingtone()
|
|
104
|
+
CallEngine.cancelIncomingCallUI()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
override fun onBackPressed() {
|
|
109
|
+
Log.d(TAG, "onBackPressed for callId: $callId → treat as decline")
|
|
110
|
+
finishReason = FinishReason.MANUAL_DISMISS
|
|
111
|
+
CallEngine.stopRingtone()
|
|
112
|
+
CallEngine.cancelIncomingCallUI()
|
|
113
|
+
CallEngine.endCall(callId)
|
|
114
|
+
finishCallActivity()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Called by CallEngine whenever ANY call ends.
|
|
119
|
+
* We only care about our own callId.
|
|
120
|
+
*/
|
|
121
|
+
override fun onCallEnded(endedCallId: String) {
|
|
122
|
+
if (endedCallId == callId && !isFinishing) {
|
|
123
|
+
Log.d(TAG, "CallActivity onCallEnded callback for callId: $callId")
|
|
124
|
+
finishReason = FinishReason.EXTERNAL_END
|
|
125
|
+
runOnUiThread { finishCallActivity() }
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private fun finishCallActivity() {
|
|
130
|
+
if (isFinishing) {
|
|
131
|
+
Log.d(TAG, "Already finishing, skip.")
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
Log.d(TAG, "Finishing CallActivity for callId: $callId")
|
|
135
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
136
|
+
finishAndRemoveTask()
|
|
137
|
+
} else {
|
|
138
|
+
finish()
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
companion object {
|
|
143
|
+
private const val TAG = "CallActivity"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
// CallInfo.kt
|
|
2
|
-
package com.margelo.nitro.qusaieilouti99.callmanager
|
|
3
|
-
|
|
4
|
-
import org.json.JSONObject
|
|
5
|
-
|
|
6
|
-
data class CallInfo(
|
|
7
|
-
val callId: String,
|
|
8
|
-
val callType: String, // "Audio" or "Video"
|
|
9
|
-
val displayName: String, // For UI display
|
|
10
|
-
val pictureUrl: String? = null, // For UI display
|
|
11
|
-
var state: CallState,
|
|
12
|
-
val timestamp: Long = System.currentTimeMillis(),
|
|
13
|
-
var wasHeldBySystem: Boolean = false,
|
|
14
|
-
var isManuallySilenced: Boolean = false
|
|
15
|
-
) {
|
|
16
|
-
fun toJsonObject(): JSONObject {
|
|
17
|
-
return JSONObject().apply {
|
|
18
|
-
put("callId", callId)
|
|
19
|
-
put("callType", callType)
|
|
20
|
-
put("displayName", displayName)
|
|
21
|
-
pictureUrl?.let { put("pictureUrl", it) }
|
|
22
|
-
put("state", state.name)
|
|
23
|
-
put("timestamp", timestamp)
|
|
24
|
-
put("wasHeldBySystem", wasHeldBySystem)
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
enum class CallState {
|
|
30
|
-
INCOMING, DIALING, ACTIVE, HELD, ENDED
|
|
31
|
-
}
|
|
1
|
+
// CallInfo.kt
|
|
2
|
+
package com.margelo.nitro.qusaieilouti99.callmanager
|
|
3
|
+
|
|
4
|
+
import org.json.JSONObject
|
|
5
|
+
|
|
6
|
+
data class CallInfo(
|
|
7
|
+
val callId: String,
|
|
8
|
+
val callType: String, // "Audio" or "Video"
|
|
9
|
+
val displayName: String, // For UI display
|
|
10
|
+
val pictureUrl: String? = null, // For UI display
|
|
11
|
+
var state: CallState,
|
|
12
|
+
val timestamp: Long = System.currentTimeMillis(),
|
|
13
|
+
var wasHeldBySystem: Boolean = false,
|
|
14
|
+
var isManuallySilenced: Boolean = false
|
|
15
|
+
) {
|
|
16
|
+
fun toJsonObject(): JSONObject {
|
|
17
|
+
return JSONObject().apply {
|
|
18
|
+
put("callId", callId)
|
|
19
|
+
put("callType", callType)
|
|
20
|
+
put("displayName", displayName)
|
|
21
|
+
pictureUrl?.let { put("pictureUrl", it) }
|
|
22
|
+
put("state", state.name)
|
|
23
|
+
put("timestamp", timestamp)
|
|
24
|
+
put("wasHeldBySystem", wasHeldBySystem)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
enum class CallState {
|
|
30
|
+
INCOMING, DIALING, ACTIVE, HELD, ENDED
|
|
31
|
+
}
|