Skip to content

Making an outgoing call 1.x

Marco Brescianini edited this page Aug 30, 2024 · 7 revisions

This guide will show you how to make an outgoing call with the BandyerSDK and how to present the call UI.

Table of contents:

Overview

Making an outgoing call with the BandyerSDK is a simple and straightforward process. It requires you to do make few simple steps in your code to setup the call and Bandyer will take care of the rest. From now on we are assuming you read the previous guides regarding the call client initialization and its life cycle. We are also assuming the Bandyer call client is started.

The steps required to place an outgoing call are the following:

  1. Start the call client and wait until it is running
  2. Create an intent containing the information needed to place the call
  3. Create or retrieve the call window
  4. Provide the intent to the call window

The BDKMakeCallIntent

In order to tell the SDK who you want to call you must create a BDKMakeCallIntent. You must provide this object the user aliases for the users you want to call, along with the options for the call that will take place. The most notable option you can provide to the BandyerSDK is the type of call you want to make.

There are three types supported:

typedef NS_ENUM(unsigned char, BDKCallType)
{
    BDKCallTypeAudioVideo = 0,
    BDKCallTypeAudioUpgradable,
    BDKCallTypeAudioOnly,
};
public enum BDKCallType : UInt8 {
    case audioVideo
    case audioUpgradable
    case audioOnly
}

The audioVideo option is the default setting. If you don't provide a call type the BandyerSDK will assume you want to start a video call.

The audioVideo call type, as the name suggests, will make the BandyerSDK start a video call. The audioOnly call type will make the BandyerSDK start a voice call which cannot be updated to a video call. The audioUpgradable call type, is a special call type which will start as a voice call and can be upgraded to a video call at any time by one of the call participants.

In the following code we are going to show you how to create a BDKMakeCallIntent:

@implementation MyViewController

- (void)startOutgoingCall:(NSArray<NSString *>*)callee
{
    BDKMakeCallIntent *intent = [BDKMakeCallIntent intentWithCallee:callee type:BDKCallTypeAudioVideo];
}

@end
class MyViewController: UIViewController {

    func startOutgoingCall(callee: [String]) {
	let intent = BDKMakeCallIntent(callee: callee, type: .audioVideo)
    }
}

The BDKMakeCallIntent provides some factory methods (initializers in swift) you can use to specify the call options you want to enable for your call. At the moment the options available, apart from the call type, are:

  • Recording
  • Maximum call duration

The former will tell our platform you want the call to be recorded. The latter will tell our platform the maximum number of seconds the call can last, when that threshold is exceeded the call will end automatically.

The BDKCallWindow

Once you created the intent for the call, it's time to create the window where the call user interface will be presented. Starting from version 1.2.0 we introduced a subclass of UIWindow named BDKCallWindow that will present the call UI in front of any content your app is displaying. This window will take care of creating and present a call view controller for you. In your code you need to do three things: create the call window (or retrieve it if you have created one already), provide the call window a configuration object, tell it to handle the previously created intent

The following code will show you these three steps:

@implementation MyViewController

//The call window instance must be created only once and kept alive keeping a reference to it
- (BDKCallWindow *)callWindow
{
    if (!_callWindow)
    {
	if (BDKCallWindow.instance)
	{
             _callWindow = BDKCallWindow.instance;
	} else
	{
             //This will automatically save the new instance inside BDKCallWindow.instance.
             _callWindow = [[BDKCallWindow alloc] init];
	}
	_callWindow.callDelegate = self;
    }

    return _callWindow;	
}

- (void)startOutgoingCall:(NSArray<NSString *>*)callee
{
    //First we create the view controller configuration object
    BDKCallViewControllerConfiguration *config = [BDKCallViewControllerConfiguration new];

    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"SIMULATOR MP4 VIDEO" ofType:@"mp4"]];
    config.fakeCapturerFileURL = url;
    
    //Then we set the configuration object on the call window   
    [self.callWindow setConfiguration:config];

    //We create the call intent
    BDKMakeCallIntent *intent = [BDKMakeCallIntent intentWithCallee:callee type:BDKCallTypeAudioVideo];

    //Finally, we present the call view controller on the window
    [self.callWindow presentCallViewControllerFor:intent completion:^(NSError * error) {
         if ([error.domain isEqualToString:BDKCallPresentationErrorDomain.value] && error.code == BDKCallPresentationErrorCodeAnotherCallOnGoing)
         {
              //Another call is already in progress...
         }
         else if (error)
         {
              //Configuration error...
          }
     }];
}

