- Create a folder called
vizbee
within your app's code repository - Copy the following template files into the
vizbee
folderVizbeeWrapper.swift
- The main wrapper for all Vizbee SDK APIsVizbeeAppAdapter.swift
- The template for writing Vizbee AppAdapterVizbeeSigninAdapter.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.
Last active
April 18, 2024 08:43
-
-
Save vizbee/fe3033211349a3ff0a7e6dbfe58c6168 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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 | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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)) | |
*/ | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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>", | |
] | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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