当前位置: 首页 > 知识库问答 >
问题:

ExoPlayer不使用广告

薛欣德
2023-03-14

我在我的应用程序中使用Codelab:https://codelabs.developers.google.com/codelabs/exoplayer-intro/#3的示例实现了ExoPlayer,算法与https://medium.com/google-exoplayer/playing-ads-with-exoplayer-and-ima-868dfd767ea的示例唯一的区别是我使用AdsMediaSource而不是已弃用的ImaAdsMediaSource。我的实现是这样的:

class HostVideoFullFragment : Fragment(), AdsMediaSource.MediaSourceFactory {

    override fun getSupportedTypes() = intArrayOf(C.TYPE_DASH, C.TYPE_HLS, C.TYPE_OTHER)

    override fun createMediaSource(uri: Uri?, handler: Handler?, listener: MediaSourceEventListener?): MediaSource {
        @C.ContentType val type = Util.inferContentType(uri)
        return when (type) {
            C.TYPE_DASH -> {
                DashMediaSource.Factory(
                        DefaultDashChunkSource.Factory(mediaDataSourceFactory),
                        manifestDataSourceFactory)
                        .createMediaSource(uri, handler, listener)
            }

            C.TYPE_HLS -> {
                HlsMediaSource.Factory(mediaDataSourceFactory)
                        .createMediaSource(uri, handler, listener)
            }

            C.TYPE_OTHER -> {
                ExtractorMediaSource.Factory(mediaDataSourceFactory)
                        .createMediaSource(uri, handler, listener)
            }

            else -> throw IllegalStateException("Unsupported type for createMediaSource: $type")
        }
    }

    private var player: SimpleExoPlayer? = null
    private lateinit var playerView: SimpleExoPlayerView
    private lateinit var binding: FragmentHostVideoFullBinding

    private var playbackPosition: Long = 0
    private var currentWindow: Int = 0
    private var playWhenReady = true

    private var inErrorState: Boolean = false

    private lateinit var adsLoader: ImaAdsLoader
    private lateinit var manifestDataSourceFactory: DataSource.Factory
    private lateinit var mediaDataSourceFactory: DataSource.Factory

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        //Initialize the adsLoader
        adsLoader = ImaAdsLoader(activity as Context, Uri.parse("https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpost&cmsid=496&vid=short_onecue&correlator="))

        manifestDataSourceFactory = DefaultDataSourceFactory(
                context, Util.getUserAgent(context, "BUO-APP"))//TODO change the applicationName with the right application name
//
        mediaDataSourceFactory = DefaultDataSourceFactory(
                context,
                Util.getUserAgent(context, "BUO-APP"),//TODO change the applicationName with the right application name
                DefaultBandwidthMeter())
    }

    private fun initializePlayer() {
        /*
        * Since the player can change from null (when we release resources) to not null we have to check if it's null.
        * If it is then reset again
        * */
        if (player == null) {
            //Initialize the Exo Player
            player = ExoPlayerFactory.newSimpleInstance(DefaultRenderersFactory(activity as Context),
                    DefaultTrackSelector())
        }

        val uri = Uri.parse(videoURl)

        val mediaSourceWithAds = buildMediaSourceWithAds(uri)

        //Bind the view from the xml to the SimpleExoPlayer instance
        playerView.player = player

        //Add the listener that listens for errors
        player?.addListener(PlayerEventListener())

        player?.seekTo(currentWindow, playbackPosition)

        player?.prepare(mediaSourceWithAds, true, false)

        //In case we could not set the exo player
        player?.playWhenReady = playWhenReady

        //We got here without an error, therefore set the inErrorState as false
        inErrorState = false

        //Re update the retry button since, this method could have come from a retry click
        updateRetryButton()
    }

    private inner class PlayerEventListener : Player.DefaultEventListener() {

        fun updateResumePosition() {
            player?.let {
                currentWindow = player!!.currentWindowIndex
                playbackPosition = Math.max(0, player!!.contentPosition)
            }
        }

        override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
            //The player state has ended
            //TODO check if there is going to be a UI change here
//            if (playbackState == Player.STATE_ENDED) {
//                showControls()
//            }
//            updateButtonVisibilities()
        }

        override fun onPositionDiscontinuity(@Player.DiscontinuityReason reason: Int) {
            if (inErrorState) {
                // This will only occur if the user has performed a seek whilst in the error state. Update
                // the resume position so that if the user then retries, playback will resume from the
                // position to which they seek.
                updateResumePosition()
            }
        }

        override fun onPlayerError(e: ExoPlaybackException?) {

            var errorString: String? = null

            //Check what was the error so that we can show the user what was the correspond problem
            if (e?.type == ExoPlaybackException.TYPE_RENDERER) {
                val cause = e.rendererException
                if (cause is MediaCodecRenderer.DecoderInitializationException) {
                    // Special case for decoder initialization failures.
                    errorString = if (cause.decoderName == null) {
                        when {
                            cause.cause is MediaCodecUtil.DecoderQueryException -> getString(R.string.error_querying_decoders)
                            cause.secureDecoderRequired -> getString(R.string.error_no_secure_decoder,
                                    cause.mimeType)
                            else -> getString(R.string.error_no_decoder,
                                    cause.mimeType)
                        }
                    } else {
                        getString(R.string.error_instantiating_decoder,
                                cause.decoderName)
                    }
                }
            }

            if (errorString != null) {
                //Show the toast with the proper error
                Toast.makeText(activity as Context, errorString, Toast.LENGTH_LONG).show()
            }

            inErrorState = true

            if (isBehindLiveWindow(e)) {
                clearResumePosition()
                initializePlayer()
            } else {
                updateResumePosition()
                updateRetryButton()
            }
        }
    }

    private fun clearResumePosition() {
        //Clear the current resume position, since there was an error
        currentWindow = C.INDEX_UNSET
        playbackPosition = C.TIME_UNSET
    }

    /*
    * This is for the multi window support
    * */
    private fun isBehindLiveWindow(e: ExoPlaybackException?): Boolean {
        if (e?.type != ExoPlaybackException.TYPE_SOURCE) {
            return false
        }
        var cause: Throwable? = e.sourceException
        while (cause != null) {
            if (cause is BehindLiveWindowException) {
                return true
            }
            cause = cause.cause
        }
        return false
    }

    private fun buildMediaSourceWithAds(uri: Uri): MediaSource {


        /*
        * This content media source is the video itself without the ads
        * */
        val contentMediaSource = ExtractorMediaSource.Factory(
                DefaultHttpDataSourceFactory("BUO-APP")).createMediaSource(uri) //TODO change the user agent

        /*
        * The method constructs and returns a ExtractorMediaSource for the given uri.
        * We simply use a new DefaultHttpDataSourceFactory which only needs a user agent string.
        * By default the factory will use a DefaultExtractorFactory for the media source.
        * This supports almost all non-adaptive audio and video formats supported on Android. It will recognize our mp3 file and play it nicely.
        * */
        return AdsMediaSource(
                contentMediaSource,
                /* adMediaSourceFactory= */ this,
                adsLoader,
                playerView.overlayFrameLayout,
                /* eventListener= */ null, null)
    }

    override fun onStart() {
        super.onStart()

        if (Util.SDK_INT > 23) {
            initializePlayer()
        }
    }

    override fun onResume() {
        super.onResume()
        hideSystemUi()

        /*
        * Starting with API level 24 Android supports multiple windows.
        * As our app can be visible but not active in split window mode, we need to initialize the player in onStart.
        * Before API level 24 we wait as long as possible until we grab resources, so we wait until onResume before initializing the player.
        * */
        if ((Util.SDK_INT <= 23 || player == null)) {
            initializePlayer()
        }
    }
}

