Thiết lập bằng DAI dịch vụ đầy đủ

Chọn nền tảng: HTML5 Android iOS tvOS Cast Roku

Hướng dẫn này trình bày cách tích hợp SDK IMA DAI vào một ứng dụng trình phát video. Nếu bạn muốn xem hoặc làm theo một mẫu tích hợp hoàn chỉnh, hãy tải BasicExample xuống từ GitHub.

Tổng quan về IMA DAI

Việc triển khai IMA DAI bao gồm 4 thành phần SDK chính, như hướng dẫn này minh hoạ:

  • IMAAdDisplayContainer – Một đối tượng vùng chứa nằm trên phần tử phát video và chứa các phần tử trên giao diện người dùng quảng cáo.
  • IMAAdsLoader – Một đối tượng yêu cầu luồng và xử lý các sự kiện được kích hoạt bởi đối tượng phản hồi yêu cầu luồng. Bạn chỉ nên tạo thực thể một trình tải quảng cáo và có thể sử dụng lại trình tải này trong suốt thời gian hoạt động của ứng dụng.
  • IMAStreamRequest – IMAVODStreamRequest hoặc IMALiveStreamRequest. Đối tượng xác định yêu cầu về luồng. Yêu cầu về luồng có thể là video theo yêu cầu hoặc sự kiện phát trực tiếp. Yêu cầu phát trực tiếp chỉ định khoá thành phần, trong khi yêu cầu VOD chỉ định mã CMS và mã video. Cả hai loại yêu cầu đều có thể bao gồm khoá API cần thiết để truy cập vào các luồng được chỉ định và mã mạng Google Ad Manager để IMA SDK xử lý giá trị nhận dạng quảng cáo như được chỉ định trong phần cài đặt Google Ad Manager.
  • IMAStreamManager – Một đối tượng xử lý các luồng chèn quảng cáo động và hoạt động tương tác với phần phụ trợ DAI. Trình quản lý luồng cũng xử lý các ping theo dõi và chuyển tiếp các sự kiện quảng cáo và luồng đến nhà xuất bản.

Điều kiện tiên quyết

Trước khi bắt đầu, bạn cần có:

Bạn cũng cần có các tham số để yêu cầu luồng từ IMA SDK. Để biết ví dụ về tham số yêu cầu, hãy xem phần Luồng mẫu.

Tham số sự kiện phát trực tiếp
Khoá thành phần Khoá thành phần xác định sự kiện phát trực tiếp của bạn trong Google Ad Manager.
Ví dụ: c-rArva4ShKVIAkNfy6HUQ
Tham số luồng VOD
Mã nguồn nội dung Mã nhận dạng nguồn nội dung từ Google Ad Manager.
Ví dụ: 2548831
Mã video Mã video từ Google Ad Manager.
Ví dụ: tears-of-steel
Tham số chung (VOD và sự kiện phát trực tiếp)
Mã mạng Mã mạng Google Ad Manager của bạn.
Ví dụ: 21775744923

Tạo dự án Xcode mới

Trong Xcode, hãy tạo một dự án iOS mới bằng Objective-C có tên là "BasicExample".

Thêm SDK IMA DAI vào dự án Xcode

Để cài đặt IMA SDK, hãy chọn một phương thức bạn muốn.

Nên dùng: Cài đặt SDK bằng Trình quản lý gói Swift

SDK quảng cáo trên phương tiện truyền thông tương tác hỗ trợ Trình quản lý gói Swift phiên bản 3.18.4 trở lên. Hãy làm theo các bước sau để nhập gói Swift.

  1. Trong Xcode, hãy cài đặt Gói Swift SDK IMA DAI: chuyển đến File (Tệp) > Add Packages (Thêm gói).

  2. Trong lời nhắc xuất hiện, hãy tìm kho lưu trữ GitHub của Gói Swift SDK IMA DAI:

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
    
  3. Chọn phiên bản của Gói Swift SDK IMA DAI mà bạn muốn sử dụng. Đối với các dự án mới, hãy sử dụng Phiên bản lớn tiếp theo.

Khi bạn hoàn tất, Xcode sẽ phân giải các phần phụ thuộc của gói và tải các phần phụ thuộc đó xuống ở chế độ nền. Để biết thêm thông tin chi tiết về cách thêm các phần phụ thuộc của gói, hãy đọc bài viết của Apple.

Tải xuống và cài đặt SDK theo cách thủ công

Nếu bạn không muốn sử dụng Trình quản lý gói Swift, hãy tải xuống và thêm IMA SDK vào dự án theo cách thủ công.

Tạo trình phát video

Triển khai trình phát video trong bộ điều khiển khung hiển thị chính; gói trình phát AV trong khung hiển thị giao diện người dùng. IMA SDK sử dụng chế độ xem giao diện người dùng để hiển thị các phần tử trên giao diện người dùng của quảng cáo hiển thị.

