LiveLike

The LiveLike Developer Hub

Welcome to the LiveLike developer hub. You'll find comprehensive guides and documentation to help you start working with LiveLike as quickly as possible, as well as support if you get stuck. Let's jump right in!

Get Started    

Getting Started

Get a basic integration up and running with the iOS SDK

This is a developers' guide for setting up a LiveLike SDK configuration for native iOS apps. We will take you through the basic technical steps for configuration and show you how to send your first widgets and chat messages. We will also provide detailed samples and instructions for a complete LiveLike integration.

Prerequisites

πŸ“˜

Even though this guide makes use of both the chat and widget components, if desired it is possible to use only one of the components.

Installation

The SDK can be installed through package managers like Carthage or Cocoapods.

Carthage

Carthage distribution of the Engagement SDK is hosted on a private repository. You will need to provide LiveLike with your Bitbucket username and we will grant you access.

https://github.com/Carthage/Carthage#adding-frameworks-to-an-application

Add the following to a Cartfile:

git "[email protected]:livelike/livelike-ios-sdk.git" ~> 1.0

and then run in the Terminal

carthage update --platform iOS

Follow the instructions in the β€œIf you’re building for iOS” section of the Carthage README adding the following text to the xcfilelists mentioned therein:

$(SRCROOT)/Carthage/Build/iOS/EngagementSDK.framework
$(SRCROOT)/Carthage/Build/iOS/PubNub.framework
$(SRCROOT)/Carthage/Build/iOS/Lottie.framework
$(SRCROOT)/Carthage/Build/iOS/Mixpanel.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/EngagementSDK.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/PubNub.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Lottie.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Mixpanel.framework

CocoaPods

https://guides.cocoapods.org/using/using-cocoapods.html

Add the following to a Podfile:

target '<application-target-name>' do
    use_frameworks!
    pod 'EngagementSDK'
end

Initialization

For this step, you will need your Client ID to initialize the Engagement SDK. To get your ClientID, follow the instructions in Retrieving your Client ID.

Import the EngagementSDK:

import EngagementSDK

Next, create an instance of the EngagementSDK. We recommend that you create the EngagementSDK instance as early as possible for your application (for example, in the application:didFinishLaunchingWithOptions: method of the AppDelegate).

🚧

Concurrent instances of the EngagementSDK are not supported; only one instance should exist at any given time.

Use your Client ID to create a EngagementSDKConfig. The EngagementSDKConfig is used to initialize the EngagementSDK.

class AppDelegate: UIResponder, UIApplicationDelegate {
  var engagementSDK: EngagementSDK!
  
  func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 
    var config = EngagementSDKConfig(clientID: "<your-client-id>")
    engagementSDK = EngagementSDK(config: config)  
    return true
  }
}

❗️

Considerations for Monthly Active User (MAU) Count

An Access Token is the unique identifier for a user and will be used to calculate the MAU of your application. We highly recommend that you override where a user's Access Token is stored to manage persistence across app installs and platforms.

By default, the EngagementSDK will fetch and store a user's Access Token in User Defaults. If an Access Token is not found we will create a new one which will count towards you MAU.

Override the Access Token storage

  1. Implement AccessTokenStorage protocol
  2. Set EngagementSDKConfig().accessTokenStorage to AccessTokenStorage implementation
class AppDelegate: UIResponder, UIApplicationDelegate {
  var engagementSDK: EngagementSDK!
  
  func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    var config = EngagementSDKConfig(clientID: "<your-client-id>")
    
    // Recommended to implement your own AccessTokenStorage for user persistence
    // By default the user access token will be stored in UserDefaults if not set
    config.accessTokenStorage = self
    
    engagementSDK = EngagementSDK(config: config)
    
    return true
  }
}

extension AppDelegate: AccessTokenStorage {
  func fetchAccessToken() -> String? {
    // fetch an access token from your local storage or server
    // if nil the EngagementSDK will generate a new access token
    return "<users-access-token>"
  }
  
  func storeAccessToken(accessToken: String) {
    // called when the EngagementSDK generates a new accessToken
    // store the generated token in your local storage or server for user persistence
  }
}

