iOS
Calls Key Functions

Key Functions

This page explains key functions of SendBird Calls consisting of how to make, receive, handle, and end a call from your client app.


DirectCall object

This object represents a one-to-one call. It has the following properties and functions:

Properties

Property nameDescription

callId

Type: String
A unique identifier for a direct call.

caller

Type: DirectCalluser
The user’s role that initiates the call.

callee

Type: DirectCalluser
The user’s role that receives the call.

isEnded

Type: Bool
Indicates whether the call is ended.

isVideoCall

Type: Bool
Indicates whether the call is a video call. The call should be configured with the video call option when initiating it.

endResult

Type: DirectCallEndResult
The result of how the call has ended.

myRole

Type: DirectCall.UserRole
The role of the local use in the call.

localUser

Type: DirectCallUser
The local user of the call.

isLoaclAudioEnabled

Type: Bool
Indicates whether the local user has enabled their audio.

isLocalVideoEnabled

Type: Bool
Indicates whether the local user has enabled their video.

localVideoView

Type: SendBirdVideoView
The SendBirdVideoView object that represents the view which renders the local user’s video. Update this property by the updateLocalVideo(_:) method.

remoteUser

Type: DirectCallUser
The remote user of the call.

isRemoteAudioEnabled

Type: Bool
Indicates whether the remote user has enabled their audio.

isRemoteVideoViewEnabled

Type: Bool
Indicates whether the remote user has enabled their video.

remoteVideoView

Type: SendBirdVideoView
The SendBirdVideoView object that represents the view which renders the remote user’s video. Update this property by the updateRemoteVideo(_:) method.

startedAt

Type: Int64
The timestamp of when the call was dialed, in Unix milliseconds. A value of 0 indicates that the call hasn’t started yet.

endAt

Type: Int64
The timestamp of when the call was ended, in Unix milliseconds. A value of 0 indicates that the call hasn’t ended yet.

duration

Type: Int64
The period from the call was accepted to when the call was ended, in Unix milliseconds. A value of 0 indicates that the call hasn’t started yet.

customItems

Type: [String:String]
A dictionary of key-value items to store customized data for the call.

