Пакеты IMA SDK упрощают интеграцию мультимедийной рекламы в ваши веб-сайты и приложения. Пакеты IMA SDK могут запрашивать рекламу с любого рекламного сервера , совместимого с VAST, и управлять её воспроизведением в ваших приложениях. Клиентские пакеты IMA SDK позволяют вам контролировать воспроизведение видеоконтента, в то время как SDK управляет воспроизведением рекламы. Реклама воспроизводится в отдельном видеоплеере, расположенном поверх видеоплеера приложения.
В этом руководстве показано, как интегрировать IMA SDK в пустой проект Android Studio, используя Android VideoView для отображения контента и рекламы. Чтобы ознакомиться с готовым примером интеграции, скачайте BasicExample с GitHub.
Обзор клиентской части IMA
Реализация IMA на стороне клиента включает четыре основных компонента SDK, которые продемонстрированы в этом руководстве:
-
AdDisplayContainer
: объект-контейнер, который указывает, где IMA отображает элементы пользовательского интерфейса рекламы и измеряет видимость, включая Active View и Open Measurement . -
AdsLoader
— объект, который запрашивает рекламу и обрабатывает события, возникающие при ответах на запросы рекламы. Необходимо создать только один экземпляр загрузчика рекламы, который можно использовать повторно на протяжении всего жизненного цикла приложения. -
AdsRequest
: объект, определяющий запрос на рекламу. Запросы на рекламу содержат URL-адрес тега VAST, а также дополнительные параметры, такие как размеры объявления. -
AdsManager
: объект, который содержит ответ на запрос рекламы, управляет воспроизведением рекламы и прослушивает события рекламы, запускаемые SDK.
Предпосылки
1. Создайте новый проект Android Studio.
Чтобы создать свой проект Android Studio, выполните следующие шаги:
- Запустите Android Studio.
- Выберите Начать новый проект Android Studio .
- На странице «Выберите свой проект» выберите шаблон «Пустая деятельность» .
- Нажмите кнопку «Далее» .
- На странице «Настройка проекта» дайте проекту имя и выберите Java в качестве языка.
- Нажмите кнопку Готово .
2. Добавьте IMA SDK в свой проект.
Сначала в файле build.gradle уровня приложения добавьте импорты для IMA SDK в раздел dependencies. В связи с размером IMA SDK, реализуйте и включите multidex здесь. Это необходимо для приложений, у которых minSdkVersion
установлен на 20 или ниже. Также добавьте новый compileOptions
для указания информации о совместимости версий Java и включения десахаринга библиотек.
Для работы IMA SDK требуется включить дешугаринг библиотек. Для этого установите значение coreLibraryDesugaringEnabled true
и добавьте coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
в качестве зависимости в файле build.gradle . Подробнее см. в разделе API Java 11+, доступные через дешугаринг с помощью спецификации nio .
apply plugin: 'com.android.application' android { namespace 'com.google.ads.interactivemedia.v3.samples.videoplayerapp' compileSdk 36 // Java 17 required by Gradle 8+ compileOptions { // Required by IMA SDK v3.37.0+ coreLibraryDesugaringEnabled true // Java 17 required by Gradle 8+ sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } defaultConfig { applicationId "com.google.ads.interactivemedia.v3.samples.videoplayerapp" 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 { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0")) implementation 'androidx.appcompat:appcompat:1.7.1' implementation 'androidx.browser:browser:1.9.0' implementation 'androidx.media:media:1.7.0' implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.37.0' }
3. Обновите макет приложения.
Обновите макет приложения, включив в него VideoView
для воспроизведения как контента, так и рекламы:
<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"> <RelativeLayout android:background="#000000" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.4" android:orientation="vertical" android:id="@+id/videoPlayerContainer" > <VideoView android:id="@+id/videoView" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageButton android:id="@+id/playButton" android:contentDescription="@string/play_description" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/ic_action_play_over_video" android:background="@null" /> </RelativeLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.6" android:id="@+id/videoDescription" > <TextView android:id="@+id/playerDescription" android:text="@string/app_name" android:textAlignment="center" android:gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingVertical="@dimen/font_size" android:textSize="@dimen/font_size" /> </FrameLayout> </LinearLayout>
4. Импортируйте IMA в основную деятельность
Добавьте операторы импорта для IMA SDK:
import android.content.Context; import android.content.res.Configuration; import android.media.AudioManager; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.MediaController; import android.widget.VideoView; import androidx.appcompat.app.AppCompatActivity; import com.google.ads.interactivemedia.v3.api.AdDisplayContainer; import com.google.ads.interactivemedia.v3.api.AdErrorEvent; import com.google.ads.interactivemedia.v3.api.AdEvent; import com.google.ads.interactivemedia.v3.api.AdsLoader; import com.google.ads.interactivemedia.v3.api.AdsManager; import com.google.ads.interactivemedia.v3.api.AdsRenderingSettings; import com.google.ads.interactivemedia.v3.api.AdsRequest; import com.google.ads.interactivemedia.v3.api.ImaSdkFactory; import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate; import java.util.Arrays;
Обновите класс MyActivity
, чтобы расширить AppCompatActivity
. Класс AppCompatActivity
обеспечивает поддержку новых функций платформы на старых устройствах Android. Затем добавьте набор приватных переменных, которые будут использоваться в приложении:
/** Main activity. */ public class MyActivity extends AppCompatActivity { private static final String LOGTAG = "IMABasicSample"; private static final String SAMPLE_VIDEO_URL = "https://storage.googleapis.com/gvabox/media/samples/stock.mp4"; /** * IMA sample tag for a single skippable inline video ad. See more IMA sample tags at * https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/tags */ private static final String SAMPLE_VAST_TAG_URL = "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/" + "single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast" + "&unviewed_position_start=1&env=vp&correlator="; // Factory class for creating SDK objects. private ImaSdkFactory sdkFactory; // The AdsLoader instance exposes the requestAds method. private AdsLoader adsLoader; // AdsManager exposes methods to control ad playback and listen to ad events. private AdsManager adsManager; // The saved content position, used to resumed content following an ad break. private int savedPosition = 0; // This sample uses a VideoView for content and ad playback. For production // apps, Android's Exoplayer offers a more fully featured player compared to // the VideoView. private VideoView videoPlayer; private MediaController mediaController; private VideoAdPlayerAdapter videoAdPlayerAdapter; private ImaSdkSettings imaSdkSettings;
5. Создайте класс VideoAdPlayerAdapter
Создайте класс VideoAdPlayerAdapter
с VideoView
и адаптируйте его к интерфейсу VideoAdPlayer
IMA. Этот класс будет обрабатывать воспроизведение контента и рекламы, а также содержать набор методов, которые должен реализовать видеоплеер для использования в IMA SDK:
import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.util.Log; import android.widget.VideoView; import com.google.ads.interactivemedia.v3.api.AdPodInfo; import com.google.ads.interactivemedia.v3.api.player.AdMediaInfo; import com.google.ads.interactivemedia.v3.api.player.VideoAdPlayer; import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; /** Example implementation of IMA's VideoAdPlayer interface. */ public class VideoAdPlayerAdapter implements VideoAdPlayer { private static final String LOGTAG = "IMABasicSample"; private static final long POLLING_TIME_MS = 250; private static final long INITIAL_DELAY_MS = 250; private final VideoView videoPlayer; private final AudioManager audioManager; private final List<VideoAdPlayerCallback> videoAdPlayerCallbacks = new ArrayList<>(); private Timer timer; private int adDuration; // The saved ad position, used to resumed ad playback following an ad click-through. private int savedAdPosition; private AdMediaInfo loadedAdMediaInfo; public VideoAdPlayerAdapter(VideoView videoPlayer, AudioManager audioManager) { this.videoPlayer = videoPlayer; this.videoPlayer.setOnCompletionListener( (MediaPlayer mediaPlayer) -> notifyImaOnContentCompleted()); this.audioManager = audioManager; }
6. Переопределите методы VideoAdPlayer
Переопределите следующие методы VideoAdPlayer
:
Метод playAd()
устанавливает URL-адрес контента или рекламы и настраивает прослушиватель на запуск воспроизведения после загрузки мультимедиа.
@Override public void addCallback(VideoAdPlayerCallback videoAdPlayerCallback) { videoAdPlayerCallbacks.add(videoAdPlayerCallback); } @Override public void loadAd(AdMediaInfo adMediaInfo, AdPodInfo adPodInfo) { // This simple ad loading logic works because preloading is disabled. To support // preloading ads your app must maintain state for the currently playing ad // while handling upcoming ad downloading and buffering at the same time. // See the IMA Android preloading guide for more info: // https://developers.google.com/interactive-media-ads/docs/sdks/android/client-side/preload loadedAdMediaInfo = adMediaInfo; } @Override public void pauseAd(AdMediaInfo adMediaInfo) { Log.i(LOGTAG, "pauseAd"); savedAdPosition = videoPlayer.getCurrentPosition(); stopAdTracking(); } @Override public void playAd(AdMediaInfo adMediaInfo) { videoPlayer.setVideoURI(Uri.parse(adMediaInfo.getUrl())); videoPlayer.setOnPreparedListener( mediaPlayer -> { adDuration = mediaPlayer.getDuration(); if (savedAdPosition > 0) { mediaPlayer.seekTo(savedAdPosition); } mediaPlayer.start(); startAdTracking(); }); videoPlayer.setOnErrorListener( (mediaPlayer, errorType, extra) -> notifyImaSdkAboutAdError(errorType)); videoPlayer.setOnCompletionListener( mediaPlayer -> { savedAdPosition = 0; notifyImaSdkAboutAdEnded(); }); } @Override public void release() { // any clean up that needs to be done. } @Override public void removeCallback(VideoAdPlayerCallback videoAdPlayerCallback) { videoAdPlayerCallbacks.remove(videoAdPlayerCallback); } @Override public void stopAd(AdMediaInfo adMediaInfo) { Log.i(LOGTAG, "stopAd"); stopAdTracking(); } /** Returns current volume as a percent of max volume. */ @Override public int getVolume() { return audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) / audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); }
7. Настройте отслеживание рекламы
Для регистрации событий рекламы необходимо вызывать VideoAdPlayerCallback.onAdProgress
по мере продвижения контента и рекламы. Для этого настройте таймер для вызова onAdProgress()
с заданным интервалом.
private void startAdTracking() { Log.i(LOGTAG, "startAdTracking"); if (timer != null) { return; } timer = new Timer(); TimerTask updateTimerTask = new TimerTask() { @Override public void run() { VideoProgressUpdate progressUpdate = getAdProgress(); notifyImaSdkAboutAdProgress(progressUpdate); } }; timer.schedule(updateTimerTask, POLLING_TIME_MS, INITIAL_DELAY_MS); } private void notifyImaSdkAboutAdEnded() { Log.i(LOGTAG, "notifyImaSdkAboutAdEnded"); savedAdPosition = 0; for (VideoAdPlayer.VideoAdPlayerCallback callback : videoAdPlayerCallbacks) { callback.onEnded(loadedAdMediaInfo); } } private void notifyImaSdkAboutAdProgress(VideoProgressUpdate adProgress) { for (VideoAdPlayer.VideoAdPlayerCallback callback : videoAdPlayerCallbacks) { callback.onAdProgress(loadedAdMediaInfo, adProgress); } } /** * @param errorType Media player's error type as defined at * https://cs.android.com/android/platform/superproject/+/master:frameworks/base/media/java/android/media/MediaPlayer.java;l=4335 * @return True to stop the current ad playback. */ private boolean notifyImaSdkAboutAdError(int errorType) { Log.i(LOGTAG, "notifyImaSdkAboutAdError"); switch (errorType) { case MediaPlayer.MEDIA_ERROR_UNSUPPORTED: Log.e(LOGTAG, "notifyImaSdkAboutAdError: MEDIA_ERROR_UNSUPPORTED"); break; case MediaPlayer.MEDIA_ERROR_TIMED_OUT: Log.e(LOGTAG, "notifyImaSdkAboutAdError: MEDIA_ERROR_TIMED_OUT"); break; default: break; } for (VideoAdPlayer.VideoAdPlayerCallback callback : videoAdPlayerCallbacks) { callback.onError(loadedAdMediaInfo); } return true; } public void notifyImaOnContentCompleted() { Log.i(LOGTAG, "notifyImaOnContentCompleted"); for (VideoAdPlayer.VideoAdPlayerCallback callback : videoAdPlayerCallbacks) { callback.onContentComplete(); } } private void stopAdTracking() { Log.i(LOGTAG, "stopAdTracking"); if (timer != null) { timer.cancel(); timer = null; } } @Override public VideoProgressUpdate getAdProgress() { long adPosition = videoPlayer.getCurrentPosition(); return new VideoProgressUpdate(adPosition, adDuration); }
8. Инициируйте IMA в методе onCreate
Перепишите метод onCreate
и добавьте необходимые назначения переменных для запуска IMA. На этом этапе создайте экземпляры следующих объектов:
-
ImaSdkSettings
-
AdsLoader
-
VideoAdPlayerAdapter
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); // 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 sdkFactory = ImaSdkFactory.getInstance(); sdkFactory.initialize(this, getImaSdkSettings()); // Create the UI for controlling the video view. mediaController = new MediaController(this); videoPlayer = findViewById(R.id.videoView); mediaController.setAnchorView(videoPlayer); videoPlayer.setMediaController(mediaController); // Create an ad display container that uses a ViewGroup to listen to taps. AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); videoAdPlayerAdapter = new VideoAdPlayerAdapter(videoPlayer, audioManager); AdDisplayContainer adDisplayContainer = ImaSdkFactory.createAdDisplayContainer( findViewById(R.id.videoPlayerContainer), videoAdPlayerAdapter); // Create an AdsLoader. adsLoader = sdkFactory.createAdsLoader(this, getImaSdkSettings(), adDisplayContainer);
Настройте кнопку воспроизведения для запроса рекламы, а затем скрывайте ее при нажатии:
// When the play button is clicked, request ads and hide the button. View playButton = findViewById(R.id.playButton); playButton.setOnClickListener( view -> { videoPlayer.setVideoPath(SAMPLE_VIDEO_URL); requestAds(SAMPLE_VAST_TAG_URL); view.setVisibility(View.GONE); });
ImaSdkSettings
: private ImaSdkSettings getImaSdkSettings() { if (imaSdkSettings == null) { imaSdkSettings = ImaSdkFactory.getInstance().createImaSdkSettings(); // Set any IMA SDK settings here. } return imaSdkSettings; }
9. Добавьте прослушиватели AdsLoader
Добавьте прослушиватели для addAdErrorListener
и addAdsLoadedListener
. В AdsLoadedListener
создайте AdsManager
и настройте прослушиватель ошибок AdsManager
:
// Add listeners for when ads are loaded and for errors. adsLoader.addAdErrorListener( new AdErrorEvent.AdErrorListener() { /** An event raised when there is an error loading or playing ads. */ @Override public void onAdError(AdErrorEvent adErrorEvent) { Log.i(LOGTAG, "Ad Error: " + adErrorEvent.getError().getMessage()); resumeContent(); } }); adsLoader.addAdsLoadedListener( adsManagerLoadedEvent -> { // Ads were successfully loaded, so get the AdsManager instance. AdsManager has // events for ad playback and errors. adsManager = adsManagerLoadedEvent.getAdsManager(); // Attach event and error event listeners. adsManager.addAdErrorListener( new AdErrorEvent.AdErrorListener() { /** An event raised when there is an error loading or playing ads. */ @Override public void onAdError(AdErrorEvent adErrorEvent) { Log.e(LOGTAG, "Ad Error: " + adErrorEvent.getError().getMessage()); String universalAdIds = Arrays.toString(adsManager.getCurrentAd().getUniversalAdIds()); Log.i( LOGTAG, "Discarding the current ad break with universal " + "ad Ids: " + universalAdIds); adsManager.discardAdBreak(); } });
10. Обработка событий рекламы IMA
Отслеживайте события рекламы IMA с помощью AdsManager.addAdEventListener
. Используя оператор switch, настройте действия для следующих событий IMA:
Фрагмент кода содержит комментарии с дополнительной информацией об использовании событий. После настройки событий вызовите AdsManager.init()
:
adsManager.addAdEventListener( new AdEvent.AdEventListener() { /** Responds to AdEvents. */ @Override public void onAdEvent(AdEvent adEvent) { if (adEvent.getType() != AdEvent.AdEventType.AD_PROGRESS) { Log.i(LOGTAG, "Event: " + adEvent.getType()); } // These are the suggested event types to handle. For full list of // all ad event types, see AdEvent.AdEventType documentation. switch (adEvent.getType()) { case LOADED -> // AdEventType.LOADED is fired when ads are ready to play. // This sample app uses the sample tag // single_preroll_skippable_ad_tag_url that requires calling // AdsManager.start() to start ad playback. // If you use a different ad tag URL that returns a VMAP or // an ad rules playlist, the adsManager.init() function will // trigger ad playback automatically and the IMA SDK will // ignore the adsManager.start(). // It is safe to always call adsManager.start() in the // LOADED event. adsManager.start(); case CONTENT_PAUSE_REQUESTED -> // AdEventType.CONTENT_PAUSE_REQUESTED is fired when you // should pause your content and start playing an ad. pauseContentForAds(); case CONTENT_RESUME_REQUESTED -> // AdEventType.CONTENT_RESUME_REQUESTED is fired when the ad // you should play your content. resumeContent(); case ALL_ADS_COMPLETED -> { // Calling adsManager.destroy() triggers the function // VideoAdPlayer.release(). adsManager.destroy(); adsManager = null; } case CLICKED -> { // When the user clicks on the Learn More button, the IMA SDK fires // this event, pauses the ad, and opens the ad's click-through URL. // When the user returns to the app, the IMA SDK calls the // VideoAdPlayer.playAd() function automatically. } default -> {} } } }); AdsRenderingSettings adsRenderingSettings = ImaSdkFactory.getInstance().createAdsRenderingSettings(); // Add any ads rendering settings here. // This init() only loads the UI rendering settings locally. adsManager.init(adsRenderingSettings); });
11. Управление переключением между рекламой и контентом
В этом разделе создайте методы pauseContentForAds
и resumeContent
, упомянутые в предыдущих шагах. Эти методы будут повторно использовать плеер для воспроизведения как контента, так и рекламы. Вам потребуется отслеживать положение контента, чтобы возобновить воспроизведение после рекламной паузы.
private void pauseContentForAds() { Log.i(LOGTAG, "pauseContentForAds"); savedPosition = videoPlayer.getCurrentPosition(); videoPlayer.stopPlayback(); // Hide the buttons and seek bar controlling the video view. videoPlayer.setMediaController(null); } private void resumeContent() { Log.i(LOGTAG, "resumeContent"); // Show the buttons and seek bar controlling the video view. videoPlayer.setVideoPath(SAMPLE_VIDEO_URL); videoPlayer.setMediaController(mediaController); videoPlayer.setOnPreparedListener( mediaPlayer -> { if (savedPosition > 0) { mediaPlayer.seekTo(savedPosition); } mediaPlayer.start(); }); videoPlayer.setOnCompletionListener( mediaPlayer -> videoAdPlayerAdapter.notifyImaOnContentCompleted()); }
12. Запрос рекламы
Теперь добавьте метод requestAds
для создания AdsRequest
и используйте его для вызова AdsLoader.requestAds()
:
private void requestAds(String adTagUrl) { // Create the ads request. AdsRequest request = sdkFactory.createAdsRequest(); request.setAdTagUrl(adTagUrl); request.setContentProgressProvider( () -> { if (videoPlayer.getDuration() <= 0) { return VideoProgressUpdate.VIDEO_TIME_NOT_READY; } return new VideoProgressUpdate( videoPlayer.getCurrentPosition(), videoPlayer.getDuration()); }); // Request the ad. After the ad is loaded, onAdsManagerLoaded() will be called. adsLoader.requestAds(request); }
Теперь вы успешно запрашиваете и показываете рекламу с помощью IMA SDK. Чтобы узнать о более продвинутых функциях, изучите другие руководства или примеры на GitHub .