Simplified SDK API-Objective-C
From Engineering Client Portal
Objective-C Code Example
Select the below link to download the sample files
Download Project Files
NielsenInit.m
// NielsenInit.m
// VideoPlayerAppObjC
// This is sample code of a very basic implementation of the Nielsen 'Simplified API'
// This code is for educational purposes only
#import "NielsenInit.h"
#import <NielsenAppApi/NielsenEventTracker.h>
@implementation NielsenInit
+ (NielsenEventTracker *)createNielsenEventTrackerWithDelegate:(id<NielsenEventTrackerDelegate>)delegate
{
//Initialising the NielsenEventTracker class by passing app information which returns the instance of NielsenEventTracker.
NSDictionary *appInformation = @{ @"appid": @"PDA7D5EE6-B1B8-4123-9277-2A788BC6XXX",
@"appversion": @"1.0",
@"appname": @"Objc Test app",
@"sfcode": @"dcr",
@"ccode": @"123",
@"dma":@"456",
@"uoo":@"0",
@"nol_devDebug": @"INFO",
@"containerId": @"1" };
return [[NielsenEventTracker alloc] initWithAppInfo:appInformation delegate:delegate];
}
@end
NielsenInit.h
#import <Foundation/Foundation.h>
@class NielsenEventTracker;
@protocol NielsenEventTrackerDelegate;
@interface NielsenInit : NSObject
+ (NielsenEventTracker *)createNielsenEventTrackerWithDelegate:(id<NielsenEventTrackerDelegate>)delegate;
@end
SDKMethods.m
#import <Foundation/Foundation.h>
#import "SDKMethods.h"
@implementation SDKMethods
//Loading content Data
- (NSDictionary *)loadContentData
{
self.url = [NSURL URLWithString:@"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4"];
NSDictionary *content = @{ @"assetName":@"ChromeCast1",
@"assetid":@"C77664",
@"length":@"3600",
@"program":@"MyProgram",
@"segB":@"CustomSegmentValueB",
@"segC":@"segmentC",
@"title":@"S2,E3",
@"type":@"content",
@"section":@"cloudApi_app",
@"airdate":@"20180120 10:00:00",
@"isfullepisode":@"y",
@"adloadtype":@"2",
@"channelName":@"My Channel 1",
@"pipMode":@"false" };
//Ad data,static data should be empty in content video dictionary
NSDictionary *metadata = @{ @"content" : content,
@"ad" : @{},
@"static" : @{} };
NSDictionary *data = @{ @"metadata" : metadata,
@"event": @"playhead",
@"type": @"content",
@"playheadPosition": @"0" };
return data;
}
//Loading Ad data
- (NSDictionary *)loadPreRollAd
{
self.url = [NSURL URLWithString:@"http://www.nielseninternet.com/NWCC-3002/prog_index.m3u8"];
//We should pass content dictionary also in Ad video.
NSDictionary *content = @{ @"assetName":@"ChromeCast1",
@"assetid":@"C77664",
@"length":@"3600",
@"program":@"MyProgram",
@"segB":@"CustomSegmentValueB",
@"segC":@"segmentC",
@"title":@"S2,E3",
@"type":@"content",
@"section":@"cloudApi_app",
@"airdate":@"20180120 10:00:00",
@"isfullepisode":@"y",
@"adloadtype":@"2",
@"channelName":@"My Channel 1",
@"pipMode":@"false" };
NSDictionary *ad = @{ @"assetid":@"AD12345",
@"title":@"ADTestTitle",
@"type":@"preroll",
@"length":@"20" };
//static data should be empty in Ad video
NSDictionary *metadata = @{ @"content" : content,
@"ad" : ad,
@"static" : @{} };
NSDictionary *data = @{ @"metadata" : metadata,
@"event": @"playhead",
@"type": @"ad",
@"playheadPosition": @"0" };
return data;
}
@end
SDKMethods.h
#import <Foundation/Foundation.h>
@interface SDKMethods : NSObject
@property(nonatomic, strong) NSURL *url;
- (NSDictionary *)loadContentData;
- (NSDictionary *)loadPreRollAd;
@end
ViewController.m
#import "ViewController.h"
#import "NielsenInit.h"
#import "SDKMethods.h"
#import <MediaPlayer/MediaPlayer.h>
#import <AVKit/AVKit.h>
#import "Constants.h"
#import <NielsenAppApi/NielsenEventTracker.h>
NSMutableDictionary *mutableData;
NSDictionary *data;
SDKMethods *sdkMethods;
AVPlayer *player;
AVPlayerViewController *playerController;
NielsenEventTracker *nielsenEventTracker;
int totalVideosPlayed = 0;
id timeObserver;
@interface ViewController()<AVPlayerViewControllerDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Mark: In NielsenInit class we are initialising the NielsenEventTracker.
//Getting the instance of NielsenEventTracker
nielsenEventTracker = [NielsenInit createNielsenEventTrackerWithDelegate:nil];
//Mark: In SDKMethods class we wrote methods which creates content,Ad objects
sdkMethods = [[SDKMethods alloc] init];
if(self.videoType == onlyContent){
//loading video content data
data = [sdkMethods loadContentData];
}else{
//loading Ad data
data = [sdkMethods loadPreRollAd];
}
//Converting "data" to mutable dictionary as we have to update playhead, event values.
mutableData =[data mutableCopy];
[self setPlayer];
[self setPlayHeadPosition];
//Setting observer to know the completion of video
[self setVideoFinishObserver];
}
-(void) setPlayer {
//creating player
player = [AVPlayer playerWithURL:[sdkMethods url]];
playerController = [[AVPlayerViewController alloc] init];
playerController.view.frame = CGRectMake(0,100,self.view.frame.size.width,300);
playerController.player = player;
playerController.showsPlaybackControls = YES;
playerController.delegate = self;
//Adding observer to player to track play,pause and reverse
[player addObserver:self
forKeyPath:@"rate"
options:(NSKeyValueObservingOptionNew)
context:nil];
[player play];
[self addChildViewController:playerController];
[self.view addSubview:playerController.view];
}
-(void) setPlayHeadPosition {
//Setting play head position
CMTime timeInterval = CMTimeMakeWithSeconds(1, 1);
[player addPeriodicTimeObserverForInterval:(timeInterval) queue:dispatch_get_main_queue() usingBlock:^(CMTime time){
NSTimeInterval seconds = CMTimeGetSeconds(time);
NSInteger intSec = seconds;
NSString* strSec = [NSString stringWithFormat:@"%li", intSec];
//updating playHead position in dictionary.
[mutableData setValue:strSec forKey:@"playheadPosition"];
//Sending data dictionary to SDK with updated playHead position.
[nielsenEventTracker trackEvent:mutableData];
}];
}
- (void) setVideoFinishObserver {
//observer fires on completion of Ad
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerController.player.currentItem];
}
//rate 0.0 = Video Pause or stopped
//rate 1.0 = Video played or resumed
//rate -1.0 = Play reversed/rewind.
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if (object == player && [keyPath isEqualToString:@"rate"]) {
NSNumber * newValue = [change objectForKey:NSKeyValueChangeNewKey];
int intValue = newValue.intValue;
if(intValue == 0){
NSLog(@"playback paused");
//on video pause, updating event as pause in dictionary
[mutableData setValue:@"pause" forKey:@"event"];
//sending the dictionary to SDK with "pause" event.
[nielsenEventTracker trackEvent:mutableData];
}else if(intValue == 1){
NSLog(@"Normal playback");
//On Play resume setting event as Playhead
[mutableData setValue:@"playhead" forKey:@"event"];
}
}
}
- (void)viewDidDisappear:(BOOL)animated
{
//on moving to other screen, updating event as pause in dictionary
[mutableData setValue:@"pause" forKey:@"event"];
//As it is a pause event setting the playheadPosition to empty.
[mutableData setValue:@"" forKey:@"playheadPosition"];
player.rate = 0;
[player pause];
[super viewDidDisappear:animated];
}
-(void)itemDidFinishPlaying:(NSNotification *) notification {
[player removeObserver:self forKeyPath:@"rate"];
[self sendCompleteEventToSDK];
//As 1 video completed playing, incrementing the variable value.
totalVideosPlayed += 1;
//Checking if total videos played or not.
if(totalVideosPlayed != self.totalVideos){
//Checking if videoType is contentWithAd, then after completion of Ad, will play the content video.
if(self.videoType == contentWithAd){
//loading video content data
data = [sdkMethods loadContentData];
mutableData =[data mutableCopy];
[self setPlayer];
//Adding observer to player to check is buffering finished
CMTime timeInterval = CMTimeMakeWithSeconds(1, 3);
timeObserver = [player addPeriodicTimeObserverForInterval:(timeInterval) queue:dispatch_get_main_queue() usingBlock:^(CMTime time){
//checking the video player status
[self handlePlayerStatus:time];
[self setPlayHeadPosition];
//Setting observer to know the completion of video
[self setVideoFinishObserver];
}];
}
}
}
- (void) handlePlayerStatus : (CMTime) time {
if(player.status == AVPlayerItemStatusReadyToPlay){
// buffering is finished, setting event as Playhead
[mutableData setValue:@"playhead" forKey:@"event"];
[player removeTimeObserver:timeObserver];
}
}
- (void) sendCompleteEventToSDK {
//onCompletion of video, updating event as complete in dictionary
[mutableData setValue:@"complete" forKey:@"event"];
//As it is a complete event setting the playheadPosition to empty.
[mutableData setValue:@"" forKey:@"playheadPosition"];
//sending the dictionary to SDK with "complete" event.
[nielsenEventTracker trackEvent:mutableData];
}
- (void)dealloc {
NSLog(@"Remove NotificationCenter dealloc");
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
ViewController.h
#import <UIKit/UIKit.h>
@class NielsenEventTracker;
@protocol NielsenEventTrackerDelegate;
@interface ViewController : UIViewController
@property (nonatomic) int videoType;
@property (nonatomic) int totalVideos;
@end
OptOutVC.m
#import "OptOutVC.h"
#import "NielsenInit.h"
#import <NielsenAppApi/NielsenEventTracker.h>
@interface OptOutVC ()
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end
@implementation OptOutVC
- (void)viewDidLoad {
[super viewDidLoad];
self.nielsenEventTracker = [NielsenInit createNielsenEventTrackerWithDelegate:nil];
//Getting the optPut URL from eventTracker
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.nielsenEventTracker.optOutURL]]];
}
@end
OptOutVC.h
#import <UIKit/UIKit.h>
@class NielsenEventTracker;
@protocol NielsenEventTrackerDelegate;
@interface OptOutVC : UIViewController
@property (nonatomic, weak) NielsenEventTracker *nielsenEventTracker;
@end