שנתחיל?

IMA SDK מאפשר לכם לשלב בקלות מודעות מולטימדיה באתרים ובאפליקציות שלכם. IMA SDK יכול לשלוח בקשה להצגת מודעות מכל שרת מודעות שתואם ל-VAST ולנהל את ההפעלה של המודעות באפליקציות שלך. ערכות SDK בצד הלקוח של IMA מאפשרות לך לשלוט בהפעלה של תוכן וידאו, בעוד מערכת ה-SDK מטפלת בהפעלת המודעות. המודעות מופעלות בנגן וידאו נפרד שממוקם מעל נגן הווידאו של תוכן האפליקציה.

מדריך זה מדגים כיצד לשלב את IMA SDK באפליקציה פשוטה של נגן וידאו. אם אתם רוצים להציג שילוב לדוגמה במלואו, או לעקוב אחריו, הורידו את BasicExample מ-GitHub.

סקירה כללית של IMA בצד הלקוח

ההטמעה של IMA בצד הלקוח כוללת ארבעה רכיבי SDK עיקריים, כמו שמוסבר במדריך הזה:

  • IMAAdDisplayContainer: אובייקט מאגר תגים שבו מודעות מעובדות.
  • IMAAdsLoader: אובייקט שמבקש מודעות ומטפל באירועים מתגובות לבקשות למודעות. יש להפעיל רק טוען מודעות אחד, שניתן לעשות בו שימוש חוזר במהלך חיי האפליקציה.
  • IMAAdsRequest: אובייקט שמגדיר בקשה להצגת מודעות. בקשות להצגת מודעות מציינות את כתובת ה-URL של תג המודעה VAST, וגם פרמטרים נוספים, כמו מאפייני המודעה.
  • IMAAdsManager: אובייקט שמכיל את התגובה לבקשה להצגת מודעה, שולט בהפעלת המודעות ומאזין לאירועי מודעות שהופעלו על ידי ה-SDK.

דרישות מוקדמות

לפני שמתחילים:

1. יצירת פרויקט Xcode חדש

ב-Xcode, יוצרים פרויקט tvOS חדש באמצעות Objective-C או Swift. משתמשים ב-BasicExample בתור שם הפרויקט.

2. הוספת IMA SDK לפרויקט Xcode

התקנת ה-SDK באמצעות CocoaPods (מועדף)

CocoaPods הוא מנהל יחסי התלות בפרויקטים של Xcode, והוא השיטה המומלצת להתקנת IMA SDK. למידע נוסף על התקנה של CocoaPods ועל השימוש בו, עיינו במשאבי העזרה של CocoaPods. אחרי ההתקנה של CocoaPods, תוכלו לבצע את ההוראות הבאות כדי להתקין את IMA SDK:

  1. באותה ספרייה שבה נמצא הקובץ BasicExample.xcodeproj, יוצרים קובץ טקסט בשם Podfile ומוסיפים את התצורה הבאה:

    source 'https://github.com/CocoaPods/Specs.git'
    platform :tvos, '14'
    target "BasicExample" do
      pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.12.0'
    end
    
  2. מהספרייה שמכילה את קובץ ה-Podfile, מריצים את pod install --repo-update

  3. כדי לוודא שההתקנה בוצעה בהצלחה, פותחים את הקובץ BasicExample.xcworkspace ומוודאים שהוא מכיל שני פרויקטים: BasicExample ו-Pods (יחסי התלות שהותקנו על ידי CocoaPods).

התקנת ה-SDK באמצעות מנהל החבילות של Swift

Interactive Media Ads SDK תומך במנהל החבילות של Swift החל מגרסה 4.8.2. על מנת לייבא את חבילת Swift, יש לבצע את השלבים הבאים.

  1. ב-Xcode, כדי להתקין את חבילת Swift של IMA SDK, עוברים אל File > Add Packages... (קובץ > הוספת חבילות).

  2. בהודעה שמופיעה, מחפשים את מאגר GitHub של IMA SDK חבילת Swift Package:

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos
    
  3. באיזו גרסה של חבילת Swift של IMA SDK שבה ברצונך להשתמש? לפרויקטים חדשים, מומלץ להשתמש בגרסה הראשית הבאה.

