با IMA DAI SDK شروع کنید

IMA SDK ادغام تبلیغات چندرسانه ای را در وب سایت ها و برنامه های شما آسان می کند. IMA SDK می‌تواند از هر سرور تبلیغاتی سازگار با VAST آگهی درخواست کند و پخش آگهی را در برنامه‌های شما مدیریت کند. با IMA DAI SDK، برنامه‌ها درخواست پخش جریانی برای آگهی و ویدیوی محتوا را ارائه می‌کنند - اعم از VOD یا محتوای زنده. سپس SDK یک جریان ویدیوی ترکیبی را برمی‌گرداند، به طوری که نیازی به مدیریت جابجایی بین آگهی و ویدیوی محتوا در برنامه خود ندارید.

راه حل DAI مورد علاقه خود را انتخاب کنید

خدمات کامل DAI

این راهنما نحوه ادغام IMA DAI SDK را در یک برنامه پخش کننده ویدیوی ساده نشان می دهد. اگر می‌خواهید نمونه یکپارچه‌سازی کامل شده را مشاهده یا دنبال کنید، BasicExample را از GitHub دانلود کنید.

نمای کلی IMA DAI

پیاده سازی IMA DAI شامل چهار جزء اصلی SDK است که در این راهنما نشان داده شده است:

  • StreamDisplayContainer : یک شی کانتینری که در بالای عنصر پخش ویدیو قرار می گیرد و عناصر رابط کاربری تبلیغات را در خود جای می دهد.
  • AdsLoader : شی ای که درخواست جریان می کند و رویدادهای ایجاد شده توسط اشیاء پاسخ درخواست جریان را مدیریت می کند. شما باید فقط یک بارکننده تبلیغات را نمونه برداری کنید، که می تواند در طول عمر برنامه مجددا استفاده شود.
  • StreamRequest : یک شی که یک درخواست جریان را تعریف می کند. درخواست‌های جریان می‌تواند برای ویدیوی درخواستی یا پخش مستقیم باشد. درخواست ها یک شناسه محتوا و همچنین یک کلید API یا نشانه احراز هویت و سایر پارامترها را مشخص می کنند.
  • StreamManager : شیئی که جریانهای درج آگهی پویا و تعاملات با باطن DAI را مدیریت می کند. مدیر جریان همچنین پینگ‌های ردیابی را مدیریت می‌کند و جریان‌ها و رویدادهای تبلیغاتی را به ناشر ارسال می‌کند.

پیش نیازها

نمونه برنامه پخش کننده ویدیو را دانلود و اجرا کنید

برنامه نمونه یک پخش کننده ویدیوی فعال را ارائه می دهد که ویدیوی HLS را پخش می کند. از این به عنوان نقطه شروع برای ادغام قابلیت‌های DAI IMA DAI SDK استفاده کنید.

  1. نمونه برنامه پخش ویدئو را دانلود کرده و آن را استخراج کنید.

  2. Android Studio را راه اندازی کنید و Open an Android Studio موجود را انتخاب کنید، یا اگر Android Studio از قبل در حال اجرا است، File > New > Import Project را انتخاب کنید. سپس SampleVideoPlayer/build.gradle را انتخاب کنید.

  3. با انتخاب Tools > Android > Sync Project with Gradle Files، همگام سازی Gradle را اجرا کنید.

  4. با استفاده از Run > Run 'app' اطمینان حاصل کنید که برنامه پخش کننده روی یک دستگاه Android فیزیکی یا یک دستگاه مجازی Android کامپایل و اجرا می شود. این طبیعی است که پخش جریانی ویدیو قبل از پخش چند لحظه طول بکشد تا بارگیری شود.

نمونه پخش کننده ویدیو را بررسی کنید

پخش‌کننده ویدیوی نمونه هنوز حاوی کد یکپارچه‌سازی IMA DAI SDK نیست. برنامه نمونه از دو بخش اصلی تشکیل شده است:

  1. samplevideoplayer/SampleVideoPlayer.java : یک پخش کننده HLS مبتنی بر ExoPlayer که به عنوان پایه ای برای ادغام IMA DAI عمل می کند.

  2. videoplayerapp/MyActivity.java : این اکتیویتی پخش کننده ویدیو را ایجاد می کند و به آن یک Context و SimpleExoPlayerView می دهد.

IMA DAI SDK را به برنامه پخش اضافه کنید

همچنین باید ارجاعی به IMA DAI SDK داشته باشید. در Android Studio، موارد زیر را به فایل build.gradle در سطح برنامه خود، واقع در 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'
}

IMA DAI SDK را یکپارچه کنید

  1. یک کلاس جدید به نام SampleAdsWrapper در بسته videoplayerapp (در app/java/com.google.ads.interactivemedia.v3.samples/videoplayerapp/ ) ایجاد کنید تا SampleVideoPlayer موجود را بپیچید و منطق پیاده‌سازی IMA DAI را اضافه کنید. برای انجام این کار، ابتدا باید یک AdsLoader ایجاد کنید که برای درخواست تبلیغات از سرورهای تبلیغاتی استفاده می شود.

    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. یک متد buildStreamRequest() به AdsLoader اضافه کنید تا بتواند یک جریان با تبلیغات درخواست کند. این یا یک پخش زنده با تبلیغات (به طور پیش فرض تنظیم شده) یا یک جریان ویدیویی بر اساس تقاضا (VOD) است که محتوای از پیش ضبط شده را با تبلیغات پخش می کند. برای فعال کردن جریان VOD، درخواست پخش زنده را نظر دهید و درخواست پخش VOD را لغو نظر کنید.

    برای کار با DAI، بازیکن باید رویدادهای ID3 را برای پخش زنده به کیت توسعه نرم‌افزار IMA DAI ارسال کند. در کد نمونه زیر، این کار با متد 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. شما همچنین به یک VideoStreamPlayer برای پخش جریان نیاز دارید، بنابراین یک متد createVideoStreamPlayer() اضافه کنید، که یک کلاس ناشناس ایجاد می کند که 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. شنونده های مورد نیاز را پیاده سازی کنید و پشتیبانی برای مدیریت خطا اضافه کنید.

    به اجرای AdErrorListener توجه کنید، زیرا اگر تبلیغات پخش نشد، URL بازگشتی را فراخوانی می کند. از آنجایی که محتوا و تبلیغات در یک جریان هستند، اگر جریان 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. اضافه کردن کد برای ورود به سیستم

    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. MyActivity در videoplayerapp برای نمونه‌سازی و فراخوانی 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. برای افزودن عناصر رابط کاربری برای ثبت گزارش activity_my.xml فایل طرح‌بندی Activity را تغییر دهید.

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

تبریک میگم اکنون در حال درخواست و نمایش تبلیغات ویدیویی در برنامه Android خود هستید. برای تنظیم دقیق پیاده سازی خود، به نشانک ها ، Snapback و مستندات API مراجعه کنید.

عیب یابی

اگر هنگام پخش یک تبلیغ ویدیویی با مشکل مواجه هستید، BasicExample کامل شده را دانلود کنید. اگر در BasicExample به درستی کار کند، احتمالاً مشکلی در کد یکپارچه سازی IMA برنامه شما وجود دارد.

اگر همچنان مشکل دارید، از انجمن IMA SDK دیدن کنید.