Android SDK - CONTENT_RESUME_REQUESTED called too early

542 views
Skip to first unread message

Tim Pauls

unread,
Aug 12, 2015, 12:35:19 PM8/12/15
to Interactive Media Ads SDK
Hello,

I am currently working on an Android app that makes use of the IMA SDK to display pre-roll and mid-roll ads in videos.
The issue that I have is that the CONTENT_RESUME_REQUESTED event is fired too early - before the ad has actually finished playing. However this is not the case for the very first ad displayed, only subsequent pre- or mid-rolls get cut off, usually after about three seconds. Unfortunately, this only occurs in our app, not in the BasicExample.
Our implementation of the IMA SDK differs a bit from the basic sample, since our MediaPlayer/VideoView structure is more complex, but after going over the code multiple times, I can not find significant functional differences that could cause this error.
The tag I am currently using is the one labeled "VMAP - Pre-roll Single Ad, Mid-roll Standard Pod with 3 ads, Post-roll Single Ad" on the Sample Tag page (https://developers.google.com/interactive-media-ads/docs/sdks/android/tags?hl=de).

In order to help me debug the problem it would be great if you could tell me a bit more about when the SDK fires the CONTENT_RESUME_REQUESTED event. What preconditions have to be met? Any ideas where my problem could lie?

Any help is greatly appreciated.

Thanks,
Tim

Vu Chau (IMA SDK Team)

unread,
Aug 12, 2015, 3:31:50 PM8/12/15
to Interactive Media Ads SDK
Hi Tim,

That is a very big cut off time. We have never seen this issue before, and if it can't be reproduced in our sample example then we might not be able to provide much insights.  

Are you able to replicate the problem when using other ad tags as well?  Straight from the documentation, CONTENT_RESUME_REQUESTED is fired when an ad finishes (when AdEvent.AdEventType COMPLETED fired) or collapses. 

However, I'm thinking it might actually be a serial issue caused by preceding events, such as the ad finishes prematurely (or is thought to have finished), resulting in CONTENT_RESUME_REQUESTED being called early. I'd check the logic of your implementation to make sure that nothing before that is terminated too soon.  If you could share some code snippets, that would be great.

Vu Chau
IMA SDK Team

Adrian Rodriguez

unread,
Oct 13, 2015, 10:15:40 AM10/13/15
to Interactive Media Ads SDK
Hey, were you able to resolve the issue?

My implementation is using ExoPlayer and I see the same issue, the first ad plays with no problem but after loadAd of the second ad, CONTENT_RESUME_REQUESTED gets called and the second ad never plays.

Regards,

Adrian.

Vu Chau (IMA SDK Team)

unread,
Oct 13, 2015, 5:03:50 PM10/13/15
to Interactive Media Ads SDK
Hi Adrian,

Would you mind sharing with us a minimal code base (preferably with an ad tag, and with ExoPlayer implemented) that reproduces this issue?

Thanks,

Vu Chau
IMA SDK Team

Adrian Rodriguez

unread,
Nov 4, 2015, 5:03:47 AM11/4/15
to Interactive Media Ads SDK
@Override
public void onStateChanged(boolean playWhenReady, int playbackState) {
    super.onStateChanged(playWhenReady, playbackState);
    switch (playbackState) {
        case ExoPlayer.STATE_READY:
            if (playWhenReady) {
                for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                    L.g(TAG, "callback.onPlay()");
                    callback.onPlay();
                }
            } else {
                for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                    L.g(TAG, "callback.onPause()");
                    callback.onPause();
                }
            }
            break;
        case ExoPlayer.STATE_ENDED:
            for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                L.g(TAG, "callback.onEnded()");
                callback.onEnded();
            }
            break;
    }
}

@Override
public void onError(Exception e) {
    super.onError(e);
    for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
        L.g(TAG, "callback.onError()");
        callback.onError();
    }
}

