Reprodução de anúncios personalizados com o SDK do IMA para Android

A maneira mais rápida e direta de integrar o SDK do IMA para Android no seu app é fazer com que o SDK processe toda a lógica de reprodução do anúncio, enquanto seu app se concentra na reprodução de conteúdo em vídeo. Essa abordagem, chamada de "Reprodução de anúncios do SDK", é a opção padrão em Vamos começar.

No entanto, se você também quiser reproduzir anúncios no seu player de vídeo, o SDK fornece uma interface para isso. Chamamos essa abordagem de "reprodução de anúncios personalizados", e o restante deste guia explica a implementação.

Pré-requisitos

  • Uma integração básica do IMA.

Caso não tenha uma integração básica do IMA, recomendamos que você consulte o Exemplo avançado (link em inglês) no GitHub como ponto de partida. Este exemplo já implementa a reprodução de anúncios personalizados. O restante deste guia descreve os recursos necessários para a reprodução de anúncios personalizados com anúncios IMA.

Interface com VideoAdPlayer

A reprodução de anúncios personalizados exige que seu app implemente a interface VideoAdPlayer. Essa interface é usada pelo SDK para notificar seu app para reproduzir vídeos de anúncio. Seu app também usa essa interface para informar o SDK sobre os principais eventos de anúncio em vídeo. Siga estas etapas para implementar a interface.

Criar um VideoAdPlayer

A primeira etapa é criar uma classe VideoAdPlayer anônima em requestAds():

private VideoAdPlayer videoAdPlayer;
...

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

Adicionar métodos de vídeo

Em seguida, adicione métodos que instruam o player de vídeo a reproduzir, carregar, interromper e pausar vídeos de anúncios. Também adicionamos os métodos para liberar o player e obter o volume aqui:

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();
        }
};

Esses métodos são wrappers finos em torno dos próprios métodos semelhantes do player de vídeo. Esses métodos definem uma variável interna que é usada para monitorar a exibição de um anúncio. Na reprodução de anúncios personalizados, o player de vídeo exibe anúncios de conteúdo e em vídeo, então é necessário acompanhar qual deles está sendo exibido.

Progresso da reprodução do anúncio

A interface VideoAdPlayer implementa outra interface, AdProgressProvider, então você também precisa implementá-la. Ele tem apenas um método, getAdProgress(), que é usado pelo SDK para coletar informações de reprodução de anúncios. Adicione-o à classe VideoAdPlayer anônima, abaixo dos outros métodos:

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() retorna um tipo VideoProgressUpdate, que precisa consistir na posição e duração atuais do vídeo. Se o player não estiver reproduzindo um anúncio ou a duração não estiver disponível, faça com que ele retorne VideoProgressUpdate.VIDEO_TIME_NOT_READY, como mostrado no exemplo.

Gerenciar callbacks de vídeo

A reprodução de anúncios personalizados exige que seu app informe o SDK sobre os principais eventos de vídeo. Na visualização do SDK, esses são os callbacks descritos pela interface VideoAdPlayer.VideoAdPlayerCallback. Antes de acessar os métodos de callback, você precisa poder adicionar e remover os callbacks à solicitação do SDK. Isso é feito dentro de VideoAdPlayer usando addCallback() e 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);
        }
};

Essa implementação usa um List<> para os callbacks em que os métodos List<>.add() e remove() são chamados.

Chamar os callbacks

Agora que o SDK tem uma maneira de instruir seu app a adicionar e remover callbacks, defina os locais em que o callback será chamado. Seu app precisa chamar esses callbacks quando ocorrerem eventos importantes de vídeo, como ao reproduzir, pausar ou retomar um vídeo, ou quando um vídeo terminar ou apresentar um erro.

Para fazer isso, expanda o SampleVideoPlayer para ter um listener para esses eventos de vídeo adicionados do VideoFragment. O motivo para criar um listener separado em SampleVideoPlayer para chamar esses callbacks de anúncio é porque o SampleVideoPlayer não sabe nada sobre anúncios, então você precisa encaminhar os eventos de vídeo para algo que possa lidar com anúncios.

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

Iniciar, pausar e retomar

Crie uma nova enumeração para monitorar o estado da reprodução e adicione novas substituições para os métodos start() e pause() em 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();
    }
}

Solucionar erros

Substitua o listener de erro anônimo do player de vídeo que você definiu em 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;
}

Implementar o listener

Volte para VideoFragment e adicione um OnVideoEventsListener anônimo à sua instância de 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();
            }
        }
    }
});

Mude o método onVideoCompleted() da OnVideoCompletedListener para processar o caso de um vídeo de anúncio terminar:

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

Alternar entre conteúdo e anúncios

Este exemplo usa a mesma instância do player de vídeo para reproduzir conteúdo e anúncios. Portanto, é necessário adicionar alguma lógica para alternar entre conteúdo e anúncios no player. Atualize e busque o conteúdo de vídeo para voltar ao ponto em que o anúncio começou. Adicione duas funções para fazer isso:

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

Eles são chamados quando os eventos CONTENT_PAUSE_REQUESTED e CONTENT_RESUME_REQUESTED são recebidos, em VideoFragment.onAdEvent(), respectivamente:

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

Ativar a reprodução de anúncios personalizados

A última etapa é informar ao SDK que você está usando a reprodução de anúncios personalizados. Para fazer isso, transmita um VideoAdPlayer para o AdDisplayContainer:

adDisplayContainer.setPlayer(videoAdPlayer);

É necessário transmitir o jogador para setPlayer(). Caso contrário, o SDK vai usar a reprodução de propriedade do SDK.

Pronto. Essas são todas as etapas necessárias para adicionar a reprodução de anúncios personalizados à sua implementação do IMA. Você pode comparar sua própria implementação com o Exemplo avançado (link em inglês) no GitHub se tiver problemas.