בסיום, Xcode פותר את יחסי התלות של החבילות ומוריד אותן ברקע. למידע נוסף על הוספת יחסי תלות של חבילות, קראו את המאמר של Apple.

הורדה והתקנה של ה-SDK באופן ידני

אם אתם לא רוצים להשתמש ב-CocoaPods, תוכלו להוריד את IMA SDK ולהוסיף אותו לפרויקט באופן ידני.

3. יצירת נגן וידאו פשוט

קודם כול, מטמיעים נגן וידאו בסיסי. בהתחלה, הנגן הזה לא משתמש ב-IMA SDK ועדיין לא מכיל שיטות להפעלה.

ViewController.m

Objective-C

#import "ViewController.h"

#import <AVKit/AVKit.h>

NSString *const kContentURLString =
    @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4";

@interface ViewController ()
@property(nonatomic) AVPlayerViewController *contentPlayerViewController;
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = UIColor.blackColor;
  [self setupContentPlayer];
}

- (void)setupContentPlayer {
  // Create a content video player.
  NSURL *contentURL = [NSURL URLWithString:kContentURLString];
  AVPlayer *player = [AVPlayer playerWithURL:contentURL];
  self.contentPlayerViewController = [[AVPlayerViewController alloc] init];
  self.contentPlayerViewController.player = player;
  self.contentPlayerViewController.view.frame = self.view.bounds;

  // Attach content video player to view hierarchy.
  [self showContentPlayer];
}

// Add the content video player as a child view controller.
- (void)showContentPlayer {
  [self addChildViewController:self.contentPlayerViewController];
  self.contentPlayerViewController.view.frame = self.view.bounds;
  [self.view insertSubview:self.contentPlayerViewController.view atIndex:0];
  [self.contentPlayerViewController didMoveToParentViewController:self];
}

// Remove and detach the content video player.
- (void)hideContentPlayer {
  // The whole controller needs to be detached so that it doesn't capture events from the remote.
  [self.contentPlayerViewController willMoveToParentViewController:nil];
  [self.contentPlayerViewController.view removeFromSuperview];
  [self.contentPlayerViewController removeFromParentViewController];
}

@end
      

Swift

import AVFoundation
import UIKit

class ViewController: UIViewController {
  static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"

  var playerViewController: AVPlayerViewController!

  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor.black;
    setUpContentPlayer()
  }

  func setUpContentPlayer() {
    // Load AVPlayer with path to your content.
    let contentURL! = URL(string: ViewController.ContentURLString)
    let player = AVPlayer(url: contentURL)
    playerViewController = AVPlayerViewController()
    playerViewController.player = player

    showContentPlayer()
  }

  func showContentPlayer() {
    self.addChild(playerViewController)
    playerViewController.view.frame = self.view.bounds
    self.view.insertSubview(playerViewController.view, at: 0)
    playerViewController.didMove(toParent:self)
  }

  func hideContentPlayer() {
    // The whole controller needs to be detached so that it doesn't capture  events from the remote.
    playerViewController.willMove(toParent:nil)
    playerViewController.view.removeFromSuperview()
    playerViewController.removeFromParent()
  }
}
      

4. ייבוא של IMA SDK

בשלב הבא, מוסיפים את המסגרת של IMA באמצעות הצהרת ייבוא מתחת לפעולות הייבוא הקיימות.

ViewController.m

Objective-C

#import "ViewController.h"

#import <AVKit/AVKit.h>
#import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h>
NSString *const kContentURLString =
    @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4";
      

Swift

import AVFoundation
import GoogleInteractiveMediaAds
import UIKit

