Swift Basic Sample

From Engineering Client Portal

The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Engineering Portal breadcrumbArrow.png Digital breadcrumbArrow.png DCR & DTVR breadcrumbArrow.png DCR Video iOS SDK breadcrumbArrow.png Swift Basic Sample

iPhone 11 Screenshot.jpg

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)
            }
        }
    }
    
    
}