Single Call

Handling new calls

Ringing the device

You can indicate to a device to start its ringing effect. This notifies the device that there is an incoming call. The ringing effect depends on the capabilities of the device, for example a flashing green LED light.

The following code sample shows how your application must react when receiving an incoming call and starts to ring the device:

using System.Runtime.ExceptionServices;

ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated


var wasAccepted = await singleCallControl.SignalIncomingCall();
if (wasAccepted)
{
   // Call has started, proceed to update your UI
}
else
{
   // Call was rejected, proceed to update your UI
}

SignalIncomingCall returns a task that resolves to true or false depending on whether the call was accepted or rejected; the task is resolved either from interacting with the (physical) device buttons or by calling the functions AcceptIncomingCall or RejectIncomingCall.

Accepting/Rejecting an Incoming Call

If your application has received a new incoming call and you have indicated that to the device, the device rings.

If the end-user interacts with your UI, you can either accept or reject the call. The acceptance or rejection is done via the AcceptIncomingCall and RejectIncomingCall methods, respectively.

Similar to interacting with the device, executing either of these methods resolves the task returned by SignalIncomingCall.

The following code sample shows how to accept the call from your application:

ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated

var incomingCall = await singleCallControl.SignalIncomingCall();
await singleCallControl.AcceptIncomingCall(); // accept the call
var wasAccepted = await incomingCall; // wasAccepted will be true

The following code sample shows how to reject the call from your application:

ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated

var incomingCall = singleCallControl.SignalIncomingCall();
singleCallControl.RejectIncomingCall(); // reject the call
var wasAccepted = await incomingCall; // wasAccepted will be false

Accepting/Rejecting Calls by interacting with the Device

When the end-user interacts with the Jabra device and the device rings, the user can accept or reject the call by physically interacting with the device via a button press.

Be aware that this can be different depending on your device.

When the call is accepted, it resolves the task returned by SignalIncomingCall. The task is then resolved with a true value.

In both cases, regardless of whether the task is resolved with a true or false value, the device stops ringing.

See the following code sample to accept a call:

ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated

try
{
    bool wasAccepted = await singleCallControl.SignalIncomingCall();

    // User presses start-call button on the device
    if (wasAccepted)
    {
        // Call was accepted, proceed to update your UI
    }
    else if (!wasAccepted)
    {
        // Call was rejected, proceed to update your UI
    }
}
catch (err)
{
    // Something bad happened.
}

Rejecting a call can be handled similarly to accepting a call. For example, the task returned by SignalIncomingCall will be resolved. However, it resolves with a false value.

The following code sample shows how to reject a call:

ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated

var wasAccepted = await singleCallControl.SignalIncomingCall();

// User presses end-call button on the device
if (!wasAccepted)
{
   // Call was rejected, proceed to update your UI
}

Starting a new call from your application

From the Jabra device's perspective, starting a new outgoing call and being in an active call (i.e., talking to someone) is handled in the same way -- you must indicate to the device that it is in an active call.

See the following code sample:

try
{
    ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated

    await singleCallControl.StartCall();
}
catch (JabraException ex)
{
    // Something bad happened. Inspect error.
    // A common mistake is to call \`StartCall()\` while the device is already in a call - that would
    // throw an exception for Single Call Control.
}

Once the call is answered, nothing should change on the device, as the StartCall function has already been called. If the other party rejects the call, the call is considered ended.

Ending a call

Option A) From your application

During an active call, the user may want to end the call. Your application may offer this functionality to the user, for example a red handset button in the UI, indicating the ability to hang up or end the call.

When the user presses the button, the call ends on your application. However, the Jabra device remains in an active call state until you indicate to it that the call has ended.

The following code sample shows how to end the call:

try
{
    ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated


    await singleCallControl.EndCall();
}
catch (err)
{
    // Something bad happened. Inspect error.
}

Option B) By interacting with the device

Jabra devices let you end a call from the device itself. Therefore, your application must stop the call when the device indicates that the user interacted with it and wants to hang up or end the call.

You can do this by subscribing to the CallActive property and acting appropriately when state changes occur.

ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated

singleCallControl.CallActive.Subscribe(
    (callActive) =>
    {
        if (callActive)
        {
            // the device is in an "active call state", reflect on the changes (e.g. update the UI)
        }
        else
        {
            // the device is no longer in a call state, reflect on the changes (e.g. update the UI)
        }
    });

Keeping track of the Active Call state of the device

In addition to keeping track of the Mute state, it is also important to keep track of the CallActive or Active Call state. If you do not do so, it can mean that your call ends, but your application will not reflect that the call has ended.

When a user accepts or starts a call from your application, the application must execute commands and reflect the changes in the state of the device.

Any call-related actions such as accepting an incoming call, starting, or ending a call, and others, trigger the CallActive observable to emit a change in call state.

The following code sample shows how to subscribe to changes in the call state:

ISingleCallControl singleCallControl; // assume `ISingleCallControl` is already instantiated

singleCallControl.CallActive.Subscribe(
    (callActive) =>
    {
        if (callActive)
        {
            // the device is in an "active call state", reflect on the changes (e.g. update the UI)
        }
        else
        {
            // the device is no longer in a call state, reflect on the changes (e.g. update the UI)
        }
    });