Swift Basic Sample
From Engineering Client Portal
Swift Version 5 Code Example
NielsenInit.swift
// This is sample code of a very basic implementation of the Nielsen API
// This code is for educational purposes only
//
import Foundation
import NielsenAppApi
class NielsenInit : NSObject {
class func createNielsenApi(delegate: NielsenAppApiDelegate) -> NielsenAppApi?{
let appInformation:[String: String] = [
"appid": "PDA7D5EE6-B1B8-4123-9277-2A788BXXXXXX",
"appversion": "1.0",
"sfcode": "dcr",
"nol_devDebug": "DEBUG"
]
return NielsenAppApi(appInfo:appInformation, delegate:delegate)
}
}
SDKMethods.swift
//
// SDKMethods.swift
// VideoPlayerWithSDKSwift
//
//
import Foundation
class SDKMethods : NSObject {
var url = NSURL(string: "")
func setContentUrl() {
//Loading Content URL
url = NSURL(string: "http://www.nielseninternet.com/NielsenConsumer/prog_index.m3u8")
}
func setAdUrl() {
//Loading Ad URL
url = NSURL(string: "http://www.nielseninternet.com/NWCC-3002/prog_index.m3u8")
}
func setDtvrUrl() {
//Loading DTVR URL
url = NSURL(string: "http://www.nielseninternet.com/VOD/NielsenScienceBehindWhatsNext/prog_index.m3u8")
}
func loadChannelInfo() -> [String : Any] {
//Loading Channel Info.
let strUrl : String = (url?.absoluteString)!
let channel = [ "channelName" : "ChannelTitle",
"mediaURL" : strUrl] as [String : Any]
return channel
}
func loadContent() -> [String : Any] {
//Loading Content data
url = NSURL(string: "http://www.nielseninternet.com/NielsenConsumer/prog_index.m3u8")
let content = [
"type":"content",
"assetid":"C77664",
"length":"3600",
"program":"MyProgram",
"segB":"CustomSegmentValueB",
"segC":"segmentC",
"title":"S2,E3",
"section":"cloudApi_app",
"airdate":"20180221 10:00:00",
"isfullepisode":"y",
"adloadtype":"2",
"channelName":"My Channel 1",
"pipMode":"false" ] as [String : Any]
return content
}
func loadPreRollAd() -> [String : Any] {
//loading Ad data.
url = NSURL(string: "http://www.nielseninternet.com/NWCC-3002/prog_index.m3u8")
let ad = [
"type":"preroll",
"assetid":"AD1",
"title":"ADPreTitle"] as [String : Any]
return ad
}
func loadDtvr() -> [String : Any] {
//Loading DTVR data
let dtvr = [
"adModel": "1" ] as [String : Any]
return dtvr
}
}
ViewController.swift
//
// ViewController.swift
// VideoPlayerWithSDKSwift
//
//
import UIKit
import AVKit
import CoreLocation
import AdSupport
import AVFoundation
import NielsenAppApi
class ViewController: UIViewController, NielsenAppApiDelegate, AVPlayerViewControllerDelegate {
var nielsenApi : NielsenAppApi!
var videoType : Int!
var player : AVPlayer!
var controller : AVPlayerViewController!
var sdkMethods : SDKMethods!
var data : [String : Any]!
var timeObserver: Any!
var totalVideosPlayed = 0
var totalVideos : Int!
var TimedMetadataObserverContext = 3
var array : Any!
let timedMetadataKey = "currentItem.timedMetadata"
override func viewDidLoad() {
super.viewDidLoad()
//Mark: In NielsenInit class we are initialising the NielsenApi.
//Getting the instance of NielsenApi
self.nielsenApi = NielsenInit.createNielsenApi(delegate: self)
//Mark: In SDKMethods class we wrote methods which creates content,Ad,DTVR objects
sdkMethods = SDKMethods()
if(videoType == Constants.onlyContent){
//loading video content url
sdkMethods.setContentUrl()
}else if(videoType == Constants.dtvrVideo){
//loading video DTVR url
sdkMethods.setDtvrUrl()
}else{
//loading video Ad url
sdkMethods.setAdUrl()
}
setPlayer()
if(videoType != Constants.dtvrVideo){
//For DTVR video playHeadPosition is not required
//For DCR Content,Ad videos only this method will execute.
setPlayHeadPosition()
}
//Setting observer to know the completion of video
setVideoFinishObserver()
}
func setPlayer() {
//creating player
player = AVPlayer.init(url: sdkMethods.url! as URL)
controller = AVPlayerViewController()
controller.view.frame = CGRect(x:0 , y:100, width: self.view.frame.width, height: 300)
controller.player = player;
controller.showsPlaybackControls = true;
controller.delegate = self;
player.play()
if(totalVideosPlayed == 0){
//For first time sending Channel info to SDK using "play" method.
nielsenApi.play(sdkMethods.loadChannelInfo())
}
if(videoType == Constants.dtvrVideo){
//loading DTVR metadata
self.data = sdkMethods.loadDtvr()
}else{
//loading video content metadata data
self.data = sdkMethods.loadContent()
}
//Sending metadata to SDK.
nielsenApi.loadMetadata(self.data)
if(videoType == Constants.contentWithOneAd){
//loading Ad data
self.data = sdkMethods.loadPreRollAd()
nielsenApi.loadMetadata(self.data)
}
//Adding observer to player to track play,pause and reverse
player.addObserver(self, forKeyPath: "rate", options: NSKeyValueObservingOptions.new, context: nil)
//Only for DTVR videos we are tracking iD3 Tags and sends to SDK after extracting.
if(videoType == Constants.dtvrVideo){
//Setting observer to track timedMetadata
player.addObserver(self, forKeyPath: timedMetadataKey, options: NSKeyValueObservingOptions.new, context: &TimedMetadataObserverContext)
}
self.addChildViewController(controller)
self.view .addSubview(controller.view)
}
func setPlayHeadPosition() {
//Setting play head position
let timeInterval : CMTime = CMTimeMakeWithSeconds(1.0, 10)
controller.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -> Void in
let time : Float64 = self.controller.player!.currentTime().seconds;
let pos = Int64(time);
//Sending playHeadPosition to SDK.
self.nielsenApi?.playheadPosition(pos);
}
}
func setVideoFinishObserver() {
//observer fires on completion video.
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: controller.player?.currentItem)
}
//rate 0.0 = Video Pause or stopped
//rate 1.0 = Video played or resumed
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == timedMetadataKey {
if(context == &TimedMetadataObserverContext){
if change != nil {
let timedMetadataArray = change![.newKey]
if timedMetadataArray != nil && (timedMetadataArray! as AnyObject) is Array<Any> {
for item in timedMetadataArray as! [AVMetadataItem] {
//Handling TimedMetadata
self.handleTimedMetadata(metadataItem: item)
}
}
}
}
}
if keyPath == "rate" {
if let rate = change?[NSKeyValueChangeKey.newKey] as? Float {
if rate == 0.0 {
print("Playback stopped")
//On Video pause calling the "stop" method of SDK.
nielsenApi.stop()
}
if rate == 1.0 {
print("normal playback")
//On video Resume calling "loadMetada" method of SDK
nielsenApi.loadMetadata(self.data)
}
}
}
}
override func viewDidDisappear(_ animated: Bool) {
//On moving to other screen calling "stop" method of SDK.
nielsenApi.stop()
player.rate = 0
player.pause()
}
@objc func playerDidFinishPlaying(note: NSNotification) {
self.player?.removeObserver(self, forKeyPath: "rate")
//As 1 video completed playing, incrementing the variable value.
totalVideosPlayed += 1
if(videoType == Constants.onlyContent || totalVideosPlayed == totalVideos){
//When content video completes or total videos finishes, call "end" method.
nielsenApi.end()
}else if(videoType == Constants.contentWithOneAd){
//On completion of "AD" call "stop" method.
nielsenApi.stop()
//After preRoll ad completes, load content video.
self.data = sdkMethods.loadContent()
}
//Checking if total videos played or not.
if(totalVideosPlayed != totalVideos){
setPlayer()
setPlayHeadPosition()
//Setting observer to know the completion of video
setVideoFinishObserver()
}
}
deinit {
print("Remove NotificationCenter Deinit")
NotificationCenter.default.removeObserver(self)
}
//######### DTVR code starts here #############//
func handleTimedMetadata(metadataItem: AVMetadataItem) {
guard let extraAttributeType = metadataItem.extraAttributes else {
return
}
let info : AVMetadataExtraAttributeKey = AVMetadataExtraAttributeKey(rawValue: "info")
let extraString = extraAttributeType[info] as AnyObject
let key = metadataItem.key as! String
//If tag starts with "www.nielsen.com", then only sending to SDK
if key == "PRIV" && extraString.range(of: "www.nielsen.com").length > 0 {
DispatchQueue.global(qos: .default).async { () -> Void in
self.nielsenApi?.sendID3(extraString as! String)
}
}
}
}