Voice Calling

Set up voice calling with the Sinch Voice & Video SDK. The SDK supports four types of calls: App-to-App (audio or video), App-to-Phone, App-to-SIP and Conference calls.

The Sinch SDK supports four types of calls: App-to-App (audio or video), App-to-Phone, App-to-SIP and Conference calls. The SINCallClient is the entry point for the calling functionality of the Sinch SDK.

Calls are placed using SINCallClient and events are received via SINCallClientDelegate. The call client (SINCallClient) is owned by the Sinch client (SINClient) and accessed using -[SINClient callClient].

Setting Up an App-to-App Call

Use the call client to start the call using the method callUserWithId:, passing the user identifier of the callee (the destination user) as an argument.

Copy
Copied
id<SINCallClient> callClient = [sinchClient callClient];
id<SINCall> call = [callClient callUserWithId:@"<remote user id>"];
call.delegate = self; // Assign delegate to observe call state changes

A call object is returned, containing details about the participants in the call, call details such as start time, call state, and possible errors.

Assuming the callee’s device is available and responsive, the delegate method callDidProgress: will be called. It notifies the application that the outbound call is progressing. If a progress tone should be played, this is where it should be started. We recommend that you use the available functionality provided by the Sinch SDK to play sounds such as ringtones (SINAudioController), see Playing Ringtones.

When the other party answers, the delegate method callDidEstablish: method will be called. Now, the users can start talking. If a progress tone has previously been initiated, it should be stopped now, in the delegate callback method.

Also see Handling Incoming Calls.

Setting Up an App-to-Phone Call

An App-to-Phone call is a call that's made to a phone on the regular telephone network. Setting up an App-to-Phone call is not much different from setting up an App-to-App call.

Initiate a call to a phone number by calling the method -[SINCallClient callPhoneNumber:]. The phone number should be specified according to the E.164 number formatting standard and should be prefixed with a ‘+’.

Copy
Copied
id<SINCallClient> callClient = [sinchClient callClient];
id<SINCall> call = [callClient callUserWithId:@"<REMOTE USERID>"];

// Set the call delegate that handles all the call state changes
call.delegate= ...

Example: To call the US phone number 415 555 0101, the phone number should be specified as +14155550101. The ‘+’ is the required prefix and the US country code ‘1’ prepended to the local subscriber number.

Presenting a number to the destination you are calling

Mandatory step!

You must provide a CLI (Calling Line Identifier) or your call will fail.

You need a number from Sinch so you can provide a valid CLI to the handset you are calling. If you have a trial account, you can use the test number that is available for free. If you have already upgraded your account, you can purchase a number to use on the dashboard.

Note:

When your account is in trial mode, you can only call your verified numbers. If you want to call any number, you need to upgrade your account!

Credits Required

Remember, placing an App-to-Phone call requires that your Sinch account has sufficient credits. Add credits on your Account page. Credits are used each time an App-to-Phone call is placed and your account balance is updated after each call.

When instantiating the SinchClient you must add the .callerIdentifier with a number from your account.

