Open-Measurement-SDKAndroid

Android OM SDK Documentation

These are the integration instructions for the Android Open Measurement SDK. If you are porting an existing integration to the newest version of OM SDK, please refer to the migration guide.

Table of Contents

Supported Versions

OM SDK supports Android API 16, Android 4.1, Jelly Bean and above versions. This includes the Amazon Fire TV and Android TV platforms as long as they meet the above version requirements.

Initial Setup

Please implement the following setup steps before moving on to the specific ad format instructions:

Importing the SDK

The first step is, of course, to add the OM SDK to your app or ads SDK. The SDK artifact to be integrated should be the output of the namespaced build generated on the IAB portal (refer the IAB OMSDK Quickstart Onboarding docs) You can include this [.AAR] artifact into your Android Studio project using any standard method like module import, etc.

Initializing the SDK

You should implement these steps as early as possible in your app or SDK lifecycle. It’s recommended that the SDK is activated on app launch.

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    this.initializeOmsdk();
    // Other logic.
  }

  private void initializeOmsdk() {
    // 1. Activate the SDK.
    // 2. Publish last activity.
  }
}

Note that OM SDK may only be used on the main UI thread. Make sure you are on the main thread when you initialize the SDK, create its objects, and invoke its methods.

1. Activate the SDK.

The first step is to initialize the OM SDK. Activate the OM SDK by passing in the SDK version, and the Application’s context:

boolean activated = Omid.activate(applicationContext);
if (!activated) {
  // SDK failed to activate. Handle appropriately.
}

Note: This method call will throw an IllegalArgumentException if the parameter is null.

2. Publish last activity.

Especially on Android TV, the app should signal to the SDK when a user interacts with app via manual input. This can be done like so:

Omid.updateLastActivity();

Note that the SDK will automatically consider app activation (specifically the onActivityStarted lifecycle callback triggered on app foregrounding) as an activity event; however, this will only detect cases when the app is backgrounded and then re-foregrounded after the OM SDK is activated. It will not detect the initial launch of the app even if the OM SDK is activated on launch. Therefore, it is recommended to call updateLastActivity on app launch right after activating the OM SDK.

Only the latest activity timestamp will be sent to measurement scripts, so that they can validate that a user is likely present.

Note that careful thought should be given to implementing calling this API, to ensure that it’s only called on user input. For example, calling this API on the start of media playback would be incorrect, since a future update may trigger via media playback via autoplay.

3. Fetch the OM SDK JS library.

Load the OM SDK JavaScript library using your preferred method (Volley, Retrofit, etc.). For example, using Volley, we retrieve the resource and save it:

String OMID_JS_SERVICE_URL = context.getString(R.string.omid_js_service);

StringRequest stringRequest = new StringRequest(Request.Method.GET, OMID_JS_SERVICE_URL,
  new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        OMID_JS_SERVICE_CONTENT = response;
    }
  },
  new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {

    }
  });
RequestQueue queue = Volley.newRequestQueue(context);
queue.add(stringRequest);

We recommend that this step is performed right after you have initialized the SDK because you will need the JS library to be available before you create any tracking session.

Note that this step is only necessary if you are injecting the OM SDK JS library client-side, which may not necessarily be true if you use only WebView ad formats. This is because WebView ad formats (not native, however) permit the injection server-side. If you are indeed injecting the JS library server-side (i.e., within the ad response itself), you can skip this step.

Note also that when integrating the native OM SDK, you must use the same or later version of the OM SDK JavaScript — ideally deploying the latest JavaScript patch versions from IAB Tech Lab

4. Identify your integration.

Create a Partner object to identify your integration. The IAB Tech Lab will assign a unique partner name to you at the time of integration, so this is the value you should use here.

The version string should represent the integration version in semantic versioning format. For an ads SDK, this should be the same as your SDK’s semantic version. For an app publisher, this should be the same as your app version.

