Gli SDK IMA ti consentono di integrare facilmente gli annunci multimediali nei tuoi siti web e nelle tue app. Gli SDK IMA possono richiedere annunci da qualsiasi ad server compatibile con VAST e gestire la riproduzione degli annunci nelle tue app. Con gli SDK IMA DAI, le app inviano una richiesta di streaming per annunci e contenuti video, VOD o contenuti in diretta. L'SDK restituisce quindi un video stream combinato, in modo che tu non debba gestire il passaggio da un annuncio all'altro all'interno della tua app.
Questa guida mostra come integrare l'SDK IMA in una semplice app di video player. Se vuoi visualizzare o seguire un'integrazione di esempio completata, scarica BasicExample da GitHub.
Panoramica dell'IMA DAI
L'implementazione dell'inserimento di annunci dinamici IMA prevede quattro componenti principali dell'SDK, illustrati in questa guida:
StreamDisplayContainer
: un oggetto contenitore posizionato sopra l'elemento di riproduzione del video e che ospita gli elementi dell'interfaccia utente dell'annuncio.AdsLoader
: un oggetto che richiede flussi e gestisce gli eventi attivati dagli oggetti risposta delle richieste di streaming. Devi creare un'unica istanza del caricatore di annunci, che può essere riutilizzato per tutta la durata dell'applicazione.StreamRequest
: un oggetto che definisce una richiesta di streaming. Le richieste di stream possono essere video on demand o live streaming. Le richieste specificano un ID contenuto, una chiave API o un token di autenticazione e altri parametri.StreamManager
: un oggetto che gestisce i flussi di inserimento di annunci dinamici e le interazioni con il backend DAI. Inoltre, gestisce i ping di monitoraggio e inoltra gli eventi in streaming e gli annunci al publisher.
Prerequisiti
- Android Studio
- L'app Video Player di esempio che utilizzerai per integrare l'SDK
Scarica ed esegui l'app di video player di esempio
L'app di esempio fornisce un video player funzionante che riproduce video HLS. Usalo come punto di partenza per l'integrazione della funzionalità DAI dell'SDK IMA per Android.
- Scarica l'app Video Player di esempio e decomprimila.
- Avvia Android Studio e seleziona Apri un progetto Android Studio esistente oppure, se Android Studio è già in esecuzione, seleziona File > Nuovo > Importa progetto. Poi scegli
SampleVideoPlayer/build.gradle
. - Esegui una sincronizzazione di Gradle selezionando Strumenti > Android > Sincronizza progetto con file Gradle.
- Assicurati che l'app del player sia compilata e eseguita su un dispositivo Android fisico o un dispositivo virtuale Android utilizzando Esegui > Esegui 'app'. È normale che il caricamento del video stream richieda qualche istante prima di essere riprodotto.
Esamina il video player di esempio
Il video player di esempio non contiene ancora alcun codice di integrazione SDK IMA. L'app di esempio è composta da due parti principali:
samplevideoplayer/SampleVideoPlayer.java
: un semplice player HLS basato su ExoPlayer che funge da base per l'integrazione di IMA DAI.videoplayerapp/MyActivity.java
: questa attività crea il video player e lo trasmette aContext
eSimpleExoPlayerView
.
Aggiungi l'SDK IMA per Android all'app del player
Devi includere anche un riferimento all'SDK IMA. In Android Studio, aggiungi quanto segue al file build.gradle
a livello di applicazione, che si trova nella posizione app/build.gradle
:
repositories { google() jcenter() } dependencies { implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.browser:browser:1.3.0' implementation 'com.google.android.exoplayer:exoplayer:2.18.1' implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.29.0' }
Integrazione dell'SDK IMA
-
Crea una nuova classe denominata
SampleAdsWrapper
nel pacchettovideoplayerapp
(inapp/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/
) per eseguire il wrapping delSampleVideoPlayer
esistente e aggiungere la logica di implementazione dell'inserimento di annunci dinamici (DAI) di IMA. A tale scopo, devi prima creare unAdsLoader
, utilizzato per richiedere gli annunci dagli ad server.videoplayerapp/SampleAdsWrapper.java
package com.google.ads.interactivemedia.v3.samples.videoplayerapp; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; import android.view.ViewGroup; import android.webkit.WebView; 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.AdsManagerLoadedEvent; import com.google.ads.interactivemedia.v3.api.CuePoint; import com.google.ads.interactivemedia.v3.api.ImaSdkFactory; import com.google.ads.interactivemedia.v3.api.ImaSdkSettings; import com.google.ads.interactivemedia.v3.api.StreamDisplayContainer; import com.google.ads.interactivemedia.v3.api.StreamManager; import com.google.ads.interactivemedia.v3.api.StreamRequest; import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate; import com.google.ads.interactivemedia.v3.api.player.VideoStreamPlayer; import com.google.ads.interactivemedia.v3.samples.samplevideoplayer.SampleVideoPlayer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class SampleAdsWrapper implements AdEvent.AdEventListener, AdErrorEvent.AdErrorListener, AdsLoader.AdsLoadedListener { // Live stream asset key. private static final String TEST_ASSET_KEY = "sN_IYUG8STe1ZzhIIE_ksA"; // VOD content source and video IDs. private static final String TEST_CONTENT_SOURCE_ID = "2528370"; private static final String TEST_VIDEO_ID = "tears-of-steel"; private static final String PLAYER_TYPE = "DAISamplePlayer"; /** * Log interface, so you can output the log commands to the UI or similar. */ public interface Logger { void log(String logMessage); } private ImaSdkFactory sdkFactory; private AdsLoader adsLoader; private StreamDisplayContainer displayContainer; private StreamManager streamManager; private List<VideoStreamPlayer.VideoStreamPlayerCallback> playerCallbacks; private SampleVideoPlayer videoPlayer; private Context context; private ViewGroup adUiContainer; private String fallbackUrl; private Logger logger; public SampleAdsWrapper(Context context, SampleVideoPlayer videoPlayer, ViewGroup adUiContainer) { this.videoPlayer = videoPlayer; this.context = context; this.adUiContainer = adUiContainer; sdkFactory = ImaSdkFactory.getInstance(); playerCallbacks = new ArrayList<>(); createAdsLoader(); displayContainer = sdkFactory.createStreamDisplayContainer( this.adUiContainer, videoStreamPlayer ); } private void createAdsLoader() { ImaSdkSettings settings = new ImaSdkSettings(); adsLoader = sdkFactory.createAdsLoader(context); } public void requestAndPlayAds() { adsLoader.addAdErrorListener(this); adsLoader.addAdsLoadedListener(this); adsLoader.requestStream(buildStreamRequest()); } }
-
Aggiungi un metodo
buildStreamRequest()
aAdsLoader
per poter richiedere uno stream con annunci. Si tratta di un live streaming con annunci (impostati per impostazione predefinita) o di un video on demand(VOD) che riproduce contenuti preregistrati con annunci. Per abilitare lo stream VOD, commenta la richiesta di live streaming e rimuovi il commento.videoplayerapp/SampleAdsWrapper.java
private StreamRequest buildStreamRequest() { VideoStreamPlayer videoStreamPlayer = createVideoStreamPlayer(); videoPlayer.setSampleVideoPlayerCallback( new SampleVideoPlayer.SampleVideoPlayerCallback() { @Override public void onUserTextReceived(String userText) { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onUserTextReceived(userText); } } @Override public void onSeek(int windowIndex, long positionMs) { // See if you would seek past an ad, and if so, jump back to it. long newSeekPositionMs = positionMs; if (streamManager != null) { CuePoint prevCuePoint = streamManager.getPreviousCuePointForStreamTime(positionMs / 1000); if (prevCuePoint != null && !prevCuePoint.isPlayed()) { newSeekPositionMs = (long) (prevCuePoint.getStartTime() * 1000); } } videoPlayer.seekTo(windowIndex, newSeekPositionMs); } @Override public void onContentComplete() { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onContentComplete(); } } @Override public void onPause() { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onPause(); } } @Override public void onResume() { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onResume(); } } @Override public void onVolumeChanged(int percentage) { for (VideoStreamPlayer.VideoStreamPlayerCallback callback : playerCallbacks) { callback.onVolumeChanged(percentage); } } }); // Live stream request. StreamRequest request = sdkFactory.createLiveStreamRequest( TEST_ASSET_KEY, null, displayContainer); // VOD request. Comment the createLiveStreamRequest() line above and uncomment this // createVodStreamRequest() below to switch from a live stream to a VOD stream. // StreamRequest request = sdkFactory.createVodStreamRequest(TEST_CONTENT_SOURCE_ID, // TEST_VIDEO_ID, null, displayContainer); return request; }
-
Ti serve anche un
VideoStreamPlayer
per riprodurre il flusso, quindi aggiungi un metodocreateVideoStreamPlayer()
, che crei una classe anonima che implementaVideoStreamPlayer
.videoplayerapp/SampleAdsWrapper.java
private VideoStreamPlayer createVideoStreamPlayer() { VideoStreamPlayer player = new VideoStreamPlayer() { @Override public void loadUrl(String url, List<HashMap<String, String>> subtitles) { videoPlayer.setStreamUrl(url); videoPlayer.play(); } @Override public void addCallback( VideoStreamPlayerCallback videoStreamPlayerCallback) { playerCallbacks.add(videoStreamPlayerCallback); } @Override public void removeCallback( VideoStreamPlayerCallback videoStreamPlayerCallback) { playerCallbacks.remove(videoStreamPlayerCallback); } @Override public void onAdBreakStarted() { // Disable player controls. videoPlayer.enableControls(false); log("Ad Break Started\n"); } @Override public void onAdBreakEnded() { // Re-enable player controls. videoPlayer.enableControls(true); log("Ad Break Ended\n"); } @Override public VideoProgressUpdate getContentProgress() { return new VideoProgressUpdate(videoPlayer.getCurrentPosition(), videoPlayer.getDuration()); } }; return player; }
-
Implementa i listener richiesti e aggiungi il supporto per la gestione degli errori.
Importante: prendi nota dell'implementazione diAdErrorListener
, poiché chiama un URL di riserva se gli annunci non vengono riprodotti. Poiché i contenuti e gli annunci si trovano in un unico stream, devi essere in grado di chiamare uno stream di riserva se si verifica un errore nello stream DAI.videoplayerapp/SampleAdsWrapper.java
/** AdErrorListener implementation **/ @Override public void onAdError(AdErrorEvent event) { // play fallback URL. videoPlayer.setStreamUrl(fallbackUrl); videoPlayer.enableControls(true); videoPlayer.play(); } /** AdEventListener implementation **/ @Override public void onAdEvent(AdEvent event) { switch (event.getType()) { case AD_PROGRESS: // Do nothing or else log are filled by these messages. break; default: log(String.format("Event: %s\n", event.getType())); break; } } /** AdsLoadedListener implementation **/ @Override public void onAdsManagerLoaded(AdsManagerLoadedEvent event) { streamManager = event.getStreamManager(); streamManager.addAdErrorListener(this); streamManager.addAdEventListener(this); streamManager.init(); } /** Sets fallback URL in case ads stream fails. **/ void setFallbackUrl(String url) { fallbackUrl = url; }
-
Aggiungi codice per il logging.
videoplayerapp/SampleAdsWrapper.java
/** Sets logger for displaying events to screen. Optional. **/ void setLogger(Logger logger) { this.logger = logger; } private void log(String message) { if (logger != null) { logger.log(message); } }
- Modifica
MyActivity
invideoplayerapp
per creare un'istanza e chiamareSampleAdsWrapper
.app videoplayer/LeMieAttività.java
… import android.view.ViewGroup; import android.widget.ScrollView; … public class MyActivity extends AppCompatActivity { … @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); View rootView = findViewById(R.id.videoLayout); videoPlayer = new SampleVideoPlayer(rootView.getContext(), (SimpleExoPlayerView) rootView.findViewById(R.id.playerView)); videoPlayer.enableControls(false); final SampleAdsWrapper sampleAdsWrapper = new SampleAdsWrapper(this, videoPlayer, (ViewGroup) rootView.findViewById(R.id.adUiContainer)); sampleAdsWrapper.setFallbackUrl(DEFAULT_STREAM_URL); final ScrollView scrollView = (ScrollView) findViewById(R.id.logScroll); final TextView textView = (TextView) findViewById(R.id.logText); sampleAdsWrapper.setLogger(new SampleAdsWrapper.Logger() { @Override public void log(String logMessage) { Log.i(APP_LOG_TAG, logMessage); if (textView != null) { textView.append(logMessage); } if (scrollView != null) { scrollView.post(new Runnable() { @Override public void run() { scrollView.fullScroll(View.FOCUS_DOWN); } }); } } }); playButton = (ImageButton) rootView.findViewById(R.id.playButton); // Set up play button listener to play video then hide play button. playButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sampleAdsWrapper.requestAndPlayAds(); playButton.setVisibility(View.GONE); } }); } … }
- Modifica il file di layout dell'attività,
activity_my.xml
, per aggiungere elementi dell'interfaccia utente per il logging.res/layout/activity_my.xml
… <TextView android:id="@+id/playerDescription" android:text="@string/video_description" android:textAlignment="center" android:gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.1" android:textSize="@dimen/font_size" /> <!-- UI element for viewing SDK event log --> <ScrollView android:id="@+id/logScroll" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.5" android:padding="5dp" android:background="#DDDDDD"> <TextView android:id="@+id/logText" android:layout_width="match_parent" android:layout_height="wrap_content"> </TextView> </ScrollView> …
Complimenti! Stai richiedendo e mostrando annunci video nella tua applicazione Android. Per perfezionare l'implementazione, consultate le guide Segnalibri e Snapback e la documentazione dell'API.
Risoluzione dei problemi
Se riscontri problemi con la riproduzione di un annuncio video, prova a scaricare il Esempio di base completato. Se funziona correttamente in BasicExample, è probabile che si sia verificato un problema con il codice di integrazione IMA della tua app. Consulta questa guida e i documenti dell'API per rilevare eventuali discrepanze.
I problemi persistono? Contattaci nel forum dell'SDK IMA.