Make a Call

Overview

This guide covers the functionalities in your Vonage Client application, in order to start in-app or server-managed voice calls.

Before you begin, make sure you added the SDK to your app.

Start an In-App Call

The quickest way to start an in-app call is by conducting an in-app to in-app call, meaning between two users.

Copy to Clipboard
new NexmoClient()
    .login(USER_JWT)
    .then(application => {
        ...
        application.inAppCall(userName);
    })
Copy to Clipboard
val callListener = object: NexmoRequestListener<NexmoCall> {
    override fun onSuccess(nexmoCall: NexmoCall?) {
        Log.d("TAG", "Call started: ${nexmoCall.toString()}")
    }

    override fun onError(apiError: NexmoApiError) {
        Log.d("TAG", "Error: Unable to start a call ${apiError.message}")
    }
}

client.call("123456", NexmoCallHandler.IN_APP, callListener);
Copy to Clipboard
NexmoRequestListener<NexmoCall> callListener = new NexmoRequestListener<NexmoCall>() {
    @Override
    public void onSuccess(@Nullable NexmoCall nexmoCall) {
        Log.d("TAG", "Call started: " + nexmoCall.toString());
    }

    @Override
    public void onError(@NonNull NexmoApiError apiError) {
        Log.d("TAG", "Error: Unable to start a call " + apiError.getMessage());
    }
};

client.call("123456", NexmoCallHandler.IN_APP, callListener)
Copy to Clipboard
NXMClient.shared.call(userName, callHandler: .inApp) { [weak self] (error, call) in
    guard let call = call else {
        // Handle create call failure
        ...
        return
    }
    // Handle call created successfully. 
    ...
})
Copy to Clipboard
[[NXMClient shared] call:userName callHandler:NXMCallHandlerInApp 
        completionHandler:^(NSError * _Nullable error, NXMCall * _Nullable call) {
    if(error) {
        // Handle create call failure
        ...
        return;
    }
    // Handle call created successfully. 
    ...
}];

The possible voice capabilities are very limited, as this doesn't utilize the Voice API. This method is recommended mostly for onboarding. Later, it is recommended to use a server managed call.

Start a Server Managed Call

This method allows you to conduct in-app calls as well as phone calls while taking advantage of the rich Voice API features.

When your client app calls this method, the answer_url webhook that is configured for your Vonage Application will execute. That defines the logic and capabilities of the call.

On the client side, start the call as such:

Copy to Clipboard
new NexmoClient()
    .login(USER_JWT)
    .then(application => {
        ...
        application.callServer(phoneNumber);
    })
Copy to Clipboard
val callListener = object: NexmoRequestListener<NexmoCall> {
    override fun onSuccess(nexmoCall: NexmoCall?) {
        Log.d("TAG", "Call started: ${nexmoCall.toString()}")
    }

    override fun onError(apiError: NexmoApiError) {
        Log.d("TAG", "Error: Unable to start a call ${apiError.message}")
    }
}

client.call("123456", NexmoCallHandler.SERVER, callListener);

Copy to Clipboard
NexmoRequestListener<NexmoCall> callListener = new NexmoRequestListener<NexmoCall>() {
    @Override
    public void onSuccess(@Nullable NexmoCall nexmoCall) {
        Log.d("TAG", "Call started: " + nexmoCall.toString());
    }

    @Override
    public void onError(@NonNull NexmoApiError apiError) {
        Log.d("TAG", "Error: Unable to start a call " + apiError.getMessage());
    }
};

client.call("123456", NexmoCallHandler.SERVER, callListener)
Copy to Clipboard
NXMClient.shared.call(userName, callHandler: .server) { [weak self] (error, call) in
    guard let call = call else {
        // Handle create call failure
        ...
        return
    }
    // Handle call created successfully. 
    ...
})
Copy to Clipboard
[[NXMClient shared] call:userName callHandler:NXMCallHandlerServer 
        completionHandler:^(NSError * _Nullable error, NXMCall * _Nullable call) {
    if(error) {
        // Handle create call failure
        ...
        return;
    }
    // Handle call created successfully. 
    ...
}];

Listen For Call Events

To see updates on the state of a call, for example, to know if the other member answered or hung up the call, you should listen to call events.

