Thiết lập SDK IMA cho DAI

SDK IMA giúp bạn dễ dàng tích hợp quảng cáo đa phương tiện vào trang web và ứng dụng của mình. SDK IMA có thể yêu cầu quảng cáo từ bất kỳ máy chủ quảng cáo tuân thủ VAST nào và quản lý việc phát quảng cáo trong ứng dụng của bạn. Với SDK DAI của IMA, các ứng dụng sẽ đưa ra yêu cầu về luồng cho quảng cáo và video nội dung – có thể là nội dung VOD hoặc nội dung trực tiếp. Sau đó, SDK sẽ trả về một luồng video kết hợp, nhờ đó bạn không phải quản lý việc chuyển đổi giữa quảng cáo và video nội dung trong ứng dụng của mình.

Chọn giải pháp DAI mà bạn quan tâm

DAI phân phát nhóm

Hướng dẫn này minh hoạ cách tích hợp SDK IMA DAI vào một ứng dụng trình phát video đơn giản. 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 PodServingExample xuống từ GitHub.

Tổng quan về DAI của IMA

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

  • 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ử giao diện người dùng của quảng cáo.
  • IMAAdsLoader – Một đối tượng yêu cầu luồng và xử lý các sự kiện do các đối tượng phản hồi yêu cầu luồng kích hoạt. Bạn chỉ nên khởi tạo một trình tải quảng cáo và có thể 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 IMAPodVODStreamRequest hoặc IMAPodStreamRequest.
  • IMAStreamManager – Một đối tượng xử lý các luồng chèn quảng cáo động và các lượt tương tác với phần phụ trợ DAI. Trình quản lý luồng phát cũng xử lý các ping theo dõi và chuyển tiếp các sự kiện luồng phát và quảng cáo đến nhà xuất bản.

Ngoài ra, để phát các luồng phân phát nhóm, bạn phải triển khai trình xử lý VTP tuỳ chỉnh. Trình xử lý VTP tuỳ chỉnh này sẽ gửi mã nhận dạng luồng đến đối tác kỹ thuật video (VTP) của bạn cùng với mọi thông tin khác mà VTP yêu cầu để trả về một tệp kê khai luồng chứa cả nội dung và quảng cáo được ghép. VTP sẽ cung cấp hướng dẫn về cách triển khai trình xử lý VTP tuỳ chỉnh.

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

Trước khi bắt đầu, bạn cần có những thông tin sau:

Bạn cũng cần các thông số dùng để yêu cầu luồng phát từ IMA SDK.

Thông số sự kiện phát trực tiếp
Mã mạng Mã mạng cho tài khoản Ad Manager 360 của bạn.
Khoá thành phần tuỳ chỉnh Khoá tài sản tuỳ chỉnh xác định sự kiện Phân phát nhóm của bạn trong Ad Manager 360. Tệp này có thể do trình thao tác tệp kê khai hoặc đối tác Phân phát nhóm quảng cáo bên thứ ba tạo.
Thông số luồng phát VOD
Mã mạng Mã mạng cho tài khoản Ad Manager 360 của bạn.

Tạo một 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à "PodServingExample".

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

Hãy sử dụng một trong 3 phương thức này để cài đặt IMA DAI SDK.

Cài đặt SDK bằng CocoaPods (nên dùng)

CocoaPods là một trình quản lý phần phụ thuộc cho các dự án Xcode và là phương thức được đề xuất để cài đặt IMA DAI SDK. Để biết thêm thông tin về cách cài đặt hoặc sử dụng CocoaPods, hãy xem tài liệu về CocoaPods. Sau khi bạn cài đặt CocoaPods, hãy làm theo hướng dẫn sau để cài đặt IMA DAI SDK:

  1. Trong cùng thư mục với tệp PodServingExample.xcodeproj, hãy tạo một tệp văn bản có tên là Podfile rồi thêm cấu hình sau:

    source 'https://github.com/CocoaPods/Specs.git'
    
    platform :ios, '14'
    
    target 'PodServingExample' do
      pod 'GoogleAds-IMA-iOS-SDK', '~> 3.26.1'
    end
    

  2. Từ thư mục chứa Podfile, hãy chạy:

    pod install --repo-update

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