Configure Your Layout

Now you have to configure your live video screen layout and declare containers for the Engagement SDK Widget and Chat views to live inside.

πŸ“˜

Even though this guide makes use of both the chat and widget components, if desired it is possible to use only one of the components.

The first step is to add two UIViews to your view layout to serve as containers for the Engagement SDK's Widget and Chat view. Regardless of whether you use Storyboards or Programmatic UI, please follow the steps that work best for your application.

Storyboards - If you are using storyboards then you need to add two UIViews to your view hierarchy for Widget and Chat. Add any constraints for managing the size and position of the subviews. Then, create and hook up an @IBOutlet in your ViewController for each view called widgetView and chatView.

🚧

If you are working in a multilayered UIView environment where the widgetView is placed above the chatView. It is best practice to instantiate the widgetView as PassthroughView. This will allow user interactions on widgetView effect the chatView when there are no activate widgets.

Programmatic - If you are using programmatic UI, you need to instantiate two UIViews called widgetView and chatView. Add them as subviews to your ViewController's view. Add any constraints for managing the size and position of the subviews.

Then, in your ViewController, create an instance of WidgetViewController and ChatViewController

🚧

Important: The width of the Widget view must be at least 260 and height 280. The width of the Chat view must be at least 292.

class ViewController: UIViewController {
    @IBOutlet var widgetView: UIView!
    @IBOutlet var chatView: UIView!

    let widgetViewController = WidgetViewController()
    let chatViewController = ChatViewController()
}

Finally, you need to add the WidgetViewController and ChatViewController as a child view controller to your ViewController. For more information on child view controllers see Apple documentation on Implementing a ContainerViewController.

In the viewDidLoad method add the following:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Add widgetViewController as child view controller  
    addChild(widgetViewController)
    widgetView.addSubview(widgetViewController.view)
    widgetViewController.didMove(toParent: self)

    // Apply constraints to fill the widgetView container
    widgetViewController.view.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        widgetViewController.view.bottomAnchor.constraint(equalTo: widgetView.bottomAnchor),
        widgetViewController.view.topAnchor.constraint(equalTo: widgetView.topAnchor),
        widgetViewController.view.trailingAnchor.constraint(equalTo: widgetView.trailingAnchor),
        widgetViewController.view.leadingAnchor.constraint(equalTo: widgetView.leadingAnchor)
    ])

    // Add chatViewController as a child view controller
    addChild(chatViewController)
    chatView.addSubview(chatViewController.view)
    chatViewController.didMove(toParent: self)

    // Apply constraints to fill the chatView container
    chatViewController.view.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        chatViewController.view.bottomAnchor.constraint(equalTo: chatView.bottomAnchor),
        chatViewController.view.topAnchor.constraint(equalTo: chatView.topAnchor),
        chatViewController.view.trailingAnchor.constraint(equalTo: chatView.trailingAnchor),
        chatViewController.view.leadingAnchor.constraint(equalTo: chatView.leadingAnchor)
    ])
}

Start a Content Session

A Content Session represents a user's subscription to a particular ProgramProgram - A time-ordered sequence of widgets. A program can have extra information attached, like scheduling data and video preview URL for aiding in producing the program in the Producer Site. A widget can only be published to a single program, and only subscribers to a given program will see its widgets. (typically a live, linear TV show, game or episode). To start a Content Session you will need a Program ID. You will need to create programs within the LiveLike system, either through the API or through the Producer Suite (see Getting Started with the Producer Suite). You should then copy the Program IDs into the relevant media metadata in your own systems, so that content sessions can be started along with media playback.

Use the following resources to get started with the Producer Suite

In your ViewController, declare a variable to maintain an instance of the ContentSession we will be creating.

🚧

Important: A reference to the ContentSession instance must be maintained in order for the session to remain valid and receive Widget and Chat events.

class ViewController: UIViewController {
    @IBOutlet var widgetView: UIView!
    @IBOutlet var chatView: UIView!

    let widgetViewController = WidgetViewController()
    let chatViewController = ChatViewController()

    var session: ContentSession?
}

