AdTagLoader: Internal error in stopAd when receiving AdEventType.LOADED event, then playing the VAST Ads
- Dominant language
- Java
- Stars
- 21.9k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
ExoPlayer and IMA version: 2.15.0
# Issue description
I try to play the VAST video ads by using the ExoPlayer IMA extension but will receive this error
```
2021-09-10 09:57:39.694 4050-4050/com.example.googleimatest D/AdTagLoader: onAdError
AdError [errorType: PLAY, errorCode: AdErrorCode [name: VAST_MEDIA_LOAD_TIMEOUT, number: 402], message: VAST media file loading reached a timeout of 8 seconds.]
at com.google.ads.interactivemedia.v3.internal.dg.f(IMASDK:1)
at com.google.ads.interactivemedia.v3.internal.ed.k(IMASDK:50)
at com.google.ads.interactivemedia.v3.internal.ej.f(IMASDK:5)
at com.google.ads.interactivemedia.v3.internal.eg.shouldOverrideUrlLoading(IMASDK:2)
at android.webkit.WebViewClient.shouldOverrideUrlLoading(WebViewClient.java:83)
at org.chromium.android_webview.AwContentsClientBridge.shouldOverrideUrlLoading(chromium-TrichromeWebViewGoogle.aab-stable-457706233:14)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:183)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2021-09-10 09:57:39.697 4050-4050/com.example.googleimatest D/AdTagLoader: stopAd AdMediaInfo[https://redirector.gvt1.com/videoplayback/id/a33fc5b2685eb16e/itag/15/source/gfp_video_ads/requiressl/yes/acao/yes/mime/video%2Fmp4/ctier/L/ip/0.0.0.0/ipbits/0/expire/1631260631/sparams/ip,ipbits,expire,id,itag,source,requiressl,acao,mime,ctier/signature/6CA0F3E39AF96DB6305D185C63ADD8DBE4168551.7F4C81AA73E3BA30D250E837830CC0F048D1AA6F/key/ck2/file/file.mp4, (0, 0)]
2021-09-10 09:57:39.698 4050-4050/com.example.googleimatest E/AdTagLoader: Internal error in stopAd
java.lang.IllegalArgumentException
at com.google.android.exoplayer2.util.Assertions.checkArgument(Assertions.java:39)
at com.google.android.exoplayer2.source.ads.AdPlaybackState$AdGroup.withAdState(AdPlaybackState.java:232)
at com.google.android.exoplayer2.source.ads.AdPlaybackState.withPlayedAd(AdPlaybackState.java:622)
at com.google.android.exoplayer2.ext.ima.AdTagLoader.stopAdInternal(AdTagLoader.java:1043)
at com.google.android.exoplayer2.ext.ima.AdTagLoader.access$2200(AdTagLoader.java:79)
at com.google.android.exoplayer2.ext.ima.AdTagLoader$ComponentListener.stopAd(AdTagLoader.java:1434)
at com.google.ads.interactivemedia.v3.internal.ek.f(IMASDK:3)
at com.google.ads.interactivemedia.v3.internal.ed.r(IMASDK:3)
at com.google.ads.interactivemedia.v3.internal.ed.k(IMASDK:126)
at com.google.ads.interactivemedia.v3.internal.ej.f(IMASDK:5)
at com.google.ads.interactivemedia.v3.internal.eg.shouldOverrideUrlLoading(IMASDK:2)
at android.webkit.WebViewClient.shouldOverrideUrlLoading(WebViewClient.java:83)
at org.chromium.android_webview.AwContentsClientBridge.shouldOverrideUrlLoading(chromium-TrichromeWebViewGoogle.aab-stable-457706233:14)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:183)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
```
# Reproduction steps
1. setup ExoPlayer, Ads and event listener
```
private fun initPlayer(vastXml: String) {
videoPlayer = SimpleExoPlayer.Builder(requireContext()).build()
.apply { addListener(playerEventListener) }
imaAdsLoader = ImaAdsLoader.Builder(requireContext())
.setDebugModeEnabled(true)
.setAdEventListener(adsEventListener)
.build()
.apply { setPlayer(videoPlayer) }
val mediaSourceWithAds = AdsMediaSource(
// We only want to play ads video and we don't have any content video
// Pass empty url here and it would raise MalformedURLException exception but we ignore it
SilenceMediaSource(0),
DataSpec(Util.getDataUriForString("text/xml", vastXml)),
vastXml,
DefaultMediaSourceFactory(requireContext()),
imaAdsLoader,
videoPlayerView
)
videoPlayer.prepare(mediaSourceWithAds)
videoPlayerView.player = videoPlayer
}
```
2. play ads video when receiving the `AdEventType.LOADED` event,
```
AdEvent.AdEventListener { event ->
if (event.type == AdEvent.AdEventType.LOADED) {
Handler(Looper.getMainLooper()).post {
videoPlayer.playWhenReady = true
}
}
}
```
I found the error coming from `Handler(Looper.getMainLooper()).post`. If I call `videoPlayer.playWhenReady = true` without `Handler(Looper.getMainLooper())`, the error will not happen.
The reason I add `Handler(Looper.getMainLooper())` is because I know that should be a single thread to access the ExoPlayer. I want to make sure `videoPlayer.playWhenReady = true` will be called on the main thread.
> ExoPlayer instances must be accessed from a single application thread. For the vast majority of cases this should be the application’s main thread. Using the application’s main thread is a requirement when using ExoPlayer’s UI components or the IMA extension.
I found there are two workaround solutions:
1. calling `videoPlayer.playWhenReady = true` directly
```
AdEvent.AdEventListener { event ->
if (event.type == AdEvent.AdEventType.LOADED) {
videoPlayer.playWhenReady = true
}
}
```
This solution works but I want to make sure this `videoPlayer.playWhenReady = true` always be calling in the main thread. So I still want to call it with `Handler(Looper.getMainLooper()).post`
2. `postDelayed` with a long time.
```
AdEvent.AdEventListener { event ->
if (event.type == AdEvent.AdEventType.LOADED) {
Handler(Looper.getMainLooper()).postDelayed({
videoPlayer.playWhenReady = true
}, 1000L)
}
}
```
Although this solution works, it will impact the performance of video loading. Also, how long it should `postDelayed` we don't know.
This issue is very similar to the crash 1 on this issue https://github.com/google/ExoPlayer/issues/8290.
The difference is I know how to reproduce.
I still want to know why we have this issue and how to fix it. Thanks
Contributor guide
Assessment
This issue has not been assessed yet.