Introduction

Adaptive DAI SDK is an Android library (AAR) that provides production‑grade video playback with integrated advertising for Android TV and Fire TV devices.

A key design goal of the SDK is to enable showing ads without interrupting the main video (side‑by‑side scenarios). This is a major advantage for Live content: ad blocks can be rendered alongside the live stream instead of hard‑stopping the broadcast.

It encapsulates complex coordination between a video player (based on ExoPlayer / AndroidX Media3) and the Google IMA SDK for VAST/VMAP ad scheduling, exposing a compact, developer‑friendly API. The SDK is designed for TV‑style applications that need:

  • server‑driven ad schedules (VMAP / VAST);
  • pre‑roll, mid‑roll, post‑roll and on‑pause ads;
  • consistent behavior across Android TV and Fire OS.

Supported Platforms and Requirements

  • Platforms: Android TV, Fire TV (Android‑based devices)
  • Minimum SDK: 24 (Android 7.0)
  • Target / Compile SDK: 35
  • Language: Java 17 (with core library desugaring)

High‑Level Architecture

At a high level, Adaptive DAI SDK is structured as:

  • Public API layer – entry points and configuration classes exported from the AAR:
    • AdaptiveDAISDK – main SDK facade and lifecycle manager.
    • AdaptiveDAIPlayer – orchestrator of playback and ad scheduling.
    • AdaptiveDAILauncher – simplified launcher for minimal integration.
    • MediaItem – content metadata model.
    • PlaybackListener – callbacks for playback and ad events.
    • VideoPlayerConfiguration and AdaptiveDAISDK.DefaultVideoPlayerConfiguration – configuration contract and default implementation.
    • ExoPlayerFactoryAdapter, ImaSdkFactoryAdapter – factory interfaces for injecting custom ExoPlayer / IMA behavior.
  • Internal playback layer – implementation of player logic, tracking, error handling and TV‑specific behavior (not part of public API).
  • Internal ads and networking layers – logic responsible for:
    • retrieving ad configuration (for example, by distributor ID);
    • building VMAP/VAST schedules;
    • coordinating the ad player with main content.

Public documentation and integration guides refer only to the public API surface listed above; internal classes and packages are considered implementation details and may change without notice.

Core Public API

AdaptiveDAISDK

AdaptiveDAISDK is the main entry point and singleton facade of the library. It is responsible for:

  • keeping global SDK state and configuration;
  • integrating partner / distributor identifiers and application name;
  • coordinating creation of the internal player (AdaptiveDAIPlayer);
  • exposing high‑level methods for player setup and content playback;
  • handling lifecycle callbacks (onActivityPaused(), onActivityResumed(), release()).

Typical usage pattern:

  1. Obtain or create the singleton instance:
    • getInstance(Context, partnerId, distributionId, applicationName, exoFactory?, imaFactory?)
  2. Provide configuration via initialize(VideoPlayerConfiguration).
  3. Bind SDK to your layout via setupPlayer(...).
  4. Play content via playMedia(MediaItem) / playMedia(MediaItem, PlaybackListener).
  5. Forward lifecycle events and release resources when done.

AdaptiveDAISDK also exposes a nested interface SDKReadyListener for asynchronous configuration readiness notifications, and DefaultVideoPlayerConfiguration as a convenient builder‑style configuration class.

AdaptiveDAIPlayer

AdaptiveDAIPlayer is the orchestrator class used internally by AdaptiveDAISDK. It:

  • owns and configures the underlying ExoPlayer instance;
  • coordinates main content playback with the ad schedule;
  • manages player state, error handling and tracking.

It is exposed as part of the public API primarily for advanced use cases (inspection, testing, debugging). For most applications, direct interaction with AdaptiveDAIPlayer is not required – it is managed by AdaptiveDAISDK.

AdaptiveDAILauncher

AdaptiveDAILauncher provides a minimal-effort integration path… It hides all SDK instance management and launches playback through a pre‑built PlayerActivity shipped with the SDK.