To see updates on the state of the call and its members:

Copy to Clipboard
application.on("call:status:changed",(call) => {
    ...
});
Copy to Clipboard
val callEventListener = object : NexmoCallEventListener {
    override fun onDTMF(digit: String?, callMember: NexmoCallMember?) {
        Log.d("TAG", "onDTMF(): digit: $digit, callMember: $callMember")
    }

    override fun onMemberStatusUpdated(memberStatus: NexmoCallMemberStatus?, callMember: NexmoCallMember?) {
        Log.d("TAG", "onMemberStatusUpdated(): status: $memberStatus, callMember: $callMember")
    }

    override fun onMuteChanged(muteState: NexmoMediaActionState?, callMember: NexmoCallMember?) {
        Log.d("TAG", ":NexmoMediaActionState(): muteState: $muteState, callMember: $callMember")
    }

    override fun onEarmuffChanged(earmuffState: NexmoMediaActionState?, callMember: NexmoCallMember?) {
        Log.d("TAG", "onEarmuffChanged(): earmuffState: $earmuffState, callMember: $callMember")
    }
}

nexmoCall?.addCallEventListener(callEventListener)

Remove the listener when needed:

Copy to Clipboard
nexmoCall?.removeCallEventListener(callEventListener)
Copy to Clipboard
NexmoCallEventListener callEventListener = new NexmoCallEventListener() {
    @Override
    public void onMemberStatusUpdated(NexmoCallMemberStatus $memberStatus, NexmoCallMember callMember) {
        Log.d("TAG", "onMemberStatusUpdated(): status: " + $memberStatus + " callMember: " + callMember);
    }

    @Override
    public void onMuteChanged(NexmoMediaActionState muteState, NexmoCallMember callMember) {
        Log.d("TAG", "NexmoMediaActionState(): muteState: " + muteState + ", callMember: " + callMember);
    }

    @Override
    public void onEarmuffChanged(NexmoMediaActionState earmuffState, NexmoCallMember callMember) {
        Log.d("TAG", "onEarmuffChanged(): earmuffState: " + earmuffState + ", callMember: " + callMember);
    }

    @Override
    public void onDTMF(String digit, NexmoCallMember callMember) {
        Log.d("TAG", "onDTMF(): digit:" + digit + ", callMember: " + callMember);
    }
};

nexmoCall.addCallEventListener(callEventListener);

Remove the listener when needed:

Copy to Clipboard
nexmoCall.removeCallEventListener(callEventListener);

Add the current ViewController, or similar, as a delegate for the call object returned when making a call:

Copy to Clipboard
call.setDelegate(self)
call.answer { [weak self] error in
    ...
}

ViewController will now have to conform to NXMCallDelegate:

Copy to Clipboard
extension ViewController: NXMCallDelegate {

    func call(_ call: NXMCall, didUpdate callMember: NXMCallMember, with status: NXMCallMemberStatus) {
        // handle call status updates
        ...
    }

    func call(_ call: NXMCall, didUpdate callMember: NXMCallMember, isMuted muted: Bool) {
        // handle call member muting updates
        ...
    }

    func call(_ call: NXMCall, didReceive error: Error) {
        print("call error: \(error.localizedDescription)")
        // handle call errors
        ...
    }

}

Add the current ViewController, or similar, as a delegate for the call object returned when making a call:

Copy to Clipboard
[call setDelegate:self];
[call answer:^(NSError * _Nullable error) {
    ...
}];

ViewController will now have to conform to NXMCallDelegate:

Copy to Clipboard
@interface ViewController () <NXMCallDelegate>
...
@end

@implementation ViewController
...

//MARK:- NXMCallDelegate

- (void)call:(nonnull NXMCall *)call didUpdate:(nonnull NXMCallMember *)callMember withStatus:(NXMCallMemberStatus)status {
    // handle call status updates
    ...
}

- (void)call:(nonnull NXMCall *)call didUpdate:(nonnull NXMCallMember *)callMember isMuted:(BOOL)muted {
    // handle call member muting updates
    ...
}

- (void)call:(nonnull NXMCall *)call didReceive:(nonnull NSError *)error {
    NSLog(@"call error: %@", [error localizedDescription]);
    // handle call errors
    ...
}

@end