class ViewController: UIViewController {
  static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"
      

5. הטמעת מעקב אחר המיקום הנוכחי של התוכן וצופה בסוף הסטרימינג

כדי להפעיל מודעות באמצע סרטון, IMA SDK צריך לעקוב אחר המיקום הנוכחי של תוכן הווידאו שלך. לשם כך, עליכם ליצור מחלקה שמטמיעה את IMAContentPlayhead. אם אתם משתמשים ב-AVPlayer, כפי שמוצג בדוגמה זו, ה-SDK מספק את המחלקה IMAAVPlayerContentPlayhead שעושה זאת בשבילכם. אם אתם לא משתמשים ב-AVPlayer, אתם צריכים להטמיע את IMAContentPlayhead במחלקה משלכם.

בנוסף, עליכם להודיע ל-SDK מתי התוכן שלכם מוכן, כדי שניתן יהיה להציג מודעות בסוף הסרטון. כדי לעשות זאת, מתקשרים ל-contentComplete ב-IMAAdsLoader באמצעות AVPlayerItemDidPlayToEndTimeNotification.

ViewController.m

Objective-C

...

@interface ViewController ()
@property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead;
@property(nonatomic) AVPlayerViewController *contentPlayerViewController;
@end

...

- (void)setupContentPlayer {
  // Create a content video player.
  NSURL *contentURL = [NSURL URLWithString:kContentURLString];
  AVPlayer *player = [AVPlayer playerWithURL:contentURL];
  self.contentPlayerViewController = [[AVPlayerViewController alloc] init];
  self.contentPlayerViewController.player = player;
  self.contentPlayerViewController.view.frame = self.view.bounds;
  self.contentPlayhead =
      [[IMAAVPlayerContentPlayhead alloc] initWithAVPlayer:self.contentPlayerViewController.player];

  // Track end of content.
  AVPlayerItem *contentPlayerItem = self.contentPlayerViewController.player.currentItem;
  [NSNotificationCenter.defaultCenter addObserver:self
                                         selector:@selector(contentDidFinishPlaying:)
                                             name:AVPlayerItemDidPlayToEndTimeNotification
                                           object:contentPlayerItem];

  // Attach content video player to view hierarchy.
  [self showContentPlayer];
}

...

- (void)contentDidFinishPlaying:(NSNotification *)notification {}

- (void)dealloc {
  [NSNotificationCenter.defaultCenter removeObserver:self];
}

@end
      

Swift

...

class ViewController: UIViewController {
  static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"

  var contentPlayhead: IMAAVPlayerContentPlayhead?
  var playerViewController: AVPlayerViewController!

  deinit {
    NotificationCenter.default.removeObserver(self)
  }

...

  func setUpContentPlayer() {
    // Load AVPlayer with path to your content.
    let contentURL! = URL(string: ViewController.ContentURLString)
    let player = AVPlayer(url: contentURL)
    playerViewController = AVPlayerViewController()
    playerViewController.player = player

    // Set up your content playhead and contentComplete callback.
    contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: player)
    NotificationCenter.default.addObserver(
      self,
      selector: #selector(ViewController.contentDidFinishPlaying(_:)),
      name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
      object: player.currentItem);

    showContentPlayer()
  }

...

  @objc func contentDidFinishPlaying(_ notification: Notification) {
    adsLoader.contentComplete()
  }
}
      

6. הפעלה של הכלי לטעינת מודעות ושליחת בקשה להצגת מודעות

כדי לבקש קבוצת מודעות, צריך ליצור מופע של IMAAdsLoader. אפשר להשתמש בכלי הטעינה הזה כדי לעבד IMAAdsRequest אובייקטים שמשויכים לכתובת URL של תג מודעה שצוין.

מומלץ לשמור רק מופע אחד של IMAAdsLoader לכל מחזור החיים של האפליקציה. כדי לשלוח בקשות נוספות להצגת מודעות, צריך ליצור אובייקט IMAAdsRequest חדש, אבל להשתמש שוב באותו IMAAdsLoader. למידע נוסף, עיינו בשאלות נפוצות בנושא IMA SDK.

ViewController.m

Objective-C

...

NSString *const kContentURLString =
    @"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4";
NSString *const kAdTagURLString = @"https://pubads.g.doubleclick.net/gampad/ads?"
    @"iu=/21775744923/external/vmap_ad_samples&sz=640x480&"
    @"cust_params=sample_ar%3Dpremidpostlongpod&"
    @"ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&"
    @"env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=";

@interface ViewController ()
@property(nonatomic) IMAAdsLoader *adsLoader;
@property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead;
@property(nonatomic) AVPlayerViewController *contentPlayerViewController;
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = UIColor.blackColor;
  [self setupContentPlayer];
  [self setupAdsLoader];
}

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  [self requestAds];
}

