Воспроизведение персонализированной рекламы с помощью IMA SDK для Android

В IMA версии 3.30.0 и более ранних версиях IMA SDK может обрабатывать всю логику воспроизведения рекламы, в то время как ваше приложение фокусируется на воспроизведении видеоконтента. Этот подход называется «воспроизведение рекламы, принадлежащей SDK».

Если вы хотите воспроизводить рекламу в своем видеоплеере, SDK предоставляет для этого интерфейс. Мы называем этот подход «воспроизведением пользовательской рекламы», и остальная часть руководства посвящена его реализации.

Предварительные условия

  • Базовая интеграция IMA.

Мы рекомендуем вам просмотреть расширенный пример на github в качестве отправной точки, если у вас в настоящее время нет базовой интеграции IMA. В этом примере уже реализовано воспроизведение пользовательской рекламы. В оставшейся части этого руководства будут описаны функции, необходимые для воспроизведения персонализированной рекламы с помощью объявлений IMA.

Интерфейс с VideoAdPlayer

Для воспроизведения пользовательской рекламы необходимо, чтобы ваше приложение реализовало интерфейс VideoAdPlayer . Этот интерфейс используется SDK для уведомления вашего приложения о воспроизведении рекламных видеороликов. Ваше приложение также использует этот интерфейс для информирования SDK об основных событиях видеорекламы. Выполните следующие шаги, чтобы реализовать интерфейс.

Создайте видеорекламный проигрыватель

Первым шагом является создание анонимного класса VideoAdPlayer в requestAds() :

private VideoAdPlayer videoAdPlayer;
...

private void requestAds(String adTagUrl) {
    videoAdPlayer = new VideoAdPlayer() {
    };
}

Добавить методы видео

Затем добавьте методы, которые сообщают вашему видеоплееру воспроизводить, загружать, останавливать и приостанавливать рекламные видеоролики. Также сюда добавляем методы для освобождения плеера и получения громкости:

videoAdPlayer = new VideoAdPlayer() {
        @Override
        public void playAd() {
            if (mIsAdDisplayed) {
                videoPlayer.resume();
            } else {
                isAdDisplayed = true;
                videoPlayer.play();
            }
        }

        @Override
        public void loadAd(String url) {
            isAdDisplayed = true;
            videoPlayer.setVideoPath(url);
        }
        @Override
        public void stopAd() {
            videoPlayer.stopPlayback();
        }
        @Override
        public void pauseAd() {
            videoPlayer.pause();
        }

        @Override
        public void release() {
            // any clean up that needs to be done
        }

        @Override
        public int getVolume() {
            return videoPlayer.getVolume();
        }
};

Эти методы представляют собой тонкие оболочки вокруг аналогичных методов вашего видеоплеера. Обратите внимание, что эти методы устанавливают внутреннюю переменную, которая используется для отслеживания того, отображается ли реклама. При воспроизведении пользовательской рекламы видеопроигрыватель воспроизводит как контентное видео, так и видеорекламу, поэтому вам необходимо отслеживать, какая из них отображается в данный момент.

Ход воспроизведения рекламы

Интерфейс VideoAdPlayer реализует другой интерфейс, AdProgressProvider , поэтому вам также необходимо реализовать его. У него есть только один метод, getAdProgress() , который используется SDK для получения информации о воспроизведении рекламы. Добавьте его в свой анонимный класс VideoAdPlayer ниже других методов:

VideoAdPlayer videoAdPlayer = new VideoAdPlayer() {
        ...
        @Override
        public VideoProgressUpdate getAdProgress() {
            if (!isAdDisplayed || videoPlayer.getDuration() <= 0) {
                return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
            }
            return new VideoProgressUpdate(videoPlayer.getCurrentPosition(),
                    videoPlayer.getDuration());
        }
};

getAdProgress() возвращает тип VideoProgressUpdate , который должен состоять из текущей позиции и продолжительности видео. Если проигрыватель не воспроизводит рекламу или продолжительность недоступна, верните VideoProgressUpdate.VIDEO_TIME_NOT_READY , как показано в примере.

Управление обратными вызовами для видео

Для воспроизведения персонализированной рекламы ваше приложение должно информировать SDK об основных видеособытиях. С точки зрения SDK, это обратные вызовы, описываемые интерфейсом VideoAdPlayer.VideoAdPlayerCallback . Прежде чем приступить к самим методам обратного вызова, вам необходимо иметь возможность добавлять и удалять обратные вызовы по запросу SDK. Это делается внутри VideoAdPlayer с помощью addCallback() и removeCallback() :

private List<VideoAdPlayerCallback> adCallbacks = new ArrayList<>(1);

VideoAdPlayer videoAdPlayer = new VideoAdPlayer() {
        ...
        @Override
        public void addCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
            adCallbacks.add(videoAdPlayerCallback);
        }

        @Override
        public void removeCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
            adCallbacks.remove(videoAdPlayerCallback);
        }
};

Эта реализация использует List<> для обратных вызовов, для которых можно вызвать методы List<>.add() и remove() .

Вызов обратных вызовов

