הוספת מודעה

אפשר להשתמש ב-ExpoPlayer כדי להוסיף מודעות גם בצד הלקוח וגם בצד השרת.

הוספת מודעה בצד הלקוח

בהוספת מודעה בצד הלקוח, הנגן עובר בין טעינת המדיה מ- לכתובות URL שונות בזמן המעבר בין הפעלת תוכן לבין מודעות. מידע מידע על מודעות נטענות בנפרד מהמדיה, למשל מ-VAST בפורמט XML או VMAP. המדד הזה יכול לכלול מיקומים של סימון מודעה ביחס להתחלה של תוכן, מזהי ה-URI של המדיה של המודעה והמטא-נתונים, למשל אם מודעה מסוימת שניתן לדלג עליה.

כשמשתמשים ב-AdsMediaSource של ExoPlayer להוספת מודעה בצד הלקוח, הנגן כולל מידע על המודעות שיוצגו. יש לכך כמה יתרונות:

  • הנגן יכול לחשוף מטא-נתונים ופונקציונליות שקשורים למודעות באמצעות ה-API שלו.
  • רכיבי ממשק המשתמש של ExoPlayer יכולים להציג סמנים למיקומי מודעות באופן אוטומטי, ולשנות את אופן הפעולה שלהם בהתאם להפעלת המודעה.
  • באופן פנימי, השחקן יכול לשמור על מאגר נתונים זמני עקבי בין מעברים מודעות ותוכן.

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

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

תמיכה הצהרתית במודעות

אפשר לציין URI של תג מודעה כשיוצרים MediaItem:

Kotlin

val mediaItem =
  MediaItem.Builder()
    .setUri(videoUri)
    .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).build())
    .build()

Java

MediaItem mediaItem =
    new MediaItem.Builder()
        .setUri(videoUri)
        .setAdsConfiguration(
            new MediaItem.AdsConfiguration.Builder(adTagUri).build())
        .build();

כדי להפעיל תמיכה בנגן בפריטי מדיה שמציינים תגי מודעות, צריך: לפתח ולהחדיר DefaultMediaSourceFactory שהוגדר באמצעות AdsLoader.Provider ו-AdViewProvider בעת יצירת הנגן:

Kotlin

val mediaSourceFactory: MediaSource.Factory =
  DefaultMediaSourceFactory(context).setLocalAdInsertionComponents(adsLoaderProvider, playerView)
val player = ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build()

Java

MediaSource.Factory mediaSourceFactory =
    new DefaultMediaSourceFactory(context)
        .setLocalAdInsertionComponents(adsLoaderProvider, /* adViewProvider= */ playerView);
ExoPlayer player =
    new ExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build();

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

PlayerView של ExoPlayer מוטמע AdViewProvider. IMA של ExoPlayer אפשר להוריד בקלות את AdsLoader, כמו שמתואר בהמשך.

פלייליסטים עם מודעות

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

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

Kotlin

// Build the media items, passing the same ads identifier for both items,
// which means they share ad playback state so ads play only once.
val firstItem =
  MediaItem.Builder()
    .setUri(firstVideoUri)
    .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
    .build()