- (void)setupAdsLoader {
  self.adsLoader = [[IMAAdsLoader alloc] init];
}

- (void)requestAds {
  // Pass the main view as the container for ad display.
  IMAAdDisplayContainer *adDisplayContainer =
      [[IMAAdDisplayContainer alloc] initWithAdContainer:self.view];
  IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:kAdTagURLString
                                                adDisplayContainer:adDisplayContainer
                                                   contentPlayhead:self.contentPlayhead
                                                       userContext:nil];
  [self.adsLoader requestAdsWithRequest:request];
}

...

- (void)contentDidFinishPlaying:(NSNotification *)notification {
  // Notify the SDK that the postrolls should be played.
  [self.adsLoader contentComplete];
}

...

@end
      

Swift

...

class ViewController: UIViewController {
  static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"
  static let AdTagURLString = "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator="

  var adsLoader: IMAAdsLoader!
  var contentPlayhead: IMAAVPlayerContentPlayhead?
  var playerViewController: AVPlayerViewController!

...

  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor.black;
    setUpContentPlayer()
    setUpAdsLoader()
  }

  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated);
    requestAds()
  }

...

  func setUpAdsLoader() {
    adsLoader = IMAAdsLoader(settings: nil)
  }

  func requestAds() {
    // Create ad display container for ad rendering.
    let adDisplayContainer = IMAAdDisplayContainer(adContainer: self.view)
    // Create an ad request with your ad tag, display container, and optional user context.
    let request = IMAAdsRequest(
        adTagUrl: ViewController.AdTagURLString,
        adDisplayContainer: adDisplayContainer,
        contentPlayhead: contentPlayhead,
        userContext: nil)

    adsLoader.requestAds(with: request)
  }

  @objc func contentDidFinishPlaying(_ notification: Notification) {
    adsLoader.contentComplete()
  }
}
      

7. הגדרת משתמש שקיבל הרשאה לטעינת מודעות

כשאירוע טעינה מוצלח, IMAAdsLoader קורא לשיטה adsLoadedWithData של בעל הגישה שהוקצה לו, ומעביר לה מופע של IMAAdsManager. לאחר מכן אפשר להפעיל את מנהל המודעות, שטוען את המודעות הנפרדות, כפי שהוגדר בתגובה לכתובת ה-URL של תג המודעה.

בנוסף, חשוב לטפל בשגיאות שעלולות להתרחש במהלך הטעינה. אם המודעות לא נטענות, צריך לוודא שהפעלת מדיה תימשך, ללא מודעות, כדי לא להפריע לחוויית המשתמש.

ViewController.m

Objective-C

...

@interface ViewController () <IMAAdsLoaderDelegate>
@property(nonatomic) IMAAdsLoader *adsLoader;
@property(nonatomic) IMAAdsManager *adsManager;
@property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead;
@property(nonatomic) AVPlayerViewController *contentPlayerViewController;
@end

@implementation ViewController

...

- (void)setupAdsLoader {
  self.adsLoader = [[IMAAdsLoader alloc] init];
  self.adsLoader.delegate = self;
}

...

#pragma mark - IMAAdsLoaderDelegate

- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
  // Initialize and listen to the ads manager loaded for this request.
  self.adsManager = adsLoadedData.adsManager;
  [self.adsManager initializeWithAdsRenderingSettings:nil];
}

- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
  // Fall back to playing content.
  NSLog(@"Error loading ads: %@", adErrorData.adError.message);
  [self.contentPlayerViewController.player play];
}

@end
      

Swift

...

class ViewController: UIViewController, IMAAdsLoaderDelegate {

...

  var adsLoader: IMAAdsLoader!
  var adsManager: IMAAdsManager!
  var contentPlayhead: IMAAVPlayerContentPlayhead?
  var playerViewController: AVPlayerViewController!

...

  func setUpAdsLoader() {
    adsLoader = IMAAdsLoader(settings: nil)
    adsLoader.delegate = self
  }

...

  // MARK: - IMAAdsLoaderDelegate

  func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) {
    adsManager = adsLoadedData.adsManager
    adsManager.initialize(with: nil)
  }

  func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) {
    print("Error loading ads: " + adErrorData.adError.message)
    showContentPlayer()
    playerViewController.player?.play()
  }
}
      

