تسهّل حِزم تطوير البرامج (SDK) لإعلانات الوسائط التفاعلية دمج إعلانات الوسائط المتعددة في مواقعك الإلكترونية وتطبيقاتك. يمكن لحِزم تطوير البرامج لإعلانات الوسائط التفاعلية طلب الإعلانات من أي خادم إعلانات متوافق مع VAST وإدارة تشغيل الإعلانات في تطبيقاتك. باستخدام حِزم تطوير البرامج لإدراج الإعلانات الديناميكي في "إعلانات الوسائط التفاعلية"، تقدّم التطبيقات طلب بث لإعلان وفيديو محتوى، سواء كان فيديو عند الطلب أو محتوى مباشر. بعد ذلك، تعرض حزمة SDK بث فيديو مدمجًا، ما يغنيك عن إدارة التبديل بين الفيديو الإعلاني وفيديو المحتوى داخل تطبيقك.
اختيار حلّ "الإعلانات الديناميكية أثناء عرض الفيديو" الذي يهمّك
إدراج إعلان ديناميكي كامل الخدمات
يوضّح هذا الدليل كيفية دمج حزمة تطوير البرامج (SDK) الخاصة بـ "إعلانات البث المباشر" في "إعلانات الوسائط التفاعلية" في تطبيق بسيط لمشغّل فيديو. إذا أردت الاطّلاع على نموذج تكامل مكتمل أو اتّباعه، يمكنك تنزيل BasicExample من GitHub.
نظرة عامة على ميزة "إدراج الإعلان الديناميكي" في IMA
يتضمّن تنفيذ "إعلانات الوسائط التفاعلية" (IMA) في "الإعلانات الديناميكية أثناء البث" ثلاثة مكوّنات رئيسية في حزمة SDK، كما هو موضّح في هذا الدليل:
IMAAdDisplayContainer: هو عنصر حاوٍ يظهر فوق عنصر تشغيل الفيديو ويحتوي على عناصر واجهة مستخدم الإعلان.-
IMAAdsLoader: عنصر يطلب بث المحتوى ويتعامل مع الأحداث التي يتم تشغيلها بواسطة عناصر الرد على طلب بث المحتوى. يجب إنشاء أداة تحميل إعلانات واحدة فقط، ويمكن إعادة استخدامها طوال مدة تشغيل التطبيق. IMAStreamRequest– إماIMAVODStreamRequestأوIMALiveStreamRequest: كائن يحدّد طلب بث. يمكن أن تكون طلبات البث المباشر لفيديوهات عند الطلب أو أحداث بث مباشر. تحدّد طلبات البث المباشر مفتاح مادة عرض، بينما تحدّد طلبات الفيديو عند الطلب معرّفًا في "نظام إدارة المحتوى" ومعرّف فيديو. يمكن أن يتضمّن كلا نوعَي الطلبات اختياريًا مفتاح واجهة برمجة التطبيقات اللازم للوصول إلى عمليات البث المحدّدة، ورمز شبكة "مدير إعلانات Google" لكي تتعامل أداة تطوير البرامج لإعلانات الوسائط التفاعلية (IMA) مع معرّفات الإعلانات على النحو المحدّد في إعدادات "مدير إعلانات Google".IMAStreamManager: عنصر يعالج عمليات بث "إدراج الإعلان الديناميكي" والتفاعلات مع الخلفية البرمجية لميزة "إدراج الإعلان الديناميكي". يتولّى مدير البث أيضًا معالجة طلبات اختبار الاتصال الخاصة بالتتبُّع وإعادة توجيه أحداث البث والإعلانات إلى الناشر.
المتطلبات الأساسية
قبل البدء، يجب أن يتوفّر لديك ما يلي:
- الإصدار 13 أو الإصدارات الأحدث من Xcode
- Swift Package Manager أو CocoaPods أو نسخة تم تنزيلها من حزمة تطوير البرامج (SDK) الخاصة بـ "إعلانات الوسائط التفاعلية" و"الفحص الديناميكي لحِزم ARP" لنظام التشغيل tvOS
إنشاء مشروع Xcode جديد
في Xcode، أنشئ مشروعًا جديدًا لتطبيق tvOS باستخدام Objective-C. استخدِم BasicExample كاسم للمشروع.
إضافة حزمة تطوير البرامج (SDK) لخدمة "الإعلانات الديناميكية أثناء البث" من "إعلانات الوسائط التفاعلية" إلى مشروع Xcode
استخدِم إحدى الطرق الثلاث التالية لتثبيت حزمة تطوير البرامج (SDK) الخاصة بميزة "الإعلانات الديناميكية أثناء عرض الفيديو" في "إعلانات الوسائط التفاعلية".
تثبيت حزمة تطوير البرامج (SDK) باستخدام Swift Package Manager
تتوافق "حزمة تطوير البرامج لإعلانات الوسائط التفاعلية" مع Swift Package Manager بدءًا من الإصدار 4.8.2. اتّبِع الخطوات التالية لاستيراد حزمة Swift.
في Xcode، ثبِّت حزمة GoogleInteractiveMediaAds Swift Package من خلال الانتقال إلى ملف > إضافة حِزم (File > Add Packages).
في الطلب الذي يظهر، ابحث عن مستودع حزمة GoogleInteractiveMediaAds Swift على GitHub:
https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvosاختَر إصدار حزمة GoogleInteractiveMediaAds Swift التي تريد استخدامها. بالنسبة إلى المشاريع الجديدة، ننصحك باستخدام الإصدار الرئيسي التالي.
بعد الانتهاء، يحلّ Xcode التبعيات المرتبطة بحِزمك وينزّلها في الخلفية. لمزيد من التفاصيل حول كيفية إضافة تبعيات الحزمة، يُرجى الاطّلاع على مقالة Apple.
تثبيت حزمة SDK باستخدام CocoaPods
CocoaPods هو نظام لإدارة التبعيات في مشاريع Xcode، وهو الطريقة المقترَحة لتثبيت حزمة تطوير البرامج (SDK) الخاصة بـ "الإعلانات الديناميكية أثناء البث" من "إعلانات الوسائط التفاعلية". لمزيد من المعلومات حول تثبيت CocoaPods أو استخدامه، يُرجى الاطّلاع على مستندات CocoaPods. بعد تثبيت CocoaPods، اتّبِع التعليمات التالية لتثبيت حزمة تطوير البرامج (SDK) الخاصة بـ "إعلانات الوسائط التفاعلية" (IMA) في البث المباشر:
في الدليل نفسه الذي يحتوي على ملف BasicExample.xcodeproj، أنشئ ملفًا نصيًا باسم Podfile وأضِف الإعداد التالي:
source 'https://github.com/CocoaPods/Specs.git' platform :tvos, '15' target "BasicExample" do pod 'GoogleAds-IMA-tvOS-SDK', '~> 4.16.0' endمن الدليل الذي يحتوي على Podfile، نفِّذ ما يلي:
pod install --repo-updateتأكَّد من نجاح عملية التثبيت من خلال فتح الملف BasicExample.xcworkspace والتأكّد من أنّه يتضمّن مشروعَين: BasicExample وPods (وهي التبعيات التي تم تثبيتها بواسطة CocoaPods).
تنزيل حزمة تطوير البرامج (SDK) وتثبيتها يدويًا
إذا كنت لا تريد استخدام Swift Package Manager أو CocoaPods، يمكنك تنزيل حزمة تطوير البرامج (SDK) الخاصة بـ "إعلانات الوسائط التفاعلية" (DAI) وإضافتها يدويًا إلى مشروعك.
استيراد "حزمة تطوير البرامج للإعلانات التفاعلية"
أضِف إطار عمل IMA باستخدام عبارة استيراد:
Objective-C
#import "ViewController.h"
#import <AVKit/AVKit.h>
@import GoogleInteractiveMediaAds;
Swift
import AVFoundation
import GoogleInteractiveMediaAds
import UIKit
إنشاء مشغّل فيديو ودمج حزمة تطوير البرامج لإعلانات الوسائط التفاعلية
يوضّح المثال التالي كيفية إعداد حزمة تطوير البرامج لإعلانات الوسائط التفاعلية:
Objective-C
// Live stream asset key, VOD content source and video IDs, and backup content URL.
static NSString *const kAssetKey = @"c-rArva4ShKVIAkNfy6HUQ";
static NSString *const kContentSourceID = @"2548831";
static NSString *const kVideoID = @"tears-of-steel";
static NSString *const kNetworkCode = @"21775744923";
static NSString *const kBackupStreamURLString =
@"http://googleimadev-vh.akamaihd.net/i/big_buck_bunny/bbb-,480p,720p,1080p,.mov.csmil/"
@"master.m3u8";
static const StreamType kDefaultStreamType = StreamTypeLive;
@interface ViewController () <IMAAdsLoaderDelegate,
IMAStreamManagerDelegate,
AVPlayerViewControllerDelegate>
@property(nonatomic) IMAAdsLoader *adsLoader;
@property(nonatomic) IMAAdDisplayContainer *adDisplayContainer;
@property(nonatomic) UIView *adContainerView;
@property(nonatomic) id<IMAVideoDisplay> videoDisplay;
@property(nonatomic) IMAStreamManager *streamManager;
@property(nonatomic) AVPlayerViewController *playerViewController;
@property(nonatomic, getter=isAdBreakActive) BOOL adBreakActive;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
self.streamType = kDefaultStreamType;
[self setupAdsLoader];
[self setupPlayer];
[self setupAdContainer];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self requestStream];
}
- (void)setupPlayer {
// Create a stream video player.
AVPlayer *player = [[AVPlayer alloc] init];
self.playerViewController = [[AVPlayerViewController alloc] init];
self.playerViewController.player = player;
// Attach video player to view hierarchy.
[self addChildViewController:self.playerViewController];
[self.view addSubview:self.playerViewController.view];
self.playerViewController.view.frame = self.view.bounds;
[self.playerViewController didMoveToParentViewController:self];
}
Swift
class ViewController:
UIViewController,
IMAAdsLoaderDelegate,
IMAStreamManagerDelegate,
AVPlayerViewControllerDelegate
{
// Live stream asset key, VOD content source and video IDs, Google Ad Manager network code, and
// backup content URL.
static let assetKey = "c-rArva4ShKVIAkNfy6HUQ"
static let contentSourceID = "2548831"
static let videoID = "tears-of-steel"
static let networkCode = "21775744923"
static let backupStreamURLString =
"http://googleimadev-vh.akamaihd.net/i/big_buck_bunny/bbb-,480p,720p,1080p,.mov.csmil/master.m3u8"
var adsLoader: IMAAdsLoader?
var videoDisplay: IMAAVPlayerVideoDisplay!
var adDisplayContainer: IMAAdDisplayContainer?
var adContainerView: UIView?
private var streamManager: IMAStreamManager?
private var contentPlayhead: IMAAVPlayerContentPlayhead?
private var playerViewController: AVPlayerViewController!
private var userSeekTime = 0.0
private var adBreakActive = false
private enum StreamType {
case live
/// Video on demand.
case vod
}
/// Set the stream type here.
private let currentStreamType: StreamType = .live
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.black
setupAdsLoader()
setupPlayer()
setupAdContainer()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
requestStream()
}
func setupPlayer() {
let player = AVPlayer()
let playerViewController = AVPlayerViewController()
playerViewController.delegate = self
playerViewController.player = player
// Set up our content playhead and contentComplete callback.
contentPlayhead = IMAAVPlayerContentPlayhead(avPlayer: player)
NotificationCenter.default.addObserver(
self,
selector: #selector(ViewController.contentDidFinishPlaying(_:)),
name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: player.currentItem)
self.addChild(playerViewController)
playerViewController.view.frame = self.view.bounds
self.view.insertSubview(playerViewController.view, at: 0)
playerViewController.didMove(toParent: self)
self.playerViewController = playerViewController
}
في viewDidLoad()، ينشئ setupAdsLoader() IMAAdsLoader، وينشئ setupPlayer() AVPlayerViewController، ويجهّز setupAdContainer() UIView لعرض الإعلانات. عندما يصبح العرض مرئيًا، يتم استدعاء viewDidAppear()requestStream() لطلب بث "إدراج الإعلانات الديناميكي".
لتحديد مَعلمات طلب البث، يستخدم هذا المثال ثوابت، مثل
asset key لأحداث البث المباشر، أو content source ID وvideo ID لبث المحتوى عند الطلب. يستخدم المثال أيضًا المكوّنات التالية لإدارة "حزمة تطوير البرامج لإعلانات الوسائط التفاعلية":
adsLoader: تعالج طلبات البث إلى "مدير إعلانات Google". ننصحك باستخدام مثيل واحد لدورة حياة التطبيق.videoDisplay: عملية تنفيذIMAVideoDisplayتتيح لأداة "إعلانات الوسائط التفاعلية" التحكّم في تشغيل الفيديو وتتبُّع أحداث التشغيل باستخدام AVPlayer.-
adDisplayContainer: يدير طريقة العرض المستخدَمة لعرض عناصر واجهة مستخدم الإعلان والتعامل مع تركيز واجهة المستخدم أثناء الفواصل الإعلانية. -
streamManager: يدير تشغيل بث الإعلان والمحتوى المدمجَين ويرسل أحداث مراحل نشاط الإعلان باستخدام العنصر المفوض. -
playerViewController: مشغّل tvOS المستخدَم لعرض بث الفيديو الذي تتم إدارته من خلال حزمة تطوير البرامج للإعلانات التفاعلية. -
adBreakActive: علامة منطقية تشير إلى ما إذا كان يتم تشغيل فاصل إعلاني، وتُستخدَم لمنع البحث السريع عن الإعلانات ولإدارة تركيز واجهة المستخدم.
تنفيذ IMAAdsLoader
بعد ذلك، أنشئ مثيلاً من IMAAdsLoader وأضِف عرض حاوية الإعلان إلى بنية العرض الهرمية.
Objective-C
- (void)setupAdsLoader {
self.adsLoader = [[IMAAdsLoader alloc] init];
self.adsLoader.delegate = self;
}
- (void)setupAdContainer {
// Attach the ad container to the view hierarchy on top of the player.
self.adContainerView = [[UIView alloc] init];
[self.view addSubview:self.adContainerView];
self.adContainerView.frame = self.view.bounds;
// Keep hidden initially, until an ad break.
self.adContainerView.hidden = YES;
}
Swift
func setupAdsLoader() {
let adsLoader = IMAAdsLoader(settings: nil)
adsLoader.delegate = self
self.adsLoader = adsLoader
}
func setupAdContainer() {
// Attach the ad container to the view hierarchy on top of the player.
let adContainerView = UIView()
self.view.addSubview(adContainerView)
adContainerView.frame = self.view.bounds
// Keep hidden initially, until an ad break.
adContainerView.isHidden = true
self.adContainerView = adContainerView
}
تقديم طلب بث
أنشئ بعض الثوابت لتخزين معلومات البث، ثم نفِّذ دالة طلب البث لإجراء الطلب.
Objective-C
- (void)requestStream {
self.videoDisplay =
[[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.playerViewController.player];
self.adDisplayContainer = [[IMAAdDisplayContainer alloc] initWithAdContainer:self.adContainerView
viewController:self];
// Use the streamType property to determine which request to create.
IMAStreamRequest *request;
switch (self.streamType) {
case StreamTypeLive: {
request = [[IMALiveStreamRequest alloc] initWithAssetKey:kAssetKey
networkCode:kNetworkCode
adDisplayContainer:self.adDisplayContainer
videoDisplay:self.videoDisplay
userContext:nil];
NSLog(@"IMA: Requesting Live Stream with Asset Key: %@.", kAssetKey);
break;
}
case StreamTypeVOD: {
request = [[IMAVODStreamRequest alloc] initWithContentSourceID:kContentSourceID
videoID:kVideoID
networkCode:kNetworkCode
adDisplayContainer:self.adDisplayContainer
videoDisplay:self.videoDisplay
userContext:nil];
NSLog(@"IMA: Requesting VOD Stream with Video ID: %@.", kVideoID);
break;
}
}
if (request) {
[self.adsLoader requestStreamWithRequest:request];
} else {
// Fallback or error handling if no request object was created
NSLog(@"IMA Error: Could not create stream request for unknown type.");
[self playBackupStream];
}
}
Swift
func requestStream() {
guard let playerViewController = self.playerViewController else { return }
guard let adContainerView = self.adContainerView else { return }
guard let adsLoader = self.adsLoader else { return }
self.videoDisplay = IMAAVPlayerVideoDisplay(avPlayer: playerViewController.player!)
let adDisplayContainer = IMAAdDisplayContainer(
adContainer: adContainerView, viewController: self)
self.adDisplayContainer = adDisplayContainer
// Variable to hold the specific stream request object.
let request: IMAStreamRequest
switch self.currentStreamType {
case .live:
// Create a live stream request.
request = IMALiveStreamRequest(
assetKey: ViewController.assetKey,
networkCode: ViewController.networkCode,
adDisplayContainer: adDisplayContainer,
videoDisplay: self.videoDisplay,
pictureInPictureProxy: nil,
userContext: nil)
print("IMA: Requesting Live Stream with asset key \(ViewController.assetKey)")
case .vod:
// Create a VOD stream request.
request = IMAVODStreamRequest(
contentSourceID: ViewController.contentSourceID,
videoID: ViewController.videoID,
networkCode: ViewController.networkCode,
adDisplayContainer: adDisplayContainer,
videoDisplay: self.videoDisplay,
pictureInPictureProxy: nil,
userContext: nil)
print(
"IMA: Requesting VOD Stream with content source ID \(ViewController.contentSourceID) and "
+ "video ID \(ViewController.videoID)")
}
adsLoader.requestStream(with: request)
}
التعامل مع أحداث البث
يتم تشغيل الأحداث IMAAdsLoader وIMAStreamManager التي تُستخدَم للتعامل مع
عمليات التهيئة والأخطاء والتغييرات في حالة البث. يتم إطلاق هذه الأحداث عبر بروتوكولَي IMAAdsLoaderDelegate وIMAStreamManagerDelegate. استمِع إلى حدث تحميل الإعلانات وابدأ البث. إذا تعذّر تحميل إعلان، شغِّل بثًا احتياطيًا بدلاً من ذلك.
Objective-C
- (void)playBackupStream {
NSURL *backupStreamURL = [NSURL URLWithString:kBackupStreamURLString];
[self.videoDisplay loadStream:backupStreamURL withSubtitles:@[]];
[self.videoDisplay play];
[self startMediaSession];
}
- (void)startMediaSession {
[[AVAudioSession sharedInstance] setActive:YES error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
}
#pragma mark - IMAAdsLoaderDelegate
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
// Initialize and listen to stream manager's events.
self.streamManager = adsLoadedData.streamManager;
self.streamManager.delegate = self;
[self.streamManager initializeWithAdsRenderingSettings:nil];
NSLog(@"Stream created with: %@.", self.streamManager.streamId);
}
- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
// Fall back to playing the backup stream.
NSLog(@"Error loading ads: %@", adErrorData.adError.message);
[self playBackupStream];
}
Swift
@objc func contentDidFinishPlaying(_ notification: Notification) {
guard let adsLoader = self.adsLoader else { return }
adsLoader.contentComplete()
}
func startMediaSession() {
try? AVAudioSession.sharedInstance().setActive(true, options: [])
try? AVAudioSession.sharedInstance().setCategory(.playback)
}
// MARK: - IMAAdsLoaderDelegate
func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
let streamManager = adsLoadedData.streamManager!
streamManager.delegate = self
streamManager.initialize(with: nil)
self.streamManager = streamManager
}
func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
print("Error loading ads: \(adErrorData.adError.message)")
let streamUrl = URL(string: ViewController.backupStreamURLString)
self.videoDisplay.loadStream(streamUrl!, withSubtitles: [])
self.videoDisplay.play()
playerViewController.player?.play()
}
التعامل مع أحداث التسجيل والأخطاء
هناك العديد من الأحداث التي يمكن أن يتعامل معها وكيل مدير البث، ولكن في عمليات التنفيذ الأساسية، تكون أهم الاستخدامات هي تسجيل الأحداث، ومنع إجراءات البحث أثناء عرض الإعلانات، والتعامل مع الأخطاء.
Objective-C
#pragma mark - IMAStreamManagerDelegate
- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {
NSLog(@"StreamManager event (%@).", event.typeString);
switch (event.type) {
case kIMAAdEvent_STREAM_STARTED: {
[self startMediaSession];
break;
}
case kIMAAdEvent_STARTED: {
// Log extended data.
NSString *extendedAdPodInfo = [[NSString alloc]
initWithFormat:@"Showing ad %zd/%zd, bumper: %@, title: %@, description: %@, contentType:"
@"%@, pod index: %zd, time offset: %lf, max duration: %lf.",
event.ad.adPodInfo.adPosition, event.ad.adPodInfo.totalAds,
event.ad.adPodInfo.isBumper ? @"YES" : @"NO", event.ad.adTitle,
event.ad.adDescription, event.ad.contentType, event.ad.adPodInfo.podIndex,
event.ad.adPodInfo.timeOffset, event.ad.adPodInfo.maxDuration];
NSLog(@"%@", extendedAdPodInfo);
break;
}
case kIMAAdEvent_AD_BREAK_STARTED: {
self.adContainerView.hidden = NO;
// Trigger an update to send focus to the ad display container.
self.adBreakActive = YES;
[self setNeedsFocusUpdate];
break;
}
case kIMAAdEvent_AD_BREAK_ENDED: {
self.adContainerView.hidden = YES;
// Trigger an update to send focus to the content player.
self.adBreakActive = NO;
[self setNeedsFocusUpdate];
break;
}
case kIMAAdEvent_ICON_FALLBACK_IMAGE_CLOSED: {
// Resume playback after the user has closed the dialog.
[self.videoDisplay play];
break;
}
default:
break;
}
}
- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {
// Fall back to playing the backup stream.
NSLog(@"StreamManager error: %@", error.message);
[self playBackupStream];
}
Swift
// MARK: - IMAStreamManagerDelegate
func streamManager(_ streamManager: IMAStreamManager, didReceive event: IMAAdEvent) {
print("StreamManager event \(event.typeString).")
switch event.type {
case IMAAdEventType.STREAM_STARTED:
self.startMediaSession()
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:
if let adContainerView = self.adContainerView {
adContainerView.isHidden = false
}
// Trigger an update to send focus to the ad display container.
adBreakActive = true
setNeedsFocusUpdate()
break
case IMAAdEventType.AD_BREAK_ENDED:
if let adContainerView = self.adContainerView {
adContainerView.isHidden = true
}
// Trigger an update to send focus to the content player.
adBreakActive = false
setNeedsFocusUpdate()
break
case IMAAdEventType.ICON_FALLBACK_IMAGE_CLOSED:
// Resume playback after the user has closed the dialog.
self.videoDisplay.play()
break
default:
break
}
}
func streamManager(_ streamManager: IMAStreamManager, didReceive error: IMAAdError) {
print("StreamManager error: \(error.message ?? "Unknown Error")")
}
هذا كل شيء! أنت الآن تطلب الإعلانات وتعرضها باستخدام حزمة تطوير البرامج لإعلانات الوسائط التفاعلية (IMA) في "الإعلانات الديناميكية أثناء عرض الفيديو". لمزيد من المعلومات حول ميزات حزمة SDK المتقدّمة، يُرجى الاطّلاع على الأدلة الأخرى أو الأمثلة على GitHub.