@qusaieilouti99/call-manager 0.1.34 → 0.1.36
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 +0 -2
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallEngine.kt +18 -11
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallForegroundService.kt +4 -2
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallManager.kt +15 -11
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/MyConnection.kt +14 -9
- package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/MyConnectionService.kt +2 -1
- package/lib/typescript/src/CallEventType.d.ts +1 -1
- package/lib/typescript/src/CallEventType.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JCallEventType.hpp +3 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/qusaieilouti99/callmanager/CallEventType.kt +2 -1
- package/nitrogen/generated/ios/swift/CallEventType.swift +4 -0
- package/nitrogen/generated/shared/c++/CallEventType.hpp +4 -0
- package/package.json +1 -1
- package/src/CallEventType.ts +2 -1
|
@@ -74,8 +74,6 @@ class CallActivity : Activity() {
|
|
|
74
74
|
|
|
75
75
|
override fun onBackPressed() {
|
|
76
76
|
Log.d(TAG, "CallActivity onBackPressed for callId: $callId. Treating as decline/dismiss.")
|
|
77
|
-
// Decision: User pressing back on the incoming call screen is treated as declining the call.
|
|
78
|
-
// If you want the call to continue ringing in the background, remove the CallEngine.endCall() line.
|
|
79
77
|
finishReason = FinishReason.MANUAL_DISMISS
|
|
80
78
|
CallEngine.endCall(this, callId)
|
|
81
79
|
finishCallActivity()
|
|
@@ -12,10 +12,16 @@ import android.media.MediaPlayer
|
|
|
12
12
|
import android.media.RingtoneManager
|
|
13
13
|
import android.net.Uri
|
|
14
14
|
import android.os.Build
|
|
15
|
-
import android.os.Bundle
|
|
15
|
+
import android.os.Bundle // Explicit import
|
|
16
16
|
import android.os.PowerManager
|
|
17
|
-
import android.telecom
|
|
18
|
-
import android.
|
|
17
|
+
import android.telecom.CallAudioState // Explicit import
|
|
18
|
+
import android.telecom.Connection // Explicit import
|
|
19
|
+
import android.telecom.DisconnectCause // Explicit import
|
|
20
|
+
import android.telecom.PhoneAccount // Explicit import
|
|
21
|
+
import android.telecom.PhoneAccountHandle // Explicit import
|
|
22
|
+
import android.telecom.TelecomManager // Explicit import
|
|
23
|
+
import android.telecom.VideoProfile // Explicit import
|
|
24
|
+
import android.util.Log // Explicit import
|
|
19
25
|
import android.graphics.Color
|
|
20
26
|
import android.app.Person
|
|
21
27
|
import org.json.JSONArray
|
|
@@ -443,7 +449,7 @@ object CallEngine {
|
|
|
443
449
|
// Returns the generated AudioRoutesInfo data class
|
|
444
450
|
fun getAudioDevices(): AudioRoutesInfo {
|
|
445
451
|
audioManager = audioManager ?: appContext?.getSystemService(Context.AUDIO_SERVICE) as? AudioManager ?: run {
|
|
446
|
-
Log.e(TAG, "getAudioDevices: AudioManager is null or appContext is not set.")
|
|
452
|
+
Log.e(TAG, "getAudioDevices: AudioManager is null or appContext is not set. Returning default.")
|
|
447
453
|
return AudioRoutesInfo(emptyArray(), "Unknown") // Return default empty info
|
|
448
454
|
}
|
|
449
455
|
val devices = mutableListOf<String>()
|
|
@@ -455,20 +461,21 @@ object CallEngine {
|
|
|
455
461
|
when (device.type) {
|
|
456
462
|
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> {
|
|
457
463
|
devices.add("Bluetooth")
|
|
458
|
-
if (audioManager?.isBluetoothScoOn == true && device.isSource
|
|
464
|
+
if (audioManager?.isBluetoothScoOn == true && !device.isSource) currentRoute = "Bluetooth" // check if output device
|
|
459
465
|
}
|
|
460
466
|
AudioDeviceInfo.TYPE_WIRED_HEADPHONES, AudioDeviceInfo.TYPE_WIRED_HEADSET -> {
|
|
461
467
|
devices.add("Headset")
|
|
462
|
-
if (audioManager?.isWiredHeadsetOn == true && device.isSource
|
|
468
|
+
if (audioManager?.isWiredHeadsetOn == true && !device.isSource) currentRoute = "Headset"
|
|
463
469
|
}
|
|
464
470
|
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> {
|
|
465
471
|
devices.add("Speaker")
|
|
466
|
-
if (audioManager?.isSpeakerphoneOn == true && device.isSource
|
|
472
|
+
if (audioManager?.isSpeakerphoneOn == true && !device.isSource) currentRoute = "Speaker"
|
|
467
473
|
}
|
|
468
474
|
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> {
|
|
469
475
|
devices.add("Earpiece")
|
|
470
476
|
// Earpiece is active if speaker, bluetooth, and headset are off
|
|
471
|
-
|
|
477
|
+
// This heuristic is tricky, relies on other routes being off
|
|
478
|
+
if (audioManager?.isSpeakerphoneOn == false && audioManager?.isWiredHeadsetOn == false && audioManager?.isBluetoothScoOn == false && !device.isSource) {
|
|
472
479
|
// This heuristic is tricky, relies on other routes being off
|
|
473
480
|
currentRoute = "Earpiece"
|
|
474
481
|
}
|
|
@@ -725,19 +732,19 @@ object CallEngine {
|
|
|
725
732
|
}
|
|
726
733
|
|
|
727
734
|
// --- Ringback Tone Management (for outgoing calls) ---
|
|
728
|
-
// Requires `res/raw/ringback_tone.
|
|
735
|
+
// Requires `res/raw/ringback_tone.mp3` for custom outgoing ringback.
|
|
729
736
|
private fun startRingback() {
|
|
730
737
|
if (ringbackPlayer != null && ringbackPlayer!!.isPlaying) {
|
|
731
738
|
Log.d(TAG, "Ringback tone already playing.")
|
|
732
739
|
return
|
|
733
740
|
}
|
|
734
741
|
try {
|
|
735
|
-
// Ensure you have `res/raw/ringback_tone.
|
|
742
|
+
// Ensure you have `res/raw/ringback_tone.mp3` in your project for this to work.
|
|
736
743
|
// If you don't want a custom ringback, you can play a silent audio file or do nothing here.
|
|
737
744
|
val ringbackUri = Uri.parse("android.resource://${appContext?.packageName}/raw/ringback_tone")
|
|
738
745
|
ringbackPlayer = MediaPlayer.create(appContext, ringbackUri)
|
|
739
746
|
if (ringbackPlayer == null) {
|
|
740
|
-
Log.e(TAG, "Failed to create MediaPlayer for ringback. Check raw/ringback_tone.
|
|
747
|
+
Log.e(TAG, "Failed to create MediaPlayer for ringback. Check raw/ringback_tone.mp3 exists.")
|
|
741
748
|
return
|
|
742
749
|
}
|
|
743
750
|
ringbackPlayer?.apply {
|
package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/CallForegroundService.kt
CHANGED
|
@@ -3,10 +3,12 @@ package com.margelo.nitro.qusaieilouti99.callmanager
|
|
|
3
3
|
import android.app.Notification
|
|
4
4
|
import android.app.NotificationChannel
|
|
5
5
|
import android.app.Service
|
|
6
|
+
import android.content.Context
|
|
6
7
|
import android.content.Intent
|
|
7
8
|
import android.os.Build
|
|
9
|
+
import android.util.Log // Explicit import
|
|
8
10
|
import android.os.IBinder
|
|
9
|
-
import android.
|
|
11
|
+
import android.app.NotificationManager // Explicit import
|
|
10
12
|
|
|
11
13
|
class CallForegroundService : Service() {
|
|
12
14
|
|
|
@@ -59,7 +61,7 @@ class CallForegroundService : Service() {
|
|
|
59
61
|
NotificationManager.IMPORTANCE_LOW
|
|
60
62
|
)
|
|
61
63
|
channel.description = "Notification for ongoing calls"
|
|
62
|
-
val manager = getSystemService(
|
|
64
|
+
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Corrected usage
|
|
63
65
|
manager.createNotificationChannel(channel)
|
|
64
66
|
Log.d(TAG, "Foreground notification channel '$CHANNEL_ID' created/updated.")
|
|
65
67
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.margelo.nitro.qusaieilouti99.callmanager
|
|
2
2
|
|
|
3
3
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
4
|
+
import android.util.Log // Explicit import
|
|
4
5
|
import org.json.JSONArray
|
|
5
6
|
import org.json.JSONObject
|
|
6
7
|
|
|
@@ -9,7 +10,9 @@ class CallManager : HybridCallManagerSpec() {
|
|
|
9
10
|
|
|
10
11
|
private val TAG = "CallManager"
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
// Listener type now directly matches the generated Func_void_CallEventType_std__string
|
|
14
|
+
// This is the correct type from your Nitro codegen output.
|
|
15
|
+
private var currentListener: Func_void_CallEventType_std__string? = null
|
|
13
16
|
|
|
14
17
|
override fun endCall(callId: String) {
|
|
15
18
|
Log.d(TAG, "endCall requested for callId: $callId")
|
|
@@ -50,24 +53,25 @@ class CallManager : HybridCallManagerSpec() {
|
|
|
50
53
|
} ?: Log.e(TAG, "App context not set for keepScreenAwake.")
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
//
|
|
56
|
+
// Corrected addListener signature to match generated HybridCallManagerSpec
|
|
57
|
+
// This is the primary fix for the `addListener overrides nothing` error.
|
|
54
58
|
override fun addListener(
|
|
55
|
-
listener: Func_void_CallEventType_std__string // Use generated type
|
|
59
|
+
listener: Func_void_CallEventType_std__string // Use generated type directly
|
|
56
60
|
): Func_void { // Return generated type
|
|
57
|
-
Log.d(TAG, "addListener called
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
currentListener =
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
CallEngine.setEventHandler(currentListener)
|
|
61
|
+
Log.d(TAG, "addListener called with listener: $listener")
|
|
62
|
+
// Store the incoming Nitro-generated listener.
|
|
63
|
+
// It already implements the (CallEventType, String) -> Unit interface.
|
|
64
|
+
currentListener = listener
|
|
65
|
+
CallEngine.setEventHandler(listener) // Pass it directly to CallEngine
|
|
64
66
|
|
|
65
|
-
// Return a generated Func_void for the remove function
|
|
67
|
+
// Return a Nitro-generated Func_void for the remove function
|
|
66
68
|
return Func_void_java {
|
|
67
69
|
if (currentListener === listener) { // Compare against the original listener passed
|
|
68
70
|
CallEngine.setEventHandler(null)
|
|
69
71
|
currentListener = null
|
|
70
72
|
Log.d(TAG, "Listener removed.")
|
|
73
|
+
} else {
|
|
74
|
+
Log.d(TAG, "Attempted to remove a listener that was not current.")
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
}
|
|
@@ -2,24 +2,26 @@ package com.margelo.nitro.qusaieilouti99.callmanager
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.net.Uri
|
|
5
|
+
import android.os.Bundle // Explicit import
|
|
5
6
|
import android.telecom.Connection
|
|
6
7
|
import android.telecom.DisconnectCause
|
|
7
|
-
import android.telecom.CallAudioState
|
|
8
|
+
import android.telecom.CallAudioState // Explicit import
|
|
8
9
|
import android.telecom.VideoProfile
|
|
9
|
-
import android.util.Log
|
|
10
|
+
import android.util.Log // Explicit import
|
|
10
11
|
import org.json.JSONObject
|
|
11
12
|
import java.util.UUID
|
|
12
13
|
|
|
13
14
|
class MyConnection(
|
|
14
15
|
private val context: Context,
|
|
15
|
-
callDataJson: String
|
|
16
|
+
callDataJson: String
|
|
16
17
|
) : Connection() {
|
|
17
18
|
|
|
18
19
|
companion object {
|
|
19
20
|
const val TAG = "MyConnection"
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
// Changed to internal val to allow access from MyConnectionService for logging
|
|
24
|
+
internal val callId: String = try {
|
|
23
25
|
JSONObject(callDataJson).optString("callId", UUID.randomUUID().toString())
|
|
24
26
|
} catch (e: Exception) {
|
|
25
27
|
UUID.randomUUID().toString()
|
|
@@ -105,10 +107,13 @@ class MyConnection(
|
|
|
105
107
|
override fun onPlayDtmfTone(digit: Char) {
|
|
106
108
|
super.onPlayDtmfTone(digit)
|
|
107
109
|
Log.d(TAG, "Playing DTMF tone: $digit for callId: $callId")
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
// NOTE: DTMF_TONE is not in your current CallEventType.ts enum.
|
|
111
|
+
// If you need to emit this event, you MUST add 'DTMF_TONE' to your CallEventType.ts
|
|
112
|
+
// and re-run nitro-codegen. For now, it's commented out to prevent compilation error.
|
|
113
|
+
// CallEngine.emitEvent(
|
|
114
|
+
// CallEventType.DTMF_TONE,
|
|
115
|
+
// JSONObject().put("callId", callId).put("digit", digit.toString())
|
|
116
|
+
// )
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
override fun onStopDtmfTone() {
|
|
@@ -116,7 +121,7 @@ class MyConnection(
|
|
|
116
121
|
Log.d(TAG, "Stopping DTMF tone for callId: $callId")
|
|
117
122
|
}
|
|
118
123
|
|
|
119
|
-
override fun onConnectionEvent(event: String, extras: Bundle?) {
|
|
124
|
+
override fun onConnectionEvent(event: String, extras: Bundle?) { // Resolved - signature is correct
|
|
120
125
|
super.onConnectionEvent(event, extras)
|
|
121
126
|
Log.d(TAG, "Connection event: $event, extras: $extras for callId: $callId")
|
|
122
127
|
}
|
package/android/src/main/java/com/margelo/nitro/qusaieilouti99/callmanager/MyConnectionService.kt
CHANGED
|
@@ -6,7 +6,8 @@ import android.telecom.ConnectionService
|
|
|
6
6
|
import android.telecom.PhoneAccountHandle
|
|
7
7
|
import android.telecom.TelecomManager
|
|
8
8
|
import android.telecom.VideoProfile
|
|
9
|
-
import android.
|
|
9
|
+
import android.telecom.CallAudioState // Explicit import
|
|
10
|
+
import android.util.Log // Explicit import
|
|
10
11
|
|
|
11
12
|
class MyConnectionService : ConnectionService() {
|
|
12
13
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type CallEventType = 'INITIAL_CALL_STATE' | 'CALL_STATE_CHANGED' | 'AUDIO_DEVICES_CHANGED' | 'AUDIO_ROUTE_CHANGED' | 'CALL_HELD' | 'CALL_UNHELD' | 'CALL_MUTED' | 'CALL_UNMUTED' | 'CALL_ANSWERED' | 'CALL_REJECTED' | 'CALL_ENDED';
|
|
1
|
+
export type CallEventType = 'INITIAL_CALL_STATE' | 'CALL_STATE_CHANGED' | 'AUDIO_DEVICES_CHANGED' | 'AUDIO_ROUTE_CHANGED' | 'CALL_HELD' | 'CALL_UNHELD' | 'CALL_MUTED' | 'CALL_UNMUTED' | 'CALL_ANSWERED' | 'CALL_REJECTED' | 'CALL_ENDED' | 'DTMF_TONE';
|
|
2
2
|
//# sourceMappingURL=CallEventType.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CallEventType.d.ts","sourceRoot":"","sources":["../../../src/CallEventType.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,aAAa,GACrB,oBAAoB,GACpB,oBAAoB,GACpB,uBAAuB,GACvB,qBAAqB,GACrB,WAAW,GACX,aAAa,GACb,YAAY,GACZ,cAAc,GACd,eAAe,GACf,eAAe,GACf,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"CallEventType.d.ts","sourceRoot":"","sources":["../../../src/CallEventType.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,aAAa,GACrB,oBAAoB,GACpB,oBAAoB,GACpB,uBAAuB,GACvB,qBAAqB,GACrB,WAAW,GACX,aAAa,GACb,YAAY,GACZ,cAAc,GACd,eAAe,GACf,eAAe,GACf,YAAY,GACZ,WAAW,CAAC"}
|
|
@@ -52,6 +52,7 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
|
|
|
52
52
|
static const auto fieldCALL_ANSWERED = clazz->getStaticField<JCallEventType>("CALL_ANSWERED");
|
|
53
53
|
static const auto fieldCALL_REJECTED = clazz->getStaticField<JCallEventType>("CALL_REJECTED");
|
|
54
54
|
static const auto fieldCALL_ENDED = clazz->getStaticField<JCallEventType>("CALL_ENDED");
|
|
55
|
+
static const auto fieldDTMF_TONE = clazz->getStaticField<JCallEventType>("DTMF_TONE");
|
|
55
56
|
|
|
56
57
|
switch (value) {
|
|
57
58
|
case CallEventType::INITIAL_CALL_STATE:
|
|
@@ -76,6 +77,8 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
|
|
|
76
77
|
return clazz->getStaticFieldValue(fieldCALL_REJECTED);
|
|
77
78
|
case CallEventType::CALL_ENDED:
|
|
78
79
|
return clazz->getStaticFieldValue(fieldCALL_ENDED);
|
|
80
|
+
case CallEventType::DTMF_TONE:
|
|
81
|
+
return clazz->getStaticFieldValue(fieldDTMF_TONE);
|
|
79
82
|
default:
|
|
80
83
|
std::string stringValue = std::to_string(static_cast<int>(value));
|
|
81
84
|
throw std::invalid_argument("Invalid enum value (" + stringValue + "!");
|
|
@@ -39,6 +39,8 @@ public extension CallEventType {
|
|
|
39
39
|
self = .callRejected
|
|
40
40
|
case "CALL_ENDED":
|
|
41
41
|
self = .callEnded
|
|
42
|
+
case "DTMF_TONE":
|
|
43
|
+
self = .dtmfTone
|
|
42
44
|
default:
|
|
43
45
|
return nil
|
|
44
46
|
}
|
|
@@ -71,6 +73,8 @@ public extension CallEventType {
|
|
|
71
73
|
return "CALL_REJECTED"
|
|
72
74
|
case .callEnded:
|
|
73
75
|
return "CALL_ENDED"
|
|
76
|
+
case .dtmfTone:
|
|
77
|
+
return "DTMF_TONE"
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
}
|
|
@@ -40,6 +40,7 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
|
|
|
40
40
|
CALL_ANSWERED SWIFT_NAME(callAnswered) = 8,
|
|
41
41
|
CALL_REJECTED SWIFT_NAME(callRejected) = 9,
|
|
42
42
|
CALL_ENDED SWIFT_NAME(callEnded) = 10,
|
|
43
|
+
DTMF_TONE SWIFT_NAME(dtmfTone) = 11,
|
|
43
44
|
} CLOSED_ENUM;
|
|
44
45
|
|
|
45
46
|
} // namespace margelo::nitro::qusaieilouti99_callmanager
|
|
@@ -65,6 +66,7 @@ namespace margelo::nitro {
|
|
|
65
66
|
case hashString("CALL_ANSWERED"): return CallEventType::CALL_ANSWERED;
|
|
66
67
|
case hashString("CALL_REJECTED"): return CallEventType::CALL_REJECTED;
|
|
67
68
|
case hashString("CALL_ENDED"): return CallEventType::CALL_ENDED;
|
|
69
|
+
case hashString("DTMF_TONE"): return CallEventType::DTMF_TONE;
|
|
68
70
|
default: [[unlikely]]
|
|
69
71
|
throw std::invalid_argument("Cannot convert \"" + unionValue + "\" to enum CallEventType - invalid value!");
|
|
70
72
|
}
|
|
@@ -82,6 +84,7 @@ namespace margelo::nitro {
|
|
|
82
84
|
case CallEventType::CALL_ANSWERED: return JSIConverter<std::string>::toJSI(runtime, "CALL_ANSWERED");
|
|
83
85
|
case CallEventType::CALL_REJECTED: return JSIConverter<std::string>::toJSI(runtime, "CALL_REJECTED");
|
|
84
86
|
case CallEventType::CALL_ENDED: return JSIConverter<std::string>::toJSI(runtime, "CALL_ENDED");
|
|
87
|
+
case CallEventType::DTMF_TONE: return JSIConverter<std::string>::toJSI(runtime, "DTMF_TONE");
|
|
85
88
|
default: [[unlikely]]
|
|
86
89
|
throw std::invalid_argument("Cannot convert CallEventType to JS - invalid value: "
|
|
87
90
|
+ std::to_string(static_cast<int>(arg)) + "!");
|
|
@@ -104,6 +107,7 @@ namespace margelo::nitro {
|
|
|
104
107
|
case hashString("CALL_ANSWERED"):
|
|
105
108
|
case hashString("CALL_REJECTED"):
|
|
106
109
|
case hashString("CALL_ENDED"):
|
|
110
|
+
case hashString("DTMF_TONE"):
|
|
107
111
|
return true;
|
|
108
112
|
default:
|
|
109
113
|
return false;
|
package/package.json
CHANGED
package/src/CallEventType.ts
CHANGED