8. הגדרת משתמש שקיבל הרשאה לניהול מודעות

לבסוף, כדי לנהל אירועים ושינויי מצב, מנהל המודעות צריך להעניק גישה משלו. ל-IMAAdManagerDelegate יש שיטות לטיפול בשגיאות ובאירועים של מודעות, וגם שיטות להפעלת תוכן הווידאו ולהשהיה שלו.

ההפעלה מתחילה

יש הרבה אירועים שאפשר לטפל בהם באמצעות השיטה didReceiveAdEvent, אבל בדוגמה הבסיסית הזו פשוט מאזינים לאירוע LOADED כדי לבקש ממנהל המודעות להתחיל בהפעלה של תוכן ומודעות.

ViewController.m

Objective-C

@interface ViewController () <IMAAdsLoaderDelegate, IMAAdsManagerDelegate>

...

- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
  // Initialize and listen to the ads manager loaded for this request.
  self.adsManager = adsLoadedData.adsManager;
  self.adsManager.delegate = self;
  [self.adsManager initializeWithAdsRenderingSettings:nil];
}

...

#pragma mark - IMAAdsManagerDelegate

- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
  // Play each ad once it has loaded.
  if (event.type == kIMAAdEvent_LOADED) {
    [adsManager start];
  }
}

...
      

Swift

...

class ViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {

...

  func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) {
    // Grab the instance of the IMAAdsManager and set yourself as the delegate.
    adsManager = adsLoadedData.adsManager
    adsManager.delegate = self
    adsManager.initialize(with: nil)
  }

...

  // MARK: - IMAAdsManagerDelegate

  func adsManager(_ adsManager: IMAAdsManager!, didReceive event: IMAAdEvent!) {
    // Play each ad once it has been loaded
    if event.type == IMAAdEventType.LOADED {
      adsManager.start()
    }
  }

...
      

טיפול בשגיאות

יש להוסיף גם handler לשגיאות במודעות. אם מתרחשת שגיאה, כמו בשלב הקודם, עליכם להמשיך את הפעלת התוכן.

ViewController.m

Objective-C


...

- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdError:(IMAAdError *)error {
  // Fall back to playing content.
  NSLog(@"AdsManager error: %@", error.message);
  [self showContentPlayer];
  [self.contentPlayerViewController.player play];
}
@end
      

Swift

...

  func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) {
    // Fall back to playing content
    print("AdsManager error: " + error.message)
    showContentPlayer()
    playerViewController.player?.play()
  }
      

הפעלת אירועים של הפעלה והשהיה

שתי שיטות הענקת הגישה האחרונות שצריך להטמיע משמשות להפעלה והשהיה של אירועי הפעלה והשהיה בתוכן הווידאו הבסיסי, בהתאם לדרישה של IMA SDK. הפעלת השהיה והפעלה כשנשלחת בקשה מונעת מהמשתמש להחמיץ חלקים מתוכן הסרטון בזמן הצגת המודעות.

ViewController.m

Objective-C

...

- (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager {
  // Pause the content for the SDK to play ads.
  [self.contentPlayerViewController.player pause];
  [self hideContentPlayer];
}

- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
  // Resume the content since the SDK is done playing ads (at least for now).
  [self showContentPlayer];
  [self.contentPlayerViewController.player play];
}

@end
      

Swift

...

  func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager!) {
    // Pause the content for the SDK to play ads.
    playerViewController.player?.pause()
    hideContentPlayer()
  }

  func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager!) {
    // Resume the content since the SDK is done playing ads (at least for now).
    showContentPlayer()
    playerViewController.player?.play()
  }
}
      

זהו! הבקשה שלך להצגת מודעות מתבצעת עכשיו באמצעות IMA SDK. למידע על תכונות נוספות של SDK, תוכלו להיעזר במדריכים האחרים או בדוגמאות ב-GitHub.

השלבים הבאים

כדי להגדיל את ההכנסות מפרסום בפלטפורמת tvOS, צריך לבקש הרשאה למעקב ולשקיפות של האפליקציה לצורך שימוש ב-IDFA.