Inizia a utilizzare l'SDK IMA DAI

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.

  1. Scarica l'app Video Player di esempio e decomprimila.
  2. 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.
  3. Esegui una sincronizzazione di Gradle selezionando Strumenti > Android > Sincronizza progetto con file Gradle.
  4. 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 a Context e SimpleExoPlayerView.

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'
}

Checkpoint: l'applicazione deve essere compilata ed eseguita, ma non hai ancora aggiunto elementi della UI o codice per richiedere e visualizzare gli annunci.

Integrazione dell'SDK IMA

  1. Crea una nuova classe denominata SampleAdsWrapper nel pacchetto videoplayerapp (in app/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/) per eseguire il wrapping del SampleVideoPlayer esistente e aggiungere la logica di implementazione dell'inserimento di annunci dinamici (DAI) di IMA. A tale scopo, devi prima creare un AdsLoader, 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());
        }
    }
              
  2. Aggiungi un metodo buildStreamRequest() a AdsLoader 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;
    }
    
  3. Ti serve anche un VideoStreamPlayer per riprodurre il flusso, quindi aggiungi un metodo createVideoStreamPlayer(), che crei una classe anonima che implementa VideoStreamPlayer.

    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;
    }
    
  4. Implementa i listener richiesti e aggiungi il supporto per la gestione degli errori.

    Importante: prendi nota dell'implementazione di AdErrorListener, 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;
    }
    
  5. 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);
        }
    }
    
  6. Modifica MyActivity in videoplayerapp per creare un'istanza e chiamare SampleAdsWrapper.

    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);
                }
            });
        }
    …
    }
  7. 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.