try {
  Partner partner = Partner.createPartner(PARTNER_NAME, PARTNER_SDK_OR_APP_VERSION);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

Ad Format Implementation Steps

The following sections describe how to implement measurement for various ad formats. They assume you have already imported the library and implemented the initialization code.

WebView Display

The steps below describe how to create a tracking session for a WebView (HTML) ad.

1. Initialize the WebView.

Initialize the WebView, and enable JavaScript within the WebView:

WebView adView;
adView = (WebView) findViewById(R.id.webviewad);
adView.getSettings().setJavaScriptEnabled(true);

2. Retrieve the ad response.

Retrieve the ad response as you normally would. For the purposes of the subsequent steps, the ad response should be an HTML string.

String adResponseHtmlString = "<html>...</html>";

3. Inject the OM SDK JS library into the ad response.

After retrieving the ad response HTML, inject the OM SDK JS library you retrieved in the previous step into the ad response, and load it in the WebView:

try {
  String htmlString = ScriptInjector.injectScriptContentIntoHtml(OMID_JS_SERVICE_CONTENT,
    adResponseHtml);
  adView.loadDataWithBaseURL("", htmlString, "text/html", "UTF-8", "");
} catch (IllegalArgumentException | IllegalStateException e) {
  e.printStackTrace();
}

Note, as mentioned in Step 2 of Initialization, if you have injected the JS service library server-side, this step is not necessary.

4. Create and configure the ad session.

Create the session in the sequence of steps outlined below.

Note: in order to prevent issues with starting the session later, you must wait until the WebView finishes loading OM SDK JavaScript before creating the AdSession. Creating the session sooner than that may result in an inability to signal events (impression, etc.) to verification scripts inside the WebView. The easiest way to avoid this issue is to create the AdSession in a webview callback WebViewClient.onPageFinished(). Alternatively, if an implementation can receive an HTML5 DOMContentLoaded event from the WebView, it can create the AdSession in a message handler for that event.

// In an implementation of WebViewClient:
public void onPageFinished(WebView webView, String url) {
  if (adSession != null) return;

  /* Create the session.
   * Eliding the steps for brevity. Please reference for full steps below.
   */
  adSession = AdSession.createAdSession(adSessionConfiguration, context);
  adSession.registerAdView(webView);

  // Start the session
  adSession.start();
}

Create context

First, create a context with a reference to the partner object you created in the setup step and the ad’s WebView:

try {
  String customReferenceData = "";
  String contentUrl = ... 
  AdSessionContext context = AdSessionContext.createHtmlAdSessionContext(partner, adView,
    contentUrl, customReferenceData);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

Create the session configuration

OMID-1.3 requires specifying the type of creative & type of impression for the ad session, along with the layer responsible for signaling the impression event. For WebView display ads this is generally the native layer. The mediaEventsOwner value should be Owner.NONE for display ads. We’ll get to the actual signaling of the event in a subsequent step:

try {
  AdSessionConfiguration adSessionConfiguration =
    AdSessionConfiguration.createAdSessionConfiguration(CreativeType.HTML_DISPLAY, ImpressionType.BEGIN_TO_RENDER, 
    Owner.NATIVE, Owner.NONE, false);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

Create session

Finally, create the session itself:

try {
  adSession = AdSession.createAdSession(adSessionConfiguration, context);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

5. Set the view on which to track viewability.

Set the view

Set the view on which to track viewability. For a WebView ad, this will be the WebView itself. For a native ad, this will be the native view that contains all the relevant elements of the ad:

try {
  adSession.registerAdView(adView);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

Register obstructions

If there are any native elements which you would consider to be part of the ad, such as a close button, some logo text, or another decoration, you should register them as friendly obstructions to prevent them from counting towards coverage of the ad. This applies to any ancestor or peer views in the view hierarchy (all sub-views of the adView will be automatically treated as part of the ad):

try {
  adSession.addFriendlyObstruction(logoView);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

Update view reference

If the view changes at a subsequent time due to a fullscreen expansion or for a similar reason, you should always update the adView reference to whatever is appropriate at that time:

try {
  adSession.registerAdView(adView);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

6. Start the session.

Starting the session does not trigger an impression yet – it only prepares the session for tracking. It is important to start the session before dispatching any events.

Generally you should start the session as soon as you’ve completed the previous steps:

adSession.start();

As described in the previous step, this should occur after the WebView has loaded.

7. Signal the loaded event.

Ideally this would occur as early in your ad session as the creative is loaded, but it is ok to send it just before the impression

try {
  AdEvents adEvents = AdEvents.createAdEvents(adSession);
  adEvents.loaded();
} catch (IllegalArgumentException | IllegalStateException e) {
  e.printStackTrace();
}

8. Signal the impression event.

The definition of an impression is generally accepted to be on ad render so this is likely when you will want to dispatch the event. The event should be dispatched only once and attempting to trigger it multiple times is an error.

try {
  adEvents.impressionOccurred();
} catch (IllegalStateException e) {
  e.printStackTrace();
}

9. Stop the session.

Stop the session when the impression has completed and the ad will be destroyed. Note, that after you’ve stopped the session it is an error to attempt to start it again or trigger an impression on the finished session.

Note that ending an OMID ad session sends a message to the verification scripts running inside the webview supplied by the integration. So that the verification scripts have enough time to handle the sessionFinish event, the integration must maintain a strong reference to the webview for at least 1.0 seconds after ending the session.

adSession.finish();
adSession = null;

WebView Video

The implementation instructions for WebView Video are similar in many respects to WebView Display on the native side. The primary point of difference is that WebView Video will generally require some additional implementation within the JavaScript layer inside the WebView. This additional JavaScript configuration will likely be performed to a large degree in your ad server so that the necessary components are embedded within the ad response by the time your app or SDK receives it.

The following implementation instructions assume that the JavaScript layer is responsible for these actions:

Impression events and playback progress can be handled from the native layer as well. You can indicate which layer is responsible for event handling at the time that you create the AdSessionConfiguration instance by passing through the appropriate owner (Native or JavaScript) for the respective events. As mentioned previously, this guide assumes you will be implementing the responsibilities cited above in the JavaScript layer. If you would like instructions on how to do the same in the native layer, please reference the Native Video implementation instructions.

1. Create a SessionClient.

Within the HTML ad response, please create a SessionClient. You will interact with classes from the SessionClient to signal events and pass metadata:

var sessionClient;

try {
  sessionClient = OmidSessionClient[SESSION_CLIENT_VERSION];
} catch (e) {}

if (!sessionClient) {
  return;
}

const AdSession = sessionClient.AdSession;
const Partner = sessionClient.Partner;
const Context = sessionClient.Context;
const VerificationScriptResource = sessionClient.VerificationScriptResource;
const AdEvents = sessionClient.AdEvents;
const MediaEvents = sessionClient.MediaEvents;

2. Retrieve the ad response.

See this step of WebView Display. This guide assumes that the ad response will contain HTML (which will render the video player) as well as a VAST component.

3. Inject the OM SDK JS library into the ad response.

See this step of WebView Display.

4. Create and configure the ad session.

See this step of WebView Display.

Note that you will want to designate which layer is responsible for signaling events differently than for WebView Display. Generally for WebView video the JavaScript layer will be signaling both the impression and video events.

As with WebView display, you should ensure the session set up and creation should happen only after receiving the WebView loaded event. Please reference this step of the WebView Display instructions for further detail.

Furthermore, you should decide on the appropriate value for the isolateVerificationScripts parameter. The effect of a true value is that measurement resources will be placed in a sandboxed iframe where they cannot access the video ad element. If you specify false, they will be placed into a same-origin iframe. The FAQ has further detail on this setting.

try {
  // The creative and impression types will be defined by the javascript layer
  AdSessionConfiguration adSessionConfiguration =
    AdSessionConfiguration.createAdSessionConfiguration(CreativeType.DEFINED_BY_JAVASCRIPT, ImpressionType.DEFINED_BY_JAVASCRIPT, 
    Owner.JAVASCRIPT, Owner.JAVASCRIPT, false);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

5. Set the view on which to track viewability.

See this step of WebView Display.

6. Prepare the measurement resources.

The following instructions assume the ad response uses the VAST 4.1 Verification node, either per the 4.1 spec exactly or in the Extensions node. The exact details are outside the scope of this document and are addressed by other Tech Lab guidance and documentation.

If you are not able to use VAST or the 4.1 node, you must find an alternative way to embed this information within the ad response and will likely need to work with each measurement vendor individually to determine the correct mechanism for loading their tags.

Using this 4.1 Verification node as an example:

<Verification vendor="vendorKey">
  <JavaScriptResource apiFramework="omid">
    <![CDATA[https://measurement.domain.com/tag.js]]>
  </JavaScriptResource>
  <VerificationParameters>
    <![CDATA[{...}]]>
  </VerificationParameters>
</Verification>

First create an array to hold one or more measurement resources that you will parse in the next step:

var resources = [];

Then, for each Verification node in the ad response, create a VerificationScriptResource instance as follows:

var vendorKey = ...; // parsed from "vendor" attribute
var params = ...;    // parsed from VerificationParameters as a string
var url = ...;       // parsed from JavaScriptResource
var resource = new VerificationScriptResource(url, vendorKey, params);
resources.add(resource);

Note that the vendorKey must match the vendor attribute from the Verification node in order for OM SDK to pass any impression specific metadata in the VerificationParameters to the correct verification script.

7. Initialize the JS ad session.

Next, create the JS ad session and pass through the measurement resources you parsed from the ad response in the previous step. You will need to use this session instance in order to subscribe to the native session start event as well as to load the resources.

Create the session

var partner = new Partner(PARTNER_NAME, PARTNER_SDK_OR_APP_VERSION);
var context = new Context(partner, resources);
var adSession = new AdSession(context);

Note that the parameters for Partner here should match those you’ve passed in the native layer.

Set the video element

In order to ensure the ad is measured correctly, you should provide a reference to the video element when it is available. The right steps will depend on whether the video element is in the top window or inside a cross-domain iframe.

Top window

Simply provide the video element reference using the Context object you created previously:

const videoElement = document.getElementById(...);
context.setVideoElement(videoElement);
Cross-domain iframe

There are two possible scenarios when the video element is in a cross-domain iframe:

  1. The Session and the element are inside the cross-domain iframe.
  2. You are able to create a Session in the top window as well as inside the cross-domain iframe with the ad element.

In the first scenario, you should mark up the iframe with a predefined class name: omid-element. This will ensure the OM SDK JS service running in the top level is able to locate the iframe. The next step is to indicate the position of the element within the iframe. This can be done by passing the element’s offset to the Session instance you created inside the iframe:

// elementBounds is a rect {x, y, width, height} that indicates the position of the video element
// inside the iframe.
adSession.setElementBounds(elementBounds)

In the second scenario, you should pass the reference to the iframe to the Session and Context instance in the top level:

const iframeElement = document.getElementById(...);
context.setSlotElement(iframeElement);

And within the iframe, provide the element’s offset to the Session instance inside the iframe:

adSession.setElementBounds(elementBounds)

Create the event publishers

In addition, you should also at this time create the event notification objects which you will use to signal the impression and playback events.

const adEvents = new AdEvents(adSession);
const mediaEvents = new MediaEvents(adSession);

8. Start the session.

Start the session in the native layer before signaling any events in the JS layer.

adSession.start();

9. Register the ad load event.

When the video has loaded, signal the load event and pass through the following metadata:

adSession.registerSessionObserver((event) => {
  if (event.type === "sessionStart") {
    // setup code
    ...
    // Set the impression/creative type here.
    if (event.data.creativeType === 'definedByJavaScript') {
      adSession.setCreativeType('video');
    }
    if (event.data.impressionType === 'definedByJavaScript') {
      adSession.setImpressionType('beginToRender');
    }        
    // load event
    adEvents.loaded({ isSkippable: skippable, skipOffset:offsetForSkip, isAutoPlay: autoplay, position: position });
    // other event code
    ...
  } else if (event.type === "sessionError") {
    // handle error
  } else if (event.type === "sessionFinish") {
    // clean up
  }
});

Note that we are dispatching the event within the session observer callback. This is to ensure that we do not dispatch any events until we’ve received session start. All events in the JS layer must be dispatched only after the session start event. You should also check the event type to ensure you handle each event type appropriately.

10. Signal the impression event.

When you are ready, signal the impression event using the events object you created in the previous step. For video, an impression is generally accepted to occur when the first frame of the video successfully plays. It should only be dispatched once, and attempting to trigger it multiple times is an error. As noted in the previous step, you must also ensure that you don’t dispatch the impression event until after you’ve received the session start event.

// this should be within the same callback as the load event from the previous step
adSession.registerSessionObserver((event) => {
  if (event.type === "sessionStart") {
    ...
    adEvents.impressionOccurred();
    ...
  } else if (event.type === "sessionError") {
    // handle error
  } else if (event.type === "sessionFinish") {
    // clean up
  }
})

Note that we are signaling this event from the JavaScript rather than native layer since we designated the JavaScript layer as the impression event owner.

11. Signal playback progress events.

As playback progresses, dispatch notifications for the playback progress events. You should at a minimum signal the following events, as appropriate:

Playback events

Monitor video playback to signal the progress events at appropriate times (reference bullet list above). Generally the timing of the events corresponds to the industry defined standards VPAID and VAST.

Note that the start event is distinct from others because it requires the duration of the ad as well as the creative volume. Please ensure that video player duration is available at the time you dispatch this event.

if (!isNaN(player.duration)) {
  mediaEvents.start(player.duration, player.volume);
} else {
  // wait until duration is available to start
}

Note that the mediaPlayerVolume parameter should only be the volume of the player element. The device volume is detected by the SDK automatically. The player volume should be normalized between 0 and 1. If the creative volume only supports muted or unmuted, it is sufficient to use the following for the mediaPlayerVolume parameter:

  mediaEvents.start(player.duration, player.muted ? 0 : player.volume);

Volume events

With respect to volume changes, you are responsible for notifying only about creative volume changes. See the note about mediaPlayerVolume in the section above.

mediaEvents.volumeChange(player.volume);

State changes

Finally, you are also responsible for signaling any player state changes. If the player can expand to fullscreen as well as exit fullscreen, you will want to signal these state changes as follows:

// entering fullscreen
mediaEvents.playerStateChange("fullscreen");

// exiting fullscreen
mediaEvents.playerStateChange("normal");

Native Display

For clarity, when we refer to Native Display, we refer to non-WebView display ad formats where the components of the ad are native (non-HTML) UI elements.

1. Retrieve the ad response.

Retrieve the ad response as you normally would. For a native ad the ad response may generally be in the form of a JSON which includes some metadata and URLs to the ad assets.

2. Prepare the measurement resources.

The steps here are conceptually similar to the same step of Native Video. Unlike video, there is no standard ad response format for display, so you must find an alternative way to determine which measurement resources should be tracking a given ad impression, but, in any case, you will most likely return this information as part of the ad response one way or another.

3. Create and configure the ad session

Create the session in the following sequence of steps:

Create context

First, create a context with a reference to the partner object you created in the setup step and the ad’s Native View:

String customReferenceData = "";
String contentUrl = ... 
try {
  AdSessionContext adSessionContext = AdSessionContext.createNativeAdSessionContext(partner,
    OMID_JS_SERVICE_CONTENT, verificationScriptResources, contentUrl, customReferenceData);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

Create the session configuration

OMID-1.3 requires specifying the type of creative & type of impression for the ad session, along with the layer responsible for signaling the impression event. For native display ads this is the native layer. The mediaEventsOwner value should be Owner.NONE for display ads.

try {
  AdSessionConfiguration adSessionConfiguration =
    AdSessionConfiguration.createAdSessionConfiguration(CreativeType.NATIVE_DISPLAY, ImpressionType.BEGIN_TO_RENDER, 
    Owner.NATIVE, Owner.NONE, false);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

Create session

Finally, create the session itself:

try {
  adSession = AdSession.createAdSession(adSessionConfiguration, adSessionContext);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

4. Set the view on which to track viewability.

See this section of WebView display.

5. Start the Session

Starting the session does not trigger an impression yet – it only prepares the session for tracking. It is important to start the session before dispatching any events.

Generally you should start the session as soon as you’ve completed the previous steps:

adSession.start();

6. Signal the loaded event.

Ideally this would occur as early in your ad session as the creative is loaded, but it is ok to send it just before the impression

try {
  AdEvents adEvents = AdEvents.createAdEvents(adSession);
  adEvents.loaded();
} catch (IllegalArgumentException | IllegalStateException e) {
  e.printStackTrace();
}

7. Signal the impression event.

The definition of an impression is generally accepted to be on ad render so this is likely when you will want to dispatch the event. The event should be dispatched only once and attempting to trigger it multiple times is an error. Note that this should only be done after starting the session.

try {
  adEvents.impressionOccurred();
} catch (IllegalStateException e) {
  e.printStackTrace();
}

8. Stop the session.

Stop the session when the impression has completed and the ad will be destroyed. Note, that after you’ve stopped the session it is an error to attempt to start it again or trigger an impression on the finished session.

adSession.finish();
adSession = null;

Native Video

Please follow the instructions below for how to correctly track a native video ad.

1. Retrieve the ad response.

Retrieve the ad response as you would normally. Generally this will be a VAST document.

2. Prepare the measurement resources.

In this step, you will determine which measurement resources should be tracking the ad. Overall the instructions are similar to this step of the WebView Video instructions. As before, we will assume that the ad response contains one or more Verification nodes as specified in VAST 4.1.

First we create an array to hold the scripts:

List<VerificationScriptResource> verificationScriptResources = new ArrayList<>();

Then parse each Verification node and add the associated VerificationScriptResource to the array of resources:

final String url = ...;
final String vendorKey = ...;
final String params = ...;
try {
  VerificationScriptResource verificationScriptResource =
    VerificationScriptResource.createVerificationScriptResourceWithoutParameters(vendorKey,
      url, params);
  verificationScriptResources.add(verificationScriptResource);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

3. Create and configure the ad session.

See this step of the Native Display implementation instructions.

Note that you will want to specify a media event owner that is different from the example provided with native display.

try {
  AdSessionConfiguration adSessionConfiguration =
    AdSessionConfiguration.createAdSessionConfiguration(CreativeType.VIDEO, ImpressionType.BEGIN_TO_RENDER, 
    Owner.NATIVE, Owner.NATIVE, false);
} catch (IllegalArgumentException e) {
  e.printStackTrace();
}

4. Set the view on which to track viewability.

See this step of WebView Display.

5. Create the event publisher instances.

You will use these instances to signal impression and playback events, so you will want to hold on to them after you’ve created them.

try {
  AdEvents adEvents = AdEvents.createAdEvents(adSession);
  MediaEvents mediaEvents = MediaEvents.createMediaEvents(adSession);
} catch (IllegalArgumentException | IllegalStateException e) {
  e.printStackTrace();
}

6. Start the session.

As noted previously, signaling the start of the session does not yet trigger the impression. This only prepares the session for tracking. You will want to do this as close to completing the previous steps as possible.

adSession.start();

7. Register the ad load event.

Dispatch the loaded event to signal that the ad has loaded and is ready to play. It is best practice for this (and all other events) to be fired only after the session has started.

final VastProperties vProps = VastProperties.createVastPropertiesForSkippableMedia(...);
try {
  adEvents.loaded(vProps);
} catch (Exception e) {
}

8. Register the impression.

Signal the start of the impression. Generally this should occur when the first frame of the video successfully plays.

try {
  adEvents.impressionOccurred();
} catch (IllegalArgumentException | IllegalStateException e) {
  e.printStackTrace();
}

9. Signal playback progress events.

As playback progresses, dispatch notifications for the playback progress events. You should at a minimum signal the following events, as appropriate:

Playback events

Monitor video playback to signal the progress events at appropriate times (reference bullet list above). Generally the timing of the events corresponds to the industry defined standards VPAID and VAST.

Note that the start event is distinct from others because it requires the duration of the ad as well as the creative volume:

try {
  mediaEvents.start(getDuration(), PLAYER_VOLUME_0_TO_1);
} catch (IllegalStateException e) {
  e.printStackTrace();
}

Volume events

Device volume is detected by the SDK automatically. With respect to volume changes, you are responsible for notifying only about creative volume changes:

try {
  mediaEvents.volumeChange(PLAYER_VOLUME_0_TO_1);
} catch (IllegalArgumentException | IllegalStateException ex) {
  ex.printStackTrace();
}

State changes

Finally, you are also responsible for signaling any player state changes. If the player can expand to fullscreen as well as exit fullscreen, you will want to signal these state changes as follows:

// enter fullscreen
mediaEvents.playerStateChange(PlayerState.FULLSCREEN);

// exit fullscreen
mediaEvents.playerStateChange(PlayerState.NORMAL);

Note the above methods should be appropriately handled for exceptions.

10. Stop the session.

Stop the session on completion or termination of ad playback.

adSession.finish();
adSession = null;

Audio ads

The setup for an audio ad is similar to the corresponding video ad, with minor exceptions…

Validating your OM SDK Implementation

Validating your steps is an important part of the integration process. Follow the instructions here.

Distribute

This section is directed at ads SDKs that will want to distribute their SDK after integrating the OM SDK in order to provide measurement across their network of publishers. While the ads SDK may very well choose to distribute the OM SDK as a separate component, this will generally provide a poorer usability experience compared to embedding the OM SDK within. The following instructions detail how to embed the OM SDK when possible. Note that the OM SDK does use namespacing so that it can be independently included within multiple ads SDKs in a single app without issues.

[TODO]

FAQ

FAQ available here

Kill Switch Guidance

Kill switch guidance available here