Skip to content

Instantly share code, notes, and snippets.

@vizbee
Last active April 18, 2024 08:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vizbee/fe3033211349a3ff0a7e6dbfe58c6168 to your computer and use it in GitHub Desktop.
Save vizbee/fe3033211349a3ff0a7e6dbfe58c6168 to your computer and use it in GitHub Desktop.

Template Files for Vizbee iOS SDK Integration

  • Create a folder called vizbee within your app's code repository
  • Copy the following template files into the vizbee folder
    • VizbeeWrapper.swift - The main wrapper for all Vizbee SDK APIs
    • VizbeeAppAdapter.swift - The template for writing Vizbee AppAdapter
    • VizbeeSigninAdapter.swift - The template for writing Vizbee signin adapter.
    • VizbeeAnalyticsHandler.swift - The template for hooking in all custom analytics handlers.
    • VizbeeStyles.swift - The template file for customizing Vizbee style to your app's brand requirements.
//
// VizbeeAnalyticsHandler.swift
// This is the template for tracking vizbee analytics
//
import Foundation
import VizbeeKit
class VizbeeAnalyticsHandler: NSObject {
override init() {
super.init()
Vizbee.getAnalyticsManager().add(self)
}
deinit {
Vizbee.getAnalyticsManager().remove(self)
}
//----------------------------
// UIFlow events
//----------------------------
/**
This handler is invoked by the Vizbee SDK when the
Cast Introduction card is shown.
- Parameter attrs: A dictionary of flow attributes
*/
func onCastIntroductionCardShown(attrs: [AnyHashable: Any]) {
// Add your custom analytics handler here
}
/**
This handler is invoked by the Vizbee SDK when the
Smart Install card is shown.
- Parameter attrs: A dictionary of flow attributes
*/
func onSmartInstallCardShown(attrs: [AnyHashable: Any]) {
// Add your custom analytics handler here
}
//----------------------------
// Screen connection events
//----------------------------
/**
This handler is invoked by the Vizbee SDK when the
mobile app is connecting to a new screen.
*/
func onConnecting() {
// Add your custom analytics handler here
}
/**
This handler is invoked by the Vizbee SDK when the
mobile app is connected to a new screen.
- Parameter screen: VZBScreen to which the mobile is connected
*/
func onConnectedToScreen(screen: VZBScreen?) {
// Add your custom analytics handler here
}
/**
This handler is invoked by the Vizbee SDK when the
mobile app is disconnected from a screen.
*/
func onDisconnect() {
// Add your custom analytics handler here
}
//----------------------------
// Video status events
//----------------------------
/**
This handler is invoked by the Vizbee SDK when the
mobile app casts a new video to the screen.
- Parameter vzbVideoStatus: VZBVideoStatus
*/
func onVideoStart(vzbVideoStatus: VZBVideoStatus) {
// Add your custom analytics handler here
}
}
extension VizbeeAnalyticsHandler: VZBAnalyticsDelegate {
func onAnalyticsEvent(_ event: VZBAnalyticsEventType, withAttrs attrs: [AnyHashable: Any]) {
switch event {
case .castIntroductionCardShown:
onCastIntroductionCardShown(attrs: attrs)
case .smartInstallCardShown:
onSmartInstallCardShown(attrs: attrs)
default:
// this is return instead of default because we don't
// want the metrics call to get executed at all
return
}
}
}
//
// VizbeeAppAdapter.swift
// This is the template for writing a custom VizbeeAppAdapter
//
import VizbeeKit
class VizbeeAppAdapter: NSObject, VZBAppAdapterDelegate {
/**
This adapter method is invoked by the Vizbee SDK to get
metadata in the Vizbee format for a given video.
- Parameter appVideoObject: The videoObject used in the app
- Parameter successCallback: callback on successful creation of VZBVideoMetadata
- Parameter failureCallback: callback on failure
*/
func getVZBMetadata(fromVideo appVideoObject: Any,
onSuccess successCallback: @escaping (VZBVideoMetadata) -> Void,
onFailure failureCallback: @escaping (Error) -> Void) {
// EXAMPLE:
/*
if let video = appVideoObject as? VideoModel {
let metadata = VZBVideoMetadata()
metadata.guid = video.id
metadata.title = video.title
metadata.subTitle = video.subtitle
metadata.imageURL = video.imageUrl
metadata.isLive = video.isLive
metadata.customMetadata = [
"userId": ""
]
successCallback(metadata)
} else {
failureCallback(NSError(domain: "Unrecognized video type: \(appVideoObject)", code: 2, userInfo: nil))
return
}
}
*/
// default
failureCallback(NSError(domain: "Not implemented", code: 2, userInfo: nil))
}
/**
This adapter method is invoked by the Vizbee SDK to get
streaming info in the Vizbee format for a given video.
- Parameter appVideoObject: The videoObject used in the app
- Parameter forScreen: The target screen to which the video is being cast
- Parameter successCallback: callback on successful creation of VZBStreamInfo
- Parameter failureCallback: callback on failure
*/
func getVZBStreamInfo(fromVideo appVideoObject: Any,
for _: VZBScreenType,
onSuccess successCallback: @escaping (VZBVideoStreamInfo) -> Void,
onFailure failureCallback: @escaping (Error) -> Void) {
// EXAMPLE:
/*
if let video = appVideoObject as? VideoModel {
let streamInfo = VZBVideoStreamInfo()
streamInfo.videoURL = video.hlsURL
streamInfo.customStreamInfo = [
"authToken" : "<authToken>",
"refreshToken" : "<refreshToken>",
...
]
successCallback(streamInfo)
} else {
failureCallback(NSError(domain: "Unrecognized video type: \(appVideoObject)", code: 2, userInfo: nil))
}
*/
// default
failureCallback(NSError(domain: "Not implemented", code: 2, userInfo: nil))
}
/**
This adapter method is invoked by the Vizbee SDK when
the mobile app 'joins' a receiver that is already playing a video.
The method is used by the Vizbee SDK to get metadata about the
video playing on the receiver by using the GUID of the video.
- Parameter guid: GUID of the video
- Parameter successCallback: callback on successful creation of VZBVideoInfo
- Parameter failureCallback: callback on failure
*/
func getVideoInfo(byGUID guid: String,
onSuccess successCallback: @escaping (Any) -> Void,
onFailure failureCallback: @escaping (Error) -> Void) {
// EXAMPLE:
/*
AppNetworking.shared.fetchVideo(id: guid) { video, error in
if let video = video {
successCallback(video)
} else if let error = error {
failureCallback(error)
}
}
*/
// default response
failureCallback(NSError(domain: "Not implemented", code: 2, userInfo: nil))
}
/**
This adapter method is invoked by the Vizbee SDK in SmartPlay flow
or the Disconnect flow to start playback of a video on the phone.
- Parameter appVideoObject: app's video object
- Parameter atPosition: resume position of video
- Parameter shouldAutoPlay: indicates if the video should start auto playing
- Parameter viewController: the presenting view controller
*/
func playVideo(onPhone appVideoObject: Any,
atPosition playHeadTime: TimeInterval,
shouldAutoPlay: Bool,
presenting viewController: UIViewController) {
// EXAMPLE:
/*
if let video = playable.videoObject as? VideoModel,
let playerController = viewController as? PlayerViewController {
playerController.playVideoOnPhone(video: video, atPosition: playHeadTime, shouldAutoPlay: shouldAutoPlay)
}
*/
}
/**
This adapter method is deprecated.
*/
func goToViewController(forGUID guid: String,
onSuccess _: @escaping (UIViewController) -> Void,
onFailure _: @escaping (Error) -> Void) {
// EXAMPLE:
/*
AppNavigationCoordinator
.tryToNavigateToDeepLink(route: DeepLinkRoute.detail(guid, 0))
*/
}
}
//
// VizbeeSigninAdapter.swift
// This is the template for writing Vizbee SigninAdapter
//
import Foundation
class VizbeeSigninAdapter: NSObject {
/**
This adapter method is invoked by the Vizbee SDK on connection to
a new device to get user signin info. The returned signin info is sent
to the receiver for automatic signin.
- Return : A dictionary with fields
{
"userId" : "<required id for user>",
"userLogin" : "<required login for user>",
"userFullName" : "<required fullname for user>", // this is shown in the welcome message on receiver
"accessToken" : "<accessToken for user>", // one of access or refresh token must be included
"refreshToken" : "<refreshToken for user>", // one of access or refresh token must be included
}
*/
func getSigninInfo(completionHandler: @escaping ([AnyHashable: Any]?) -> Void) {
// EXAMPLE:
/*
AccountManager.shared().session?.getRefreshToken().done({ obj in
let refreshToken = obj?.token
DispatchQueue.main.async {
let userInfo = [
"userId": AccountManager.shared().profileId ?? "",
"userLogin": AccountManager.shared().userEmail ?? "",
"userFullName": AccountManager.shared().profileName ?? "",
"accessToken": AccountManager.shared().accessToken ?? "",
"refreshToken": refreshToken ?? ""
]
completionHandler(userInfo)
}
}, rejected: { _ in
DispatchQueue.main.async {
completionHandler(nil)
}
})
*/
// default
completionHandler(nil)
}
}
//
// VizbeeStyles.swift
// This is the template file for customizing Vizbee UI styles to your app's brand requirements.
import Foundation
import VizbeeKit
class VizbeeStyles : NSObject {
static func uiStyle() -> [String : Any] {
return darkTheme
}
//----------------------------
// MARK : - Light Theme
//---------------------------
static let lightTheme: [String: Any] = [
// ===============================================================
// Basic Style Customization (Required)
// ===============================================================
"base" : "LightTheme",
"references" : [
/* Your app's theme colors -->
1. Primary Color - this is typically the background color used on most of your app screens
2. Secondary Color - this is the highlight or accent color used on buttons etc. in your app screens
3. Tertiary Color - this is the text color used in most of your app screens
Update the colors below to suit your app.
*/
"@primaryColor" : "#FFFFFF",
"@secondaryColor" : "#FF140F",
"@tertiaryColor" : "#0C0C0C",
"@lighterTertiaryColor" : "#323236",
/* Your app's theme fonts
Provide fonts located in your supporting files folder including any nested directories.
i.e 'yourFont.<extension>' or 'fonts/yourFont.<extension>.
Update the fonts below to suit your app.
*/
"@primaryFont" : "<apps_primary_font_name>",
"@secondaryFont" : "<apps_secondary_font_name>",
],
// ===============================================================
// Advanced Style Customization (Optional)
// ===============================================================
"classes" : [
/* Card background
set this attribute if you prefer an image background for Vizbee screens
"BackgroundLayer": [
"backgroundType" : "image",
"backgroundImageName" : "<image_name.png>"
],
*/
]
/*
OVERLAY CARD
Customize the Overlay cards as shown here
https://gist.github.com/vizbee/7e9613f76a546c8f9ed9087e91bdc7b1#customize-overlay-cards
*/
/*
INTERSTITIAL CARD
Customize the Interstitial cards as shown here
https://gist.github.com/vizbee/7e9613f76a546c8f9ed9087e91bdc7b1#customize-interstitial-cards
*/
/*
SPECIFIC CARD ATTRIBUTES
Player Card
Customize the Player card as shown here
https://gist.github.com/vizbee/7e9613f76a546c8f9ed9087e91bdc7b1#customize-player-card
*/
]
//---------------------------
// MARK : - Dark Theme
//---------------------------
static let darkTheme: [String: Any] = [
// ===============================================================
// Basic Style Customization (Required)
// ===============================================================
"base" : "DarkTheme",
"references" : [
/* Your app's theme colors -->
1. Primary Color - this is typically the background color used on most of your app screens
2. Secondary Color - this is the highlight or accent color used on buttons etc. in your app screens
3. Tertiary Color - this is the text color used in most of your app screens
Update the colors below to suit your app.
*/
"@primaryColor" : "#0C0C0C",
"@secondaryColor" : "#FF140F",
"@tertiaryColor" : "#FFFFFF",
/* Your app's theme fonts
Provide fonts located in your supporting files folder including any nested directories.
i.e 'yourFont.<extension>' or 'fonts/yourFont.<extension>.
Update the fonts below to suit your app.
*/
"@primaryFont" : "<apps_primary_font_name>",
"@secondaryFont" : "<apps_secondary_font_name>",
]
]
}
//
// VizbeeWrapper.swift
// This is the template file for intializing Vizbee SDK and listening for session changes
//
import Foundation
import VizbeeKit
class VizbeeWrapper: NSObject {
static let shared = VizbeeWrapper()
var isSDKInitialized: Bool = false
static let kVZBCastConnected = "vizbee.cast.connected"
static let kVZBCastDisconnected = "vizbee.cast.disconnected"
var isConnected = false
private var sessionManager: VZBSessionManager?
private var vizbeeAnalyticsHandler: VizbeeAnalyticsHandler?
// ------------------
// MARK: - SDK init
// -----------------
func initVizbeeSDK() {
if (!isSDKInitialized) {
isSDKInitialized = true
/*
* SDK init
*/
let appAdapter = VizbeeAppAdapter()
let options = VZBOptions()
options.uiConfig = VizbeeStyles.lightTheme
// Update with correct Vizbee assigned VizbeeAppID
Vizbee.start(withAppID: "vzb*********",
appAdapterDelegate: appAdapter,
andVizbeeOptions: options)
/*
* Setup session manager
*/
sessionManager = Vizbee.getSessionManager()
addSessionStateDelegate(sessionDelegate: self)
/*
* Init vizbee analytics
*/
vizbeeAnalyticsHandler = VizbeeAnalyticsHandler();
}
}
// ------------------
// MARK: - SignIn
// ------------------
func doSignIn() {
let vizbeeSigninAdapter = VizbeeSigninAdapter()
guard let sessionManager = sessionManager else { return }
guard let currentSession = sessionManager.getCurrentSession() else { return }
vizbeeSigninAdapter.getSigninInfo { authInfo in
guard let authInfo = authInfo else { return }
let eventManager = currentSession.eventManager
eventManager.sendEvent(withName: "tv.vizbee.homesign.signin", andData: ["authInfo": authInfo])
}
}
}
// ----------------------------
// MARK: - Session Management
// ----------------------------
extension VizbeeWrapper: VZBSessionStateDelegate {
func addSessionStateDelegate(sessionDelegate: VZBSessionStateDelegate) {
guard let sessionManager = sessionManager else { return }
sessionManager.add(sessionDelegate)
}
func onSessionStateChanged(_ newState: VZBSessionState) {
switch newState {
case VZBSessionState.noDeviceAvailable: fallthrough
case VZBSessionState.notConnected:
onDisconnected()
case VZBSessionState.connecting:
onDisconnected()
// analytics handler
vizbeeAnalyticsHandler?.onConnecting()
case VZBSessionState.connected:
onConnected()
default:
isConnected = false
}
}
func onConnected() {
isConnected = true
addVideoStatusListener()
// post cast connected notification
NotificationCenter.default.post(name: Notification.Name(VizbeeWrapper.kVZBCastConnected), object: nil)
// analytics handler
let screen = sessionManager?.getCurrentSession()?.vizbeeScreen
vizbeeAnalyticsHandler?.onConnectedToScreen(screen: screen)
// signin handler
doSignIn()
}
func onDisconnected() {
if (isConnected) {
isConnected = false
removeVideoStatusListener()
// post cast disconnected notification
NotificationCenter.default.post(name: Notification.Name(VizbeeWrapper.kVZBCastDisconnected), object: nil)
// analytics handler
vizbeeAnalyticsHandler?.onDisconnect()
}
}
func getConnectedScreen() -> VZBScreen? {
return sessionManager?.getCurrentSession()?.vizbeeScreen
}
func disconnectSession() {
sessionManager?.disconnectSession()
}
}
// --------------------------------
// MARK: - Video Status Management
// --------------------------------
extension VizbeeWrapper: VZBVideoStatusUpdateDelegate {
func addVideoStatusListener() {
sessionManager?.getCurrentSession()?.videoClient.addVideoStatusDelegate(self)
}
func removeVideoStatusListener() {
sessionManager?.getCurrentSession()?.videoClient.removeVideoStatusDelegate(self)
}
func onVideoStatusUpdate(_ videoStatus: VZBVideoStatus?) {
guard let videoStatus = videoStatus,
let _ = videoStatus.guid else { return }
switch videoStatus.playerState {
case .started:
vizbeeAnalyticsHandler?.onVideoStart(vzbVideoStatus: videoStatus)
default:
break
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment