如何通过ExoPlayer Cast扩展创建CastPlayer?适配ExoPlayer 2.7.2
嘿,针对你在ExoPlayer 2.7.2上添加投屏功能的需求,我分两种场景给你详细说明,都是基于官方Cast扩展的方案:
解决ExoPlayer 2.7.2添加投屏功能的两种方案
一、将现有原生ExoPlayer转换为CastPlayer
如果你已经有一个正在运行的原生ExoPlayer实例,想无缝切换到投屏播放,可以按以下步骤操作:
1. 添加Cast扩展依赖
首先在Module级别的build.gradle里加入对应版本的Cast扩展依赖——版本必须和你的ExoPlayer主版本完全一致(2.7.2),不然会出现兼容性问题:
implementation 'com.google.android.exoplayer:extension-cast:2.7.2'
2. 初始化CastContext
在你的Application类或者主Activity的onCreate()方法里初始化Cast上下文,这是所有投屏功能的基础:
CastContext castContext = CastContext.getSharedInstance(this);
3. 添加投屏设备选择按钮
把系统自带的MediaRouteButton加到你的布局里,用户点击它就能看到并选择可用的Cast设备:
<androidx.mediarouter.app.MediaRouteButton android:id="@+id/media_route_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:mediaRouteTypes="user" />
然后在代码里为按钮绑定路由选择器,让它只识别Cast设备:
MediaRouter mediaRouter = MediaRouter.getInstance(this); MediaRouteSelector routeSelector = new MediaRouteSelector.Builder() .addControlCategory(CastMediaControlIntent.categoryForCast(castContext.getApplicationId())) .build(); MediaRouteButton mediaRouteButton = findViewById(R.id.media_route_button); mediaRouteButton.setRouteSelector(routeSelector);
4. 切换到CastPlayer播放
当用户选中投屏设备后,我们需要创建CastPlayer实例,把本地ExoPlayer的播放状态同步过去,实现无缝切换:
// 监听Cast会话的状态变化 castContext.addCastStateListener(new CastStateListener() { @Override public void onCastStateChanged(int state) { if (state == CastState.CONNECTED) { CastSession castSession = castContext.getSessionManager().getCurrentCastSession(); if (castSession != null) { // 创建CastPlayer并关联当前会话 CastPlayer castPlayer = new CastPlayer(castSession); // 同步本地播放器的媒体源、播放位置和播放状态 MediaSource mediaSource = localExoPlayer.getMediaSource(); long currentPosition = localExoPlayer.getCurrentPosition(); boolean isPlaying = localExoPlayer.isPlaying(); castPlayer.setMediaSource(mediaSource); castPlayer.prepare(); castPlayer.seekTo(currentPosition); if (isPlaying) { castPlayer.play(); } // 暂停本地播放器,把UI控制绑定到CastPlayer(比如播放按钮、进度条) localExoPlayer.pause(); } } else if (state == CastState.DISCONNECTED || state == CastState.NO_DEVICES_AVAILABLE) { // 投屏断开,切换回本地播放器 if (localExoPlayer != null && castPlayer != null) { long castPosition = castPlayer.getCurrentPosition(); localExoPlayer.seekTo(castPosition); if (castPlayer.isPlaying()) { localExoPlayer.play(); } // 释放CastPlayer资源,避免内存泄漏 castPlayer.release(); } } } // 实现其他CastStateListener的默认方法(比如onCastDeviceDetected) });
二、直接基于Cast扩展创建CastPlayer
如果你的场景不需要本地播放,想直接用CastPlayer实现投屏播放,步骤会更简洁:
1. 先搞定依赖和CastContext初始化
和上面的步骤1、2完全一致,确保依赖版本匹配,CastContext初始化完成。
2. 创建CastPlayer并监听会话连接
直接初始化CastPlayer,然后设置会话监听器,等待用户连接投屏设备:
CastPlayer castPlayer = new CastPlayer(); // 设置会话监听器,处理连接成功和断开的逻辑 castPlayer.setSessionManagerListener(new SessionManagerListener<CastSession>() { @Override public void onSessionStarted(CastSession session, String sessionId) { // 投屏会话连接成功,设置媒体源并开始播放 // 这里以渐进式媒体源为例,你可以根据自己的媒体类型调整(比如DASH、HLS) DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory( getApplicationContext(), Util.getUserAgent(getApplicationContext(), "你的应用名称")); MediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory) .createMediaSource(Uri.parse("你的媒体URL")); castPlayer.setMediaSource(mediaSource); castPlayer.prepare(); castPlayer.play(); } @Override public void onSessionEnded(CastSession session, int error) { // 投屏会话断开,释放CastPlayer资源 castPlayer.release(); } // 实现其他必要的SessionManagerListener方法(比如onSessionResumed、onSessionSuspended) }); // 把CastPlayer的监听器绑定到CastContext的SessionManager castContext.getSessionManager().addSessionManagerListener( castPlayer.getSessionManagerListener(), CastSession.class);
3. 绑定投屏控制UI
同样使用MediaRouteButton让用户选择投屏设备,当用户选中后,CastPlayer会自动触发onSessionStarted回调,你只需要在回调里处理播放逻辑即可。
关键注意事项
- 版本一致性:ExoPlayer主库和Cast扩展的版本必须完全相同,2.7.2版本不要混用其他版本的扩展,否则会出现崩溃或者功能异常。
- 资源释放:无论是本地ExoPlayer还是CastPlayer,在Activity销毁、投屏结束时,一定要调用
release()方法释放资源,避免内存泄漏。 - 媒体兼容性:Cast设备支持的媒体格式和本地可能有差异,尽量使用H.264编码的MP4、常见的HLS/DASH流等兼容性好的格式。
内容的提问来源于stack exchange,提问作者khateeb
相关产品推荐
相关产品推荐