广告从不显示,如果显示,则显示渲染错误 从不允许视频显示。我已经运行了IMA广告中的示例https://developers.google.com/interactive-media-ads/docs/sdks/android/示例代码,它也不起作用。是否有人使用最新的ExoPlayer库版本成功地实现了Exo Player?请帮忙。谢谢

共有2个答案

夹谷奇
2023-03-14

问题是模拟器无法渲染视频。因此,它没有显示广告或视频。在手机上运行该应用程序,它就会工作

靳祺然
2023-03-14

在模拟器上时,请务必在虚拟设备上启用gpu渲染

 类似资料:
  • 我最近在使用EXOPlayer IMA SDK做广告。我在使用DFP的视频广告(双击发布者)。 我知道如何从xml布局中自定义EXO Player ControllerUI。但是我想知道,我们可以删除广告底部的广告(时间)和广告顶部的了解更多按钮吗?因为它们是我们自己的家庭广告,所以我想删除这些广告。 我没有找到任何与此相关的东西。我已经通过编程自定义了Adsense或AdMob广告,但我不知道如

  • 我试图在场景上添加一个本地对话框,用exoplayer播放视频。到目前为止,我已经成功地正确显示了对话框,但当我开始调用exoplayer时,我在logcat中遇到了这个异常: 我刚刚添加了一个纹理视图,并在我的android部分添加了exoplayer,就像它是一个正常的项目一样。 我不知道我可以补充什么,所以如果你需要更多信息,请随时提问:)有什么想法吗? 祝好

  • ExoPlayer 是 Android 上一个应用级的媒体播放器。它为 Android MediaPlayer 的 API 在播放本地或在线的视频与音频上提供了一个候选。ExoPlayer 支持一些 Android MediaPlayer API 无法提供的特性,包括 DASH 和 SmoothStreaming 自适应回放,持久的高速缓存和自定义渲染器。不像 MediaPlayer API,EX

  • 你好,我正在开发一个应用程序,我可以在其中使用widevine drm保护来播放dash stream。我已经阅读了exoplayer的示例,但我的需求不同,我会在我的网站上,当单击dash url时,它将开始在exoplayer中播放流。我已经成功地完成了打开exoplayer活动的第一部分,但是我不知道如何在exoplayer上运行受drm保护的流。 我知道流和drm许可证url。 我正在编写

  • 在android中,有一个名为Exoplayer的库,它与从给定URL流媒体视频有关。 根据这一点,firebase不支持视频流,尽管您可以将uri从url传递到videoview(它实际上会流)。 问题:

  • 嘿,伙计们,我一直试图在exoPlayer中显示视频,因为2天,但没有任何进展,请指导我做错了什么。谢谢提前。 这是我对create函数的代码调用。 我的图书馆版本是