private VideoAdPlayer mIMAAdPlayer = new VideoAdPlayer() {
    @Override
    public void loadAd(String url) {
        L.g(TAG, "AdPlayer.loadAd: " + url);
        if (mAdsManager == null) {
            L.g(TAG, "AdPlayer.loadAd: mAdsManager null");
            return;
        }

        mAdPlayerListener.onAdPlaying();
       
        RendererBuilder rendererBuilder = getRendererBuilder(StreamType.UNKNOWN, url, null);
        if (rendererBuilder == null) {
            for (VideoAdPlayer.VideoAdPlayerCallback callback : mAdCallbacks) {
                callback.onError();
            }
        } else {
            initExoPlayer(rendererBuilder);
            prepareExoPlayer();
        }
    }

    @Override
    public void playAd() {
        L.g(TAG, "AdPlayer.playAd");
        if (mAdsManager == null || getExoPlayer() == null) {
            L.g(TAG, "AdPlayer.playAd: mAdsManager null");
            return;
        }
        if (mAdUiContainer != null) {
            mAdUiContainer.requestFocus();
        }
        getExoPlayer().setPlayWhenReady(true);
    }

    @Override
    public void stopAd() {
        L.g(TAG, "AdPlayer.stopAd");
        if (getExoPlayer() != null) {
            getExoPlayer().stop();
        }
    }

    @Override
    public void pauseAd() {
        L.g(TAG, "AdPlayer.pauseAd");
        if (getExoPlayer() != null) {
            getExoPlayer().setPlayWhenReady(false);
        }
    }

    @Override
    public void resumeAd() {
        L.g(TAG, "AdPlayer.resumeAd");
        playAd();
    }

    @Override
    public void addCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
        if (videoAdPlayerCallback != null) {
            mAdCallbacks.add(videoAdPlayerCallback);
        }
    }

    @Override
    public void removeCallback(VideoAdPlayerCallback videoAdPlayerCallback) {
        if (videoAdPlayerCallback != null) {
            mAdCallbacks.remove(videoAdPlayerCallback);
        }
    }

    @Override
    public VideoProgressUpdate getAdProgress() {
        ExoPlayerWrapper player = getExoPlayer();
        if (player == null) {
            return VideoProgressUpdate.VIDEO_TIME_NOT_READY;
        } else {
            return new VideoProgressUpdate(player.getCurrentPosition(), player.getDuration());
        }
    }
};


private class VpAdEventListener implements AdEvent.AdEventListener {
    @Override
    public void onAdEvent(AdEvent adEvent) {
        L.g(TAG, "AD onAdEvent: " + adEvent.getType());
        switch (adEvent.getType()) {
            case LOADED:
                if (mAdsManager != null) {
                    mAdsManager.start();
                }
                break;

            case CONTENT_PAUSE_REQUESTED:
                break;

            case CONTENT_RESUME_REQUESTED:
                break;

            case STARTED:
                mTrackingNrOfAds++;
                break;

            case COMPLETED:
                break;

            case ALL_ADS_COMPLETED:
                // Stop & hide ad
                releaseAdPlayer();
                mAdPlayerListener.onAdFinished();
                break;

            case PAUSED:
                break;

            case RESUMED:
                break;

            case SKIPPED:
                break;
            case LOG:
                break;
            default:
                break;
        }
    }
}

That's some of the code. it's difficult to provide you with a full working code of the IMA player.

Adrian Rodriguez

unread,
Nov 4, 2015, 5:10:34 AM11/4/15
to Interactive Media Ads SDK

This is the sequence of events I'm getting when trying to play 2 ads, ALWAYS after the first ad finishes:

D/ExoPlayerWrapper: onPlayerStateChanged: true, 5
D/AdPlayer: callback.onEnded()
D/AdPlayer: AdPlayer.stopAd
D/AdPlayer: AD onAdEvent: COMPLETED
D/OMX: SendBroadCasting VIDEO_PLAYBACK_STOP
D/ExoPlayerWrapper: onPlayerStateChanged: true, 1
D/AdPlayer: AD onAdEvent: LOADED
I/ExoPlayerImpl: Init 1.5.1
D/ExoPlayerWrapper: onRenderers(): com.z.renderers.Renderers@3241a4b4
D/ExoPlayerWrapper: onPlayerStateChanged: true, 1
D/ExoPlayerWrapper: onPlayerStateChanged: true, 2
I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
D/AdPlayer: AdPlayer.playAd
D/AdPlayer: AD onAdEvent: CONTENT_RESUME_REQUESTED
D/AdPlayer: AdPlayer.pauseAd
D/ExoPlayerWrapper: onPlayerStateChanged: false, 2
D/SDK_DEBUG: Destroying NativeVideoDisplay
D/AdPlayer: AD onAdEvent: ALL_ADS_COMPLETED

I appreciate any help you can provide us with.

Regards,

Adrian.

Vu Chau (IMA SDK Team)

unread,
Nov 4, 2015, 4:48:26 PM11/4/15
to Interactive Media Ads SDK
Hi Adrian,

Thanks for providing us with the code snippets.  The inlined code looks fine to me.  So would you mind sending us a minified and zipped project so I might share with the engineering team if necessary?

In the meantime, I have a couple other questions to make sure we are on the same page:
  1. Are you able to confirm if CONTENT_RESUME_REQUESTED is also called prematurely when using other ad tags (VMAP, or ad rules) as well?  If so, which ones have you tried?
  2. Are you able to reproduce the issue using our sample app? If not then we'd need to dig into your project to understand more about the logic.
Thanks,

Vu Chau
IMA SDK Team

Reply all
Reply to author
Forward
0 new messages