Public methods:

  • Init(Context, partnerId, distributionId, applicationName, exoFactory?, imaFactory?) – one-time SDK initialization.
  • playVideo(Context, MediaItem, boolean adsEnabled) – start playback in the SDK’s PlayerActivity without a listener.
  • playVideo(Context, MediaItem, boolean adsEnabled, PlaybackListener listener) – same as above, but additionally wires a PlaybackListener instance into the internal player so that you can observe playback and ad events even when using the built-in PlayerActivity.

This is the recommended entry point… In SimpleDemo the overload without PlaybackListener is used, but you can switch to the 4-argument overload with a trivial listener implementation with almost no changes…

MediaItem

MediaItem is the central data structure used to describe video content. It is a simple POJO with fields such as:

  • id – content identifier;
  • title – display name;
  • streamUrl – URL of the video stream (e.g. HLS);
  • catId – category identifier;
  • durationSec – duration in seconds;
  • macros – optional key/value map with additional macro values for ad URLs.

Instances of MediaItem are passed into AdaptiveDAISDK and AdaptiveDAILauncher to identify and describe the content being played.

The optional macros field is used by the SDK’s macro system (e.g. MacroProvider / UrlMacroProcessor) when building ad tag URLs and VMAP documents. If you do not need custom macros, you can pass null.

PlaybackListener

PlaybackListener is the primary callback interface for monitoring playback and ad state:

  • onPlaybackStarted() – content has started playing for the first time;
  • onPlaybackPaused() – content is paused (user/system);
  • onPlaybackResumed() – content resumed after a pause;
  • onPlaybackCompleted() – end of content reached;
  • onAdsStarted() – an ad break has started (including on‑pause ads);
  • onAdsFinished() – the current ad break has finished and content is resuming or has resumed;
  • onPlaybackError(String error) – an error occurred.

It can be attached via AdaptiveDAISDK.playMedia(MediaItem, PlaybackListener) or at lower levels. Internally AdaptiveDAIPlayer supports multiple PlaybackListener instances (registered via addPlaybackListener(...) / removePlaybackListener(...)), and all callbacks are broadcast to every registered listener.

VideoPlayerConfiguration and DefaultVideoPlayerConfiguration

VideoPlayerConfiguration defines the minimal configuration contract used by the SDK for:

  • enabling/disabling ads;

AdaptiveDAISDK.DefaultVideoPlayerConfiguration is a public concrete implementation that offers chainable setters for common options:

  • setAdsEnabled(boolean)

Typical usage:

VideoPlayerConfiguration config = new AdaptiveDAISDK.DefaultVideoPlayerConfiguration()
    .setAdsEnabled(true);

AdaptiveDAISDK sdk = AdaptiveDAISDK.getInstance(context, partnerId, distributionId, appName, null, null)
    .initialize(config);

Factory Adapters: ExoPlayerFactoryAdapter and ImaSdkFactoryAdapter

For advanced scenarios the SDK allows you to inject custom factories:

  • ExoPlayerFactoryAdapter – customizes creation of ExoPlayer, track selectors, load control, renderers, etc.
  • ImaSdkFactoryAdapter – customizes creation of IMA SDK objects.

These interfaces are part of the public API so that you can:

  • enforce your own buffering strategy;
  • plug in custom logging or analytics;
  • adjust how IMA is configured and instantiated.

If you do not provide custom factories, default implementations are used internally.

Typical SDK Lifecycle

Below is a simplified lifecycle for a typical integration using AdaptiveDAISDK directly:

1. Create configuration

AdaptiveDAISDK.DefaultVideoPlayerConfiguration config =
    new AdaptiveDAISDK.DefaultVideoPlayerConfiguration()
        .setAdsEnabled(true);

2. Obtain SDK instance and initialize