`

Methods

MethodDescription

accept(with: AcceptParams)

Accepts an incoming call.

end()

Ends the call. The DirectCallDelegate.didEnd(call:) delegate method will be called after receiving a success callback from SendBird server. This delegate is also called when the remote user has ended the call.

muteMicrophone()

Mutes the local user's audio. The DirectCallDelegate.didRemoteAudioSettingsChange() delegate method of the remote user will be called. If the remote user changes their audio settings, the local user will be notified through the same delegate method.

unmuteMicrophone()

Unmutes the local user's audio. The DirectCallDelegate.didRemoteAudioSettingsChange() delegate method of the remote user will be called. If the remote user changes their audio settings, the local user will be notified through the same delegate method.

startVideo()

Starts the local video. If the remote user changes video settings, the local user will be notified through the DirectCallDelegate.didRemoteVideoSettingsChange() delegate method.

stopVideo()

Stops the local video. If the remote user changes video settings, the local user is notified through the DirectCallDelegate.didRemoteVideoSettingsChange() delegate method.

updateLocalVideoView(_:)

Updates the local SendBirdVideoView object. Another view object can be used to render the local video.

updateRemoteVideoView(_:)

Updates the remote SendBirdVideoView object. Another view object can be used to render the remote video.

updateCustomItems(customItems:completionHandler:)

Updates the custom items of the call.

deleteCustomItems(customItemsKeys:completionHandler:)

Deletes the custom items of the call.

deleteAllCustomItems(completionHandler:)

Delete all custom items of the call.


DirectCallDelegate event delegate

MethodDescription

didConnect(call:)

Media devices (for example, microphone and speakers) between the caller and callee are connected and can start the call.

didEstablish(call:)

The callee has accepted the call by using the call.accept() method, but the media devices of caller and callee are not yet connected.

didStartReconnecting(call:)

The call begins attempting to reconnect to SendBird server after losing connection.

didReconnect(call:)

The call successfully reconnects to SendBird server.

didRemoteAudioSettingsChange(call:)

The remote user changes their audio settings.

didRemoteVideoSettingsChange(call:)

The remote user changes their video settings.

didEnd(call:)

One of the parties ends a call by using the call.end() method and a call is ended due to other reasons such as decline or connection lost.

didAudioDeviceChange(call:session:previousRoute:reason:)

The audio device has been changed. It provides information about the audio session, previous audio route, and change of reason.

didUpdateCustomItems(call:updatedKeys:)

The custom items of the call that match the updatedKeys parameter are updated.

didDeleteCustomItems(call:deletedKeys:)

The custom items of the call that match the deletedKeys parameter are deleted.


Make a call

Initiate a call by providing the callee’s user ID into the SendBirdCall.dial() method. Use the CallOptions object to choose a call’s initial settings.

Light Color Skin
Copy
let directCall = SendBirdCall.dial(to: CALLEE_ID, callOptions: CallOptions()) { (directCall, error) in
    // 
}

directCall.delegate = self

Configure video settings

In a video call, configure the video view settings prior to making the call so that the transition from a voice call to a video call will be seamless. Create SendBirdVideoView instances to render local and remote video streams as shown below:

Light Color Skin
Copy
let localSBView = SendBirdVideoView(frame: self.localVideoView?.frame ?? CGRect.zero) 
let remoteSBView = SendBirdVideoView(frame: self.remoteVideoView?.frame ?? CGRect.zero)
 
self.call.updateLocalVideoView(localSBView)
self.call.updateRemoteVideoView(remoteSBView)
 
// When making a call or accepting an incoming call.
let callOptions = CallOptions(
            isAudioEnabled = true,
            isVideoEnabled = true,
            localVideoView: localSBVideoView
            remoteVideoView: remoteSBVideoView)
 
// Or when updating local / remote view
self.call.updateLocalVideoView(localSBView)
self.call.updateRemoteVideoView(remoteSBView)

Receive a call

To receive an incoming call, a SendBirdCallDelegate event delegate should already be registered in the callee’s client app. Accept or decline the call using the directCall.accept() or the directCall.end() method. If the call is accepted, a media session will automatically be established by the Calls SDK.

Before accepting the call, the call-specific DirectCallDelegate event delegate must be added to the call object. It enables the callee’s app to react to events during the call through its delegate methods.

Light Color Skin
Copy
class MyClass: SendBirdCallDelegate {
    func didEnterRinging(_ call: DirectCall) { 
        call.delegate = self
    }
}

The callee’s client app receives an incoming call through either the established connection with SendBird server or PushKit if the app uses CallKit. To use the Calls SDK in the callee’s client app, the SendBirdCall instance must deliver received PushKit messages to the Calls SDK.

Light Color Skin
Copy
class AppDelegate: PKPushRegistryDelegate {
    func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) {
        SendBirdCall.pushRegistry(registry, didReceiveIncomingPushWith: payload, for: type)
    }
}

If a client app has CallKit implemented and propagates PushKit messages through the PKPushRegistryDelegate’s pushRegistry(:didReceiveIncomingPushWith:for:completion) method, incoming calls displayed by PushKit messages should be delivered to the DidStartRinging delegate method as shown below:

Light Color Skin
Copy
func didStartRinging(_ call: DirectCall) { 
    // IMPORTANT: An incoming call should be delivered to this delegate method when you receive a PushKit push message for the call.
    let provider = CXProvider(configuration: CXProviderConfiguration)
    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(type: .generic, value: HANDLE_VALUE)
    provider.reportNewIncomingCall(with: uuid, update: update) { (error) in
        completion()
    })
}

Handle a current call

Audio

During a current call, both the caller and callee’s audio can be muted or unmuted by the directCall.muteMicrophone() or directCall.unmuteMicrophone() method. If one party changes audio settings, the other party receives an event callback through the DirectCallDelegate.didRemoteAudioSettingsChange(_:) delegate method.

Light Color Skin
Copy
// Mute my microphone
call.muteMicrophone()
// Unmute my microphone
call.unmuteMicrophone()
class MyClass: SendBirdCallDelegate {
    func didRemoteAudioSettingsChange(_ call: DirectCall) {
        if (call.isRemoteAudioEnabled) {
            // The remote user has been unmuted. 
            // TODO: Update UI components Accordingly
             } else {
            // The remote user has been muted. 
            // TODO: Update UI components Accordingly
             }
         }
}

Video

During a current call, both the caller and callee’s video can be enabled or disabled by the directCall.startVideo() or directCall.stopVideo() method. If one party changes audio settings, the other party receives an event callback through the DirectCallDelegate.didRemoteVideoSettingsChange(_:) delegate method.

Light Color Skin
Copy
// Start my local video
call.startVideo()
// Stop my local video
call.stopVideo()
 
// receives the event
class MyClass: DirectCallDelegate {
    func didRemoteVideoSettingsChange(_ call: DirectCall) {
        if (call.isRemoteVideoEnabled) {
            // The remote user has started video.
        } else {
            // The remote user has ended video.
        }
    }
}

End a call

The directCall.end() method ends a current call of either the caller or callee’s side. If one party ends a current call, the other party receives an event callback through the DirectCallDelegate.didEnd() method.

Light Color Skin
Copy
// End a call
call.end();
 
// Receiving the end event
class MyClass: DirectCallDelegate {
    ...
    
    func didEnd(_ call: DirectCall) {
        // TODO: Update UI components Accordingly
    }

    ...
}

Retrieve call information

One party’s information can be retrieved through the directCall.getLocalUser() method while the other party’s information through the directCall.getRemoteUser() method.


Retrieve call history

A user’s call history can be retrieved using the next() method of a DirectCallLogListQuery instance which returns a list of call objects.

Light Color Skin
Copy
let params = DirectCallLogListQuery.Params()
params.myRole = .caller     // Filter for current user’s role in the call
params.endResultsArray = [.cancel, .decline, .complete]     // Filter for end results of the call
params.limit = 25       // Number of call logs to be returned at once. 
let query = SendBirdCall.createDirectCallLogListQuery(with: params)
 
if query.hasNext {
    query.next(completionHandler: { (callLogs, error) in
        // The query.next() can be called once more to fetch more call logs.
    }
}