IMA SDK memudahkan integrasi iklan multimedia ke dalam situs dan aplikasi Anda. IMA SDK dapat meminta iklan dari server iklan yang sesuai dengan VAST dan mengelola pemutaran iklan di aplikasi Anda. Dengan SDK sisi klien IMA, Anda mempertahankan kontrol pemutaran video konten, sementara SDK menangani pemutaran iklan. Iklan diputar di pemutar video terpisah yang diposisikan di atas pemutar video konten aplikasi.
Panduan ini menunjukkan cara mengintegrasikan IMA SDK ke dalam project Android Studio kosong menggunakan Android VideoView untuk menampilkan konten dan iklan. Untuk mengikuti contoh integrasi lengkap, download BasicExample dari GitHub.
Ringkasan sisi klien IMA
Mengimplementasikan sisi klien IMA melibatkan empat komponen SDK utama, yang ditunjukkan dalam panduan ini:
AdDisplayContainer
: Objek penampung yang menentukan tempat IMA merender elemen UI iklan dan mengukur visibilitas, termasuk Tampilan Aktif dan Open Measurement.AdsLoader
: Objek yang meminta iklan dan menangani peristiwa dari respons permintaan iklan. Anda hanya boleh membuat instance satu loader iklan, yang dapat digunakan kembali selama masa aktif aplikasi.AdsRequest
: Objek yang menentukan permintaan iklan. Permintaan iklan menentukan URL untuk tag iklan VAST, serta parameter tambahan, seperti dimensi iklan.AdsManager
: Objek yang berisi respons terhadap permintaan iklan, mengontrol pemutaran iklan, dan memproses peristiwa iklan yang diaktifkan oleh SDK.
Prasyarat
1. Membuat project Android Studio baru
Untuk membuat project Android Studio, selesaikan langkah-langkah berikut:
- Mulai Android Studio.
- Pilih Start a new Android Studio project.
- Di halaman Choose your project, pilih template Empty Activity.
- Klik Berikutnya.
- Di halaman Configure your project, beri nama project Anda dan pilih Java untuk bahasa.
- Klik Selesai.
2. Menambahkan IMA SDK ke project Anda
Pertama, dalam file build.gradle level aplikasi, tambahkan impor untuk IMA SDK ke
bagian dependensi. Karena ukuran IMA SDK, terapkan dan aktifkan multidex di sini. Hal ini
diperlukan untuk aplikasi dengan minSdkVersion
yang ditetapkan ke 20 atau lebih rendah. Selain itu, tambahkan
compileOptions
baru untuk menentukan informasi kompatibilitas versi Java.
android { namespace 'com.google.ads.interactivemedia.v3.samples.videoplayerapp' compileSdkVersion 34 compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } defaultConfig { applicationId "com.google.ads.interactivemedia.v3.samples.videoplayerapp" minSdkVersion 21 targetSdkVersion 34 multiDexEnabled true versionCode 1 versionName "1.0" } ... } dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.browser:browser:1.6.0' implementation 'androidx.media:media:1.6.0' implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.36.0' ... }
3. Menambahkan izin yang diperlukan IMA SDK
Tambahkan izin pengguna yang diperlukan oleh IMA SDK untuk meminta iklan.
app/src/main/AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project name"> <!-- Required permissions for the IMA SDK --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> ... </manifest>
4. Memperbarui tata letak aplikasi
Perbarui tata letak aplikasi untuk menyertakan VideoView
guna memutar konten dan
iklan.
<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: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:textSize="@dimen/font_size" /> </FrameLayout> </LinearLayout>
5. Mengimpor IMA ke aktivitas utama
Tambahkan pernyataan impor untuk IMA SDK. Kemudian, update
class MyActivity
untuk memperluas AppCompatActivity
. Class
AppCompatActivity
memungkinkan dukungan fitur platform yang lebih baru di perangkat
Android lama. Kemudian, tambahkan kumpulan variabel pribadi yang akan digunakan di aplikasi.
import android.content.Context; import android.media.AudioManager; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.MediaController; import android.widget.VideoView; 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.AdsManagerLoadedEvent; 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; ... 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&impl=s&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 View playButton; private VideoAdPlayerAdapter videoAdPlayerAdapter; }
6. Membuat class VideoAdPlayerAdapter
Buat class VideoAdPlayerAdapter
dengan VideoView
,
dan sesuaikan dengan antarmuka
VideoAdPlayer
IMA. Class ini akan menangani pemutaran konten dan iklan, serta akan berisi kumpulan
metode yang harus diterapkan pemutar video agar dapat digunakan oleh 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; } }
7. Mengganti metode VideoAdPlayer
Ganti metode VideoAdPlayer
berikut:
Metode playAd()
menetapkan konten atau URL iklan dan menetapkan pemroses untuk memulai
pemutaran setelah media dimuat.
/** Example implementation of IMA's VideoAdPlayer interface. */ public class VideoAdPlayerAdapter implements VideoAdPlayer { ... @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); }
8. Menyiapkan pelacakan iklan
Agar peristiwa iklan terdaftar,
VideoAdPlayerCallback.onAdProgress
harus dipanggil saat konten dan iklan berlangsung. Untuk mendukung hal ini, siapkan timer untuk memanggil onAdProgress()
pada interval yang ditetapkan.
/** Example implementation of IMA's VideoAdPlayer interface. */ public class VideoAdPlayerAdapter implements VideoAdPlayer { ... 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); } }
9. Memulai IMA dalam metode onCreate
Ganti metode onCreate
dan tambahkan penetapan variabel yang diperlukan untuk memulai
IMA. Pada langkah ini, buat hal berikut:
ImaSdkSettings
AdsLoader
Langkah ini juga akan membuat VideoAdPlayerAdapter
, class yang akan Anda buat nanti
dalam panduan ini.
Terakhir, siapkan tombol putar untuk meminta iklan, lalu sembunyikan saat diklik.
app/src/main/java/com/example/project name/MyActivity.java... public class MyActivity extends AppCompatActivity { ... private VideoView videoPlayer; private MediaController mediaController; private View playButton; private VideoAdPlayerAdapter videoAdPlayerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); // 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. ViewGroup videoPlayerContainer = findViewById(R.id.videoPlayerContainer); AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); videoAdPlayerAdapter = new VideoAdPlayerAdapter(videoPlayer, audioManager); sdkFactory = ImaSdkFactory.getInstance(); AdDisplayContainer adDisplayContainer = ImaSdkFactory.createAdDisplayContainer(videoPlayerContainer, videoAdPlayerAdapter); // Create an AdsLoader. ImaSdkSettings settings = sdkFactory.createImaSdkSettings(); adsLoader = sdkFactory.createAdsLoader(this, settings, adDisplayContainer); // When the play button is clicked, request ads and hide the button. playButton = findViewById(R.id.playButton); playButton.setOnClickListener( view -> { videoPlayer.setVideoPath(SAMPLE_VIDEO_URL); requestAds(SAMPLE_VAST_TAG_URL); view.setVisibility(View.GONE); }); } }
10. Menambahkan pemroses AdsLoader
Tambahkan pemroses untuk addAdErrorListener
dan
addAdsLoadedListener
. Di AdsLoadedListener
, buat
AdsManager
, dan siapkan pemroses error AdsManager
.
@Override protected void onCreate(Bundle savedInstanceState) { ... // Create an AdsLoader. ImaSdkSettings settings = sdkFactory.createImaSdkSettings(); adsLoader = sdkFactory.createAdsLoader(this, settings, adDisplayContainer); // 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( new AdsLoader.AdsLoadedListener() { @Override public void onAdsManagerLoaded(AdsManagerLoadedEvent 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(); } }); } });
11. Menangani peristiwa iklan IMA
Proses peristiwa iklan IMA dengan
AdsManager.addAdEventListener
. Dengan menggunakan pernyataan switch, siapkan tindakan untuk peristiwa IMA berikut:
Cuplikan kode menyertakan komentar dengan informasi selengkapnya tentang cara menggunakan peristiwa. Setelah peristiwa disiapkan, Anda dapat memanggil AdsManager.init()
.
adsLoader.addAdsLoadedListener( new AdsLoader.AdsLoadedListener() { @Override public void onAdsManagerLoaded(AdsManagerLoadedEvent adsManagerLoadedEvent) { ... 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(); break; case CONTENT_PAUSE_REQUESTED: // AdEventType.CONTENT_PAUSE_REQUESTED is fired when you // should pause your content and start playing an ad. pauseContentForAds(); break; case CONTENT_RESUME_REQUESTED: // AdEventType.CONTENT_RESUME_REQUESTED is fired when the ad // you should play your content. resumeContent(); break; case ALL_ADS_COMPLETED: // Calling adsManager.destroy() triggers the function // VideoAdPlayer.release(). adsManager.destroy(); adsManager = null; break; 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. break; default: break; } } }); AdsRenderingSettings adsRenderingSettings = ImaSdkFactory.getInstance().createAdsRenderingSettings(); adsManager.init(adsRenderingSettings); }
12. Menangani peralihan antara iklan dan konten
Di bagian ini, buat metode pauseContentForAds
dan resumeContent
yang dirujuk di langkah sebelumnya. Metode ini akan menggunakan kembali pemutar untuk memutar
konten dan iklan. Anda harus melacak posisi konten untuk
melanjutkan pemutaran setelah jeda iklan.
/** Main activity. */ public class MyActivity extends AppCompatActivity { ... 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()); } }
13. Permintaan iklan
Sekarang tambahkan metode requestAds
untuk mem-build
AdsRequest
dan menggunakannya untuk memanggil AdsLoader.requestAds()
.
/** Main activity. */ public class MyActivity extends AppCompatActivity { ... 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); } }
Selesai. Sekarang Anda meminta dan menampilkan iklan dengan IMA SDK. Untuk mempelajari fitur SDK tambahan, lihat panduan lain atau contoh di GitHub.