Copy
Copied
(void)createClientWithUserId:(NSString *)userId completion:(void (^)(NSError *))completion {
  if (self.client == nil) {
    NSError *error;
    self.client = [Sinch clientWithApplicationKey:APPLICATION_KEY
                                  environmentHost:ENVIRONMENT_HOST
                                           userId:userId
                                              cli:@"<YOUR PURCHASED SINCH NUMBER>"
                                            error:&error];
    if (!self.client && completion) {
      completion(error);
      return;
    }
Testing DTMF

In an App-to-Phone scenario, it's possible to issue DTMF sequences using the Sinch SDK. Note that if the receiving end of the call is an iOS device, you might have to disable VoLTE ("Voice over LTE") option in the settings of the phone at the receiving end of the call in order to be able to hear DTMF tones.

Setting Up an App-to-SIP Call

An App-to-SIP call is a call that's made to a SIP server. Use the method -[SINCallClient callSIP:] or -[SINCallClient callSIP:headers:] to initiate a SIP call. The destination SIP identity follows the form of email addresses (user@domain), for example alice@sip.your-sip-provider.com.

Copy
Copied
id<SINClient> sinchClient = ...; // Sinch client setup since before.
id<SINCallClient> callClient = [sinchClient callClient];
id<SINCall> call = [callClient callSIP:@"<SIP identity>"];

When custom SIP headers are passed as using -[SINCallClient callSIP:headers:], the headers should be prefixed with ‘x-’.

Setting Up a Conference Call

A Conference call can be made to connect a user to a conference room where multiple users can be connected at the same time.

Copy
Copied
id<SINCallClient> callClient = [sinchClient callClient];
id<SINCall> call = [callClient callConferenceWithId:@"<conference id>"];

it's also possible to connect users to a conference call via the Sinch REST API.

️Note

The identifier for a conference room may not be longer than 64 characters.

Handling Incoming Calls

To act on the incoming calls, implement the protocol SINCallClientDelegate and assign a delegate to the call client. The call client delegate is notified of new incoming calls via the delegate method didReceiveIncomingCall:.

To get events related to the call, assign a call delegate. The call object contains details about participants, start time, potential error codes, and error messages. See -[SINCall details] and SINCallDetails.

If you using VoIP Push Notifications and CallKit, use didReceiveIncomingCall: primarily to associate the SINCall with the CallKit-call. example this may be implemented by keeping a mapping between CallKit calls and SINCall. Example:

Copy
Copied
- (void)client:(id<SINCallClient>)client didReceiveIncomingCall:(id<SINCall>)call {
    // Assign delegate
    call.delegate = self;

    // Store in a NSDictionary for later, to be able to act on CXCallAction (CallKit action).
    [self.calls setObject:call forKey: [[NSUUID alloc] initWithUUIDString:call.callId]];
}
See our CallKit sample apps

In the Sinch SDK download, there is a sample app SinchCallKit.xcodeproj with a detailed example on how to associate SINCall with CallKit calls.

If you are not using VoIP Push Notifications and CallKit, then use didReceiveIncomingCall: to assign a delegate, and present a call UI. If the application is in foreground, you may also want to play a ringtone.

Copy
Copied
- (void)client:(id<SINCallClient>)client didReceiveIncomingCall:(id<SINCall>)call {
    // Assign delegate
    call.delegate = self;

    // Play ringtone

    // Present UI for call (UIViewController / segue)
}

Incoming Video Call

A video call will just like a voice-only call trigger the delegate method didReceiveIncomingCall:. To determine whether an incoming call contains a video stream, the property SINCallDetails.isVideoOffered can be used. Also see Video Calling for details on how to add video views.

Answering an Incoming Call

To answer a call, use the method -[SINCall answer]. If a ringtone was previously played, it should be stopped now.

User presses the answer button:

Copy
Copied
// User answers the call
[call answer];

// Stop playing ringing tone (unless using CallKit)

Now, the clients on both ends will establish the connection. When the call is established and the voice streams are running in both directions, the callDidEstablish: delegate method is called.

Declining an Incoming Call

If the call shouldn't be answered, use the method -[SINCall hangup] to decline the call. The caller will be notified that the incoming call was denied (via -[SINCallDelegate callDidEnd:]). If a ringtone was previously played, it should be stopped now.

User presses the hangup button:

Copy
Copied
// User declines the call
[call hangup];

// Stop playing ringing tone

Disconnecting a Call

When the user wants to disconnect an ongoing call, use the method -[SINCall hangup]. Either user taking part in a call can disconnect it.

Hanging up a call:

Copy
Copied
[call hangup];

When either party disconnects a call, the application is notified using the call delegate method -[SINCallDelegate callDidEnd:]. This allows the user interface to be updated, an alert tone to be played, or similar actions to occur.

A call can be disconnected before it has been completely established.

Hanging up a connecting call:

Copy
Copied
// Starting a call
id<SINCall> call = [client callUserWithId:@"<remote user id>"];

// User changed his/her mind, let's hangup.
[call hangup];

Handling a call that ends:

Copy
Copied
// SINCallDelegate implementation

- (void)callDidEnd:(id<SINCall>) call {
  // Update user interface, example hide the call screen.

Request User Permission for Using the Microphone

Recording audio always requires explicit permission from the user. Your app must provide a description for its use of the microphone in terms of the Info.plist key NSMicrophoneUsageDescription.

See Apple documentation on +[AVCaptureDevice requestAccessForMediaType:completionHandler:] for details on how to request user permission.

info

Unless the application has explicitly requested permission to use the microphone, the user is shown a dialog the first time the microphone is activated. This may not provide the best user experience, so we advice to consider explicitly requesting microphone permission in advance.

We'd love to hear from you!
Rate this content:
Still have a question?
 
Ask the community.