Pierwsze kroki z pakietem IMA DAI SDK

Pakiety IMA SDK ułatwiają integrację reklam multimedialnych z witrynami i aplikacjami. Pakiety IMA SDK mogą żądać reklam z dowolnego serwera reklam zgodnego z VAST i zarządzać odtwarzaniem reklam w Twoich aplikacjach. Dzięki pakietom IMA DAI aplikacje mogą wysyłać żądania strumienia w przypadku reklam i treści wideo (VOD lub na żywo). Pakiet SDK zwraca następnie połączony strumień wideo, dzięki czemu nie musisz zarządzać przełączaniem między reklamami wideo a treściami wideo w aplikacji.

Wybierz rozwiązanie DAI, które Cię interesuje

Kompleksowe funkcje DAI

W tym przewodniku pokazujemy, jak zintegrować pakiet IMA SDK z prostą aplikacją odtwarzacza wideo. Jeśli chcesz wyświetlić lub przeanalizować ukończoną przykładową integrację, pobierz BasicExample z GitHuba.

Omówienie IMA DAI

Wdrożenie IMA DAI obejmuje 4 główne komponenty pakietu SDK, co pokazano w tym przewodniku:

  • StreamDisplayContainer: obiekt w kontenerze, który znajduje się na górze elementu odtwarzania filmu i zawiera elementy interfejsu reklamy.
  • AdsLoader: obiekt, który wysyła żądania strumieni i obsługuje zdarzenia wywoływane przez obiekty odpowiedzi żądania strumienia. Utwórz tylko jeden taki program.
  • StreamRequest: obiekt definiujący żądanie strumienia. Żądania strumienia mogą dotyczyć filmów na żądanie lub transmisji na żywo. Żądania określają identyfikator treści, a także klucz interfejsu API lub token uwierzytelniania i inne parametry.
  • StreamManager: obiekt, który obsługuje strumienie dynamicznego wstawiania reklam i interakcje z backendem DAI. Menedżer strumienia obsługuje też pingi śledzenia oraz przekazuje wydawcy strumień i zdarzenia reklamowe.

Wymagania wstępne

  • Android Studio,
  • Przykładowa aplikacja odtwarzacza wideo do integracji z pakietem SDK

Pobieranie i uruchamianie przykładowej aplikacji odtwarzacza wideo

Przykładowa aplikacja ma działający odtwarzacz wideo, który odtwarza filmy HLS. Użyj tego jako punktu wyjścia do integracji funkcji DAI w pakiecie IMA Android SDK.

  1. Pobierz przykładową aplikację odtwarzacza wideo i wyodrębnij ją.

  2. Uruchom Android Studio i wybierz Otwórz istniejący projekt Android Studio. Jeśli jednak Android Studio jest już uruchomiony, kliknij kolejno Plik > Nowy > Importuj projekt. Następnie wybierz SampleVideoPlayer/build.gradle.

  3. Aby uruchomić synchronizację Gradle, wybierz Narzędzia > Android > Synchronizuj projekt z plikami Gradle.

  4. Upewnij się, że aplikacja odtwarzacza skompiluje i działa na fizycznym urządzeniu z Androidem lub na wirtualnym urządzeniu z Androidem. Aby to zrobić, kliknij Uruchom > Uruchom „app”. Wczytywanie strumienia wideo przed odtworzeniem to zjawisko normalne.

Sprawdzanie przykładowego odtwarzacza wideo

Przykładowy odtwarzacz wideo nie zawiera jeszcze kodu integracji pakietu IMA SDK. Przykładowa aplikacja składa się z 2 głównych części:

  1. samplevideoplayer/SampleVideoPlayer.java: odtwarzacz HLS oparty na ExoPlayer, który jest podstawą integracji IMA DAI.

  2. videoplayerapp/MyActivity.java: to działanie tworzy odtwarzacz wideo i przekazuje mu Context oraz SimpleExoPlayerView.

Dodawanie pakietu IMA Android SDK do aplikacji odtwarzacza

Należy też dołączyć odniesienie do pakietu IMA SDK. W Android Studio dodaj ten kod do pliku build.gradle na poziomie aplikacji znajdującego się pod adresem app/build.gradle:

repositories {
  google()
  mavenCentral()
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.media3:media3-exoplayer:1.3.1'
    implementation 'com.google.ads.interactivemedia.v3:interactivemedia:3.33.0'
}

Integracja pakietu IMA SDK

  1. Utwórz w pakiecie videoplayerapp (w formacie app/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/) nową klasę o nazwie SampleAdsWrapper, aby opakować istniejący obiekt SampleVideoPlayer i dodać logikę implementującą IMA DAI. W tym celu musisz najpierw utworzyć obiekt AdsLoader, który będzie służyć do wysyłania żądań reklam do serwerów reklam.

    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 {
    
        // Livestream 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 = "2548831";
        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. Dodaj metodę buildStreamRequest() do interfejsu AdsLoader, aby umożliwić żądanie strumienia z reklamami. Jest to transmisja na żywo z reklamami (ustawiona domyślnie) lub transmisja wideo na żądanie(VOD), która odtwarza nagrane wcześniej treści z reklamami. Aby włączyć strumień VOD, dodaj komentarz do żądania transmisji na żywo i usuń znacznik komentarza z żądania.

    Aby działać z DAI, odtwarzacz musi przekazywać do pakietów IMA SDK zdarzenia ID3 w przypadku transmisji na żywo. W poniższym przykładowym kodzie wykonuje się to za pomocą metody callback.onUserTextReceived().

    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);
                        }
                    }
                });
    
        // Livestream 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 livestream to a VOD stream.
        // StreamRequest request = sdkFactory.createVodStreamRequest(TEST_CONTENT_SOURCE_ID,
        //        TEST_VIDEO_ID, null, displayContainer);
        return request;
    }
    
  3. Potrzebujesz też klasy VideoStreamPlayer, aby odtworzyć strumień, dlatego dodaj metodę createVideoStreamPlayer(), która utworzy anonimową klasę implementującą 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. Zaimplementuj wymagane detektory i dodaj obsługę błędów.

    Zwróć uwagę na implementację AdErrorListener, ponieważ w razie niepowodzenia reklamy wywołuje zastępczy adres URL. Treści i reklamy znajdują się w jednym strumieniu, więc musisz mieć możliwość wywołania strumienia zastępczego, jeśli w strumieniu z dynamicznym wstawianiem reklam wystąpi błąd.

    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. Dodaj kod do logowania.

    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. Zmodyfikuj MyActivity w videoplayerapp, aby utworzyć instancję i wywołać usługę SampleAdsWrapper.

    videoplayerapp/MyActivity.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. Zmodyfikuj plik układu aktywności activity_my.xml, aby dodać elementy interfejsu na potrzeby logowania.

    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>
    ...
    

Gratulacje! Żądasz i wyświetlasz reklamy wideo w aplikacji na Androida. Aby dostosować implementację, zapoznaj się z informacjami o zakładkach, Snapback i dokumentacji interfejsu API.

Rozwiązywanie problemów

Jeśli masz problemy z odtworzeniem reklamy wideo, pobierz uzupełniony BasicExample. Jeśli działa ona prawidłowo w przykładzie podstawowym, prawdopodobnie występuje problem z kodem integracji IMA Twojej aplikacji.

Jeśli nadal masz problemy, odwiedź forum IMA SDK.