如何在ExoPlayer DAI中动态添加/移除自定义请求头?
实现ExoPlayer DAI动态请求头切换方案
针对你用ExoPlayer androidx v1.0.1实现DAI时的请求头动态切换需求,核心思路是放弃全局固定请求头,通过自定义DataSourceFactory配合广告/播放状态监听,动态控制请求头的添加与移除,具体实现步骤如下:
1. 自定义动态请求头的HttpDataSourceFactory
不要全局预设自定义头,而是在创建DataSource实例时,根据当前播放状态(内容/广告)决定是否添加自定义头:
class DynamicHeaderHttpDataSourceFactory( private val context: Context, private val customHeaders: Map<String, String>, private var isPlayingAd: Boolean = false ) : DefaultHttpDataSource.Factory() { init { setAllowCrossProtocolRedirects(true) setUserAgent(context.getString(R.string.player_name)) setTransferListener( DefaultBandwidthMeter.Builder(context) .setResetOnNetworkTypeChange(false) .build() ) } // 对外暴露状态切换方法 fun updateAdState(isPlayingAd: Boolean) { this.isPlayingAd = isPlayingAd } override fun createDataSource(): DefaultHttpDataSource { val dataSource = super.createDataSource() // 每次创建数据源时清空原有请求头,避免残留 dataSource.defaultRequestProperties.clear() if (!isPlayingAd) { // 播放直播内容时添加自定义头 customHeaders.forEach { (key, value) -> dataSource.defaultRequestProperties.set(key, value) } } // 播放广告时仅保留UserAgent等基础配置,不添加自定义头 return dataSource } }
2. 监听广告状态切换,同步请求头配置
通过DAI的ImaAdsLoader监听广告的加载、播放、结束事件,实时切换请求头状态:
// 初始化DAI广告加载器 val adsLoader = ImaAdsLoader.Builder(context).build() adsLoader.setAdEventListener(object : ImaAdsLoader.AdEventListener { override fun onAdPlaybackStateChanged(adPlaybackState: AdPlaybackState) { // 判断当前是否处于广告播放状态 val isAdActive = adPlaybackState.adCount > 0 && adPlaybackState.currentAdIndex != C.INDEX_UNSET dynamicHeaderFactory.updateAdState(isAdActive) } override fun onAdFailedToLoad(adError: AdError) { // 广告加载失败时,切回内容请求头状态 dynamicHeaderFactory.updateAdState(false) } })
3. 监听Player播放状态,确保状态同步
配合Player的监听事件,在媒体切换、播放状态变化时修正请求头状态,避免异常:
player.addListener(object : Player.Listener { override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) { // 切换到直播内容时,强制切回内容请求头状态 if (mediaItem?.mediaId == YOUR_LIVE_CONTENT_MEDIA_ID) { dynamicHeaderFactory.updateAdState(false) } } override fun onPlaybackStateChanged(playbackState: Int) { // 播放就绪且未在播放广告时,确保请求头为内容模式 if (playbackState == Player.STATE_READY && !player.isPlayingAd) { dynamicHeaderFactory.updateAdState(false) } } })
4. 预取场景处理
预取直播内容时,需要强制切换到内容请求头状态,预取完成后恢复当前播放状态:
// 触发预取操作前 val currentAdState = player.isPlayingAd dynamicHeaderFactory.updateAdState(false) // 执行预取逻辑(比如用ExoPlayer的预加载API或自定义缓存逻辑) // ... // 预取完成后恢复原有状态 dynamicHeaderFactory.updateAdState(currentAdState)
5. 替换原有全局DataSourceFactory
将自定义的DynamicHeaderHttpDataSourceFactory传入MediaSourceFactory,替换原来的全局配置:
// 初始化动态请求头工厂 val dynamicHeaderFactory = DynamicHeaderHttpDataSourceFactory( context, mCustomHeaders ) // 配置MediaSourceFactory,关联广告加载器 val mediaSourceFactory = DefaultMediaSourceFactory(dynamicHeaderFactory) .setAdsLoaderProvider { adsLoader } .setAdViewProvider(yourAdViewProvider) // 初始化Player player = ExoPlayer.Builder(context) .setMediaSourceFactory(mediaSourceFactory) .build()
内容的提问来源于stack exchange,提问作者BejanCorneliu
相关产品推荐
相关产品推荐

