Suggestions

close search

Add Messaging, Voice, and Authentication to your apps with Vonage Communications APIs

Visit the Vonage API Developer Portal

Back to Tutorials

Set up a Basic iOS Client (Objective-C)

This tutorial will walk you through the steps of setting up a basic iOS client that uses the Vonage Video API.

Overview

All applications that use the Vonage Video API require both a client and a server component. The client-side code is what loads in an end-user's iOS device and handles the majority of OpenTok functionality, including connecting to the session, publishing audio-video streams to the session, and subscribing to other clients’ streams. For more information on clients, servers, and sessions, see Video API Basics.

In this tutorial, you will be utilizing the OpenTok iOS SDK, OpenTok's client-side library for iOS devices, to quickly and easily build a real-time interactive video application.

Note: The code in this tutorial is written in Objective-C. There is also a tutorial with the code written in Swift.

Here are the items that will be covered in this tutorial:


Estimated completion time: 25 mins

Want to skip this tutorial? You can jump to the completed iOS Objective-C client code in the Basic-Video-Chat folder of our iOS sample app repo on GitHub. The repo includes a README with documentation for running and exploring the code.

Requirements

To complete this tutorial, you'll need:

Step 1: Creating a new project

  1. Open Xcode and create a new project.

  2. Select Single View Application as the template.

  3. Select Objective-C as the language for the app code.

Step 2: Adding the OpenTok library

Follow the steps below to use CocoaPods to add the OpenTok library and its dependencies to your app. If you would prefer not to use CocoaPods, follow these instructions for using the SDK.

  1. In the Terminal, navigate to the root directory of your project and enter the following:

    pod init

    This creates a Podfile at the root of your project directory.

  2. Edit the Podfile and add the following line after the comment that says # Pods for [YourProjectName] (The podfile will not be visible in your XCode project, so you will need to open it from the project folder directly):

    pod 'OpenTok'
  3. Save changes to the Podfile.

  4. In the Terminal, in your project root directory type:

    pod install
  5. Close your project in Xcode. Then reopen your project by double-clicking the new .xcworkspace file in the Finder (in the root directory of your project).

For camera and microphone access you need to modify the Info.plist file:

  1. In the lefthand navigator panel in Xcode, click the project file (with the name of your project) to open the center project panel.

    To the left of the General tab in the project panel, you should see your project name. If the name is something different from your project (such as [YourProjectName]Tests), click on it and set the target to your project name.

  2. Inside the panel, switch to the Info tab.

  3. Expand the Custom iOS Target Properties section if it’s collapsed

  4. Mouse over any key and click the + button to add a new key. Add a Privacy - Camera Usage Description key and assign it the following string:

    $(PRODUCT_NAME) uses the camera.

    Then click the + button to add a new Privacy - Microphone Usage Description key and assign it the following string:

    $(PRODUCT_NAME) uses the microphone.

    The app displays these strings when the application first accesses the camera and microphone.

    (These security features were added in iOS 10.)

Add the OpenTok library to the view controller.

Step 3: Setting up authentication

In order to connect to an OpenTok session, the client will need access to some authentication credentials — an API key, session ID, and token. In a production application, these credentials should be generated by a server, but to speed things up we will just hard code the values for now:

  1. Start by copying the following code block and adding it to your ViewController.m file:

    // Replace with your OpenTok API key
    static NSString* kApiKey = @"";
    // Replace with your generated session ID
    static NSString* kSessionId = @"";
    // Replace with your generated token
    static NSString* kToken = @"";
    

    Add these lines before the @interface declaration.

  2. Adjust the code by hard coding the values for the kApiKey, kSessionId and kToken (inside the empty quotation marks).

    To do this, log into your Video API account, either create a new OpenTok API project or use an existing OpenTok API project, then go to your project page and scroll down to the Project Tools section. From there, you can generate a session ID and token manually. Use the project's API key along with the session ID and token you generated.

Important: You can continue to get the session ID and token values from your Account during testing and development, but before you go into production you must set up a server. We will discuss this in Next steps at the end of this tutorial.

For more information on sessions, tokens, and servers, check out Video API Basics.

Step 4: Connecting to the session