AdaptiveDAISDK sdk = AdaptiveDAISDK.getInstance(
    context,
    partnerId,
    distributionId,
    appName,
    null,   // optional ExoPlayerFactoryAdapter
    null    // optional ImaSdkFactoryAdapter
);

sdk.initialize(config);

3. Setup UI and player

sdk.setupPlayer(
    playerView,        // PlayerView for main content
    adsVideoView,      // VideoView for ads (optional)
    mainLayout,        // parent layout
    fadeOverlay,       // overlay for fade animations (optional)
    contentImageView   // ImageView for on-pause image ads (optional)
);

4. Play content

MediaItem mediaItem = new MediaItem(
    "https://example.com/video.m3u8", // streamUrl
    "Movie Title",                    // title
    "1",                              // id
    "456",                            // category id
    3600,                              // duration in seconds
    null                               // optional macros map (can be null)
);

sdk.playMedia(mediaItem, new PlaybackListener() {
    @Override
    public void onPlaybackStarted() { /* ... */ }

    @Override
    public void onPlaybackPaused() { /* ... */ }

    @Override
    public void onPlaybackResumed() { /* ... */ }

    @Override
    public void onPlaybackCompleted() { /* ... */ }

    @Override
    public void onAdsStarted() { /* ... */ }

    @Override
    public void onAdsFinished() { /* ... */ }

    @Override
    public void onPlaybackError(String error) { /* ... */ }
});

5. Handle lifecycle and cleanup

@Override
protected void onPause() {
    super.onPause();
    sdk.onActivityPaused();
}

@Override
protected void onResume() {
    super.onResume();
    sdk.onActivityResumed();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    sdk.release();
}

For the simplest cases, the AdaptiveDAILauncher utility can be used to avoid manual lifecycle management and UI wiring by delegating to the SDK’s own PlayerActivity.

Ads and Scheduling (Conceptual)

Although the internal implementation details are not part of the public API, it is useful to understand the conceptual model used by Adaptive DAI SDK.

Primary mode

  • The primary and recommended mode is for the SDK to fetch ad rules from a backend service using distributionId (and partnerId).
  • The backend returns ad rules as an ACF (Ads Config File) JSON document that describes ad types, layout, view rectangles, over/under layers, audio behavior, etc.
  • The ACF format is described in the public ACF_SPEC_EN.md document.

In all modes, regardless of the configuration source, the SDK builds an internal ad schedule and coordinates it with main content.

Supported ad types conceptually include: - Pre‑roll – before main content; - Mid‑roll – at configured positions during content; - Post‑roll – after content is finished; - On‑pause – when the user pauses playback (image or video).

The exact implementation classes that transform these inputs into a schedule are internal and not part of the public contract; only the configuration interfaces and DefaultVideoPlayerConfiguration are public.

Choosing an Integration Strategy

Adaptive DAI SDK supports several levels of integration, which are illustrated by the demo apps shipped in the repository:

  1. Minimal integration (SimpleDemo)
    • Use AdaptiveDAILauncher and the SDK’s built‑in PlayerActivity.
    • Minimal custom code; fastest way to get ad‑enabled playback.
  2. Custom ExoPlayer + SDK Activity (CustomExoDemo)
    • Provide a custom ExoPlayerFactoryAdapter while still using the SDK’s PlayerActivity.
    • Good balance between control (buffering, track selection, listeners) and development speed.
  3. Full custom Activity (FullDemo)
    • Use AdaptiveDAISDK directly, provide your own Activity and layout.
    • Maximum flexibility for complex TV UIs and bespoke user journeys.

These scenarios are described in detail in the integration examples documentation (SDK_INTEGRATION_EXAMPLES_EN.md).

Next Steps

  • For a deeper architectural view, refer to this technical overview (warp.md) and the generated JavaDoc for the public API.
  • For practical guidance and code‑level instructions, continue with:
    • SDK_USER_GUIDE_EN.md – installation and step‑by‑step integration;
    • SDK_INTEGRATION_EXAMPLES_EN.md – three complete integration patterns based on demo apps.