Objective-c Basic example

From Engineering Client Portal

Revision as of 21:04, 2 October 2018 by Admin3 (talk | contribs) (Created page with "{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{Breadcrumb|DCR_Video_iOS_SDK}} {{CurrentBreadcrumb}} Category:Digital [[File:iphonescreenshot.png|thumb]...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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 Objective-c Basic example

iphonescreenshot.png

Objective-C Code Example

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/NielsenAppApi.h>

@implementation NielsenInit

+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate
{
    //Initialising the NielsenAppApi class by passing app information which returns the instance of NielsenAppApi.
    
    NSDictionary *appInformation = @{ @"appid": @"PDA7D5EE6-B1B8-4123-9277-2A788BC653CA",
                                      @"appversion": @"1.0",
                                      @"sfcode": @"dcr",
                                      @"nol_devDebug": @"DEBUG" };
    
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];
}


@end

NielsenInit.h

#import <Foundation/Foundation.h>

@class NielsenAppApi;
@protocol NielsenAppApiDelegate;

@interface NielsenInit : NSObject

+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate;

@end

SDKMethods.m

#import <Foundation/Foundation.h>
#import "SDKMethods.h"


@implementation SDKMethods
NSDictionary *content;

-(void)setContentUrl
{
    //Loading Content URL    
    self.url = [NSURL URLWithString:@"http://www.nielseninternet.com/NielsenConsumer/prog_index.m3u8"];
}

-(void)setAdUrl
{
    //Loading Ad URL    
    self.url = [NSURL URLWithString:@"http://www.nielseninternet.com/NWCC-3002/prog_index.m3u8"];
}

-(void)setDtvrUrl
{
    //Loading DTVR URL    
    self.url = [NSURL URLWithString:@"http://www.nielseninternet.com/VOD/NielsenScienceBehindWhatsNext/prog_index.m3u8"];
}

- (NSDictionary *)loadChannelInfo
{
    //Loading Channel Info.    
    NSString *strUrl = self.url.absoluteString;  
    NSDictionary *channel = @{  @"channelName" : @"ChannelTitle",
                             @"mediaURL": strUrl };   
    return channel;
}

// http://www.nielseninternet.com/NielsenConsumer/prog_index.m3u8
- (NSDictionary *)loadContent
{
    //Loading Content data
        self.url = [NSURL URLWithString:@"http://www.nielseninternet.com/NielsenConsumer/prog_index.m3u8"];   
    NSDictionary *content = @{    @"type":@"content",
                                @"assetid":@"C77664",
                                @"length":@"3600",
                                @"program":@"MyProgram",
                                @"segB":@"CustomSegmentValueB",
                                @"segC":@"segmentC",
                                @"title":@"S2,E3",
                                @"section":@"cloudApi_app",
                                @"airdate":@"20180301 10:00:00",
                                @"isfullepisode":@"y",
                                @"adloadtype":@"2",
                                @"channelName":@"My Channel 1",
                                @"pipMode":@"false" };
    
    return content;
}

- (NSDictionary *)loadPreRollAd
{
    //loading Ad data.   
    self.url = [NSURL URLWithString:@"http://www.nielseninternet.com/NWCC-3002/prog_index.m3u8"];   
    NSDictionary *ad = @{ @"type":@"preroll",
                        @"assetid":@"AD1",
                        @"title":@"ADPreTitle" };    
    return ad;
}

- (NSDictionary *)loadDtvr{
    
    //Loading DTVR data  
    NSDictionary *dtvr = @{ @"adModel":@"1" };  
    return dtvr;
}

@end

SDKMethods.h

#import <Foundation/Foundation.h>

@interface SDKMethods : NSObject

@property(nonatomic, strong) NSURL *url;

- (void)setContentUrl;
- (void)setAdUrl;
- (void)setDtvrUrl;
- (NSDictionary *)loadChannelInfo;
- (NSDictionary *)loadContent;
- (NSDictionary *)loadPreRollAd;
- (NSDictionary *)loadDtvr;

@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/NielsenAppApi.h>

NSMutableDictionary *mutableData;
NSDictionary *data;
SDKMethods *sdkMethods;
AVPlayer  *player;
AVPlayerViewController *playerController;
NielsenAppApi *nielsenApi;

int totalVideosPlayed;
id timeObserver;
static void *TimedMetadataObserverContext = &TimedMetadataObserverContext;
NSString *timedMetadataKey = @"currentItem.timedMetadata";
id array;

