The SSAI Plugin for the Native SDK for Android

Product(s)
Video Cloud
Brightcove Player
Role(s)
Device SDK Developer
Task(s)
Develop with the Native SDKs
Topic(s)
General Info
SDK
Android

In this topic, you will learn how to use the Server-Side Ad Insertion (SSAI) plugin with the Brightcove Native SDK for Android. It also details how to migrate from using the OnceUX plugin.

Using the SSAI Plugin

The SSAI plugin allows you to play content with Dynamic Delivery and server-side advertising.

There are two options for playing content with server-side ads:

  1. Provide a URL for SSAI content
  2. Provide a Video with VMAP

In either case, the SSAI plugin will request the VMAP source, parse it and automatically add it to the VideoView.

Provide a URL for SSAI content

With an SSAI asset URL, call the following method:

SSAIComponent.processVideo(String url)

Here is an example:

String ssaiUrl = "https://onceux.host.com/path/to/content.once"
SSAIComponent ssaiComponent = new SSAIComponent(context, brightcoveVideoView);
ssaiComponent.processVideo(ssaiUrl);

Provide a Video with VMAP

For this option, you will provide a Video with a Source containing a VMAP property with the SSAI asset URL. To use the SSAI plugin, follow these steps:

  1. In order to request VideoCloud SSAI content, your account must first be configured to use Dynamic Delivery and SSAI. For details, see the Video Cloud SSAI Overview document.
  2. Next, you will need to create an Ad Configuration (adConfig) object. For details, see the Configuring Server-Side Ad Settings document. Please note that the Brightcove Native SDK for Android does not itself contain any functionality to create or manage adConfigs.
  3. Use the adConfig's id property as a URL parameter (ad_config_id) added to the Catalog method call:
    findVideoById

    or

    findVideoByReferenceId  
  4. Having retrieved the Video object with the findVideo method, call the following method in the SSAI plugin:
    SSAIComponent.processVideo(Video ssaiVideo)

Here is an example:

Catalog catalog = new Catalog(eventEmitter, myAccountId, myPolicyKey);
SSAIComponent plugin = new SSAIComponent(appContext, getBrightcoveVideoView());

// Set the ad_config_id URL parameter
HttpRequestConfig httpRequestConfig = new HttpRequestConfig.Builder()
        .addQueryParameter("ad_config_id", myAdConfig)
        .build();

// Find the Video by ID
catalog.findVideoByID(myVideoId, httpRequestConfig, new VideoListener() {
        @Override
        public void onVideo(Video video) {

        // Process the Video
        plugin.processVideo(video);
    }
});

Working with companion ads

If your ads have Companions, you can easily display them in your app by providing a ViewGroup to hold the Companion image, by calling:

SSAIComponent.addCompanionContainer(ViewGroup companionContainer)

Here is an example. First, Add the FrameLayout to your activity or fragment layout:

// my_activity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
 ...
  <FrameLayout
        android:id="@+id/ad_frame"
        android:layout_width="300dp"
        android:layout_height="250dp"
        android:visibility="invisible" />
…
</RelativeLayout>

Then, use that FrameLayout to pass it to the plugin:

ViewGroup viewGroup = findViewById(R.id.ad_frame);
plugin.addCompanionContainer(viewGroup);

// process your Video
plugin.processVideo(video);

Handling events

For SSAI-specific events, you can listen to them using the EventEmitter. These events can be found in the SSAIEventType class.

The START_AD_SEGMENT and END_AD_SEGMENT events were replaced with EventType.AD_BREAK_STARTED and EventType.AD_BREAK_COMPLETED respectively. For details, see Appendix B and Appendix C.

To get relative and absolute positions, get the com.brightcove.ssai.AdPod with the SSAIEvent.AD_POD key. Here is an example:

private void registerEventHandlers() {
  EventEmitter eventEmitter = brightcoveVideoView.getEventEmitter();
  eventEmitter.on(EventType.AD_BREAK_STARTED, new EventListener() {
    @Override
    public void processEvent(Event event) {
      Object adPodObject = event.getProperties().get(SSAIEvent.AD_POD);
      if (adPodObject instanceof AdPod) {
        AdPod adPod = (AdPod) adPodObject;
        adPod.getRelativeStartPosition();
        adPod.getAbsoluteStartPosition();
        adPod.getAbsoluteEndPosition();
      }
    }
  });
}

Handling errors

All errors will be surface to the developer using the EventType.ERROR event, as shown here:

eventEmitter.on(EventType.ERROR, new EventListener() {
  @Override
  public void processEvent(Event event) {
    String errorMessage = event.getProperty(Event.ERROR_MESSAGE, String.class);
    Throwable error = event.getProperty(Event.ERROR, Throwable.class);
    Log.w(TAG, String.format("Received the error message: %s with error: %s", errorMessage, error));
  }
});