val secondItem =
  MediaItem.Builder()
    .setUri(secondVideoUri)
    .setAdsConfiguration(MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
    .build()
player.addMediaItem(firstItem)
player.addMediaItem(secondItem)

Java

// Build the media items, passing the same ads identifier for both items,
// which means they share ad playback state so ads play only once.
MediaItem firstItem =
    new MediaItem.Builder()
        .setUri(firstVideoUri)
        .setAdsConfiguration(
            new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
        .build();
MediaItem secondItem =
    new MediaItem.Builder()
        .setUri(secondVideoUri)
        .setAdsConfiguration(
            new MediaItem.AdsConfiguration.Builder(adTagUri).setAdsId(adTagUri).build())
        .build();
player.addMediaItem(firstItem);
player.addMediaItem(secondItem);

ספריית IMA של ExoPlayer

ספריית ה-IMA של ExoPlayer מספקת ImaAdsLoader, וכך קל מאוד: לשלב באפליקציה שלך הכנסת מודעות בצד הלקוח. הוא כולל את הפונקציונליות של את ה-IMA SDK בצד הלקוח כדי לתמוך בהוספת מודעות VAST/VMAP. עבור הוראות לשימוש בספרייה, כולל איך לטפל ברקע ולהמשיך את ההפעלה, יש לעיין ב-README.

האפליקציה להדגמה (דמו) משתמשת בספריית IMA וכוללת כמה דוגמאות תגי מודעות VAST/VMAP ברשימת הדוגמאות.

שיקולים בקשר לממשק המשתמש

אמצעי הבקרה להעברה של PlayerView מוסתר במהלך הפעלת מודעות על ידי כברירת מחדל, אבל אפליקציות יכולות לשנות את ההתנהגות הזו על ידי התקשרות setControllerHideDuringAds. ה-IMA SDK יציג צפיות נוספות בנוסף בנגן בזמן שהמודעה מוצגת (לדוגמה, קישור ל'מידע נוסף' ולחצן דילוג, אם רלוונטי).

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

למידע נוסף על תצוגות של שכבות-על, ראה פותחים את 'מדידה' ב-IMA SDK.

מודעות נלוות

תגי מודעות מסוימים מכילים מודעות נלוות נוספות שניתן להציג ב'משבצות' תוך שימוש ממשק המשתמש של האפליקציה. ניתן להעביר את המקומות האלה דרך ImaAdsLoader.Builder.setCompanionAdSlots(slots) מידע נוסף זמין במאמר הבא: הוספת מודעות נלוות.

מודעות עצמאיות

IMA SDK מיועד להוספת מודעות לתוכן מדיה, ולא להפעלה מודעות עצמאיות. לכן אין תמיכה בהפעלה של מודעות עצמאיות בספריית IMA. מומלץ להשתמש במקום זאת ב-Google Mobile Ads SDK בתרחיש לדוגמה הזה.

שימוש ב-SDK להצגת מודעות של צד שלישי

אם צריך לטעון מודעות באמצעות Ads SDK של צד שלישי, כדאי לבדוק אם הוא כבר מספק שילוב של ExoPlayer. אם לא, הטמעה של תבנית מותאמת אישית השיטה המומלצת היא AdsLoader שעוטף את ה-SDK להצגת מודעות של צד שלישי, כי הוא מספק את היתרונות של AdsMediaSource שתוארו למעלה. ImaAdsLoader משמש כהטמעה לדוגמה.

אפשרות נוספת היא להשתמש בתמיכה בפלייליסטים של ExoPlayer כדי ליצור רצף. של מודעות וקליפים עם תוכן:

Kotlin

// A pre-roll ad.
val preRollAd = MediaItem.fromUri(preRollAdUri)
// The start of the content.
val contentStart =
  MediaItem.Builder()
    .setUri(contentUri)
    .setClippingConfiguration(ClippingConfiguration.Builder().setEndPositionMs(120000).build())
    .build()
// A mid-roll ad.
val midRollAd = MediaItem.fromUri(midRollAdUri)
// The rest of the content
val contentEnd =
  MediaItem.Builder()
    .setUri(contentUri)
    .setClippingConfiguration(ClippingConfiguration.Builder().setStartPositionMs(120000).build())
    .build()

// Build the playlist.
player.addMediaItem(preRollAd)
player.addMediaItem(contentStart)
player.addMediaItem(midRollAd)
player.addMediaItem(contentEnd)

Java

// A pre-roll ad.
MediaItem preRollAd = MediaItem.fromUri(preRollAdUri);
// The start of the content.
MediaItem contentStart =
    new MediaItem.Builder()
        .setUri(contentUri)
        .setClippingConfiguration(
            new ClippingConfiguration.Builder().setEndPositionMs(120_000).build())
        .build();
// A mid-roll ad.
MediaItem midRollAd = MediaItem.fromUri(midRollAdUri);
// The rest of the content
MediaItem contentEnd =
    new MediaItem.Builder()
        .setUri(contentUri)
        .setClippingConfiguration(
            new ClippingConfiguration.Builder().setStartPositionMs(120_000).build())
        .build();

// Build the playlist.
player.addMediaItem(preRollAd);
player.addMediaItem(contentStart);
player.addMediaItem(midRollAd);
player.addMediaItem(contentEnd);

הוספת מודעות בצד השרת

בהוספת מודעות בצד השרת (שנקרא גם 'הוספת מודעות דינמיות' או DAI), המערכת מדיה בסטרימינג מכילה גם מודעות וגם תוכן. מניפסט DASH עשוי להפנות של תכנים ופלחי מודעות, לפעמים בתקופות נפרדות. למידע על HLS, יש לעיין ב-Apple מידע על שילוב מודעות בפלייליסט.

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

המכשיר DefaultMediaSourceFactory של ExoPlayer יכול להקצות את כל המשימות האלה הוספת מודעה בצד השרת MediaSource עבור מזהי URI שמשתמשים בסכימה ssai://:

Kotlin

val player =
  ExoPlayer.Builder(context)
    .setMediaSourceFactory(
      DefaultMediaSourceFactory(context).setServerSideAdInsertionMediaSourceFactory(ssaiFactory)
    )
    .build()

Java

Player player =
    new ExoPlayer.Builder(context)
        .setMediaSourceFactory(
            new DefaultMediaSourceFactory(context)
                .setServerSideAdInsertionMediaSourceFactory(ssaiFactory))
        .build();

ספריית IMA של ExoPlayer

ספריית IMA של ExoPlayer מספקת ImaServerSideAdInsertionMediaSource, לאפשר שילוב קל עם זרמי המודעות שנוספו בצד השרת של IMA אפליקציה. הוא כולל את הפונקציונליות של IMA DAI SDK ל-Android משלבת בנגן את המטא-נתונים של המודעה שסופקו. לדוגמה, המדיניות מאפשרת להשתמש בשיטות כמו Player.isPlayingAd(), להאזין למעברים בין מודעות תוכן לבין מודעות תוכן ומאפשרים לנגן להתמודד עם הלוגיקה של הפעלת מודעות, כמו דילוג על מודעות שכבר הופעלו.

כדי להשתמש בכיתה הזו, צריך להגדיר את ImaServerSideAdInsertionMediaSource.AdsLoader וגם ImaServerSideAdInsertionMediaSource.Factory ומחברים אותם לנגן:

Kotlin

// MediaSource.Factory to load the actual media stream.
val defaultMediaSourceFactory = DefaultMediaSourceFactory(context)
// AdsLoader that can be reused for multiple playbacks.
val adsLoader =
  ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build()
// MediaSource.Factory to create the ad sources for the current player.
val adsMediaSourceFactory =
  ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory)
// Configure DefaultMediaSourceFactory to create both IMA DAI sources and
// regular media sources. If you just play IMA DAI streams, you can also use
// adsMediaSourceFactory directly.
defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory)
// Set the MediaSource.Factory on the Player.
val player = ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build()
// Set the player on the AdsLoader
adsLoader.setPlayer(player)

