IMA SDKs make it easy to integrate multimedia ads into your websites and apps. IMA SDKs can request ads from any VAST-compliant ad server and manage ad playback in your apps. With IMA client-side SDKs, you maintain control of content video playback, while the SDK handles ad playback. Ads play in a separate video player positioned on top of the app's content video player.
This guide demonstrates how to integrate the IMA SDK into an empty Android Studio project using the ExoPlayer IMA extension. If you would like to view or follow along with a completed sample integration, download the BasicExample from GitHub.
IMA client-side overview
Implementing IMA client-side involves four main SDK components, which are demonstrated in this guide:
AdDisplayContainer
: A container object that specifies where IMA renders ad UI elements and measures viewability, including Active View and Open Measurement.AdsLoader
: An object that requests ads and handles events from ads request responses. You should only instantiate one ads loader, which can be reused throughout the life of the application.AdsRequest
: An object that defines an ads request. Ads requests specify the URL for the VAST ad tag, as well as additional parameters, such as ad dimensions.AdsManager
: An object that contains the response to the ads request, controls ad playback, and listens for ad events fired by the SDK.
Prerequisites
Before you begin, you need Android Studio 3.0 or higher.
1. Create a new Android Studio project
To create your Android Studio project, complete the following steps:
- Start Android Studio.
- Select Start a new Android Studio project.
- In the Choose your project page, select the Empty Activity template.
- Click Next.
- In the Configure your project page, name your project and select Java for the language.
- Click Finish.
2. Add the ExoPlayer IMA extension to your project
First, in the application-level build.gradle file, add imports for the extension to the
dependencies section. Because of the size of the ExoPlayer IMA extension, implement and enable
multidex here. This is necessary for apps with minSdkVersion
set to 20 or lower.
Also, add new compileOptions
to specify the Java version compatibility information.
apply plugin: 'com.android.application' android { namespace 'com.google.ads.interactivemedia.v3.samples.exoplayerexample' compileSdk 36 // Java 17 required by Gradle 8+ compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } defaultConfig { applicationId "com.google.ads.interactivemedia.v3.samples.exoplayerexample" minSdkVersion 21 targetSdkVersion 36 multiDexEnabled true versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } repositories { google() mavenCentral() } dependencies { def media3_version = "1.8.0" implementation "androidx.media3:media3-ui:$media3_version" implementation "androidx.media3:media3-exoplayer:$media3_version" // The library adds the IMA ExoPlayer integration for ads. implementation "androidx.media3:media3-exoplayer-ima:$media3_version" implementation 'androidx.multidex:multidex:2.0.1' }
3. Create the ad UI container
Create the view to use as the ExoPlayer PlayerView by creating a
androidx.media3.ui.PlayerView
. Also, change the
androidx.constraintlayout.widget.ConstraintLayout
to a LinearLayout
.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MyActivity" tools:ignore="MergeRootFrame"> <androidx.media3.ui.PlayerView android:id="@+id/player_view" android:layout_width="match_parent" android:layout_height="wrap_content" /> <!-- UI element for viewing SDK event log --> <TextView android:id="@+id/logText" android:gravity="bottom" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxLines="100" android:scrollbars="vertical" android:textSize="@dimen/font_size"> </TextView> </LinearLayout>
4. Import the ExoPlayer IMA extension
Add the import statements for the ExoPlayer extension:
import static android.os.Build.VERSION.SDK_INT; import android.annotation.SuppressLint; import android.app.Activity; import android.net.Uri; import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.widget.TextView; import androidx.media3.common.MediaItem; import androidx.media3.datasource.DataSource; import androidx.media3.datasource.DefaultDataSource; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.exoplayer.ima.ImaAdsLoader; import androidx.media3.exoplayer.source.DefaultMediaSourceFactory; import androidx.media3.exoplayer.source.MediaSource; import androidx.media3.ui.PlayerView; import androidx.multidex.MultiDex; import com.google.ads.interactivemedia.v3.api.AdEvent; import com.google.ads.interactivemedia.v3.api.ImaSdkFactory; import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
Then, update the MainActivity
class to extend Activity
by adding
private variables for the PlayerView
, ExoPlayer
,
ImaAdsLoader
, and ImaSdkSettings
:
/** Main Activity. */ @SuppressLint("UnsafeOptInUsageError") /* @SuppressLint is needed for new media3 APIs. */ public class MyActivity extends Activity { private static final String SAMPLE_VIDEO_URL = "https://storage.googleapis.com/gvabox/media/samples/stock.mp4"; private static final String SAMPLE_VAST_TAG_URL = "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/" + "single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90" + "&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&correlator="; private static final String LOG_TAG = "ImaExoPlayerExample"; private PlayerView playerView; private TextView logText; private ExoPlayer player; private ImaAdsLoader adsLoader; private ImaSdkSettings imaSdkSettings;
5. Create an adsLoader
instance
Overwrite the onCreate
method and add the required variable assignments to create a
new adsLoader
object with the ad tag URL.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); MultiDex.install(this); // Initialize the IMA SDK as early as possible when the app starts. If your app already // overrides Application.onCreate(), call this method inside the onCreate() method. // https://developer.android.com/topic/performance/vitals/launch-time#app-creation ImaSdkFactory.getInstance().initialize(this, getImaSdkSettings()); playerView = findViewById(R.id.player_view); // Create an AdsLoader. adsLoader = new ImaAdsLoader.Builder(/* context= */ this) .setAdEventListener(buildAdEventListener()) .setImaSdkSettings(getImaSdkSettings()) .build(); }
Create the buildAdEventListener()
method to return an AdEventListener
object to log IMA events for debugging. The ExoPlayer IMA extension already handles IMA events
and does not need anything additional here to function.
public AdEvent.AdEventListener buildAdEventListener() { logText = findViewById(R.id.logText); logText.setMovementMethod(new ScrollingMovementMethod()); return event -> { AdEvent.AdEventType eventType = event.getType(); if (eventType == AdEvent.AdEventType.AD_PROGRESS) { return; } String log = "IMA event: " + eventType; if (logText != null) { logText.append(log + "\n"); } Log.i(LOG_TAG, log); }; }
Create the getImaSdkSettings()
helper method to return an
ImaSdkSettings
object to set any IMA SDK settings:
private ImaSdkSettings getImaSdkSettings() { if (imaSdkSettings == null) { imaSdkSettings = ImaSdkFactory.getInstance().createImaSdkSettings(); // Set any IMA SDK settings here. } return imaSdkSettings; }
6. Initialize and release the player
Add methods to release and initialize the player. In the initializePlayer()
method, create the ExoPlayer
. Then, create the AdsMediaSource
and set it to the player:
private void releasePlayer() { adsLoader.setPlayer(null); playerView.setPlayer(null); player.release(); player = null; } private void initializePlayer() { // Set up the factory for media sources, passing the ads loader and ad view providers. DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(this); MediaSource.Factory mediaSourceFactory = new DefaultMediaSourceFactory(dataSourceFactory) .setLocalAdInsertionComponents(unusedAdTagUri -> adsLoader, playerView); // Create an ExoPlayer and set it as the player for content and ads. player = new ExoPlayer.Builder(this).setMediaSourceFactory(mediaSourceFactory).build(); playerView.setPlayer(player); adsLoader.setPlayer(player); // Create the MediaItem to play, specifying the content URI and ad tag URI. Uri contentUri = Uri.parse(SAMPLE_VIDEO_URL); Uri adTagUri = Uri.parse(SAMPLE_VAST_TAG_URL); MediaItem mediaItem = new MediaItem.Builder() .setUri(contentUri) .setAdsConfiguration(new MediaItem.AdsConfiguration.Builder(adTagUri).build()) .build(); // Prepare the content and ad to be played with the SimpleExoPlayer. player.setMediaItem(mediaItem); player.prepare(); // Set PlayWhenReady. If true, content and ads will autoplay. player.setPlayWhenReady(false); }
7. Handle player events
Finally, create callbacks for the player's lifecycle events:
onStart
onResume
onStop
onPause
onDestroy
@Override public void onStart() { super.onStart(); if (SDK_INT > 23) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onResume() { super.onResume(); if (SDK_INT <= 23 || player == null) { initializePlayer(); if (playerView != null) { playerView.onResume(); } } } @Override public void onPause() { super.onPause(); if (SDK_INT <= 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override public void onStop() { super.onStop(); if (SDK_INT > 23) { if (playerView != null) { playerView.onPause(); } releasePlayer(); } } @Override protected void onDestroy() { adsLoader.release(); super.onDestroy(); }
You're now successfully requesting and displaying ads with the IMA SDK. To learn about more advanced features, explore the other guides or the samples on GitHub.