Migrating from the OnceUx Plugin

If you are already using the OnceUx plugin to play your SSAI videos in your app, you only need to follow a few steps to migrate to the new SSAI plugin.

  1. In your app’s build.gradle file, replace
    implementation 'com.brightcove.player:android-onceux-plugin:6.5.1'
    

    with the following: (use the latest plugin version)

    implementation 'com.brightcove.player:android-ssai-plugin:6.7.0'
    
  2. Replace the OnceUxComponent class with the SSAIComponent class.
  3. Replace OnceUxEventType.NO_AD_DATA_URL with EventType.ERROR.
  4. If your code uses any of the constants that were found in OnceUxEventType class, replace these with SSAIEventType and SSAIEvent constants, according to their function:
    • The constants used to listen for an event are now found in the SSAIEventType class. For example:
      SSAIEventtType.AD_DATA_READY
    • The constants used as keys for Event properties are now found in the SSAIEvent class. For example:
      SSAIEvent.SSAI_AD
  5. The SSAI and OnceUx plugins share an internal library responsible for parsing the VMAP object. If your app directly uses objects from this library (package com.brightcove.iab), there are changes in the new version that you might find useful.
  6. For more information, see Appendix A.

    For a comparison between the Events sent in the OnceUx plugin and the SSAI plugin, see the following:

Appendix A

This table shows the changes in the internal IAB Android library 1.5.0:

  • Added the following methods to return timed values in microseconds:
    • com.brightcove.iab.ssai.BrightcoveSSAI.getContentLengthUs():long
    • com.brightcove.iab.ssai.BrightcoveSSAI.getPayloadLengthUs():long
    • com.brightcove.iab.vmap.AdBreak.getTimeOffsetUs():long
    • com.brightcove.iab.vmap.AdBreak.getDurationUs():long
    • com.brightcove.iab.vast.Linear.getDurationUs():long
    • com.brightcove.iab.vast.Linear.getSkipOffsetUs():long
    • com.brightcove.iab.vast.NonLinear.getMinSuggestedDurationUs():long
    • com.brightcove.iab.vast.Icon.getDurationUs():long
    • com.brightcove.iab.vast.Icon.getOffsetUs():long
    • com.brightcove.iab.vast.Tracking.getOffsetUs():long
  • Added AdBreak.POST_ROLL_TIME_OFFSET_US to specify the value of a post-roll AdBreak when using AdBreak.getTimeOffsetUs().
  • Added the BrightcoveSSAI property getters following the camelcase naming convention.
  • Deprecated the BrightcoveSSAI property getters not following the camelcase naming convention.

Appendix B

This table shows the differences between the EventType properties sent with the OnceUx and the SSAI plugin:

EventType class OnceUx plugin SSAI plugin
AD_BREAK_STARTED none Event.DURATION:Integer
Event.PLAYHEAD_POSITION:Integer
SSAIEvent.STITCHED_POSITION:Integer
SSAIEvent.AD_POD:com.brightcove.ssai.AdPod
AD_STARTED Event.AD_ID:String
Event.AD_TITLE:String
OnceUxEventType.EXECUTED:Integer
OnceUxEventType.VAST_LINEAR:com.brightcove.iab.vast.Linear
OnceUxEventType.STITCHED_POSITION:Integer
Event.AD_ID:String
Event.AD_TITLE:String
SSAIEvent.VAST_LINEAR:com.brightcove.iab.vast.Linear
SSAIEvent.STITCHED_POSITION:Integer
AD_PAUSED Event.AD_ID:String
Event.AD_TITLE:String
Event.PLAYHEAD_POSITION:Integer
Event.VIDEO:Video
same
AD_RESUMED Event.AD_ID:String
Event.AD_TITLE:String
Event.VIDEO_DURATION:Integer
Event.PLAYHEAD_POSITION:Integer
Event.SOURCE:Source
Event.VIDEO:Video
Event.FORWARD_BUFFER_SECONDS:Integer
same
AD_PROGRESS Event.AD_ID:String
Event.AD_TITLE:String
Event.VIDEO_DURATION:Integer
Event.PLAYHEAD_POSITION:Integer
Event.ORIGINAL_PLAYHEAD_POSITION:Integer
Event.SOURCE:Source
Event.VIDEO:Video
Event.FORWARD_BUFFER_SECONDS:Integer
OnceUxEventType.VMAP_SEGMENT_INDEX:Integer
Event.AD_ID:String
Event.AD_TITLE:String
Event.VIDEO_DURATION:Integer
Event.PLAYHEAD_POSITION:Integer
Event.ORIGINAL_PLAYHEAD_POSITION:Integer
Event.SOURCE:Source
Event.VIDEO:Video
Event.FORWARD_BUFFER_SECONDS:Integer
AD_COMPLETED Event.AD_ID:String
Event.AD_TITLE:String
OnceUxEventType.EXECUTED:Integer
OnceUxEventType.VAST_LINEAR:com.brightcove.iab.vast.Linear
OnceUxEventType.STITCHED_POSITION:Integer
Event.AD_ID:String
Event.AD_TITLE:String
SSAIEvent.VAST_LINEAR:com.brightcove.iab.vast.Linear
SSAIEvent.STITCHED_POSITION:Integer
AD_BREAK_COMPLETED none Event.DURATION:Integer
Event.PLAYHEAD_POSITION:Integer
SSAIEvent.STITCHED_POSITION:Integer
SSAIEvent.AD_POD:com.brightcove.ssai.AdPod