Objective-C

#import "ViewController.h"

#import <AVKit/AVKit.h>

/// Content URL.
static NSString *const kBackupContentUrl =
    @"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8";

@interface ViewController ()
/// Play button.
@property(nonatomic, weak) IBOutlet UIButton *playButton;

@property(nonatomic, weak) IBOutlet UIView *videoView;
/// Video player.
@property(nonatomic, strong) AVPlayer *videoPlayer;
@end

@implementation ViewController

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

  // Load AVPlayer with the path to your content.
  NSURL *contentURL = [NSURL URLWithString:kBackupContentUrl];
  self.videoPlayer = [AVPlayer playerWithURL:contentURL];

  // Create a player layer for the player.
  AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];

  // Size, position, and display the AVPlayer.
  playerLayer.frame = self.videoView.layer.bounds;
  [self.videoView.layer addSublayer:playerLayer];
}

- (IBAction)onPlayButtonTouch:(id)sender {
  [self.videoPlayer play];
  self.playButton.hidden = YES;
}

@end

Swift

// Copyright 2024 Google LLC. All rights reserved.
//
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under
// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
// ANY KIND, either express or implied. See the License for the specific language governing
// permissions and limitations under the License.

import AVFoundation
import UIKit

class ViewController: UIViewController {

  /// Content URL.
  static let backupStreamURLString =
    "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"

  /// Play button.
  @IBOutlet private weak var playButton: UIButton!

  @IBOutlet private weak var videoView: UIView!
  /// Video player.
  private var videoPlayer: AVPlayer?

  override func viewDidLoad() {
    super.viewDidLoad()

    playButton.layer.zPosition = CGFloat(MAXFLOAT)

    // Load AVPlayer with path to our content.
    // note: this unwrap is safe because the URL is a constant string.
    let contentURL = URL(string: ViewController.backupStreamURLString)!
    videoPlayer = AVPlayer(url: contentURL)

    // Create a player layer for the player.
    let playerLayer = AVPlayerLayer(player: videoPlayer)

    // Size, position, and display the AVPlayer.
    playerLayer.frame = videoView.layer.bounds
    videoView.layer.addSublayer(playerLayer)
  }

  @IBAction func onPlayButtonTouch(_ sender: Any) {
    videoPlayer?.play()
    playButton.isHidden = true
  }
}

Khởi chạy trình tải quảng cáo

Nhập SDK IMA vào trình điều khiển chế độ xem và áp dụng các giao thức IMAAdsLoaderDelegate và IMAStreamManagerDelegate để xử lý các sự kiện của trình tải quảng cáo và trình quản lý luồng.

Thêm các thuộc tính riêng tư này để lưu trữ các thành phần chính của IMA SDK:

  • IMAAdsLoader
    • Quản lý các yêu cầu về luồng trong suốt vòng đời của ứng dụng.
  • IMAAdDisplayContainer
    • Xử lý việc chèn và quản lý các phần tử giao diện người dùng quảng cáo.
  • IMAAVPlayerVideoDisplay – Giao tiếp giữa IMA SDK và trình phát nội dung nghe nhìn của bạn, đồng thời xử lý siêu dữ liệu theo thời gian.
  • IMAStreamManager – Quản lý việc phát luồng và kích hoạt các sự kiện liên quan đến quảng cáo.

Khởi chạy trình tải quảng cáo, vùng chứa hiển thị quảng cáo và màn hình video sau khi chế độ xem tải.

Objective-C

@import GoogleInteractiveMediaAds;

// ...

@interface ViewController () <IMAAdsLoaderDelegate, IMAStreamManagerDelegate>
/// The entry point for the IMA DAI SDK to make DAI stream requests.
@property(nonatomic, strong) IMAAdsLoader *adsLoader;
/// The container where the SDK renders each ad's user interface elements and companion slots.
@property(nonatomic, strong) IMAAdDisplayContainer *adDisplayContainer;
/// The reference of your video player for the IMA DAI SDK to monitor playback and handle timed
/// metadata.
@property(nonatomic, strong) IMAAVPlayerVideoDisplay *imaVideoDisplay;
/// References the stream manager from the IMA DAI SDK after successful stream loading.
@property(nonatomic, strong) IMAStreamManager *streamManager;