Now call the contentSession method of your instance of the EngagementSDK - passing in your Program ID. This will return a ContentSession object. You must store this in the ContentSession variable declared earlier.

Assign the ContentSession to the WidgetViewController so the user can begin receiving widgets published from the CMS.

Assign the ContentSession to the ChatViewController so the user will also be able to participate in the chat room.

func startContentSession(engagementSDK: EngagementSDK) {
    let config = SessionConfiguration(programID: "<program-id>")
    session = engagementSDK.contentSession(config: config)
    widgetViewController.session = session
    chatViewController.session = session
}
- (*void*)startContentSession: (LLEngagementSDK*)engagementSDK {
    LLSessionConfiguration *config = [[LLSessionConfiguration alloc] initWithProgramID:@"<program-id>"];                  
    id<LLContentSession> session = [engagementSDK contentSessionWithConfig:config];
    self.session = session;
    chatViewController.session = session;
    widgetViewController.session = session;
}

Pause a Content Session

Content Sessions can be paused to temporarily ignore all incoming Widgets and Chat messages until resumed. This needs to be done whenever the app loses focus. It can also be useful in other scenarios, for example, if you need to display an advertisement without overlay from the Engagement SDK.

//Pause
session?.pause()

//Resume
session?.resume()

❗️

Important

Please call ContentSession.pause() when the user has backgrounded your application and then call ContentSession.resume() when the user has returned your application to foreground.

This is to ensure that the application does not receive, and is not charged for, chat and widgets while it is not in view. For more information see Managing Your App's Life Cycle.

Close a Content Session

When the user returns to your application's home page and away from your live video screen you will want to close the ContentSession. Closing a session will disconnect from Widgets and Chat and release all the related resources.

πŸ“˜

You can also set the session reference to nil, this is the same as calling close

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    self.session?.close()
    //or
    self.session = nil
}

Sample Integration

The following is a summary of what the steps above look like when taken together:

import UIKit
import EngagementSDK

class ViewController: UIViewController {

    @IBOutlet weak var widgetView: UIView!
    @IBOutlet weak var chatView: UIView!

    var engagementSDK: EngagementSDK!

    //Creating the Widget and Chat ViewControllers
    let widgetViewController = WidgetViewController()
    let chatViewController = ChatViewController()

    //Holding a reference to the session to keep it valid
    var session: ContentSession?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        engagementSDK = EngagementSDK(clientID: "<client-id>")
        
        // Adding widgetViewController as child view controller
        addChild(widgetViewController)
        widgetView.addSubview(widgetViewController.view)
        widgetViewController.didMove(toParent: self)
        
        // Applying constraints to fill the container
        widgetViewController.view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            widgetViewController.view.bottomAnchor.constraint(equalTo: widgetView.bottomAnchor),
            widgetViewController.view.topAnchor.constraint(equalTo: widgetView.topAnchor),
            widgetViewController.view.trailingAnchor.constraint(equalTo: widgetView.trailingAnchor),
            widgetViewController.view.leadingAnchor.constraint(equalTo: widgetView.leadingAnchor)
            ])
        
        // Adding chatViewController as a child view controller
        addChild(chatViewController)
        chatView.addSubview(chatViewController.view)
        chatViewController.didMove(toParent: self)
        
        // Applying constraints to fill the container
        chatViewController.view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            chatViewController.view.bottomAnchor.constraint(equalTo: chatView.bottomAnchor),
            chatViewController.view.topAnchor.constraint(equalTo: chatView.topAnchor),
            chatViewController.view.trailingAnchor.constraint(equalTo: chatView.trailingAnchor),
            chatViewController.view.leadingAnchor.constraint(equalTo: chatView.leadingAnchor)
            ])

        //Creating a Content Session
        let config = SessionConfiguration(programID: "<program-id>")
        session = engagementSDK.contentSession(config: config)
        session.delegate = self

       // Applying the Content Session to the Widget and Chat ViewControllers
        widgetViewController.session = session
        chatViewController.session = session
    }

    //Ending a session
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        self.session?.close()
    }
}

Updated 25 days ago

Getting Started


Get a basic integration up and running with the iOS SDK

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.