GSYVideoPlayer 如何在 Jetpack Compose 中用 GSYVideoPlayerView 快速播放视频并处理生命周期
【免费下载链接】GSYVideoPlayerVideo players (IJKplayer, ExoPlayer, MediaPlayer), HTTPS, 16k page size, danmaku (bullet chat) support, external subtitles, support for filters, watermarks, and GIF screenshots, pre-roll and mid-roll ads, multiple simultaneous playback, basic seeking/dragging, volume and brightness adjustment, play-while-cache support项目地址: https://gitcode.com/GitHub_Trending/gs/GSYVideoPlayer
如果你的界面已经用 Jetpack Compose 编写,想在不退回 XML 布局的情况下播放视频,并且希望播放器能跟随页面生命周期自动暂停、恢复和释放,GSYVideoPlayer 的gsyVideoPlayer-compose模块提供的 Wrapper 模式就是直接的路径:一个GSYVideoPlayerViewComposable 把StandardGSYVideoPlayer包进 Compose 屏,默认自动桥接onPause/onResume,并在离开 Composition 时自动release()。完成本文操作后,你在 Compose 屏里可以起播一段视频,切走页面再回来时播放状态正确恢复。
适用前提(来自模块文档):
minSdk ≥ 23,Kotlin 2.0.x,AGP 8.6+,本机 JDK ≥ 17(README 说明该模块在 CI 用 JDK 21、本地用 JDK 17 验证,两者都可以,只要本机 JDK ≥ 17 就能跑通 Kotlin 2.0.21 + AGP 8.6.1);compose-bom已由模块以api方式透出(模块内部用compose-bom 2024.06.00统一版本,使用 Compose Compiler Gradle Plugin,无需再单独指定composeCompilerVersion);你自己的androidx.compose.*依赖仍按自身工程版本管理。
引入 gsyVideoPlayer-compose 依赖
在 app 模块的 Gradle 依赖里二选一(见 README.md 第 D 节与 doc/COMPOSE_USE.md):
// 方式 A:Maven Central(外部项目推荐) implementation 'io.github.carguo:gsyvideoplayer-compose:13.2.1' // 方式 B:在 GSYVideoPlayer 仓库内开发调试时,直接源码依赖 implementation project(':gsyVideoPlayer-compose')模块本身已api依赖gsyVideoPlayer-java,不需要重复引入。只有需要 EXO / Ali 内核时才按 README 原有方式额外引入对应坐标。注意两处文档的版本差异:doc/COMPOSE_USE.md 正文示例写的是首发版本13.1.0,而 README.md 给出的是当前坐标13.2.1,按 README 的13.2.1使用即可。
第一次起播:GSYVideoPlayerView + GSYVideoOptionBuilder
setUp参数里的写法与在 XML 里拿到 player 后调用builder.build(player)完全等价。最小可用示例(取自 doc/COMPOSE_USE.md 的 Cookbook「最小播放」):
@Composable fun MyVideoScreen(url: String) { GSYVideoPlayerView( modifier = Modifier .fillMaxWidth() .aspectRatio(16f / 9f), setUp = { player -> GSYVideoOptionBuilder() .setUrl(url) .setVideoTitle("Compose Demo") .setIsTouchWiget(true) .build(player) player.startPlayLogic() }, // 默认会自动桥接 onPause/onResume 与离屏 release autoPauseResume = true, autoReleaseOnDispose = true, ) }url替换为你自己的视频地址。想先跑通验证,可以直接用仓库 demo 的同款测试 URL——DemoVideoUrls.java 中的SAMPLE_GSY = "https://res.exexm.com/cw_145225549855002",demo 各 Compose Activity 的DemoSamples.SAMPLE_URL用的就是它。
按需追加的高频 builder 选项(在 BasicWrapperActivity.kt 里有完整演示):
.setCacheWithPlay(true):demo 界面里对应「边播边存」开关;.setRotateViewAuto(true).setLockLand(true).setNeedLockFull(true):自动旋转横屏全屏、锁定横屏、全屏锁屏,全屏由内部OrientationUtils接管;.setVideoAllCallBack(object : GSYSampleCallBack() { ... }):在onPrepared/onAutoComplete/onPlayError/onClickStartIcon里做埋点或更新 UI 状态。
一个容易踩的点:仓库里的BasicWrapperActivitydemo 并不是自动起播——它通过onPlayerCreated = { playerRef = it }拿到 player 引用,由界面底部「开始播放」按钮手动调playerRef?.startPlayLogic()(builder 里虽设了setStartAfterPrepared(true),仍需按钮触发)。如果你按上面的最小示例把startPlayLogic()写进setUp,则进入页面即播。两种写法都以 demo 为准对照即可。
URL 变化时如何重新播放:setUpKey
setUp默认只在 factory 阶段调用一次,这是有意设计:每次 recomposition 都重新执行builder.build(player)会重置 URL、重启播放,反而制造问题。因此 update 阶段默认是 no-op。
如果 URL 等参数变化时希望主动重跑setUp,传setUpKey:
GSYVideoPlayerView( setUp = { player -> GSYVideoOptionBuilder().setUrl(url).build(player) player.startPlayLogic() }, setUpKey = url, // url 变化时再次调用 setUp,否则 update 阶段是 no-op )setUpKey为null(默认)时兼容老用法。需要其它NormalGSYVideoPlayer子类(如ListGSYVideoPlayer、SampleControlVideo)时,改用通用版GSYAnyVideoPlayerView,通过factory = { ctx -> SampleControlVideo(ctx) }指定创建方式。
生命周期:暂停、恢复与释放
Wrapper 模式下生命周期不需要手写,两个参数默认都为true:
autoPauseResume = true:内部通过 Lifecycle 桥接(LifecycleBridge.kt 的LifecycleEffect)把Lifecycle.Event.ON_PAUSE → GSYVideoManager.onPause()、ON_RESUME → GSYVideoManager.onResume();autoReleaseOnDispose = true:组件离开 Composition(页面销毁)时自动调用player.release(),可显式关闭。
桥接逻辑的实现在 GSYVideoPlayerView.kt:LifecycleEffect注册LifecycleEventObserver,DisposableEffect(Unit) { onDispose { ... } }负责离屏 release。
如果需要在切走页面时自己决定行为(比如只暂停不释放、或切换音频焦点策略),传autoPauseResume = false,文档给出的替代做法是自己用LifecycleEffect监听事件并手动调用GSYVideoManager对应方法。全屏能力与原生一致:在setUp或回调里直接调底层player.startWindowFullscreen(...),返回键拦截在BackHandler { ... }内调用player.onBackFullscreen()。
验证播放是否成功
两种验证路径,都来自仓库文档。
路径一:跑仓库自带的 demo 应用确认环境。编译运行 app 模块后,Compose 入口在Compose Demo(ComposeDemoListActivity.kt),其中第 1 项「P0 · Wrapper 基础」即BasicWrapperActivity。doc/COMPOSE_TEST_PLAYBOOK.md 给出的定位方式是直接启动列表页:
adb shell am start -n com.example.gsyvideoplayer/.compose.ComposeDemoListActivity进入「P0 · Wrapper 基础」后注意它不自动起播,需要点界面底部的「开始播放」按钮。播放成功的判定信号(Ijk 默认内核,logcat -d过滤):
| 信号 | 含义 |
|---|---|
onPrepared≥ 1 | 准备完成 |
CURRENT_STATE_PLAYING≥ 1 | 进入播放态 |
MEDIA_INFO_VIDEO_RENDERING_START≥ 1 | 画面开始渲染 |
Net speed:≥ 1 | 边播边存网络进度 |
playbook 对普通 Ijk 自动起播的 PASS 条件是prep ≥ 1 && play ≥ 1 && render ≥ 1 && net ≥ 1,并要求全局FATAL EXCEPTION == 0 && ANR == 0(adb logcat -d -b crash | grep -c "FATAL EXCEPTION")。滚屏定位等辅助脚本在 doc/test_scripts/(find_xy.py、locate_and_test.sh、real_test.sh)。
路径二:在你自己的 App 里验证。用同样的 Ijk 内核日志信号即可:接入后先确认onPrepared出现(或setVideoAllCallBack的onPrepared回调被触发),再看CURRENT_STATE_PLAYING与MEDIA_INFO_VIDEO_RENDERING_START;出现onPlayError/CURRENT_STATE_ERROR类日志则说明 URL 或内核初始化有问题。如果你的播放器走 EXO 内核(见下节),渲染信号改为videoSizeChanged/videoWidth:,且 EXO 路径不打Net speed:。
边界与后续
- Wrapper vs Native:
GSYVideoPlayerView保留 GSY 全部内置 UI(全屏、手势、字幕、弹幕、滤镜),与 Java/XML demo 一一对应,是「存量业务最快平移」的路径。如果目标是控制层完全用 Compose 自绘、用controller.events/stateFlow流式驱动 UI,文档给出的替代是 Native 模式(GSYComposePlayer + GSYPlayerController),两条链路可共用同一份 Builder 配置,可先 Wrapper 跑通再按需局部替换。 - 内核切换不受 Compose 模块影响,写法与原版一致:
PlayerFactory.setPlayManager(Exo2PlayerManager::class.java);对应缓存管理用CacheFactory.setCacheManager(ExoPlayerCacheManager::class.java)。 - 能力缺口与路线图:当前 Wrapper/Native 的能力差异矩阵(列表多 item、真并行多窗口、跨 Activity 复用等场景各自的限制)和已知缺口记录在 doc/COMPOSE_BACKLOG.md,接入前建议过一遍「九、能力矩阵」章节,确认你的场景落在 ✅ 列而不是 ❌ 列。
- 仓库内还有 24 个可运行 Compose Activity 可按需对照,入口文件见 doc/COMPOSE_USE.md 第六节的完整索引表(如
SwitchUrlActivity演示 Wrapper 切流、MultiWindowParallelComposeActivity演示并行多窗口)。
【免费下载链接】GSYVideoPlayerVideo players (IJKplayer, ExoPlayer, MediaPlayer), HTTPS, 16k page size, danmaku (bullet chat) support, external subtitles, support for filters, watermarks, and GIF screenshots, pre-roll and mid-roll ads, multiple simultaneous playback, basic seeking/dragging, volume and brightness adjustment, play-while-cache support项目地址: https://gitcode.com/GitHub_Trending/gs/GSYVideoPlayer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考