SDK Quảng cáo tương tác trên phương tiện truyền thông hỗ trợ Trình quản lý gói Swift kể từ phiên bản 3.18.4. 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 DAI của IMA bằng cách 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 kiếm kho lưu trữ GitHub cho Gói Swift SDK DAI của IMA:

    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 DAI của IMA mà bạn muốn sử dụng. Đối với các dự án mới, bạn nên 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 xem bài viết của Apple.

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

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

Tạo một trình phát video đơn giản

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

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 IMA SDK vào trình điều khiển chế độ xem và áp dụng các giao thức IMAAdsLoaderDelegateIMAStreamManagerDelegate để 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 phát.

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 SDK IMA:

  • IMAAdsLoader – Quản lý các yêu cầu truyền phát trực tuyến 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 SDK IMA và trình phát đa phương tiện của bạn, đồng thời xử lý siêu dữ liệu có dấu thời gian.
  • IMAStreamManager – Quản lý hoạt động phát trực tuyến 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à vùng hiển thị 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 each ad's user interface elements and companion
    // slots.
    adDisplayContainer = IMAAdDisplayContainer(
      adContainer: videoView,
      viewController: self,
      companionSlots: nil)

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

Đưa ra yêu cầu phát trực tuyến

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

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

Objective-C

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

- (void)requestStream {
  // Create a stream request.
  IMAStreamRequest *request;
  if (kStreamType == StreamTypeLive) {
    // Live stream request. Replace the network code and custom asset key with your values.
    request = [[IMAPodStreamRequest alloc] initWithNetworkCode:kNetworkCode
                                                customAssetKey:kCustomAssetKey
                                            adDisplayContainer:self.adDisplayContainer
                                                  videoDisplay:self.imaVideoDisplay
                                         pictureInPictureProxy:nil
                                                   userContext:nil];
  } else {
    // VOD request. Replace the network code with your value.
    request = [[IMAPodVODStreamRequest alloc] initWithNetworkCode:kNetworkCode
                                               adDisplayContainer:self.adDisplayContainer
                                                     videoDisplay:self.imaVideoDisplay
                                            pictureInPictureProxy:nil
                                                      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 = IMAPodStreamRequest(
      networkCode: ViewController.networkCode,
      customAssetKey: ViewController.customAssetKey,
      adDisplayContainer: adDisplayContainer!,
      videoDisplay: self.imaVideoDisplay,
      pictureInPictureProxy: nil,
      userContext: nil)
    adsLoader?.requestStream(with: request)
  } else {
    // VOD stream request.
    let request = IMAPodVODStreamRequest(
      networkCode: ViewController.networkCode,
      adDisplayContainer: adDisplayContainer!,
      videoDisplay: self.imaVideoDisplay,
      pictureInPictureProxy: nil,
      userContext: nil)
    adsLoader?.requestStream(with: request)
  }
}

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

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 phát trực tuyến.

Trong phương thức uỷ quyền adsLoadedWithData, hãy đặt IMAStreamManagerDelegate. Truyền mã nhận dạng luồng đến trình xử lý VTP tuỳ chỉnh của bạn và truy xuất URL tệp kê khai luồng. Đối với sự kiện phát trực tiếp, hãy tải URL tệp kê khai vào màn hình video rồi bắt đầu phát. Đối với luồng VOD, hãy truyền URL tệp kê khai đến phương thức loadThirdPartyStream của trình quản lý luồng. Phương thức này yêu cầu dữ liệu sự kiện quảng cáo từ Ad Manager 360, sau đó tải URL tệp kê khai và bắt đầu phát.

Trong phương thức uỷ 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;

  // Build the Pod serving Stream URL.
  NSString *streamID = adsLoadedData.streamManager.streamId;
  // Your custom VTP handler takes the stream ID and returns the stream manifest URL.
  NSString *urlString = gCustomVTPHandler(streamID);
  NSURL *streamUrl = [NSURL URLWithString:urlString];
  if (kStreamType == StreamTypeLive) {
    // Load live streams directly into the AVPlayer.
    [self.imaVideoDisplay loadStream:streamUrl withSubtitles:@[]];
    [self.imaVideoDisplay play];
  } else {
    // Load VOD streams using the `loadThirdPartyStream` method in IMA SDK's stream manager.
    // The stream manager loads the stream, requests metadata, and starts playback.
    [self.streamManager loadThirdPartyStream:streamUrl streamSubtitles:@[]];
  }
}

- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
  // Log the error and play the backup 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

  // Initialize the stream manager to handle ad click and user interactions with ad UI elements.
  streamManager!.initialize(with: nil)

  // Build the Pod serving Stream URL.
  let streamID = streamManager!.streamId
  // Your custom VTP handler takes the stream ID and returns the stream manifest URL.
  let urlString = ViewController.customVTPParser(streamID!)
  let streamUrl = URL(string: urlString)
  if ViewController.requestType == StreamType.live {
    // Live streams can be loaded directly into the AVPlayer.
    imaVideoDisplay.loadStream(streamUrl!, withSubtitles: [])
    imaVideoDisplay.play()
  } else {
    // VOD streams are loaded using the IMA SDK's stream manager.
    // The stream manager loads the stream, requests metadata, and starts playback.
    streamManager!.loadThirdPartyStream(streamUrl!, streamSubtitles: [])
  }
}

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

Triển khai trình xử lý VTP tuỳ chỉnh

Trình xử lý VTP tuỳ chỉnh sẽ gửi mã nhận dạng luồng của người xem đến đối tác kỹ thuật video (VTP) của bạn cùng với mọi thông tin khác mà VTP của bạn yêu cầu để trả về một tệp kê khai luồng chứa cả nội dung và quảng cáo được ghép. VTP của bạn sẽ cung cấp hướng dẫn cụ thể về cách triển khai trình xử lý VTP tuỳ chỉnh.

Ví dụ: VTP có thể bao gồm một URL mẫu kê khai chứa macro [[STREAMID]]. Trong ví dụ này, trình xử lý chèn Mã nhận dạng luồng thay cho macro và trả về URL tệp kê khai kết quả.

Objective-C

/// Custom VTP Handler.
///
/// Returns the stream manifest URL from the video technical partner or manifest manipulator.
static NSString *(^gCustomVTPHandler)(NSString *) = ^(NSString *streamID) {
  // Insert synchronous code here to retrieve a stream manifest URL from your video tech partner
  // or manifest manipulation server.
  // This example uses a hardcoded URL template, containing a placeholder for the stream
  // ID and replaces the placeholder with the stream ID.
  NSString *manifestUrl = @"YOUR_MANIFEST_URL_TEMPLATE";
  return [manifestUrl stringByReplacingOccurrencesOfString:@"[[STREAMID]]"
                                                withString:streamID];
};

Swift

/// Custom VTP Handler.
///
/// Returns the stream manifest URL from the video technical partner or manifest manipulator.
static let customVTPParser = { (streamID: String) -> (String) in
  // Insert synchronous code here to retrieve a stream manifest URL from your video tech partner
  // or manifest manipulation server.
  // This example uses a hardcoded URL template, containing a placeholder for the stream
  // ID and replaces the placeholder with the stream ID.
  let manifestURL = "YOUR_MANIFEST_URL_TEMPLATE"
  return manifestURL.replacingOccurrences(of: "[[STREAMID]]", with: streamID)
}

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 truyền trực tuyến đế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")")
}

Dọn dẹp các thành phần DAI của IMA

Để dừng phát trực tuyến, hãy dừng tất cả hoạt động theo dõi quảng cáo và giải phóng tất cả các thành phần luồng đã tải, hãy gọi IMAStreamManager.destroy().

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