doc/COMPOSE_BACKLOG.md
本文件归档 [v13.0.0 ~ master
46ef8db3] 三路并行审核(破坏性 / 能力对齐 / Demo 对齐)的全部结论,并把后续工作拆成可逐轮推进、可勾选完成的子任务。Compose 模块当前状态:未发布(Unreleased)。所有动作均不打 tag,随 master 滚动迭代;首发将以本文件 P4-1 全部完成 + P5-1 至少一半完成 为基线再视情况评估。
校对时间:2026-05-20(J 轮 Java 端基础能力真机回归)。基线 commit:
9cafdb08。
| 维度 | 现状 | 目标 |
|---|---|---|
| 是否破坏既有功能 | ✅ 0 破坏 | 持续保持(每轮 :app:assembleDebug + :app:assembleRelease + 真机 monkey + crash buffer 空) |
| Wrapper 模式 vs Java | ✅ 几乎完全等价 | 维持,仅做小修补(autoPauseResume 已默认开) |
| Native 模式 vs Java | ⚠️ "最小子集 + 逃生口堵死" | P4-1 → P4-2 推进至"等价" |
| Demo 覆盖 | 8/41 ≈ 19.5%,13 类差异化能力空白 | P5-1 必补 8 个 → P5-2 选补 8 个 → 总覆盖 ≈ 24/41 ≈ 58%(当前进度:24/41 ≈ 58%,P5-1 8/8 已完成;P5-2 8/8 已完成(D9/D10/D11/D14 上半场 + D12/D13/D15/D16 下半场),首发基线达成) |
| 文档与发布约束 | doc/COMPOSE_USE.md 已写明"未发布" | 持续与代码同步,每轮回归此文件 |
✅ R2 已全部修复(详见 § 3 进度跟踪表);下表保留作为历史可追溯的"问题→定位→验收→实际落点"记录。
| ID | 问题 | 现状定位 | 验收标准 | R2 落点 |
|---|---|---|---|---|
| P0-1 ✅ | GSYPlayerController.host 是 internal,Native 模式所有"Standard 已有但 Controller 未暴露"的能力(字幕 / 滤镜 / 镜像 / 列表小窗 / setSeekOnStart / 快照截图 / GIF)无法通过逃生口访问 | GSYPlayerController.kt#L23-L24 | 提供 controller.withHost { player -> ... } 闭包(限定主线程 + 自动 null-check + released 期间 no-op);新增单测/Demo 覆盖一次"调 setSubtitleSources" 路径 | ✅ Controller 新增 withHost<R>(block):主线程检查(非主线程抛 IllegalStateException)+ released no-op 返回 null;KDoc 显式禁止在 block 里调 setVideoAllCallBack;host: internal var 保留不破坏二进制 |
| P0-2 ✅ | installInternalCallback 直接 player.setVideoAllCallBack(...),覆盖用户 callback;用户用 withHost 调 setVideoAllCallBack 时也会反向覆盖内部 callback,事件流断裂 | GSYPlayerController.kt#L165-L187 | 改为"内部 callback 链式分发 + 保留用户 setUserVideoAllCallBack 注入点";单测:用户 callback 与 events 同时触发时双方都收到 | ✅ 重构为稳定 dispatcher 单例(internalDispatcher,22 项全覆盖)+ @Volatile userCallback 字段;新增 setUserVideoAllCallBack(callback) 公开入口;克隆全屏时 dispatcher 引用本身被 Java 侧 setVideoAllCallBack 复制,事件流跨克隆体不断 |
| P0-3 ✅ | Native 模式没有全屏切换 API:GSYPlayerController 缺 enterFullscreen / exitFullscreen,GSYPlayerEvent 缺 EnterFull / QuitFull | GSYPlayerEvent.kt GSYPlayerController.kt | Controller 新增 enterFullscreen(activity, hideActionBar=true, hideStatusBar=true) / exitFullscreen(activity);GSYPlayerEvent 加 EnterFull / QuitFull;Demo FullFeatureNativeActivity 接入按钮真机回归 ≤ 1.5s 切回 | ✅ Controller 新增 enterFullscreen(activity, hideActionBar, hideStatusBar) / exitFullscreen(activity) / isFullscreen;GSYPlayerEvent 加 EnterFull / QuitFull data object;ΔD2/ΔD8 接入;额外修复 GSYComposeHostPlayer.java class+构造器 → public(GSY 反射克隆要求 public Constructor,否则 NoSuchMethodException);emulator 回归:双 host 树确认(原 host + app:id/full_id 克隆体),BACK 退出 OK,二轮 round trip 0 crash |
| ID | 问题 | 现状定位 | 验收标准 |
|---|---|---|---|
| P1-1 | Native 模式手势完全禁用且无 Compose 替代品:vol/brightness/seek 三 flag 强制 false,未提供 Modifier.gsyGestureControl(controller);锁屏退化为单纯布尔标志 | GSYComposeHostPlayer.java#L99-L105 | 新文件 GSYGestureModifier.kt 提供 Modifier.gsyGestureControl(controller, enableSeek/Volume/Brightness, onCenterToast);锁屏激活时手势屏蔽生效;FullFeatureNativeActivity Demo 集成 |
| P1-2 | rememberGSYPlayerController 只 release,不自动 pause/resume;后台切换不暂停,与 Wrapper 行为不一致 | GSYPlayerController.kt#L1-L60 GSYPlayerSurface.kt | rememberGSYPlayerController(autoPauseResume = true) 默认开;ON_PAUSE → GSYVideoManager.onPause();ON_RESUME → GSYVideoManager.onResume();HOME → 切回真机回归无 crash |
| P1-3 | GSYPlayerEvent 仅 3 类,VideoAllCallBack 22 项中 19 项未映射:缺 Buffering(start/end/percent) / SeekComplete / EnterSmall / QuitSmall / ClickStart/Resume/Stop/Seekbar/Blank / TouchScreenSeek* 等 | GSYPlayerEvent.kt | sealed class 扩 19 项;installInternalCallback 全数 tryEmit;保持兼容(旧的 Prepared/AutoComplete/Error 不动) |
| P1-4 | Native Snapshot 只读字段缺失:videoSar(Num/Den) / netSpeed(Long/text) / isCacheReady 全部没暴露 | GSYPlayerSnapshot.kt | 扩字段 + syncFromHost 同步;Demo 加可视化 |
| P1-5 | builder-only 字段没有 controller 直 setter:headers / cachePath / setSeekOnStart / setLooping / setStartAfterPrepared / setOverrideExtension / setShowPauseCover / setReleaseWhenLossAudio | GSYPlayerController.kt | Controller 加直 setter,内部委托 host;保留 setUp(builder) 的兼容路径 |
| P1-6 | 缓冲粒度差异:500ms 轮询会丢真实 onBufferingUpdate(percent) 抖动 | 同 P1-3 / GSYPlayerController.kt#L34-L42 | events.BufferingProgress(percent) 实时发;Snapshot 保留低频字段 |
✅ R1 已全部修复(详见 § 3 进度跟踪表);下表保留作为历史可追溯的"问题→定位→验收→实际落点"记录。
| ID | 问题 | 现状定位 | 验收标准 | R1 落点 |
|---|---|---|---|---|
| P2-1 | "9 个 Compose Demo" 措辞错误,实际只有 8 个(DemoSamples.kt 是 data object,不是 Activity) | README.md#L156-L158 README_CN.md#L159-L161 doc/COMPOSE_USE.md ComposeDemoListActivity.kt | 三处文档统一改为"8 个示例",并标明每个示例对应的 Java demo 来源 | ✅ 三处全改为 "8 个可运行 Compose Activity",并显式说明 DemoSamples.kt 是 data object |
| P2-2 | 9 个 Compose Activity 全部 exported="true",与老 Activity 默认 false 不一致 | AndroidManifest.xml#L250-L294 | 改 exported="false";adb am start -n 调试需求改写到 README 用 monkey 替代说明 | ✅ 9 个 Activity 全改 exported="false";emulator 验证:内部跳转 ✅ + 外部 am start 被严格拒绝(SecurityException: not exported from uid 10211) |
| P2-3 | consumer-rules.pro 仅 7 行注释空规则;将来如有反射 / @Composable 类被业务做反射查找会被 R8 剥离 | consumer-rules.pro | 加最小兜底:-dontwarn com.shuyu.gsyvideoplayer.compose.** + 注释说明保留底线 | ✅ 加最小集 keep(HostPlayer / Controller / Snapshot / Surface + Event sealed 全部子类 + Wrapper Kt facade + LifecycleBridgeKt),assembleRelease R8 通过 |
| P2-4 | mediaVersion 1.10.0→1.10.1 升级与 Compose 任务捆绑,未独立 commit | gradle/dependencies.gradle#L5 | 文档备注(影响极小,不强制回滚);后续依赖升级单独 commit | ✅ 在 gsyVideoPlayer-compose/build.gradle 顶部加注释块,说明本模块不直接引用 media3、版本统一由 root gradle/dependencies.gradle 管理;后续仅需在根 mediaVersion 改一处即可 |
| P2-5 | README 未明确"JDK 17"硬要求,新接入者用 JDK 8 会困惑 | app/build.gradle#L30-L37 | README 顶部"环境要求"加一行 JDK ≥ 17 | ✅ 在 README.md / README_CN.md 的 Compose 章节"未发布"提示块下追加 🛠 工具链说明:CI=JDK 21 / 本地 JDK 17(模块 jvmTarget=17,要求 ≥ 17) |
| P2-6 | PAT fallback 仍是有效 token 明文 | build.gradle#L36-L42 | 提交 fallback 改空字符串(同时由仓主在 GitHub 撤旧 token + 新发;文档同步说明) | ✅ 状态核实:release.yml 已使用 secrets.GITHUB_TOKEN(CI 内置),未硬编码 PAT、无 fallback;build.gradle 取 token 路径在前轮 P3-5 已改为 properties/env 优先;本项无需再改文件 |
| ID | 待补 Demo | 对位 Java demo | 关键演示能力 |
|---|---|---|---|
| D1 | DetailFilterComposeActivity | DetailFilterActivity | GLSurface 滤镜 / 镜像 / 自定义 Render |
| D2 | CacheDownloadComposeActivity | DetailDownloadPlayer + DetailDownloadExoPlayer + change_cache/clear_cache 按钮 | 缓存进度 + 清缓存 + Proxy↔EXO 切换 |
| D3 | AdInListComposeActivity | ListADVideoActivity2 + DetailADPlayer | 列表内夹广告 + 前贴片 |
| D4 | SubtitleComposeActivity | SubtitleDetailPlayer + GSYExoSubTitleDetailPlayer | 通用字幕 + EXO 外挂字幕选轨 |
| D5 | DanmakuComposeActivity | DanmkuVideoActivity | 弹幕叠加 |
| D6 | ExoSwitchSourceComposeActivity | DetailExoListPlayer + ExoAdaptiveTrackActivity | 自定义 EXO MediaSource + HLS/DASH 自适应 |
| D7 | MultiWindowParallelComposeActivity | ListMultiVideoActivity(CustomManager 真并行) | 升级现有 MultiWindow 由"互斥激活"为"真·多 Manager 并行" |
| D8 | SwitchSeamlessComposeActivity | SwitchListVideoActivity + SwitchUtil | 列表 → 详情共享 surface 不重拉流 |
| ID | 待补 Demo | 对位 Java demo |
|---|---|---|
| D9 | VerticalShortVideoComposeActivity ✅ | ViewPager2Activity |
| D10 | FloatingWindowComposeActivity ✅ | WindowActivity |
| D11 | MoreTypeComposeActivity ✅ | DetailMoreTypeActivity |
| D12 ✅ | AudioOnlyComposeActivity | AudioDetailPlayer |
| D13 ✅ | LocalFileComposeActivity | InputUrlDetailActivity 本地分支 |
| D14 | WebDetailComposeActivity ✅ | WebDetailActivity |
| D15 ✅ | MediaCodecComposeActivity | RecyclerView3Activity |
| D16 ✅ | CustomControlsThemeComposeActivity | 参考 LandLayoutVideo / SampleControlVideo |
| ID | 待补 Demo | 对位 Java demo |
|---|---|---|
| D17 | TransparentVideoComposeActivity | DetailTransparentActivity |
| D18 | KeepLastFrameComposeActivity | KeepLastFrameDemoActivity |
| D19 | SmartPickComposeActivity | PlayPickActivity |
| D20 | TVFocusComposeActivity | PlayTVActivity |
| D21 | SharedElementTransitionComposeActivity | PlayActivity |
| D22 | FragmentInteropComposeActivity | FragmentVideoActivity |
| ID | 已有 Demo | 浅在哪里 | 升级目标 |
|---|---|---|---|
| ΔD1 | BasicWrapperActivity | builder 仅设了 5 项,缺 ~30+ 项配置示范 | 加 setVideoAllCallBack + setSeekRatio + setShowPauseCover 等 |
| ΔD2 ✅ | DetailNativeActivity | 全屏只是 requestedOrientation,没用底层全屏管线 | ✅ R2 已切换为 controller.enterFullscreen / exitFullscreen + events.EnterFull/QuitFull 同步本地标志位;BackHandler(enabled=fullscreen) 拦 BACK |
| ΔD3 | FullFeatureNativeActivity | 缺音量/亮度/进度手势条 + 中央 toast | P1-1 完成后接入 Modifier.gsyGestureControl |
| ΔD4 | ListPlayNativeActivity | 仅"滚出屏暂停",没有"释放占位/封面恢复" | 演示 setThumbImageView + 离屏 release |
| ΔD5 | SwitchUrlActivity | 名为"切换 URL",实为 setUp 重置;没演示真 SwitchUtil | D8 出来后此 demo 文档加"see also"指向 |
| ΔD6 | MultiWindowActivity | 单例 GSYVideoManager 互斥,没用 CustomManager | D7 出来后此 demo 改名为"互斥版",新增"并行版"对照 |
| ΔD7 | AutoPlayListActivity | 用 events.AutoComplete setUp 下一段,丢 surface 接管 | 先以注释说明取舍,等 P0-1 后可演示更深路径 |
| ΔD8 ✅ | ListWithFullscreenActivity | 用 BackHandler+Insets 模拟,没用底层全屏管线 | ✅ R2 已删除 WindowInsetsControllerCompat / 手动 requestedOrientation / FullscreenLayer 自绘,改为 controller.enterFullscreen + events.EnterFull/QuitFull,全屏渲染由内核克隆体接管 |
推荐顺序:P3 轻量 → P4-1 P0 → P4-2 P1 → P5-1 必补 demo → P5-2 选补 demo → P5-Δ 老 demo 升级 + 文档收口 → 评估首发。
每轮收尾必跑:
./gradlew :gsyVideoPlayer-compose:assembleRelease./gradlew :app:assembleDebug./gradlew :gsyVideoPlayer-compose:publishToMavenLocal(默认 +-PPUBLISH_TARGET=mavenCentral)- emulator-5554 真机回归(受影响 demo + crash buffer 空验证)
- doc/COMPOSE_USE.md + README.md/README_CN.md 同步
- 不发 tag,commit + push master
exported="false"consumer-rules.pro 加最小兜底mediaVersion 备注(在 compose 模块 build.gradle 顶部加注释块)am start 被严格拒绝(SecurityException: not exported from uid 10211)./gradlew :app:assembleDebug :gsyVideoPlayer-compose:assembleRelease :gsyVideoPlayer-compose:publishToMavenLocal -x lint —— BUILD SUCCESSFUL in 17scompose: R1 housekeeping (P2-1~6 docs/manifest/consumer-rules) 并 push(不发 tag)controller.withHost { player -> ... } 公开闭包;保留 host: internal 不破坏二进制installInternalCallback 重构为内部分发器:internalCallback + userCallback 链式enterFullscreen / exitFullscreen + GSYPlayerEvent.EnterFull / QuitFullgetConstructor(Class[]) 仅返回 public 构造器;非 public 时 emulator 报 NoSuchMethodException 全屏失败)app:id/full_id 克隆体出现/移除);ΔD2 二轮 round trip dispatcher 复用稳定;ΔD8 全屏进/退(首次 setUp + 等 host attach 后的第二次点击进入全屏,符合 Compose 异步重组语义);6 个其他 demo same-uid 启动;cross-uid am start 仍被严格拒绝;AndroidRuntime FATAL 与 crash buffer 全空./gradlew :app:assembleDebug :gsyVideoPlayer-compose:assembleRelease :gsyVideoPlayer-compose:publishToMavenLocal -x lint —— BUILD SUCCESSFUL in 29scompose: R2 P0 fixes (withHost + callback fanout + fullscreen) 并 push(不发 tag)Modifier.gsyGestureControl(controller, ...) + 锁屏联动 ✅ 新文件 GSYGestureModifier.kt:横向 drag = seek(onDragEnd commit),左半屏纵向 = 亮度,右半屏纵向 = 音量;snapshot.isLocked 时所有手势短路;ΔD3 接入并加中央 toastrememberGSYPlayerController(autoPauseResume = true) 默认开 ✅ ON_PAUSE → GSYVideoManager.onPause(),ON_RESUME → GSYVideoManager.onResume()GSYPlayerEvent 扩 19 项 + installInternalCallback 全数 emit ✅ sealed class 5→24 项;dispatcher 22 项 callback 各加 _events.tryEmitevents.BufferingProgress(percent) + SeekComplete 实时 ✅ GSYComposeHostPlayer.java 加 BufferingHook / SeekCompleteHook;Controller 在 attachHost / setUp 安装、detachHost / release 清理--pct-touch 60 --pct-motion 30 0 FATAL;状态显示 Playing | 01:02 / 1:32:27controller.withHost { player.setEffectFilter(...) } 注入 6 种 GLSL 滤镜(NoEffect / Gamma / 黑白 / 反色 / Sepia / 高斯模糊),GSYVideoType.setRenderType(GLSURFACE) 在 onCreate 设置、onDestroy 还原ProxyCacheManager.instance().newProxy(ctx).getProxyUrl(url) 套缓存代理 + setCacheWithPlay(true);展示 snapshot.isCacheReady / bufferPercent / netSpeedText;清缓存按钮调 GSYVideoManager.instance().clearAllDefaultCache(ctx)events.AutoComplete 边沿事件链 setUp 切正片,简化 Java 双 player 模式;emulator 实证 阶段:广告播放中 → 正片播放中PlayerFactory.setPlayManager(IjkPlayerManager.class) 切回 IJK;3 字幕源(SRT 本地 / VTT 本地 / SRT 网络);controller.withHost 注入 setSubtitleSources / setSubtitleStyle / setSubtitleEnabled / selectSubtitle;字号 16↔22 sp 切换rememberTextMeasurer 自绘 12 条 3 轨弹幕,与 controller.snapshot.currentPosition 联动;不依赖 master.flame.danmaku;emulator 实证 Playing 48s/5547s 真起播PlayerFactory.setPlayManager(Exo2PlayerManager.class) 切 EXO 内核;4 源(MP4/HLS/GSY 默认/IMG_0382)+ 5 档倍速(0.75/1.0/1.25/1.5/2.0);emulator logcat ExoPlayerImpl: Init [AndroidXMedia3/1.10.1] 实证;切 HLS 后新 instance Init + onPreparedsetPlayTag + setPlayPosition → 路由到独立 CustomManager.getCustomManager(getKey());区别于现有 P1 MultiWindowActivity(互斥版);onDispose 释放 3 个 managerGSYPlayerSurface attach/detach 切换位置),不重 setUp、不释放、进度连续exported="false"ExoPlayerImpl: Init + onPrepared + 切 HLS Release/Init / D5 长视频 Playing 48s/5547s / D3 阶段切换 ad→feature 实证 / D7 onPrepared + CURRENT_STATE_PLAYING;Monkey 100 events 0 FATAL;logcat AndroidRuntime FATAL/crash buffer 全空VerticalPager + rememberPagerState,单 controller 通过 snapshotFlow { pagerState.currentPage }.distinctUntilChanged().collect 跨页 setUp,仅在当前页 attach GSYPlayerSurface;setLooping(true) + setCacheWithPlay(true);emulator 实证 page 1 Playing 1/5 + page 2 切页后 logcat GSYVideoPlayer: onPrepared 链路通rememberLauncherForActivityResult(StartActivityForResult()) 申请 SYSTEM_ALERT_WINDOW + Util.hasPermission 检测;复用 FloatPlayerView(Wrapper 路线)证明 Compose Activity 同样能驱动全局画中画;onDestroy → FloatWindow.destroy();emulator 实证 权限状态:✅ 已授予 / 悬浮窗状态:▶ 已显示enum CellType { Normal, Ad, Cover, Unknown } 4 类 cell;6 条 entry LazyColumn;单 controller 仅 attach activeIndex;emulator 实证点 Normal cell 后 当前激活:#1 样片 #1 · 普通视频 | Playing 1115/5547619 ms + logcat videoWidth: 480 videoHeight: 384GSYPlayerSurface + GSYDefaultControls(Compose 区),下方 AndroidView { WebView } Modifier.weight(1f) 弹性占据剩余空间;emulator 实证 当前:Playing | 1904/10027 ms + logcat libwebviewchromium_plat_support.so 加载(WebView 渲染)+ CURRENT_STATE_PLAYINGexported="false" + configChanges 全集--pct-touch 60 --pct-motion 30 0 FATAL;logcat AndroidRuntime FATAL/crash buffer 全空LaunchedEffect { GSYVideoManager.instance().enableRawPlay(applicationContext) } + android.resource://$pkg/${R.raw.test3|test33} 双 raw 音频源;圆形播放图标 + ${snapshot.state} 状态显示 + if (snapshot.isPlaying) onVideoPause() else onVideoResume() 暂停/继续;关键 bug 修复:原设计无 GSYPlayerSurface 时 controller.host = null → setUp 是 no-op,故必须挂 Modifier.size(1.dp) 隐身 GSYPlayerSurface 让 controller 拿到 host;emulator 实证 当前:本地 raw · test3.mp3 | Playing + 进度:10677/173448 ms · buffer 99% + logcat Audio focus request granted + IjkMediaPlayer_native_setup + CURRENT_STATE_PLAYINGOutlinedTextField URL 输入 + Checkbox cache 开关 + 3 个预设源(HTTP mov_bbb.mp4 / raw test.mp4 / raw test4.mp4);起播 / Release / 填入预设 三按钮;emulator 实证 00:07/00:10 + logcat IjkMediaPlayer_start + CURRENT_STATE_PLAYING + FFP_MSG_AUDIO_SEEK_RENDERING_STARTSwitch 实时切换 GSYVideoType.enableMediaCodec()/enableMediaCodecTexture() ↔ disableMediaCodec()/disableMediaCodecTexture();var hwOn by remember { mutableStateOf(GSYVideoType.isMediaCodec()) };onDispose { runCatching { GSYVideoType.disableMediaCodec() } } 离开页面还原;emulator 实证 状态:✅ 已启用 + Playing | 11554/5547619 ms · 480x384 + logcat ffpipenode_create_video_decoder_from_android_mediacodec + MediaCodec: H264_HIGH: enabled + ffpipeline_select_mediacodec_l(emulator 限制无真实 hw codec,IJK fallback 软解符合预期,硬解管线已激活)enum class ControlTheme { Neon, Sunset, Mono } 各带 fg/bg/Brush.verticalGradient;完全自绘 overlay 替代 GSYDefaultControls:渐变 Box + 圆形播放按钮 + Slider seek(dragging/dragValue 双通道)+ 主题切换条;detectTapGestures(onTap = { overlayVisible = !overlayVisible }) 点画面切浮层;formatMs() 工具函数;emulator 实证 Neon | Playing + 00:12/92:27 + 主题点击切换响应 Sunset | Playing + logcat onPrepared + CURRENT_STATE_PLAYING + videoWidth: 480 videoHeight: 384exported="false" + configChanges 全集--pct-touch 60 --pct-motion 30 0 FATALsetVideoAllCallBack / setSeekRatio(0.5/1/2/3x 切换条)/ setShowPauseCover(Switch)/ setReleaseWhenLossAudio(Switch)/ setStartAfterPrepared;UI 实时显示 回调状态:onPrepared #N,emulator 实证起播后 onPrepared #1(onPrepared 累计 1 次)setShowPauseCover),未播放时 Compose 自绘占位封面(标题 + 渐变色块,等价 setThumbImageView 的 Native 路径替代方案);emulator 实证占位封面文案展示 + 点击播放 → 暂停 / 继续 + logcat Net speed: 0 KB/s percent 8 真起播基线核对(截至本轮):
:app:assembleDebug + :gsyVideoPlayer-compose:assembleDebug + :gsyVideoPlayer-compose:assembleRelease + publishToMavenLocal 全 BUILD SUCCESSFUL,diagnostics 0 error结论:✅ 满足"去掉未发布标识"的全部前置条件,但本轮按既定纪律不打 tag —— 上限是把 README.md / README_CN.md 中"未发布(Unreleased)"提示块改为"已 GA"+ doc/COMPOSE_BACKLOG.md 顶部状态线同步(建议后续单独一轮 G "Go-Live" 处理:单独 commit 改 README、再走一次双通道回归后正式打 tag)。本轮 R6 仅产出"评估通过"结论 + 文档完备,留 G 轮去掉未发布标识 + 打 v8.x.x tag。
仍未做(不阻塞首发):
| 轮次 | 状态 | 起止 commit | 备注 |
|---|---|---|---|
| R1 | ✅ 已完成 | 24360bff (归档 plan 落盘) → 276420b7 (R1 修复) | P2 六项全过;构建 + 模拟器双回归通过;不发 tag |
| R2 | ✅ 已完成 | 276420b7 (R1 修复) → 6f5f846c (R2 修复) | P0-1/2/3 三项全过;额外修复 GSYComposeHostPlayer public class+构造器(反射克隆门票);构建 + 模拟器双回归通过;不发 tag |
| R3 | ✅ 已完成 | 6f5f846c (R2) → fe66e7fd (R3 P1 reactive parity) | P1 五项全过;events SharedFlow + stateFlow + setUserVideoAllCallBack + 8 直 setter + BufferingProgress/SeekComplete + ΔD3 手势;emulator Monkey 50 events 0 FATAL |
| R4 | ✅ 已完成(8/8 demo) | fe66e7fd (R3) → 47ce1877 (R4 上半场 D1/D2/D4/D8) → 本轮 (R4 续 D3/D5/D6/D7) | P5-1 全部 8 项已落(滤镜 / 缓存下载 / 前贴片广告 / 字幕 / 自绘弹幕 / EXO 多源 / Wrapper 真并行 / Seamless 切换);ComposeDemoListActivity 8 → 16 项;emulator 真 UI 点击实证:D6 EXO 内核切换 logcat 实证 + D5 长视频 Playing 48s/5547s + D3 ad→feature 阶段切换 + D7 真起播 0 crash;Monkey 100 events 0 FATAL |
| R5 | ✅ 已完成(8/8) | 47ce1877 (R4 上半场) → d05d0a8c (R4 续 D3/D5/D6/D7) → eceebd31 (R5 上半场 D9/D10/D11/D14) → 本轮 (R5 下半场 D12/D13/D15/D16) | P5-2 全部 8 项已落(VerticalPager 短视频 / 悬浮窗 + 系统权限申请 / 多类型 cell 列表 / WebView 图文混排 / 纯音频 raw + 1dp 隐身 Surface bug 修 / URL 输入起播 / MediaCodec 硬解 Switch 切换 / 自绘主题化 controls overlay);ComposeDemoListActivity 16 → 20 → 24 项;emulator 真 UI 点击实证 8 个 demo 全起播:D9 page1 Playing 1/5 / D10 悬浮窗状态:▶ 已显示 / D11 Playing 1115/5547619 ms / D14 Playing 1904/10027 ms + libwebviewchromium / D12 Playing 10677/173448 ms + IjkMediaPlayer_native_setup / D13 00:07/00:10 HTTP mov_bbb.mp4 / D15 Playing 11554/5547619 ms · 480x384 + MediaCodec: H264_HIGH: enabled / D16 Sunset/Neon Playing 00:12/92:27 + 主题切换响应;上下半场各 Monkey 100 events 0 FATAL;首发基线达成 |
| V | ✅ 已完成 | (R5 之后) → 本轮 | Demo URL 中央化:新建 DemoVideoUrls.java 中央常量表(8 条可达 URL + 8 条语义别名);39 Java + 6 Kotlin 文件全量替换硬编码 URL;4 条不可达 URL(vorwaerts BBB / IMG_0382 / flipfit / 7xjmzj)按协议同语义替换为 MP4_BBB/HLS_MUX;清理 5 个文件中 9 行 dead URL 注释 + DetailPlayer.java L617-L681 注释墓地;双通道构建 + Monkey 100 events 0 FATAL;详见 doc/VIDEO_URLS.md |
| R6 | ✅ 已完成 | (V 之后 ae0c37ba) → 本轮 | P5-Δ 5/5 老 demo 升级(ΔD1 5 高频 builder 选项 + UI 回调显示 / ΔD4 离屏 setUp 重置 vs pause + setShowPauseCover Switch + Compose 自绘占位封面 / ΔD5 see-also D8 / ΔD6 标题"互斥版" + D7 跳转提示 / ΔD7 KDoc surface 接管取舍);COMPOSE_USE.md 加 § 9 能力矩阵 + § 10 Cookbook;双通道构建 BUILD SUCCESSFUL;emulator-5554 装机 + 5 ΔActivity 全启动 + ΔD1 实证 onPrepared #1 + ΔD4 实证 Net speed: 0 KB/s percent 8 + 防回归对照 DetailNormalActivityPlayer + Monkey 100 events 0 FATAL + crash buffer 空;首发评估通过(结论以 doc 形式落地,按纪律本轮不打 tag,留 G 轮 Go-Live) |
| H | ✅ 已完成 | ae0c37ba (R6) → 1e935452 (H 轮 P0 修复) | H 轮 P0 fixes for library, demo and docs:补齐 Compose 库与 Demo 的小修补;Java/Compose 双通道构建 + emulator 模拟器回归通过;不发 tag |
| I-1 | ✅ 已完成 | 1e935452 (H) → 74c8a0eb (Controller 拆分) | GSYPlayerController.release() / dispose() 拆分(避免 Compose 重组时误销毁 host);构建 + emulator 双回归通过;不发 tag |
| I-2 | ✅ 已完成 | 74c8a0eb (I-1) → c8ce3203 (PLAYBOOK + 脚本) → 90ab81a8 (PLAYBOOK 录入 I-2 结果 + Wrapper 自动播放注解修订) | 新增 doc/COMPOSE_TEST_PLAYBOOK.md + 配套可复用 shell/python 脚本;I-2 全量 Compose 回归(24 demo 真 UI 实证 + Monkey 0 FATAL)+ 修订 Wrapper 自动播放说明;不发 tag |
| I-3 | ✅ 已完成 | 90ab81a8 (I-2) → 本轮 | 文档全量回归(37 份 markdown):修复 README_CN.md 坏链 README_EN.md → README.md;4 份发布文档示例版本 11.3.0 → 13.0.0(ARCHITECTURE.md 5 处 / DUAL_CHANNEL_PUBLISH.md 8 处 / README_DEPENDENCY_GUIDE.md 6 处 / MAVEN_CENTRAL_AUTOMATION.md 2 处);本表 §0 校对时间 + §3 进度表追加 H/I/I-2/I-3 四轮;纯文档变更,按纪律豁免模拟器回归;不发 tag |
| J | ✅ 已完成 | 9cafdb08 (I-3) → 本轮 | Java 端 4 项基础能力真机回归(用户犀利质疑触发立项:18 轮自动化只测过 Compose,Java 端从未真测过 A 播放暂停 / B 拖进度 / C 全屏 / D 切换内核)。新增 doc/JAVA_TEST_PLAYBOOK.md + doc/test_scripts/java_basic_regression.sh(一键 6/6 PASS) + doc/test_scripts/java_cold_smoke.sh(39 entry 38/39 PASS,唯一 FAIL 为 toggle 按钮非跳页)。DetailPlayer 端到端 logcat 实证:A onClickStop/onClickResume/CURRENT_STATE_PAUSE/CURRENT_STATE_PLAYING;B onClickSeekbar/onSeekComplete,progress 12%→80% / currentPosition 226489ms→1458000ms;C orientation=landscape + WindowManager: finishDrawing of orientation change DetailPlayer 141ms;D 三态文字循环 IJK→EXO→系统 + 切到 EXO 后 logcat 真实出现 ExoPlayerImpl: Init [AndroidXMedia3/1.10.1],与默认 IJK 状态的 nativeloader: libijkffmpeg.so 形成内核切换底层实证。5 个代表 Activity(DetailPlayer / DetailListPlayer / DetailMoreType / DetailFilter / DetailADPlayer2)跑出真实差异:DetailListPlayer/MoreType/AD2 的暂停按钮坐标与 DetailPlayer 不同、DetailFilter progress 控件 ID 不同 → 后续 K 轮承接为各 Activity 提供 layout 适配映射。识别并文档化 5 个真实自动化坑(Activity 不 exported / resource-id 包名前缀 / textAllCaps / controls 自动隐藏 / sed 贪婪匹配);不发 tag |
| R7 | ☐ pending | — | 选做 |
每轮完成后,将本表格状态 ☐ 改为 ✅ 并附 commit hash;同时把 § 1 / § 2 中已完成项的
[ ]改为[x]。
compose: R<N> ... 前缀串起跟踪。withHost / enterFullscreen / events 扩项 / 直 setter)时,每条都应在 doc/COMPOSE_USE.md 给出可点击的 file 链接,便于贡献者跟读。