Initializing

This document explains how to integrate the Dolby Interactivity APIs Client SDK into your application. If you use UI components, please refer to the Client UXKit.

Prerequisites

Before using the SDK in your project, find your Consumer Key and Consumer Secret by following these steps:

  1. Select the SIGN IN link located in the upper right corner of the Dolby.io page. Log in using your email and password.
  2. Click the DASHBOARD link visible in the upper right corner of the website.
  3. Select your application from the APPLICATIONS category located on the left side menu.
  4. Select the API Keys category from the drop-down menu visible under your application.
  5. In the Interactivity APIs section, you can access your Consumer Key and Consumer Secret.

Add the SDK into your application

  • JavaScript
  • JavaScript Browser
  • Swift
  • Java

Add the voxeet-web-sdk by using yarn or npm command as in the following example:

npm i @voxeet/voxeet-web-sdk
yarn add @voxeet/voxeet-web-sdk

Add this command inside your HTML file to access the Dolby Interactivity APIs Web SDK.

<script
  src="https://unpkg.com/@voxeet/voxeet-web-sdk@Version"
  type="text/javascript"
></script>

With Carthage dependency manager:

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate Dolby Interactivity APIs iOS SDK into your Xcode project using Carthage, specify it in your Cartfile:

binary "https://raw.githubusercontent.com/voxeet/voxeet-sdk-ios/master/VoxeetSDK.json" ~> 2.0

Run carthage update to build the frameworks and drag VoxeetSDK.framework and WebRTC.framework into your Xcode project. For more information, see: https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos.

Or download the lastest release zip:

VoxeetSDK: https://github.com/voxeet/voxeet-sdk-ios/blob/master/VoxeetSDK.json

Unzip and drag and drop frameworks into your project, select 'Copy items if needed' with the right target. Then in the general tab of your target, add the VoxeetUXKit.framework, VoxeetSDK.framework and WebRTC.framework into 'Embedded Binaries'.

Add the public-sdk in the dependencies block of your app's build.gradle

compile("com.voxeet.sdk:public-sdk:${voxeetSdkVersion}") {
    transitive = true
}

Where voxeetSdkVersion is the latest version of the SDK.

Initialize the SDK with secure authentication

There are two ways to initialize the SDK. You can either use the recommended secure authentication method or simply embed the app secrets in the app and call the initialize method. For security reasons Dolby recommends the secure authentication method in production; the simpler method is suitable for prototyping of the app.

This section describes how to use the secure method.

The Dolby Interactivity APIs provide an easy to use server-side RESTful API that allows customers’ servers to act as brokers that refresh tokens, so the application secrets are not distributed over the Internet.

The following diagram illustrates the workflow of the secure authentication model.

Secure Auth Sequence

Customer’s server

A sample server can be found within the voxeet-io-web repository. The README file explains how to run the server with the secrets for your application.

The examples shown use the API presented by the sample server for communication between the application and the server. The examples assume that this communication is secure and the application is trusted. In a real service, the application’s user would need to log into this server.

Initial authentication

The customer’s server, acting as an authentication broker, needs the application key and secret to authenticate against the /oauth2/token API. The access token is returned and the customer’s server passes it back to the application. Upon receiving the access token from the customer’s server, the application calls the initializeToken API to initialize the Dolby Interactivity APIs Client SDK.

The customer’s server can request the access token with:

let consumerKey = "consumerKey"
let consumerSecret = "consumerSecret"
let authHeader =
  "Basic " + btoa(encodeURI(consumerKey) + ":" + encodeURI(consumerSecret))

let tokenURL = "https://session.voxeet.com/v1/oauth2/token"
let tokenParams = {
  method: "POST",
  headers: {
    Authorization: authHeader,
  },
  body: {
    grant_type: "client_credentials",
  },
}

var access_token

fetch(tokenURL, tokenParams)
  .then(data => {
    return data.json()
  })
  .then(result => {
    access_token = result.access_token
    // Return the access_token to the application

    console.log(`returned access_token is ${result.access_token}`)
  })

When the application has received the access token from the customer’s server, it can initialize the SDK with:

  • JavaScript
  • JavaScript Browser
  • Swift
  • Java

fetch(serverURL + '/api/token')
    .then(data => { return data.json() })
    .then(result => {
        access_token = result.access_token

        VoxeetSDK.initializeToken(access_token, () => {
            // This callback is called when the token needs to be refreshed. See the next section for details.
            ...
        }).catch(error => {
            // An Error has occured
        })
    })

fetch(serverURL + '/api/token')
    .then(data => { return data.json() })
    .then(result => {
        access_token = result.access_token

        VoxeetSDK.initializeToken(access_token, () => {
            // This callback is called when the token needs to be refreshed. See the next section for details.
            ...
        }).catch(error => {
            // An Error has occured
        })
    })

import VoxeetSDK

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func fetchToken(completion: @escaping (_ token: String?) -> Void) {
        let url = URL(string: serverURL + "/api/token")!
        let task = URLSession.shared.dataTask(with: url) { data, _, _ in
            if let data = data,
              let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
              let accessToken = json["access_token"] as? String {
                completion(accessToken)
            } else {
                completion(nil)
            }
        }
        task.resume()
    }

    func application(
        application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        // Fetch access token.
        fetchToken { accessToken in
            guard let token = accessToken else { return }

            // Voxeet SDK OAuth initialization.
            VoxeetSDK.shared.initialize(accessToken: token) { refreshClosure in
                // VoxeetSDK calls this closure when the token needs to be refreshed.
                // See the next section for details.
            }
        }

        return true
    }
}

String url = serverURL + "/api/token";

JsonObjectRequest fetchRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            VoxeetSDK.initialize(token, (refreshClosure) -> {
                // VoxeetSDK calls this closure when the token needs to be refreshed. See the next section for details.
            })
        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            // TODO: Handle error

        }
    }
);

// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(fetchRequest);

Refresh authentication

An access token has a limited period of validity and needs periodic refreshing. In the application, the Dolby Interactivity APIs Client SDK invokes the callback provided to the initialize call when the access token needs to be refreshed. This callback contacts the customer’s server, which in turn calls the /oauth2/token API again and returns the refreshed token, which is passed back to the Client SDK by the application.

When the application has received the refreshed access token from the customer’s server, it can pass this to the SDK with this change:

  • JavaScript
  • JavaScript Browser
  • Swift
  • Java

The callback to VoxeetSDK.initializeToken must return a Promise containing the refreshed access token:

    ...
    VoxeetSDK.initializeToken(accessToken, () => {
        // This callback is called when the token needs to be refreshed.

        // Call the server to get the refreshed token
        fetch(serverURL + '/api/token')
            .then(data => { return data.json() })
            .then(result => {
                access_token = result.access_token
                return access_token
            })
    }).catch(error => {
        // An Error has occured
    })

The callback to VoxeetSDK.initializeToken must return a Promise containing the refreshed access token:

    ...
    VoxeetSDK.initializeToken(accessToken, () => {
        // This callback is called when the token needs to be refreshed.

        // Call the server to get the refreshed token
        fetch(serverURL + '/api/token')
            .then(data => { return data.json() })
            .then(result => {
                access_token = result.access_token
                return access_token
            })
    }).catch(error => {
        // An Error has occured
    })

The last parameter passed to VoxeetSDK.initialize(accessToken:refreshTokenClosure:) is a closure that is called when the token needs to be refreshed. This closure is passed a single parameter, which is a VoxeetSDK closure, which the application calls with the refreshed access token:

import VoxeetSDK

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    ...

    func application(
        application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        // Fetch access token.
        fetchToken { accessToken in
            guard let token = accessToken else { return }

            // Voxeet SDK OAuth initialization.
            VoxeetSDK.shared.initialize(accessToken: token) { refreshClosure in
                // VoxeetSDK calls this closure when the token needs to be refreshed.
                fetchToken { accessToken in
                    guard let token = accessToken else { return }

                    // Call the SDK’s refresh closure with the new token
                    refreshClosure(token)
                }
            }
        }

        return true
    }
}

JsonObjectRequest fetchRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            VoxeetSDK.initialize(token, (refreshClosure) -> {
                // VoxeetSDK calls this closure when the token needs to be refreshed.
                // Call the SDK’s refresh closure with the new token
                refreshClosure(token);
            })
        }
    }, new Response.ErrorListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            // TODO: Handle error

        }
    }
);

Open a session

  • JavaScript
  • JavaScript Browser
  • Swift
  • Java

Open a session for the participant using the following code:

/* Example of participantInfo */
VoxeetSDK.session.open({ name: "John Doe" })

Open a session for the participant using the following code:

/* Example of participantInfo */
VoxeetSDK.session.open({ name: "John Doe" })

Open a session for the participant using the following code:

let info = VTParticipantInfo(externalID: nil, name: "Username", avatarURL: nil)
VoxeetSDK.shared.session.open(info: info) { error in }

Open a session for the user using the following code:

ParticipantInfo participantInfo = new UserInfo("a name", "optionnal id", "optionnal https avatar url");

VoxeetSDK.session().open(participantInfo).then(new PromiseExec<Boolean, Object>() {
    @Override
    public void onCall(@Nullable Boolean result, @NonNull Solver<Object> solver) {
        //insert your logic
    }
}).error(error());

Note: You can cascading promises

Close a session

  • JavaScript
  • JavaScript Browser
  • Swift
  • Java

After the conference, you can close it using the following code:

VoxeetSDK.session.close()

After the conference, you can close it using the following code:

VoxeetSDK.session.close()

After the conference, you can close it using the following code:

Example

VoxeetSDK.shared.session.close { error in }

After the conference, you can close it using the following code:

VoxeetSDK.session().close().then(new PromiseExec<Boolean, Object>() {
    @Override
    public void onCall(@Nullable Boolean result, @NonNull Solver<Object> solver) {
        //insert your logic
    }
}).error(error());

Note: You can cascading promises