Теперь, когда у SDK есть возможность указать вашему приложению добавлять и удалять обратные вызовы, определите места, где вызывается обратный вызов. Ваше приложение должно вызывать эти обратные вызовы, когда происходят важные видеособытия, такие как воспроизведение, приостановка или возобновление видео, а также когда видео заканчивается или возникает ошибка.

Для этого разверните SampleVideoPlayer , чтобы иметь прослушиватель этих видеособытий, добавляемых из VideoFragment . Причина создания в SampleVideoPlayer отдельного прослушивателя для вызова этих обратных вызовов рекламы заключается в том, что SampleVideoPlayer ничего не знает о рекламе, поэтому вам необходимо перенаправить его видеособытия чему-то, что может обрабатывать рекламу.

public interface OnVideoEventsListener {
    void onPlay();
    void onResume();
    void onPause();
    void onError();
}

private final List<OnVideoEventsListener> onVideoEventsListeners = new ArrayList<>(1);

public void addVideoEventsListener(OnVideoEventsListener listener) {
    onVideoEventsListeners.add(listener);
}

Запуск, пауза и возобновление

Создайте новое перечисление для отслеживания состояния воспроизведения и добавьте новые переопределения для методов start() и pause() в SampleVideoPlayer :

private enum PlaybackState {
    STOPPED, PAUSED, PLAYING
}

private PlaybackState playbackState = PlaybackState.STOPPED;

@Override
public void start() {
    super.start();
    switch (playbackState) {
        case STOPPED:
            for (OnVideoEventsListener listener : onVideoEventsListeners) {
                listener.onPlay();
            }
            break;
        case PAUSED:
            for (OnVideoEventsListener listener : onVideoEventsListeners) {
                listener.onResume();
            }
            break;
        default:
            // Already playing; do nothing.
            break;
    }
    playbackState = PlaybackState.PLAYING;
}

@Override
public void pause() {
    super.pause();
    playbackState = PlaybackState.PAUSED;
    for (OnVideoEventsListener listener : onVideoEventsListeners) {
        listener.onPause();
    }
}

Обработка ошибок

Переопределите анонимный прослушиватель ошибок видеоплеера, который вы установили в init() :

@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
    playbackState = PlaybackState.STOPPED;
    for (OnVideoEventsListener listener : onVideoEventsListeners) {
        listener.onError();
    }

    // Returning true signals to MediaPlayer that the error was handled.
    // This  prevents the completion handler from being called.
    return true;
}

Реализация прослушивателя

Вернитесь в VideoFragment и добавьте анонимный OnVideoEventsListener в свой экземпляр SampleVideoPlayer :

mVideoPlayer.addVideoEventsListener(new OnVideoEventsListener() {
    @Override
    public void onPlay() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onPlay();
            }
        }
    }

    @Override
    public void onResume() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onResume();
            }
        }
    }

    @Override
    public void onPause() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onPause();
            }
        }
    }

    @Override
    public void onError() {
        if (isAdDisplayed) {
            for (VideoAdPlayerCallback callback : adCallbacks) {
                callback.onError();
            }
        }
    }
});

Измените метод onVideoCompleted() объекта OnVideoCompletedListener , чтобы он обрабатывал случай завершения рекламного видео:

public void onVideoCompleted() {
    // Handle completed event for playing post-rolls.
    if (isAdDisplayed) {
        for (VideoAdPlayerCallback callback : adCallbacks) {
            callback.onEnded();
        }
    } else {
        if (adsLoader != null) {
            adsLoader.contentComplete();
    }
}

Переключение между контентом и рекламой

В этом примере используется один и тот же экземпляр видеоплеера для воспроизведения контента и рекламы, поэтому вам необходимо добавить некоторую логику для переключения между контентом и рекламой в вашем проигрывателе. Затем вы можете перезагрузить и найти видеоконтент, чтобы вернуться к моменту начала рекламы. Добавьте для этого две функции:

private int savedContentPosition = 0;

private void pauseContent() {
    savedContentPosition = videoPlayer.getCurrentPosition();
    videoPlayer.stopPlayback();
    isAdDisplayed = true;
}

private void resumeContent() {
    videoPlayer.setVideoPath(getString(R.string.content_url));
    videoPlayer.seekTo(mSavedContentPosition);
    videoPlayer.play();
    isAdDisplayed = false;
}

Они вызываются при получении событий CONTENT_PAUSE_REQUESTED и CONTENT_RESUME_REQUESTED в VideoFragment.onAdEvent() соответственно:

case CONTENT_PAUSE_REQUESTED:
    pauseContent();
    break;
case CONTENT_RESUME_REQUESTED:
    resumeContent();
    break;

Включить воспроизведение персонализированной рекламы

Последний шаг — сообщить SDK, что вы используете воспроизведение настраиваемой рекламы. Это делается путем передачи VideoAdPlayer в ваш AdDisplayContainer :

adDisplayContainer.setPlayer(videoAdPlayer);

Необходимо передать ваш плеер в setPlayer() . В противном случае SDK использует воспроизведение, принадлежащее SDK.

Вот и все. Это все шаги, необходимые для добавления воспроизведения пользовательской рекламы в вашу реализацию IMA. Если у вас возникнут проблемы, вы можете сравнить свою собственную реализацию с расширенным примером на github.