Java

// MediaSource.Factory to load the actual media stream.
DefaultMediaSourceFactory defaultMediaSourceFactory = new DefaultMediaSourceFactory(context);
// AdsLoader that can be reused for multiple playbacks.
ImaServerSideAdInsertionMediaSource.AdsLoader adsLoader =
    new ImaServerSideAdInsertionMediaSource.AdsLoader.Builder(context, adViewProvider).build();
// MediaSource.Factory to create the ad sources for the current player.
ImaServerSideAdInsertionMediaSource.Factory adsMediaSourceFactory =
    new ImaServerSideAdInsertionMediaSource.Factory(adsLoader, defaultMediaSourceFactory);
// Configure DefaultMediaSourceFactory to create both IMA DAI sources and
// regular media sources. If you just play IMA DAI streams, you can also use
// adsMediaSourceFactory directly.
defaultMediaSourceFactory.setServerSideAdInsertionMediaSourceFactory(adsMediaSourceFactory);
// Set the MediaSource.Factory on the Player.
Player player =
    new ExoPlayer.Builder(context).setMediaSourceFactory(defaultMediaSourceFactory).build();
// Set the player on the AdsLoader
adsLoader.setPlayer(player);

כדי לטעון את מפתח נכס ה-IMA, את מזהה מקור התוכן ואת מזהה הסרטון, צריך ליצור כתובת URL עם ImaServerSideAdInsertionUriBuilder:

Kotlin

val ssaiUri =
  ImaServerSideAdInsertionUriBuilder()
    .setAssetKey(assetKey)
    .setFormat(C.CONTENT_TYPE_HLS)
    .build()
player.setMediaItem(MediaItem.fromUri(ssaiUri))

Java

Uri ssaiUri =
    new ImaServerSideAdInsertionUriBuilder()
        .setAssetKey(assetKey)
        .setFormat(C.CONTENT_TYPE_HLS)
        .build();
player.setMediaItem(MediaItem.fromUri(ssaiUri));

לסיום, משחררים את טוען המודעות כשלא משתמשים בו יותר:

Kotlin

adsLoader.release()

Java

adsLoader.release();

שיקולים בקשר לממשק המשתמש

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

מודעות נלוות

תגי מודעות מסוימים מכילים מודעות נלוות נוספות שניתן להציג ב'משבצות' תוך שימוש ממשק המשתמש של האפליקציה. ניתן להעביר את המקומות האלה דרך ImaServerSideAdInsertionMediaSource.AdsLoader.Builder.setCompanionAdSlots(slots) מידע נוסף זמין במאמר הוספת מודעות נלוות.

שימוש ב-SDK להצגת מודעות של צד שלישי

אם צריך לטעון מודעות באמצעות SDK של צד שלישי להצגת מודעות, כדאי לבדוק אם הוא כבר מספק שילוב של ExoPlayer. אם לא, מומלץ מספקים MediaSource בהתאמה אישית שמקבל URI עם הסכמה ssai:// דומה ל-ImaServerSideAdInsertionMediaSource.

אפשר לתת לכלל המשתמשים גישה ללוגיקה בפועל של יצירת מבנה המודעה למטרה ServerSideAdInsertionMediaSource, שעוטפת את השידור MediaSource ומאפשרת למשתמש להגדיר ולעדכן את AdPlaybackState שמייצג את המודעה מטא-נתונים.

לעיתים קרובות, שידורים של מודעות שהוכנסו בצד השרת מכילים אירועים מתוזמנים לשליחת הודעה לשחקן על מטא נתונים של מודעות. בקטע פורמטים נתמכים אפשר להבין הפורמטים המתוזמנים של מטא-נתונים נתמכים על ידי ExoPlayer. SDK למודעות בהתאמה אישית MediaSource של הטמעות יכולות להאזין לאירועי מטא-נתונים מתוזמנים מהנגן באמצעות Player.Listener.onMetadata.