Konfigurowanie pakietu IMA SDK na potrzeby DAI

Pakiety IMA SDK ułatwiają integrację reklam multimedialnych z witrynami i aplikacjami. Pakiety IMA SDK mogą wysyłać żądania reklam do dowolnego serwera reklam zgodnego z VAST i zarządzać odtwarzaniem reklam w aplikacjach. Za pomocą pakietów IMA DAI SDK aplikacje wysyłają żądanie strumienia reklamy i treści wideo – VOD lub treści na żywo. Pakiet SDK zwraca wtedy połączony strumień wideo, dzięki czemu nie musisz zarządzać przełączaniem między reklamą a treściami wideo w aplikacji.

Wybierz interesujące Cię rozwiązanie DAI

Wyświetlanie bloków reklamowych w ramach dynamicznego wstawiania reklam

Z tego przewodnika dowiesz się, jak zintegrować pakiet IMA DAI SDK z prostą aplikacją odtwarzacza wideo. Jeśli chcesz wyświetlić gotową przykładową integrację lub ją przeprowadzić, pobierz PodServingExample z GitHub.

Omówienie IMA DAI

Wdrażanie IMA DAI obejmuje 4 główne komponenty pakietu SDK, które zostały opisane w tym przewodniku:

  • IMAAdDisplayContainer – kontener, który znajduje się nad elementem odtwarzania wideo i zawiera elementy interfejsu reklamy.
  • IMAAdsLoader – obiekt, który wysyła żądania strumieni i obsługuje zdarzenia wywoływane przez obiekty odpowiedzi na żądanie strumienia. Należy utworzyć tylko jeden moduł wczytywania reklam, który można ponownie wykorzystywać przez cały okres działania aplikacji.
  • IMAStreamRequest IMAPodVODStreamRequest lub IMAPodStreamRequest.
  • IMAStreamManager– Obiekt, który obsługuje strumienie dynamicznego wstawiania reklam i interakcje z backendem DAI. Menedżer strumienia obsługuje też pingi śledzące i przesyła zdarzenia strumienia i reklamy do wydawcy.

Dodatkowo, aby odtwarzać strumienie wyświetlania podów, musisz zaimplementować niestandardowy moduł obsługi VTP. Ten niestandardowy moduł obsługi VTP wysyła identyfikator strumienia do partnera technicznego ds. wideo (VTP) wraz z wszelkimi innymi informacjami, których potrzebuje on do zwrócenia manifestu strumienia zawierającego zarówno treści, jak i połączone reklamy. Dostawca platformy VTP przekaże Ci instrukcje dotyczące implementacji niestandardowego modułu obsługi VTP.

Wymagania wstępne

Zanim zaczniesz, musisz mieć:

Potrzebujesz też parametrów używanych do przesyłania żądań strumienia z pakietu IMA SDK.

Parametry transmisji na żywo
Kod sieci Kod sieci na koncie Ad Managera 360.
Niestandardowy klucz pliku Niestandardowy klucz zasobu, który identyfikuje zdarzenie wyświetlania w ramach Pod Serving w usłudze Ad Manager 360. Może go utworzyć manipulator pliku manifestu lub zewnętrzny partner w zakresie wyświetlania bloków reklamowych.
Parametry strumienia VOD
Kod sieci Kod sieci na koncie Ad Managera 360.

Tworzenie nowego projektu Xcode

W Xcode utwórz nowy projekt iOS w Objective-C o nazwie „PodServingExample”.

Dodawanie pakietu IMA DAI SDK do projektu w Xcode

Aby zainstalować pakiet IMA DAI SDK, użyj jednej z tych 3 metod.

Instalowanie pakietu SDK za pomocą CocoaPods (zalecane)

CocoaPods to menedżer zależności dla projektów Xcode. Jest to zalecana metoda instalowania pakietu IMA DAI SDK. Więcej informacji o instalowaniu i używaniu CocoaPods znajdziesz w dokumentacji CocoaPods. Po zainstalowaniu CocoaPods wykonaj te instrukcje, aby zainstalować pakiet IMA DAI SDK:

  1. W tym samym katalogu, w którym znajduje się plik PodServingExample.xcodeproj, utwórz plik tekstowy o nazwie Podfile i dodaj tę konfigurację:

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

  2. W katalogu zawierającym plik Podfile uruchom:

    pod install --repo-update

Instalowanie pakietu SDK za pomocą menedżera pakietów Swift

Pakiet SDK do wyświetlania interaktywnych reklam medialnych obsługuje Swift Package Manager od wersji 3.18.4. Aby zaimportować pakiet Swift, wykonaj te czynności:

  1. W Xcode zainstaluj pakiet IMA DAI SDK Swift, wybierając File > Add Packages (Plik > Dodaj pakiety).

  2. W wyświetlonym oknie wyszukaj repozytorium pakietu IMA DAI SDK Swift Package w GitHubie:

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
    
  3. Wybierz wersję pakietu IMA DAI SDK Swift Package, której chcesz używać. W przypadku nowych projektów zalecamy używanie opcji Do następnej wersji głównej.