// ...

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  // ...

  self.adsLoader = [[IMAAdsLoader alloc] initWithSettings:nil];
  self.adsLoader.delegate = self;

  // Create an ad display container for rendering each ad's user interface elements and companion
  // slots.
  self.adDisplayContainer =
      [[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
                                          viewController:self
                                          companionSlots:nil];

  // Create an IMAAVPlayerVideoDisplay to give the SDK access to your video player.
  self.imaVideoDisplay = [[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.videoPlayer];
}

Swift

import GoogleInteractiveMediaAds
// ...

class ViewController: UIViewController, IMAAdsLoaderDelegate, IMAStreamManagerDelegate {
  // ...

  /// The entry point for the IMA DAI SDK to make DAI stream requests.
  private var adsLoader: IMAAdsLoader?
  /// The container where the SDK renders each ad's user interface elements and companion slots.
  private var adDisplayContainer: IMAAdDisplayContainer?
  /// The reference of your video player for the IMA DAI SDK to monitor playback and handle timed
  /// metadata.
  private var imaVideoDisplay: IMAAVPlayerVideoDisplay!
  /// References the stream manager from the IMA DAI SDK after successfully loading the DAI stream.
  private var streamManager: IMAStreamManager?

  // ...

  override func viewDidLoad() {
    super.viewDidLoad()

    // ...

    adsLoader = IMAAdsLoader(settings: nil)
    adsLoader?.delegate = self

    // Create an ad display container for rendering ad UI elements and the companion ad.
    adDisplayContainer = IMAAdDisplayContainer(
      adContainer: videoView,
      viewController: self,
      companionSlots: nil)

    // Create an IMAAVPlayerVideoDisplay to give the SDK access to your video player.
    imaVideoDisplay = IMAAVPlayerVideoDisplay(avPlayer: videoPlayer)
  }

Tạo yêu cầu phát trực tiếp

Khi người dùng nhấn vào nút phát, hãy tạo một yêu cầu luồng mới. Sử dụng lớp IMALiveStreamRequest cho sự kiện phát trực tiếp. Đối với luồng VOD, hãy sử dụng lớp IMAVODStreamRequest.

Yêu cầu về luồng cần có các tham số luồng, cũng như thông tin tham chiếu đến vùng chứa hiển thị quảng cáo và màn hình video.

Objective-C

- (IBAction)onPlayButtonTouch:(id)sender {
  [self requestStream];
  self.playButton.hidden = YES;
}

- (void)requestStream {
  // Create a stream request. Use one of "Live stream request" or "VOD request", depending on your
  // type of stream.
  if (kStreamType == StreamTypeLive) {
    // Live stream request. Replace the asset key with your value.
    IMALiveStreamRequest *request =
        [[IMALiveStreamRequest alloc] initWithAssetKey:kLiveStreamAssetKey
                                           networkCode:kNetworkCode
                                    adDisplayContainer:self.adDisplayContainer
                                          videoDisplay:self.imaVideoDisplay
                                           userContext:nil];
    request.useHLSInterstitials = YES;
    [self.adsLoader requestStreamWithRequest:request];
  } else {
    // VOD request. Replace the content source ID and video ID with your values.
    IMAVODStreamRequest *request =
        [[IMAVODStreamRequest alloc] initWithContentSourceID:kVODContentSourceID
                                                     videoID:kVODVideoID
                                                 networkCode:kNetworkCode
                                          adDisplayContainer:self.adDisplayContainer
                                                videoDisplay:self.imaVideoDisplay
                                                 userContext:nil];
    [self.adsLoader requestStreamWithRequest:request];
  }
}

Swift

@IBAction func onPlayButtonTouch(_ sender: Any) {
  requestStream()
  playButton.isHidden = true
}

func requestStream() {
  // Create a stream request. Use one of "Livestream request" or "VOD request".
  if ViewController.requestType == StreamType.live {
    // Livestream request.
    let request = IMALiveStreamRequest(
      assetKey: ViewController.assetKey,
      networkCode: ViewController.networkCode,
      adDisplayContainer: adDisplayContainer!,
      videoDisplay: imaVideoDisplay,
      userContext: nil)
    request.useHLSInterstitials = true
    adsLoader?.requestStream(with: request)
  } else {
    // VOD stream request.
    let request = IMAVODStreamRequest(
      contentSourceID: ViewController.contentSourceID,
      videoID: ViewController.videoID,
      networkCode: ViewController.networkCode,
      adDisplayContainer: adDisplayContainer!,
      videoDisplay: imaVideoDisplay,
      userContext: nil)
    adsLoader?.requestStream(with: request)
  }
}

Theo dõi các sự kiện tải luồng

Lớp IMAAdsLoader gọi các phương thức IMAAdsLoaderDelegate khi khởi chạy thành công hoặc không thành công yêu cầu luồng.

Trong phương thức uỷ quyền adsLoadedWithData, hãy đặt IMAStreamManagerDelegate. Khởi chạy trình quản lý luồng. Khi khởi chạy, trình quản lý luồng sẽ bắt đầu phát.

Trong phương thức uỷ quyền failedWithErrorData, hãy ghi lại lỗi. Bạn có thể phát luồng dự phòng (không bắt buộc). Xem các phương pháp hay nhất về DAI.

Objective-C

- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
  NSLog(@"Stream created with: %@.", adsLoadedData.streamManager.streamId);
  self.streamManager = adsLoadedData.streamManager;
  self.streamManager.delegate = self;
  [self.streamManager initializeWithAdsRenderingSettings:nil];
}

- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
  // Log the error and play the content.
  NSLog(@"AdsLoader error, code:%ld, message: %@", adErrorData.adError.code,
        adErrorData.adError.message);
  [self.videoPlayer play];
}