@interface ViewController()<AVPlayerViewControllerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //Setting background image
    UIImage *backgroundImage = [UIImage imageNamed:@"bg_image.jpg"];
    UIImageView *backgroundImageView=[[UIImageView alloc]initWithFrame:self.view.frame];
    backgroundImageView.image=backgroundImage;
    [self.view insertSubview:backgroundImageView atIndex:0];
    
    //Mark: In NielsenInit class we are initialising the NielsenEventTracker.
    
    //Getting the instance of NielsenEventTracker
    nielsenApi = [NielsenInit createNielsenAppApiWithDelegate:nil];
    
    //Mark: In SDKMethods class we wrote methods which creates content,Ad objects
    sdkMethods = [[SDKMethods alloc] init];
    
    if(self.videoType == onlyContent){
        //loading video content url
        [sdkMethods setContentUrl];
        
    }else if(self.videoType == dtvrVideo){
        //loading video DTVR url
        [sdkMethods setDtvrUrl];
        
    }else{
        //loading video Ad url
        [sdkMethods setAdUrl];
    }
    
    [self setPlayer];
    
    if(self.videoType != dtvrVideo){
        
        //For DTVR video playHeadPosition is not required
        //For DCR Content,Ad videos only this method will execute.
        [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;
    
    [player play];
    
    if(totalVideosPlayed == 0){
        //For first time sending Channel info to SDK using "play" method.
        [nielsenApi play:([sdkMethods loadChannelInfo])];
    }
    
    if(self.videoType == dtvrVideo){
        
        //loading DTVR metadata
        data = [sdkMethods loadDtvr];
    }else{
        
        //loading video content metadata data
        data = [sdkMethods loadContent];
    }
    //Sending metadata to SDK.
    [nielsenApi loadMetadata:(data)];
    
    if(self.videoType == contentWithOneAd){
        //loading Ad data
        data = [sdkMethods loadPreRollAd];
        [nielsenApi loadMetadata:(data)];
    }
    
    //Adding observer to player to track play,pause and reverse
    [player addObserver:self
             forKeyPath:@"rate"
                options:(NSKeyValueObservingOptionNew)
                context:nil];
    
    //Only for DTVR videos we are tracking iD3 Tags and sends to SDK after extracting.
    if(self.videoType == dtvrVideo){
        
        //Setting observer to track timedMetadata
        [player addObserver:self
                 forKeyPath: timedMetadataKey
                    options: (NSKeyValueObservingOptionNew)
                    context: &TimedMetadataObserverContext];
        
    }
    
    [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;
        
        //Sending data dictionary to SDK with updated playHead position.
        [nielsenApi playheadPosition:(intSec)];
    }];
}

- (void) setVideoFinishObserver {
    
    //observer fires on completion of Ad
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:playerController.player.currentItem];
}

//rate 0 = Video Pause or stopped
//rate 1 = Video played or resumed
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if(keyPath == timedMetadataKey){
        if(context == &TimedMetadataObserverContext){
            
            id newMetadataArray = [change objectForKey:NSKeyValueChangeNewKey];
            if (newMetadataArray != [NSNull null])
            {
                array = newMetadataArray;
                for (AVMetadataItem *metadataItem in array)
                {
                    //Handling TimedMetadata
                    [self handleTimedMetadata: metadataItem];
                }
            }
            
        }
    }
    
    
    if (object == player && [keyPath isEqualToString:@"rate"]) {
        
        NSNumber * newValue = [change objectForKey:NSKeyValueChangeNewKey];
        int intValue = newValue.intValue;
        if(intValue == 0){
            NSLog(@"playback paused");
            
            //On Video pause calling the "stop" method of SDK.
            [nielsenApi stop];
            
        }else if(intValue == 1){
            NSLog(@"Normal playback");
            
            //On video Resume calling "loadMetada" method of SDK
            [nielsenApi loadMetadata:(data)];
            
        }
    }
}

- (void)viewDidDisappear:(BOOL)animated
{
    ///On moving to other screen calling "stop" method of SDK.
    [nielsenApi stop];
    
    player.rate = 0;
    [player pause];
    
    [super viewDidDisappear:animated];
}

-(void)playerDidFinishPlaying:(NSNotification *) notification {
    
    [player removeObserver:self forKeyPath:@"rate"];
    
    //As 1 video completed playing, incrementing the variable value.
    totalVideosPlayed += 1;
    
    if(self.videoType == onlyContent || totalVideosPlayed == self.totalVideos){
        //When content video completes or total videos finishes, call "end" method.
        [nielsenApi end];
        
    }else if(self.videoType == contentWithOneAd){
        
        //On completion of "AD" call "stop" method.
        [nielsenApi stop];
        
        //After preRoll ad completes, load content video.
        data = [sdkMethods loadContent];
        
    }
    
    //Checking if total videos played or not.
    if(totalVideosPlayed != self.totalVideos){
        
        [self setPlayer];
        [self setPlayHeadPosition];
        
        //Setting observer to know the completion of video
        [self setVideoFinishObserver];
        
    }
}

- (void)dealloc {
    NSLog(@"Remove NotificationCenter dealloc");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)handleTimedMetadata:(AVMetadataItem *)timedMetadata
{
    // We expect the content to contain plists encoded as timed metadata
    // AVPlayer turns these into NSDictionaries
    
    id extraAttributeType = [timedMetadata extraAttributes];
    NSString *extraString = nil;
    if ([extraAttributeType isKindOfClass:[NSDictionary class]])
    {
        extraString = [extraAttributeType valueForKey:@"info"];
    }
    else if ([extraAttributeType isKindOfClass:[NSString class]])
    {
        extraString = extraAttributeType;
    }
    
    NSString *key = [NSString stringWithFormat:@"%@", [timedMetadata key]];
    
    //If tag starts with "www.nielsen.com", then only sending to SDK
    if ([key isEqualToString:@"PRIV"] && [extraString rangeOfString:@"www.nielsen.com"].length > 0)
    {
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [nielsenApi sendID3:extraString];
        });
    }
}

@end

ViewController.h

#import <UIKit/UIKit.h>

@class NielsenAppApi;
@protocol NielsenAppApiDelegate;


@interface ViewController : UIViewController

@property (nonatomic) int videoType;
@property (nonatomic) int totalVideos;

@end

OptOutVC.h

#import <UIKit/UIKit.h>

@class NielsenEventTracker;
@protocol NielsenEventTrackerDelegate;

@interface OptOutVC : UIViewController

@property (nonatomic, weak) NielsenEventTracker *nielsenEventTracker;

@end