Appendix C

This table shows the differences between the OnceUxEventType and the SSAIEventType classes and their properties:

Plugin Constant OnceUx plugin - OnceUxEventType class SSAI plugin - SSAIEventType class
AD_DATA_READY OnceUxEventType.VMAP_EVENT_MAP:List<Event>
OnceUxEventType.VMAP_TIMELINE:TImeline
OnceUxEventType.VMAP_RESPONSE:VMAP
SSAIEvent.VMAP_TIMELINE:TImeline (ssai)
SSAIEvent.VMAP_RESPONSE:VMAP (iab)
START_AD_SEGMENT Event.DURATION:Integer
Event.PLAYHEAD_POSITION:Integer
Event.SEEK_CONTROLS_VISIBILITY:HashMap<String:View.Visibility>
OnceUxEventType.EXECUTED:Integer
OnceUxEventType.STITCHED_POSITION:Integer
OnceUxEventType.VMAP_AD_SEGMENT:com.brightcove.iab.vmap.AdSegment
removed
START_AD_BREAK OnceUxEventType.EXECUTED:Integer none
START_AD OnceUxEventType.VAST_AD:com.brightcove.iab.vast.Ad SSAIEvent.VAST_AD:com.brightcove.iab.vast.Ad
START_LINEAR Event.AD_ID:String
Event:AD_TITLE:String
OnceUxEventType.EXECUTED:Integer
OnceUxEventType.VAST_LINEAR:com.brightcove.iab.vast.Linear
OnceUxEventType.STITCHED_POSITION:Integer
Event.AD_ID:String
Event:AD_TITLE:String
SSAIEvent.VAST_LINEAR:com.brightcove.iab.vast.Linear
SSAIEvent..STITCHED_POSITION:Integer
END_LINEAR Event.AD_ID:String
Event:AD_TITLE:String
OnceUxEventType.EXECUTED:Integer
OnceUxEventType.VAST_LINEAR:com.brightcove.iab.vast.Linear
OnceUxEventType.STITCHED_POSITION:Integer
Event.AD_ID:String
Event:AD_TITLE:String
SSAIEvent.VAST_LINEAR:com.brightcove.iab.vast.Linear
SSAIEvent.STITCHED_POSITION:Integer
END_AD OnceUxEventType.EXECUTED:Integer SSAIEvent.VAST_AD:com.brightcove.iab.vast.Ad
END_AD_BREAK OnceUxEventType.EXECUTED:Integer none
END_AD_SEGMENT Event.DURATION:Integer
Event.PLAYHEAD_POSITION:Integer
Event.SEEK_CONTROLS_VISIBILITY:HashMap<String:View.Visibility>
OnceUxEventType.EXECUTED:Integer
OnceUxEventType.STITCHED_POSITION:Integer
OnceUxEventType.VMAP_AD_SEGMENT:com.brightcove.iab.vmap.AdSegment
removed
START_COMPANION OnceUxEventType.VAST_COMPANION:com.brightcove.iab.vast.Companion SSAIEvent.VAST_COMPANION:com.brightcove.iab.vast.Companion
END_COMPANION OnceUxEventType.VAST_COMPANION:com.brightcove.iab.vast.Companion SSAIEvent.VAST_COMPANION:com.brightcove.iab.vast.Companion
SEND_IMPRESSION OnceUxEventType.EXECUTED:Integer
OnceUxEventType.IMPRESSION:com.brightcove.iab.vast.Impression
SSAIEvent.IMPRESSION:com.brightcove.iab.vast.Impression
SEND_TRACKING_BEACON OnceUxEventType.EXECUTED:Integer OnceUxEventType.VAST_TRACKING:com.brightcove.iab.vast.Tracking SSAIEvent.VAST_TRACKING:com.brightcove.iab.vast.Tracking SSAIEvent.TRACKING_TYPE: Creative.TrackingType
CLICK_THROUGH_LINEAR OnceUxEventType.VAST_VIDEO_CLICKS:com.brightcove.iab.vast.VideoClicks removed
CLICK_LINEAR_CREATIVE n/a SSAIEvent.CREATIVE_CLICKS:com.brightcove.ssai.ad.creative.Click