Swift

func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
  print("DAI stream loaded. Stream session ID: \(adsLoadedData.streamManager!.streamId!)")
  streamManager = adsLoadedData.streamManager!
  streamManager!.delegate = self
  streamManager!.initialize(with: nil)
}

func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
  print("Error loading DAI stream. Error message: \(adErrorData.adError.message!)")
  // Play the backup stream.
  videoPlayer.play()
}

Theo dõi các sự kiện quảng cáo

IMAStreamManager gọi các phương thức IMAStreamManagerDelegate để truyền các sự kiện và lỗi của luồng đến ứng dụng của bạn.

Trong ví dụ này, hãy ghi lại các sự kiện quảng cáo chính vào bảng điều khiển:

Objective-C

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {
  NSLog(@"Ad event (%@).", event.typeString);
  switch (event.type) {
    case kIMAAdEvent_STARTED: {
      // Log extended data.
      NSString *extendedAdPodInfo = [[NSString alloc]
          initWithFormat:@"Showing ad %ld/%ld, bumper: %@, title: %@, description: %@, contentType:"
                         @"%@, pod index: %ld, time offset: %lf, max duration: %lf.",
                         (long)event.ad.adPodInfo.adPosition, (long)event.ad.adPodInfo.totalAds,
                         event.ad.adPodInfo.isBumper ? @"YES" : @"NO", event.ad.adTitle,
                         event.ad.adDescription, event.ad.contentType,
                         (long)event.ad.adPodInfo.podIndex, event.ad.adPodInfo.timeOffset,
                         event.ad.adPodInfo.maxDuration];

      NSLog(@"%@", extendedAdPodInfo);
      break;
    }
    case kIMAAdEvent_AD_BREAK_STARTED: {
      NSLog(@"Ad break started");
      break;
    }
    case kIMAAdEvent_AD_BREAK_ENDED: {
      NSLog(@"Ad break ended");
      break;
    }
    case kIMAAdEvent_AD_PERIOD_STARTED: {
      NSLog(@"Ad period started");
      break;
    }
    case kIMAAdEvent_AD_PERIOD_ENDED: {
      NSLog(@"Ad period ended");
      break;
    }
    default:
      break;
  }
}

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {
  NSLog(@"StreamManager error with type: %ld\ncode: %ld\nmessage: %@", error.type, error.code,
        error.message);
  [self.videoPlayer play];
}

Swift

func streamManager(_ streamManager: IMAStreamManager, didReceive event: IMAAdEvent) {
  print("Ad event \(event.typeString).")
  switch event.type {
  case IMAAdEventType.STARTED:
    // Log extended data.
    if let ad = event.ad {
      let extendedAdPodInfo = String(
        format: "Showing ad %zd/%zd, bumper: %@, title: %@, "
          + "description: %@, contentType:%@, pod index: %zd, "
          + "time offset: %lf, max duration: %lf.",
        ad.adPodInfo.adPosition,
        ad.adPodInfo.totalAds,
        ad.adPodInfo.isBumper ? "YES" : "NO",
        ad.adTitle,
        ad.adDescription,
        ad.contentType,
        ad.adPodInfo.podIndex,
        ad.adPodInfo.timeOffset,
        ad.adPodInfo.maxDuration)

      print("\(extendedAdPodInfo)")
    }
    break
  case IMAAdEventType.AD_BREAK_STARTED:
    print("Ad break started.")
    break
  case IMAAdEventType.AD_BREAK_ENDED:
    print("Ad break ended.")
    break
  case IMAAdEventType.AD_PERIOD_STARTED:
    print("Ad period started.")
    break
  case IMAAdEventType.AD_PERIOD_ENDED:
    print("Ad period ended.")
    break
  default:
    break
  }
}

func streamManager(_ streamManager: IMAStreamManager, didReceive error: IMAAdError) {
  print("StreamManager error with type: \(error.type)")
  print("code: \(error.code)")
  print("message: \(error.message ?? "Unknown Error")")
}

Chạy ứng dụng của bạn. Nếu thành công, hãy yêu cầu và phát các luồng DAI của Google bằng IMA SDK. Để tìm hiểu thêm về các tính năng nâng cao của SDK, hãy xem các hướng dẫn khác trong thanh bên trái hoặc mẫu trên GitHub.