Call Transfers and Call Forwarding¶
This article describes the call transfer and user initiated call forwarding features of the mobile SDK.
Overview¶
The SDK supports the following types of call redirection:
Blind transfer - the party initiating the transfer (the “Transferor”) sends the call directly to the third party (the “Target”) without waiting to establish a session with the Target first.
Attended transfer - party initiating the transfer (the “Transferor”) speaks with the third party (the “Target”) before completing the transfer from the original call party (the “Transferee”).
Call forwarding - the party initiating the forwarding sends the call directly to the third party while the original call is still ringing.
There are two ways to perform and manage redirection:
Direct usage of libSoftphone APIs - suitable for simple call redirection scenarios or for scenarios where the developer wants to have full control over the redirection process.
CallRedirectionManager - a higher level API that simplifies the call redirection management.
The direct APIs¶
The Swift SoftphoneBridge
and Java Instance
offer the following methods for call redirection:
transfer
Performs a blind transfer of an Established call to the specified target.
attendedTransfer
Performs an attended transfer of an Established call to another Established call.
forward
Forwards an IncomingTrying, IncomingRinging or IncomingIgnored call to the specified target.
acceptOfferedTransfer
Accepts an offered transfer.
rejectOfferedTransfer
Rejects an offered transfer.
The following callbacks are exposed in Swift SoftphoneObserverProxy
and Java Listeners
classes are available to monitor the progress of the call redirection:
onTransferResult
Reports the result of blind and attended transfers.
onTransferOffered
Informs about an incoming transfer offer. The offer can be accepted or rejected via
acceptOfferedTransfer
andrejectOfferedTransfer
.
A successful call forward is reported via transition of call into IncomingForwarded
state which is reported in onCallStateChanged
callback.
Using CallRedirectionManager¶
The CallRedirectionManager
is a higher level API that simplifies the call redirection management. It is designed in order to lead the developer through the call redirection process and to provide a simple way to implement the call redirection UI by providing a set of unified functions, callbacks and unified state.
The CallRedirectionManager
is a singleton object which is accessible both in Swift and Java.
The CallRedirectionManager
instance can be retrieved in Swift as follows:
1let manager = CallRedirectionManager.shared
And in Java:
1CallRedirectionManager callRedirectionManager = SDKServices.get(CallRedirectionManager.class);
CallRedirectionManager state¶
CallRedirectionManager tracks the redirection state and provides a set of functions to manage the redirection. The redirection state is represented by the RedirectionState
enum.
The state set description follows:
Inactive - no redirection is in progress
SourceAssigned - the redirect source call is assigned, the GUI should direct the user to select the target call by navigating to the dialpad or contact list
TargetAssigned - the target call is assigned and attended transfer can be performed, this state
only occurs in case of attended transfer
InProgress - both redirect source and target have been assigned, in case of transfers, the REFER will be sent, in case of call forwarding a 302 reponse will be sent as response to the INVITE. At this point it is not possible to change the source nor the target. It is not possible to cancel the redirection nor change the redirection type.
Succeeded - the redirection succeeded
Failed - the redirection failed
Cancelled - the redirection was cancelled, e.g. by user, or by some unexpected event, such as one of the calls was disconnected.
The redirection is tracked from the moment the source call is assigned until the source or target call objects are closed. This means the GUI code can retrieve the state, type, source and target call objects even after the redirect has finished or has been cancelled.
The state can be tracked by registering a listener, here’s a Swift example:
1class SomeClassName: RedirectionDelegate
2{
3 ...
4 func addRedirectionDelegate()
5 {
6 CallRedirectionManager.shared.addStateChangeDelegate(self)
7 }
8
9 func redirectStateChanged(state: CallRedirectState, type: CallRedirectType)
10 {
11 var message: String?
12 if state.isSourceAssigned()
13 {
14 message = "Please pick %s target";
15 }
16 else if state.isTargetAssigned()
17 {
18 message = "%s target assigned";
19 }
20 else if state.isInProgress()
21 {
22 message = "%s target assigned";
23 }
24 else if state.isSucceeded()
25 {
26 message = "%s success";
27 }
28 else if state.isFailed()
29 {
30 message = "%s failed";
31 }
32 else if state.isCancelled()
33 {
34 message = "%s cancelled";
35 }
36 else
37 {
38 message = nil;
39 }
40
41 if m = message
42 {
43 let typePlaceholder = type.isTransferType() ? "Call Transfer" : "Call Forwarding"
44 let formattedMessage = String(format: message, typePlaceholder)
45 print(formattedMessage)
46 }
47 }
48}
And in Java:
1CallRedirectionManager callRedirectionManager = SDKServices.get(CallRedirectionManager.class);
2Disposable redirectionStateDisposable = callRedirectionManager.registerOnStateChangedCallback((type, state) -> {
3 String message = null;
4 switch(state)
5 {
6 case SourceAssigned:
7 message = "Please pick %s target";
8 break;
9 case TargetAssigned:
10 message = "%s target assigned";
11 break;
12 case InProgress:
13 // we can show progress indicator here
14 message = "%s in progress";
15 break;
16 case Succeeded:
17 message = "%s success";
18 break;
19 case Failed:
20 message = "%s failed";
21 break;
22 case Cancelled:
23 message = "%s cancelled";
24 break;
25 default:
26 break;
27 }
28 if (message != null)
29 {
30 String typePlaceholder = type.isTransferType() ? "Call Transfer" : "Call Forwarding";
31 Toast.makeText(this, String.format(message, typePlaceholder), Toast.LENGTH_SHORT).show();
32 }
33});
You can also retrieve the current active redirection type by invoking getCurrentRedirectFlow
and the current state by invoking getState
.
API overview¶
The breakdown of the most important redirection manager functions follows:
getCurrentRedirectFlow
Returns the current redirection flow or None if no redirection is currently tracked.
getState
Returns the current redirection state.
getRedirectSource
Returns the source call object.
getRedirectTarget
Returns the target call object (only available in attended transfer).
cancelRedirect
Cancels any tracked redirection flow. Cancel has no effect if redirect state is InProgress.
canInitiateRedirect
Checks if the redirect manager is ready perform a transfer or forward.
getRedirectCapabilities
Returns the transfer and forward capabilities of the supplied call.
setBlindTransferSource
Sets the source call for blind transfer. The source call must be in Established state.
setAttendedTransferSource
Sets the source call for attended transfer. The source call must be in Established state.
setForwardingSource
Sets the source call for call forwarding. The source call must be in IncomingTrying, IncomingRinging or IncomingIgnored state.
setAttendedTransferTarget
Sets the target call for attended transfer. The target call must be in Established state.
performForwardToTarget
Performs a call forward to the specified target. The forwarding source call must be set
setForwardingSource
before calling this function and the state must beSourceAssigned
.performBlindTransferToTarget
Performs a blind transfer to the specified target. The forwarding source call must be set
setForwardingSource
before calling this function and the state must beSourceAssigned
.performAttendedTransfer
Performs an attended transfer between the source previously set via
setAttendedTransferSource
and the target previously set viasetAttendedTransferTarget
. The state must beTargetAssigned
.performAttendedTransferBetween
Performs an attended transfer between the supplied source and target. This can be invoked directly without setting the source and target calls. The state must not be
InProgress
.
Blind transfer flow¶
The typical flow of blind transfer is as follows:
A call is established.
GUI checks the redirection capabilities by calling
getRedirectCapabilities
for the current call, and enables the transfer button if blind transfer is available.The user clicks on the transfer button on the call screen.
GUI invokes
setBlindTransferSource
for the current call.GUI gets notified via its registered
StateChangeCallback
about a transition toRedirectState::SourceAssigned
.The GUI updates the UI to allow the user enter the number/contact to transfer to. The user should be able to cancel the transfer via a button, if the cancel button is clicked,
cancelRedirect
is called.The user dials a number or selects a contact to transfer to
GUI creates and posts a CallEvent for the call to be transferred to, as if it were a regular outgoing call
GUI gets notified via its registered
StateChangeCallback
about a transition toRedirectState::InProgress
.GUI updates the UI to show that the transfer is in progress, at this point it is no longer possible to cancel the transfer.
Based on the result of the transfer, GUI gets notified via its registered
StateChangeCallback
about a transition toRedirectState::Succeeded
orRedirectState::Failed
orRedirectState::Cancelled
.GUI updates its layout to show the result of the transfer.
The original call is disconnected. The GUI should close the call object. When the call object is closed, the state transitions back to
RedirectState::Inactive
state.
Attended transfer flow - multiple established calls¶
The simplest possible scenario of attended transfer starts with two established calls:
Two calls are established.
GUI checks the redirection capabilities by invoking
getRedirectCapabilities
for the current call, and enables the attended transfer button if attended transfer is available.The user clicks on the attended transfer button on the call screen.
The capabilities are queried again via
getRedirectCapabilities
, theAttendedTransferCapability
field of theRedirectCapabilities
object is checked to see if attended transfer is still available.As two calls are currently established, the
AttendedTransferCapability
returns the valueDirect
.The transfer target call is retrieved from
RedirectCapabilities::attendedTransferTargets
array, and GUI callsperformAttendedTransferBetween
with the two calls as parameters.
The case with three or more established calls is similar to the case with two calls. The AttendedTransferCapability
shows the
type PickAnotherCall
, and the GUI needs to present the user with a list of calls to choose from. The GUI can use the RedirectCapabilities::attendedTransferTargets
array to get the list of calls that can be used as transfer targets.
Once the user selects a target call, the GUI invokes performAttendedTransferBetween
with the source and target calls as parameters.
Attended transfer flow - one established call¶
The most complex attended transfer flow occurs when only one call is established:
A call is established.
GUI checks the redirection capabilities by invokes
getRedirectCapabilities
for the current call, and enables the attended transfer button if attended transfer is available.The user clicks on the attended transfer button on the call screen.
The capabilities are queried again via
getRedirectCapabilities
, theAttendedTransferCapability
field of theRedirectCapabilities
returnsNewCall
.GUI invokes
setAttendedTransferSource
for the current call.GUI gets notified via its registered
StateChangeCallback
about a transition toRedirectState::SourceAssigned
.The GUI updates the UI to allow the user enter the number/contact to transfer to. The user should be able to cancel the transfer via a button, if the cancel button is clicked,
cancelRedirect
is invoked.The user dials a number or selects a contact to transfer to.
GUI creates and posts a CallEvent for the target call, as if it were a regular outgoing call.
Once the call gets into
Call::State::Established
state, the redirection manager callssetAttendedTransferTarget
on the new call automatically.GUI gets notified via its registered
StateChangeCallback
about a transition toRedirectState::TargetAssigned
.GUI should display the new call and should allow the user to switch between the calls, merge them into a conference, or put them on hold etc.
User clicks on the attended transfer button again.
GUI invokes
performAttendedTransfer
.GUI gets notified via its registered
StateChangeCallback
about a transition toRedirectState::InProgress
.Based on the result of the transfer, GUI gets notified about a state transition to
RedirectState::Succeeded
orRedirectState::Failed
orRedirectState::Cancelled
GUI updates its layout according to the result of the forward.
The source and target calls are disconnected. GUI should close the call object. When the call object is closed, the state transitions back to
RedirectState::Inactive
state.