Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for multiples calls (End and Accept/Decline) #115

Merged
merged 9 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ func onPushCall(call: Call) {
```

Likewise for ending calls, the `endCallFromCallkit(endAction:action)` method should be called from :

```Swift
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {

Expand All @@ -625,7 +625,68 @@ func provider(_ provider: CXProvider, perform action: CXEndCallAction) {

2. Logs on the receiver's end are essential for thorough debugging of issues related to push notifications. However, the debugger is not attached when the app is completely killed. To address this, you can simply put the app in the background. VOIP push notifications should then come through, and the debugger should capture all logs.


__*Handling Multiple Calls*__

To handle multiples, we can rely on the `CXProviderDelegate` delegate which invokes functions corresponding to
what action was performed on the callkit user interface.

1. End and Accept or Decline : The **end and accept** button on the callkit user interface accepts the nwe call and ends the previous call.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nwe -> new

Callkit then invokes the `CXAnswerCallAction` and `CXEndCallAction` when the **end and accept** button is pressed.
You can handle this scenario by :
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the space before :


```Swift
var currentCall: Call?
var previousCall: Call?
//current calkit uuid
var callKitUUID: UUID?

func onIncomingCall(call: Call) {
guard let callId = call.callInfo?.callId else {
print("AppDelegate:: TxClientDelegate onIncomingCall() Error unknown call UUID")
return
}
print("AppDelegate:: TxClientDelegate onIncomingCall() callKitUUID [\(String(describing: self.callKitUUID))] callId [\(callId)]")

self.callKitUUID = call.callInfo?.callId

//Update the previous call with the current call
self.previousCall = self.currentCall

//Update the current call with the incoming call
self.currentCall = call
..
}

```
Subsequently, when the user clicks on the End and Accept or Decline Button, you will need to determine which og these buttons was clicked.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

og -> of

You can do that as follows:

```Swift
//Callkit invokes CXEndCallAction and CXAnswerCallAction delegate function for accept and answer
func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
print("AppDelegate:: END call action: callKitUUID [\(String(describing: self.callKitUUID))] action [\(action.callUUID)]")

// if the callKitUUID is the same as the one provided by the action
// callkit expects you to end the current call
if(self.callKitUUID == action.callUUID){
if let onGoingCall = self.previousCall {
self.currentCall = onGoingCall
self.callKitUUID = onGoingCall.callInfo?.callId
}
}else {
//endPrevious Call
self.callKitUUID = self.currentCall?.callInfo?.callId
}
self.telnyxClient?.endCallFromCallkit(endAction:action)
}
```

**Note**

While handling multiple calls, you should **not** report the **call end** to callkit. This will keep your calls active with the callkit
user interface until there are no more active sessions.



### Disable Push Notification
Push notfications can be disabled for the current user by calling :
Expand Down
31 changes: 16 additions & 15 deletions TelnyxRTC/Telnyx/TxClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -257,16 +257,19 @@ public class TxClient {
}

/// To end and control callKit active and conn
public func endCallFromCallkit(endAction:CXEndCallAction) {
public func endCallFromCallkit(endAction:CXEndCallAction,callId:UUID? = nil) {
self.endCallAction = endAction
endAction.fulfill()

///Hangup call if there's a current pushCall
if(self.calls[currentCallId] != nil){
self.calls[currentCallId]?.hangup()
resetPushVariables()
currentCallId = UUID()
// Place the code you want to delay here
if let call = self.calls[endAction.callUUID] {
Logger.log.i(message: "EndClient:: Ended Call with Id \(endAction.callUUID)")
call.hangup()
} else {
Logger.log.i(message: "EndClient:: Ended Call")
self.calls[self.currentCallId]?.hangup()
}
self.resetPushVariables()

}


Expand Down Expand Up @@ -518,17 +521,15 @@ extension TxClient {
environment: serverConfiguration.environment,
pushMetaData: pushMetaData)
// Check if we are already connected and logged in
if isConnected() {
if !isConnected() {
Logger.log.i(message: "TxClient:: push flow socket already connected: disconnect")
self.disconnect()
do {
try self.connect(txConfig: txConfig, serverConfiguration: pnServerConfig)
} catch let error {
Logger.log.e(message: "TxClient:: push flow connect error \(error.localizedDescription)")
}
}

Logger.log.i(message: "TxClient:: push flow connect")
do {
try self.connect(txConfig: txConfig, serverConfiguration: pnServerConfig)
} catch let error {
Logger.log.e(message: "TxClient:: push flow connect error \(error.localizedDescription)")
}
self.isCallFromPush = true
}

Expand Down
1 change: 1 addition & 0 deletions TelnyxWebRTCDemo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var telnyxClient : TxClient?
var currentCall: Call?
var previousCall: Call?
var callKitUUID: UUID?

var userDefaults: UserDefaults = UserDefaults.init()
Expand Down
13 changes: 12 additions & 1 deletion TelnyxWebRTCDemo/Extensions/AppDelegateCallKitExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,24 @@ extension AppDelegate : CXProviderDelegate {
print("AppDelegate:: ANSWER call action: callKitUUID [\(String(describing: self.callKitUUID))] action [\(action.callUUID)]")

self.telnyxClient?.answerFromCallkit(answerAction: action, customHeaders: ["X-test-answer":"ios-test"])

}

func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
print("AppDelegate:: END call action: callKitUUID [\(String(describing: self.callKitUUID))] action [\(action.callUUID)]")

if(self.callKitUUID == action.callUUID){
//request to end current call
if let onGoingCall = self.previousCall {
self.currentCall = onGoingCall
self.callKitUUID = onGoingCall.callInfo?.callId
}
}else {
//request to end Previous Call
self.callKitUUID = self.currentCall?.callInfo?.callId
}
self.telnyxClient?.endCallFromCallkit(endAction:action)

}

func providerDidReset(_ provider: CXProvider) {
Expand Down
22 changes: 12 additions & 10 deletions TelnyxWebRTCDemo/Extensions/AppDelegateTelnyxVoIPExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,8 @@ extension AppDelegate: TxClientDelegate {
}
print("AppDelegate:: TxClientDelegate onIncomingCall() callKitUUID [\(String(describing: self.callKitUUID))] callId [\(callId)]")

if let currentCallUUID = self.currentCall?.callInfo?.callId {
print("AppDelegate:: TxClientDelegate onIncomingCall() end previous call [\(currentCallUUID)]")
executeEndCallAction(uuid: currentCallUUID) //Hangup the previous call if there's one active
}
self.callKitUUID = call.callInfo?.callId
self.previousCall = self.currentCall
self.currentCall = call //Update the current call with the incoming call
let headers = call.inviteCustomHeaders
print("\n Custom Headers onIncomingCall: \(String(describing: headers)) \n")
Expand All @@ -72,12 +69,17 @@ extension AppDelegate: TxClientDelegate {

func onRemoteCallEnded(callId: UUID) {
print("AppDelegate:: TxClientDelegate onRemoteCallEnded() callKitUUID [\(String(describing: self.callKitUUID))] callId [\(callId)]")
self.voipDelegate?.onRemoteCallEnded(callId: callId)
let reason = CXCallEndedReason.remoteEnded
if let provider = self.callKitProvider,
let callKitUUID = self.callKitUUID {
provider.reportCall(with: callKitUUID, endedAt: Date(), reason: reason)
if(self.previousCall != nil){
self.previousCall = nil
}else {
let reason = CXCallEndedReason.remoteEnded
if let provider = self.callKitProvider,
let callKitUUID = self.callKitUUID {
provider.reportCall(with: callKitUUID, endedAt: Date(), reason: reason)
}
}
self.voipDelegate?.onRemoteCallEnded(callId: callId)

}

func onCallStateUpdated(callState: CallState, callId: UUID) {
Expand All @@ -93,7 +95,7 @@ extension AppDelegate: TxClientDelegate {
if callState == .DONE {
if let currentCallId = self.currentCall?.callInfo?.callId,
currentCallId == callId {
self.currentCall = nil // clear current call
// self.currentCall = nil // clear current call
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion TelnyxWebRTCDemo/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ extension ViewController : UIIncomingCallViewDelegate {
}

func onRejectButton() {
self.appDelegate.currentCall?.hangup()
guard let callID = self.appDelegate.currentCall?.callInfo?.callId else { return }
self.appDelegate.executeEndCallAction(uuid:callID)
}
}
// MARK: - UICallScreenDelegate
Expand Down
Loading