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:
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:
- 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.
- 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.
- Use the adConfig's
id
property as a URL parameter (ad_config_id
) added to the Catalog method call:findVideoById
or
findVideoByReferenceId
- 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.
- 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'
- Replace the
OnceUxComponent
class with theSSAIComponent
class. - Replace
OnceUxEventType.NO_AD_DATA_URL
withEventType.ERROR
. - If your code uses any of the constants that were found in
OnceUxEventType
class, replace these withSSAIEventType
andSSAIEvent
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
- The constants used to listen for an event are now found in the
- 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. -
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 usingAdBreak.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 :IntegerEvent.PLAYHEAD_POSITION :IntegerSSAIEvent.STITCHED_POSITION :IntegerSSAIEvent.AD_POD:com.brightcove.ssai.AdPod |
AD_STARTED | Event.AD_ID :StringEvent.AD_TITLE :StringOnceUxEventType.EXECUTED :IntegerOnceUxEventType.VAST_LINEAR:com.brightcove.iab.vast.Linear OnceUxEventType.STITCHED_POSITION :Integer |
Event.AD_ID :StringEvent.AD_TITLE :StringSSAIEvent.VAST_LINEAR:com.brightcove.iab.vast.Linear SSAIEvent.STITCHED_POSITION :Integer |
AD_PAUSED | Event.AD_ID :StringEvent.AD_TITLE :StringEvent.PLAYHEAD_POSITION :IntegerEvent.VIDEO :Video |
same |
AD_RESUMED | Event.AD_ID :StringEvent.AD_TITLE :StringEvent.VIDEO_DURATION :IntegerEvent.PLAYHEAD_POSITION :IntegerEvent.SOURCE :SourceEvent.VIDEO :VideoEvent.FORWARD_BUFFER_SECONDS :Integer |
same |
AD_PROGRESS | Event.AD_ID :StringEvent.AD_TITLE :StringEvent.VIDEO_DURATION :IntegerEvent.PLAYHEAD_POSITION :IntegerEvent.ORIGINAL_PLAYHEAD_POSITION :IntegerEvent.SOURCE :SourceEvent.VIDEO :VideoEvent.FORWARD_BUFFER_SECONDS :IntegerOnceUxEventType.VMAP_SEGMENT_INDEX :Integer |
Event.AD_ID :StringEvent.AD_TITLE :StringEvent.VIDEO_DURATION :IntegerEvent.PLAYHEAD_POSITION :IntegerEvent.ORIGINAL_PLAYHEAD_POSITION :IntegerEvent.SOURCE :SourceEvent.VIDEO :VideoEvent.FORWARD_BUFFER_SECONDS :Integer |
AD_COMPLETED | Event.AD_ID :StringEvent.AD_TITLE :StringOnceUxEventType.EXECUTED :IntegerOnceUxEventType.VAST_LINEAR:com.brightcove.iab.vast.Linear OnceUxEventType.STITCHED_POSITION:Integer |
Event.AD_ID :StringEvent.AD_TITLE :StringSSAIEvent.VAST_LINEAR:com.brightcove.iab.vast.Linear SSAIEvent.STITCHED_POSITION:Integer |
AD_BREAK_COMPLETED | none | Event.DURATION :IntegerEvent.PLAYHEAD_POSITION :IntegerSSAIEvent.STITCHED_POSITION :IntegerSSAIEvent.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 :TImelineOnceUxEventType.VMAP_RESPONSE :VMAP |
SSAIEvent.VMAP_TIMELINE :TImeline (ssai)SSAIEvent.VMAP_RESPONSE :VMAP (iab) |
START_AD_SEGMENT | Event.DURATION :IntegerEvent.PLAYHEAD_POSITION :IntegerEvent.SEEK_CONTROLS_VISIBILITY :HashMap<String:View.Visibility>OnceUxEventType.EXECUTED :IntegerOnceUxEventType.STITCHED_POSITION :IntegerOnceUxEventType.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 :StringEvent:AD_TITLE :StringOnceUxEventType.EXECUTED :IntegerOnceUxEventType.VAST_LINEAR :com.brightcove.iab.vast.Linear OnceUxEventType.STITCHED_POSITION :Integer |
Event.AD_ID :StringEvent:AD_TITLE :StringSSAIEvent.VAST_LINEAR :com.brightcove.iab.vast.Linear SSAIEvent..STITCHED_POSITION :Integer |
END_LINEAR | Event.AD_ID :StringEvent:AD_TITLE :StringOnceUxEventType.EXECUTED :IntegerOnceUxEventType.VAST_LINEAR :com.brightcove.iab.vast.Linear OnceUxEventType.STITCHED_POSITION :Integer |
Event.AD_ID :StringEvent:AD_TITLE :StringSSAIEvent.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 :IntegerEvent.PLAYHEAD_POSITION :IntegerEvent.SEEK_CONTROLS_VISIBILITY :HashMap<String:View.Visibility>OnceUxEventType.EXECUTED :IntegerOnceUxEventType.STITCHED_POSITION :IntegerOnceUxEventType.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 :IntegerOnceUxEventType.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 |