Next, we will connect to the OpenTok session. You must do this before you can publish your audio-video stream to the session or view other participants streams.

  1. Add a session property to the ViewController class:

    @interface ViewController()
    @property (nonatomic) OTSession *session;
    @end
    

    The OTSession class is defined in the OpenTok iOS SDK. It represents an OpenTok session and includes methods for interacting with the session.

  2. Add a method to instantiate the OTSession object and call its [OTSession connectWithToken: error:] method. Then you can call it in viewDidLoad:

    - (void)viewDidLoad {
        [super viewDidLoad];
        [self connectToAnOpenTokSession];
    }
    
    - (void)connectToAnOpenTokSession {
        _session = [[OTSession alloc] initWithApiKey:kApiKey sessionId:kSessionId delegate:self];
    
        NSError *error;
        [_session connectWithToken:kToken error:&error];
        if (error) {
            NSLog(@"%@", error);
        }
    }
    

    The [OTSession initWithApiKey:sessionId:delegate:] method takes three parameters:

    • Your OpenTok API key
    • The session ID
    • The object that implements the OTSessionDelegate protocol

    The [OTSession connectWithToken: error:] method connects the client application to the OpenTok session. You must connect before sending or receiving audio-video streams in the session (or before interacting with the session in any way). The method takes two parameters:

    • token is the authentication token for this client to connect to the OpenTok session.

    • error is set to an OTError object if an error occurs synchronously when calling the method.

  3. Change the ViewController interface declaration to indicate that the class implements the OTSessionDelegate protocol:

    @interface ViewController() <OTSessionDelegate>
    

    Next we will implement methods of the OTSessionDelegate protocol. Add the following code to the end of the ViewController class (before the class's @end statement):

    # pragma mark - OTSession delegate callbacks
    
    - (void)sessionDidConnect:(OTSession*)session
    {
       NSLog(@"The client connected to the OpenTok session.");
    }
    
    - (void)sessionDidDisconnect:(OTSession*)session
    {
       NSLog(@"The client disconnected from the OpenTok session.");
    }
    
    - (void) session:(OTSession*)session
    didFailWithError:(OTError*)error
    {
       NSLog(@"The client failed to connect to the OpenTok session: (%@)", error);
    }
    
    - (void)session:(OTSession*)session
     streamCreated:(OTStream *)stream
    {
       NSLog(@"A stream was created in the session.");
    }
    
    - (void)session:(OTSession*)session
    streamDestroyed:(OTStream *)stream
    {
       NSLog(@"A stream was destroyed in the session.");
    
    }
    

    This protocol includes methods for handling events related to the session:

    • When the client connects to the OpenTok session, the [OTSessionDelegate sessionDidConnect:] message is sent.

    • If the client fails to connect to the OpenTok session, the [OTSessionDelegate session:didFailWithError:] message is sent.

    • When the client disconnects from the OpenTok session, the [OTSessionDelegate sessionDidDisconnect:] message is sent.

    • When another client publishes a stream to the OpenTok session the [OTSessionDelegate session:streamCreated:] message is sent.

    • When another client stops publishing a stream to the OpenTok session the [OTSessionDelegate session:streamDestroyed:] message is sent.

    For now, the app prints to the debugger console when any of these events occur.

Debug your application. If the app successfully connects to the OpenTok session, the the [OTSessionDelegate sessionDidConnect:] method should print to the debug console.

Step 5: Publishing a stream to the session

When the app connects to the OpenTok session, we want it to publish an audio-video stream to the session, using the device's camera and microphone:

  1. Add a publisher property to the ViewController class:

    @interface ViewController() <OTSessionDelegate>
    @property (nonatomic) OTSession *session;
    @property (nonatomic) OTPublisher *publisher;
    @end
    

    The OTPublisher class is defined in the OpenTok iOS SDK. It uses the device's camera and microphone, to publish a stream OpenTok session.

  2. Modify the implementation of the sessionDidConnect(_:) method to include code to publish a stream to the session:

    - (void)sessionDidConnect:(OTSession*)session
    {
       OTPublisherSettings *settings = [[OTPublisherSettings alloc] init];
       _publisher = [[OTPublisher alloc]
                     initWithDelegate:self
                     settings:settings];
    
       OTError *error = nil;
       [_session publish:_publisher error:&error];
       if (error)
       {
           NSLog(@"Unable to publish (%@)", error.localizedDescription);
           return;
       }
    
       CGSize screenSize = [UIScreen mainScreen].bounds.size;
       CGRect rect = CGRectMake(screenSize.width - 150 - 20, screenSize.height - 150 - 20, 150, 150);
       [_publisher.view setFrame:rect];
       [self.view addSubview:_publisher.view];
    }
    

    When the app connects to a session, it initializes an instance of the OTPublisher, defined in the OpenTok iOS SDK. The [OTPublisher initWithDelegate:] method takes two parameters: the object that implements the OTPublisherDelegate protocol and a settingsobject.

    The code then passes the OTPublisher object in as a parameter of the [OTSession publish:] method. This method publishes an audio-video stream to the OpenTok session, using the camera and microphone of the iOS device. (Note that in the Xcode simulator, the OpenTok iOS SDK uses a test video when publishing a stream.)

    The OTPublisher object has a view property, which is a UIView object. This view displays the video captured from the device's camera. The code adds this view as a subview of the main ViewController's view.

  3. Change the ViewController interface declaration to indicate that the class implements the OTPublisherDelegate protocol:

    @interface ViewController() <OTSessionDelegate, OTPublisherDelegate>
    

    Next we will implement methods of the OTSessionDelegate protocol. Add the following code to the end of the ViewController class (before the class's @end statement):

    # pragma mark - OTPublisher delegate callbacks
    - (void)publisher:(OTPublisherKit*)publisher
    didFailWithError:(OTError*) error
    {
       NSLog(@"The publisher failed: %@", error);
    }
    

    If the client fails to publish to the OpenTok session, an OTError object is passed into the [OTPublisherDelegate publisher:didFailWithError:] method.

Debug your application. If the app successfully connects to the OpenTok session, it will publish a stream to the session, and you will see the publisher's video in the app.

Step 6: Subscribing to other clients' streams

Finally, we want clients to be able to subscribe to (or view) other clients' streams in the session:

  1. Add a subscriber property to the ViewController class:

    @interface ViewController() <OTSessionDelegate, OTPublisherDelegate>
    @property (nonatomic) OTSession *session;
    @property (nonatomic) OTPublisher *publisher;
    @property (nonatomic) OTSubscriber *subscriber;
    @end
    

    The OTSubscriber class is defined in the OpenTok iOS SDK. It uses the device's camera and microphone, to subscribe a stream OpenTok session.

  2. Modify the implementation of the [OTSessionDelegate session: streamCreated] method (one of the OTSessionDelegate callbacks) to include code to subscribe to other clients' streams the session:

    - (void)session:(OTSession*)session
    streamCreated:(OTStream *)stream
    {
        _subscriber = [[OTSubscriber alloc] initWithStream:stream
                                                delegate:self];
        OTError *error = nil;
        [_session subscribe:_subscriber error:&error];
        if (error)
        {
            NSLog(@"Unable to subscribe (%@)", error.localizedDescription);
            return;
        }
        [_subscriber.view setFrame:[UIScreen mainScreen].bounds];
        [self.view insertSubview:_subscriber.view atIndex:0];
    }
    

    When another client publishes a stream to a session, this method is called, and an OTStream object is passed in. The OTStream class is defined in the OpenTok iOS SDK, and it represents an audio-video stream in the OpenTok session. The code initializes an instance of the OTSubscriber class, defined in the OpenTok iOS SDK. The OTSubscriber() constructor takes two parameters: The OTStream object (for the stream you want to view) and the object that implements the OTSubscriberDelegate protocol.

  3. Change the ViewController interface declaration to indicate that the class implements the OTSubscriberDelegate protocol:

    @interface ViewController() <OTSessionDelegate, OTPublisherDelegate,OTSubscriberDelegate>
    

    Next we will implement methods of the OTSessionDelegate protocol. Add the following code to the end of the ViewController class (before the class's @end statement):

    # pragma mark - OTSubscriber delegate callbacks
    - (void)subscriberDidConnectToStream:(OTSubscriberKit *)subscriber {
        NSLog(@"The subscirber: %@ did connect to the stream", subscriber);
    }
    
    - (void)subscriber:(OTSubscriberKit*)subscriber
     didFailWithError:(OTError*)error
    {
       NSLog(@"subscriber %@ didFailWithError %@",
             subscriber.stream.streamId,
             error);
    }
    
    • If the client fails to connect to the OpenTok session, an OTError object is passed into the subscriber(_: didFailWithError:) method.

Step 7: Running the app

Now that your code is complete, you can run the app in the XCode emulator. This will create a simulated publisher video — since the emulator cannot access your webcam, the publisher video will display a spinning teapot graphic instead of your camera feed.

To add a second publisher (which will display as a subscriber in your emulator), either run the app a second time in a connected iOS device or use the OpenTok Playground to connect to the session in a supported web browser by following the steps below:

  1. Go to OpenTok Playground (must be logged into your Account)

  2. Select the Join existing session tab

  3. Copy the session ID you used in your ViewController.m file and paste it in Session ID input field

  4. Click Join Session

  5. On the next screen, click Connect, then click Publish Stream

  6. You can adjust the Publisher options (not required), then click Continue to connect and begin publishing and subscribing

At this point you should see the stream being published from your webcam as well as the stream being published by the emulator. Returning to the emulator, you should also see the new publisher displayed on the emulated screen.

Congratulations! You've finished the 'Set up a Basic iOS Client (Objective-C)' tutorial.
You can continue to play with and adjust the code you've developed here for the client-side of your application, but keep in mind that you'll need to implement the server component of your application before going to production (see Setting up your server below).

You can view a completed version of this sample app in the Basic-Video-Chat folder of the opentok-ios-sdk-samples repo on GitHub. This completed version adds code to load the session ID, token, and API key from a web service (instead of using hard coded values).

Setting up your server

In the tutorial above, we had you hard code your authentication credentials. However, for a production application, the sessionId and token values in your code must be generated by your app server and passed to the client. Here are a couple of reasons why you don't want hard coded credentials in your production app:

You can continue testing your application with hard coded values, but when you're ready to set up a server there are a number of ways to do so:

Server Option 1 — Launch a simple REST server on Heroku with one click

This is probably the fastest way to get a server up and running, but it has limited functionality. Simply click the Heroku button below, at which point you'll be sent to Heroku's website and prompted for your OpenTok API Key and API Secret — you can get these values on your project page in your Video API account. If you don't have a Heroku account, you'll need to sign up (it's free).

Deploy

Want to explore the code? The button above launches server code from the learning-opentok-php GitHub repo. Visit the repo to review the code as well as additional documentation — you can even fork the repo and make changes before deploying.

Prefer Node.js? Visit the learning-opentok-node repo for the same functionality using Node.js (including Heroku deploy button.)

Once the server is deployed on Heroku, you'll need to add a few lines to your client-side code. Instead of calling connectToAnOpenTokSession directly, you'll need to make a networking call to the path /session on your server to fetch valid OpenTok credentials first.

Copy the following code and use it to replace viewDidLoad in your ViewController.m file:

- (void)viewDidLoad {
  [super viewDidLoad];

  NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
  NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
  NSURL *url = [NSURL URLWithString:<#https://YOURAPPNAME.herokuapp.com/session#>];
  NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

      if (!error) {
          NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
          kApiKey = dict[@"apiKey"];
          kSessionId = dict[@"sessionId"];
          kToken = dict[@"token"];
          [self connectToAnOpenTokSession];
      }
      else {
          NSLog(@"%@", error);
      }
  }];
  [dataTask resume];
  [session finishTasksAndInvalidate];
}

You'll need to replace https://YOURAPPNAME.herokuapp.com with your actual Heroku app url — you can find this on your app page on the Heroku website.

The code above makes a request to the /session endpoint (https://YOURAPPNAME.herokuapp.com/session), which should return an HTTP response that includes the session ID, the token, and API key formatted as JSON data, which is then assigned to the corresponding variables.

This /session endpoint will always return the same session ID, but will produce a new token each time it's called — this results in each client receiving a unique token.

Server Option 2 — Build from scratch using the server SDKs

Option 1 uses REST endpoints for transmitting credentials to the client, but that's only one of many ways to implement a server with OpenTok. If you want a greater level of customization, you can review OpenTok's Server SDK documentation for the server-side language of your choice (available for PHP, Node.js, Java, .NET, Python and Ruby). The documentation goes over the setup process and the various methods you'll need to generate sessions and tokens, as well as other server-side functionality.