Preloading media

The IMA SDK supports preloading video ad assets. You can enable this feature in your SDK integration to provide a more seamless transition between ads and content. This guide goes over the technical details of implementing media preload with the IMA SDK.

Prerequisite

Preloading requires version 3.17.0 or higher of the IMA Android SDK.

Enable preloading

To enable preloading, use AdsRenderingSettings.setEnablePreloading() to set preloading to true. This must be done within the onAdsManagerLoaded() callback:

@Override
public void onAdsManagerLoaded(AdsManagerLoadedEvent adsManagerLoadedEvent) {
  ...
  AdsRenderingSettings adsRenderingSettings =
      ImaSdkFactory.getInstance().createAdsRenderingSettings();
  adsRenderingSettings.setEnablePreloading(true);
  mAdsManager.init(adsRenderingSettings);
}

Supporting preloading with a custom VideoAdPlayer

We recommend the ExoPlayer-IMA extension that is used in the Android BasicExample app. When integrated, the ExoPlayer-IMA extension has preloading enabled by default and includes built-in preloading support.

If you are implementing preloading without the ExoPlayer-IMA extension, additional changes are required once setEnablePreloading() is called. In order for a video player to support preloading ads, it must keep track of the AdMediaInfo objects which are passed in calls from loadAd() and playAd(), and include the correct AdMediaInfo on the AdPlayerCallback calls. This may require a data-structure to manage AdMediaInfo objects, given that loadAd() for a subsequent AdMediaInfo may occur while a prior AdMediaInfo is currently playing back. The following example demonstrates some of the changes you may need to make for your app to support preloading:

// enum for cases of PlayerState.
static enum PlayerState {
  IDLE,
  LOADED,
  PLAYING,
  PAUSED,
}

...

private final List<VideoAdPlayer.VideoAdPlayerCallback> callbacks;
private final ArrayList<AdMediaInfo> mediaInfos = new ArrayList<>();
private PlayerState playerState;
private boolean adCurrentlyLoaded;

...

@Override
public void playAd(AdMediaInfo adMediaInfo) {
  switch (playerState) {
    case LOADED:
      for (VideoAdPlayerCallback callback : callbacks) {
        callback.onPlay(adMediaInfo);
      }
      break;
    case PAUSED:
      for (VideoAdPlayerCallback callback : callbacks) {
        callback.onResume(adMediaInfo);
      }
      break;
    case PLAYING:
      // Intentionally and silently ignore since it is already playing from a prior media item,
      // note that onPlay is triggered by positionDiscontinuity.
      return;
    case IDLE:
      throw new IllegalStateException("Call to playAd when player state is not LOADED.");
  }
  playerState = PlayerState.PLAYING;
  player.setPlayWhenReady(true);
}

@Override
public void loadAd(AdMediaInfo adMediaInfo, AdPodInfo adPodInfo) {
  if (adCurrentlyLoaded == true) {
    mediaInfos.add(adMediaInfo);
    return;
  }
  player.stop();
  player.seekTo(0);
  mediaInfos.clear();
  mediaInfos.add(adMediaInfo);
  player.setPlayWhenReady(false);
  player.loadMedia(adMediaInfo.getUrl());
  playerState = PlayerState.LOADED;
  adCurrentlyLoaded = true;
}

@Override
public void stopAd(AdMediaInfo adMediaInfo) {
  if (allAdsInBreakHavePlayed()) {
    if (isFinalAd(adMediaInfo)) {
      // handle clean up after all ads have played.
    } else {
      seekToNextItem(player);
    }
  } else {
    mediaInfos.remove(adMediaInfo);
  }
}

private boolean allAdsInBreakHavePlayed() {
  // Code to determine if all the ads in the current ad break have completed.
}

private boolean isFinalAd(AdMediaInfo adMediaInfo) {
  // Code to determine if this adMediaInfo is the final ad.
}

private void seekToNextItem(YourPlayerClass player) {
  // Code to seek your player to the next media item.
}

Testing custom preloading implementations

For custom preloading implementations, testing the following edge-cases is recommended to verify a correct preloading setup:

  • Single ad preroll
  • 3 ad pod preroll
  • 3 ad pod midroll
  • Seeking to a second midroll after the first midroll has begun preloading but before it has played
  • Postroll playback

Timing

The following table summarizes the changes in ad-load timing when preloading is enabled:

Event With Preload Without Preload
Ad VAST requested AdsLoader.requestAds() AdsLoader.requestAds()
Pre-roll loaded (single ad) AdsManager.init() AdsManager.start()
Pre-roll loaded (VMAP/Ad rules) AdsManager.init() AdsManager.init()
Mid-roll or post-roll loaded For the 1st ad in an ad break, 4 seconds before ad start time. For consecutive ads, when the previous ad starts playing. At ad start time.

FAQ

Does media preloading load the full creative?
No, the creative is usually not fully loaded when ad playback begins. Preloading is intended for improving the user experience by minimizing the time it takes for the ad to load. It is not intended to support offline ad serving. The IMA SDK loads as much of the media as the browser allows, limited by the user's internet connection and the size of the creative.
Does media preloading need to be enabled for the ad's VAST as well as media?
No, the SDK always preloads the ad's VAST, regardless of this preload setting.