这份文档还在翻译中,预期年底前完成。欢迎您提供宝贵的意见及建议。

Make a Call

Overview

This guide covers the functionalities in your Nexmo 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.

new NexmoClient()
    .login(USER_JWT)
    .then(application => {
        ...
        application.inAppCall(userName);
    })
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);
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)
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. 
    ...
})
[[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 Nexmo 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 Nexmo Voice API features.

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

On the client side, start the call as such:

new NexmoClient()
    .login(USER_JWT)
    .then(application => {
        ...
        application.callServer(phoneNumber);
    })
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);

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)
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. 
    ...
})
[[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:

application.on("call:status:changed",(call) => {
    ...
});
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:

nexmoCall?.removeCallEventListener(callEventListener)
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:

nexmoCall.removeCallEventListener(callEventListener);

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

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

ViewController will now have to conform to NXMCallDelegate:

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:

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

ViewController will now have to conform to NXMCallDelegate:

@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