@end
class MyViewController: UIViewController {

    //The call window instance must be created only once and kept alive keeping a reference to it
    lazy var callWindow: CallWindow = {
        var window: CallWindow
	if CallWindow.instance != nil {
	    window = CallWindow.instance!
	} else {
	    window = CallWindow()
	}

	window.callDelegate = self
	return window
    }()
	
    func startOutgoingCall(callee: [String]) {
	
        //First we create the view controller configuration object
	let config = CallViewControllerConfiguration()
	let filePath = Bundle.main.path(forResource: "SIMULATOR MP4 VIDEO", ofType: "mp4")

	guard let path = filePath else {
             fatalError("The fake file for the file capturer could not be found")
	}
	
        config.fakeCapturerFileURL = URL(fileURLWithPath:path)
		
	//Then we set the configuration object on the call window
	callWindow.setConfiguration(config)
		
	//We create the call intent
	let intent = BDKMakeCallIntent(callee: callee, type: .audioVideo)
		
	//Finally, we present the call view controller on the window
	callWindow.presentCallViewController(for: intent) { error in
            guard let error = error else { return }
            
            switch error {
            case let presentationError as CallPresentationError where presentationError.errorCode == CallPresentationErrorCode.anotherCallOnGoing.rawValue:
                //Another call is already in progress...
            default:
                //Configuration error...
            }       
        }
    }
}

The code listing above shows you how to present and start an outgoing call along with the call user interface. It doesn't show you how to dismiss the call user interface once the call has ended. To do that you must register as the call window delegate and implement the required methods of the protocol. As you might have noticed, in the code listing above we registered as the call window delegate, when we lazily created the call window. The call window will call its delegate to inform it when important events have occurred, like the call interface must be dismissed or if the user has requested to open a chat with the user is performing the call. In the following code listing we implement the CallWindowDelegate, and we dismiss the window when it informs us it has finished handling the call.

@implementation MyViewController

- (BDKCallWindow *)callWindow
{
    if (!_callWindow)
    {
         if (BDKCallWindow.instance)
	 {
	     _callWindow = BDKCallWindow.instance;
	 } else
	 {
	     //This will automatically save the new instance inside BDKCallWindow.instance.
	     _callWindow = [[BDKCallWindow alloc] init];
	 }
		
	 //Here we are registering as the call window delegate
	 _callWindow.callDelegate = self;
    }

    return _callWindow;	
}

- (void)startOutgoingCall:(NSArray<NSString *>*)callee
{
    //....
}

#pragma mark - Call window delegate

- (void)callWindowDidFinish:(BDKCallWindow *)window
{
    self.callWindow.hidden = YES;
}

- (void)callWindow:(BDKCallWindow *)window openChatWith:(BCHOpenChatIntent *)intent
{
    NSLog(@"Open chat with intent %@", intent);
}

@end
class MyViewController: UIViewController {

    //The call window instance must be created only once and kept alive keeping a reference to it
    lazy var callWindow: CallWindow = {
        var window: CallWindow
	if CallWindow.instance != nil {
	    window = CallWindow.instance!
	} else {
	    window = CallWindow()
	}
	
        window.callDelegate = self
	return window
    }()
	
    func startOutgoingCall(callee: [String]) {
	// .....
    }
}

extension MyViewController: CallWindowDelegate {
    func callWindowDidFinish(_ window: CallWindow) {
        window.isHidden = true
    }

    func callWindow(_ window: CallWindow, openChatWith intent: OpenChatIntent) {
    	print("Open chat with intent \(intent)")
    }
}

That's it! the steps you've seen are the only steps required to make an outgoing call.

Where to go from here

The next guide Receiving an incoming call will show you how to receive an incoming call. Also, if you haven't already, we suggest you to take a look at our sample apps (objective-c swift) to see how to make an outgoing call in a real app.

What's next

Clone this wiki locally