Gdy skończysz, Xcode przetworzy zależności pakietu i pobierze je w tle. Więcej informacji o dodawaniu zależności pakietów znajdziesz w artykule Apple.

Ręczne pobieranie i instalowanie pakietu SDK

Jeśli nie chcesz używać narzędzi Swift Package Manager ani CocoaPods, możesz pobrać pakiet IMA DAI SDK i ręcznie dodać go do projektu.

Tworzenie prostego odtwarzacza wideo

Zaimplementuj odtwarzacz wideo w głównym kontrolerze widoku, używając odtwarzacza AV opakowanego w widok interfejsu. Pakiet IMA SDK używa widoku interfejsu do wyświetlania elementów interfejsu reklamy.

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
  }
}

Zainicjuj moduł wczytywania reklam.

Zaimportuj pakiet IMA SDK do kontrolera widoku i zaimplementuj protokoły IMAAdsLoaderDelegate i IMAStreamManagerDelegate do obsługi zdarzeń modułu wczytywania reklam i menedżera strumienia.

Dodaj te prywatne właściwości, aby przechowywać kluczowe komponenty pakietu IMA SDK:

  • IMAAdsLoader – zarządza żądaniami strumieniowania przez cały okres działania aplikacji.
  • IMAAdDisplayContainer – obsługuje wstawianie elementów interfejsu użytkownika reklam i zarządzanie nimi.
  • IMAAVPlayerVideoDisplay – komunikuje się między pakietem IMA SDK a odtwarzaczem multimediów i obsługuje metadane czasowe.
  • IMAStreamManager – zarządza odtwarzaniem strumienia i wywołuje zdarzenia związane z reklamami.

Po wczytaniu widoku zainicjuj moduł wczytywania reklam, kontener wyświetlania reklam i wyświetlanie wideo.

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)
  }

Tworzenie żądania strumienia

Gdy użytkownik naciśnie przycisk odtwarzania, wyślij nowe żądanie strumienia. Użyj klasy IMAPodStreamRequest w przypadku transmisji na żywo. W przypadku strumieni VOD użyj klasy IMAPodVODStreamRequest.

Żądanie strumienia wymaga parametrów strumienia, a także odwołania do kontenera wyświetlania reklam i wyświetlania wideo.

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)
  }
}

Nasłuchiwanie zdarzeń wczytywania strumienia

Klasa IMAAdsLoader wywołuje metody IMAAdsLoaderDelegate po udanej inicjalizacji lub niepowodzeniu żądania strumienia.

W metodzie delegata adsLoadedWithData ustaw IMAStreamManagerDelegate. Przekaż identyfikator strumienia do niestandardowego modułu obsługi VTP i pobierz adres URL manifestu strumienia. W przypadku transmisji na żywo wczytaj adres URL pliku manifestu do wyświetlacza wideo i rozpocznij odtwarzanie. W przypadku strumieni VOD przekaż adres URL pliku manifestu do metody loadThirdPartyStream menedżera strumieni. Ta metoda wysyła do Ad Managera 360 żądanie danych o zdarzeniach związanych z reklamami, a następnie wczytuje adres URL pliku manifestu i rozpoczyna odtwarzanie.

W metodzie delegata failedWithErrorData zapisz błąd w dzienniku. Opcjonalnie możesz odtworzyć strumień zapasowy. Zobacz sprawdzone metody 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()
}

Wdrażanie niestandardowego modułu obsługi VTP

Niestandardowy moduł obsługi VTP wysyła identyfikator strumienia widza do Twojego partnera technicznego ds. wideo (VTP) wraz z wszelkimi innymi informacjami, których VTP potrzebuje do zwrócenia manifestu strumienia zawierającego zarówno treści, jak i połączone reklamy. Dostawca platformy weryfikacji tożsamości dostarczy Ci szczegółowe instrukcje dotyczące implementacji niestandardowego modułu obsługi platformy VTP.

Na przykład szablon VTP może zawierać adres URL szablonu manifestu z makrem [[STREAMID]]. W tym przykładzie moduł obsługi wstawia identyfikator strumienia w miejsce makra i zwraca wynikowy adres URL pliku manifestu.

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)
}

Nasłuchiwanie zdarzeń reklamowych

IMAStreamManager wywołuje metody IMAStreamManagerDelegate, aby przekazywać zdarzenia strumieniowe i błędy do aplikacji.

W tym przykładzie zaloguj w konsoli główne zdarzenia reklamy:

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")")
}

Czyszczenie zasobów IMA DAI

Aby zatrzymać odtwarzanie strumienia, zatrzymać śledzenie reklam i zwolnić wszystkie załadowane komponenty strumienia, wywołaj funkcję IMAStreamManager.destroy().

Uruchom aplikację. Jeśli wszystko przebiegnie prawidłowo, możesz wysyłać żądania strumieni Google DAI i je odtwarzać za pomocą pakietu IMA SDK. Więcej informacji o zaawansowanych funkcjach pakietu SDK znajdziesz w innych przewodnikach na pasku bocznym po lewej stronie lub w przykładach na GitHubie.