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 aplikacjach. Dzięki pakietom IMA DAI SDK aplikacje wysyłają żądanie strumienia reklamy i treści wideo (VOD lub treści na żywo). Pakiet SDK zwraca następnie połączony strumień wideo, dzięki czemu nie musisz zarządzać przełączaniem się między reklamą a filmem z treściami w aplikacji.

Wybierz interesujące Cię rozwiązanie DAI

Pełna obsługa DAI

Ten przewodnik pokazuje, jak zintegrować pakiet IMA DAI SDK z prostym odtwarzaczem. Jeśli chcesz zobaczyć lub prześledzić przykładową integrację, pobierz BasicExample z GitHub.

Omówienie IMA DAI

Wdrożenie interfejsu IMA DAI wymaga 4 głównych komponentów pakietu SDK, jak opisano w tym przewodniku:

  • StreamDisplayContainer: obiekt kontenera, który znajduje się nad elementem odtwarzania filmu i zawiera elementy interfejsu reklamy.
  • AdsLoader: Obiekt, który żąda strumieni i obsługuje zdarzenia wywoływane przez obiekty odpowiedzi żądania strumienia. Należy utworzyć tylko 1 ładowarkę reklam, którą można ponownie wykorzystać w trakcie działania aplikacji.
  • StreamRequest: obiekt definiujący żądanie strumienia. Żądania strumieni mogą dotyczyć filmów na żądanie lub transmisji na żywo. Żądania zawierają identyfikator treści, a także klucz interfejsu API lub token uwierzytelniający oraz inne parametry.
  • StreamManager: obiekt, który obsługuje strumienie dynamicznego wstawiania reklam i interakcje z backendem DAI. Menedżer strumienia odpowiada też za pingi śledzenia i przekazuje wydawcy zdarzenia związane z reklamą i strumieniem.

Wymagania wstępne

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

Pobieranie i uruchamianie przykładowej aplikacji odtwarzacza filmów

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

  1. Pobierz przykładową aplikację odtwarzacza filmów i wyodrębnij ją.

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

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

  4. Upewnij się, że aplikacja odtwarzacza jest skompilowana i działa na fizycznym urządzeniu z Androidem lub na urządzeniu wirtualnym Androida, korzystając z opcji Uruchom > Uruchom „aplikację”. Wczytywanie strumienia wideo może chwilę potrwać.

Sprawdzanie przykładowego odtwarzacza

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

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

  2. videoplayerapp/MyActivity.java: ta aktywność tworzy odtwarzacz filmów i przekazuje mu wartości Context i SimpleExoPlayerView.

Dodaj pakiet IMA DAI SDK do aplikacji odtwarzacza

Musisz też dołączyć odwołanie do pakietu IMA DAI SDK. W Android Studio dodaj te informacje do pliku build.gradle na poziomie aplikacji, który znajduje się w folderze 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.36.0'
}

Integracja pakietu IMA DAI SDK

  1. Utwórz nową klasę o nazwie SampleAdsWrapper w pakiecie videoplayerapp (w pliku app/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/), aby owijać istniejący element SampleVideoPlayer oraz dodawać logikę implementującą interfejs DAI IMA. Aby to zrobić, musisz najpierw utworzyć AdsLoader, który 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 do AdsLoader metodę buildStreamRequest(), aby mogła poprosić o strumień z reklamami. Może to być transmisja na żywo z reklamami (domyślnie) lub strumień wideo na żądanie(VOD) z reklamami odtwarzającymi wcześniej nagrane treści. Aby włączyć strumień VOD, skomentuj żądanie dotyczące transmisji na żywo i odkomentuj żądanie dotyczące strumienia VOD.

    Aby współpracować z DAI, odtwarzacz musi przekazywać zdarzenia ID3 dotyczące transmisji na żywo do IMA DAI SDK. W poniższym przykładowym kodzie jest to realizowane 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. Do odtwarzania strumienia potrzebny jest też obiekt VideoStreamPlayer, więc dodaj metodę createVideoStreamPlayer(), która tworzy anonimową klasę implementującą interfejs 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());
            }
    
            @Override
            public int getVolume() {
                return videoPlayer.getVolume();
            }
        };
        return player;
    }
    
  4. Wdrożyć wymagane odbiorniki i dodać obsługę błędów.

    Zwróć uwagę na implementację AdErrorListener, ponieważ w przypadku awarii reklam wywołuje adres URL awaryjny. Treści i reklamy znajdują się w jednym strumieniu, więc musisz być gotowy do wywołania strumienia zapasowego, jeśli strumień DAI napotka 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 rejestrowania.

    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. Zmień MyActivityvideoplayerapp, aby utworzyć instancję i wywołać funkcję 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. Zmień plik układu aktywności activity_my.xml, aby dodać elementy interfejsu użytkownika do 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! Reklamy wideo są teraz żądane i wyświetlane w Twojej aplikacji na Androida. Aby dostosować implementację, zapoznaj się z funkcjami ZakładkiSnapback oraz z dokumentacją API.

Rozwiązywanie problemów

Jeśli masz problemy z odtwarzaniem reklamy wideo, pobierz gotowy projekt BasicExample. Jeśli w przykładzie podstawowym wszystko działa prawidłowo, prawdopodobnie wystąpił problem z kodem integracji IMA Twojej aplikacji.

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