原生 App 自己掌控媒体:全屏、自动播放、后台音频都正常。进了 WebView,这种掌控就没了。全屏需要宿主手写一个原生视图;自动播放除非宿主翻两个隐藏配置开关否则被拦;App 一切后台,音频就死。宿主自有的 runtime 提供媒体桥——一块跨设备一致的、可预期的播放面。

WebView 自己没法全屏

在 Android 上,HTML 的 requestFullscreen() 对 <video> 毫无作用,除非 App 的 WebChromeClient 重写了 onShowCustomView() 与 onHideCustomView()。WebView 把视频画面交给宿主后就干等;宿主不实现这个回调,全屏按钮就彻底失灵。跨版本更糟:从 Android 4.0 起,回调拿到的就是一个私有内部类 surface,想侦测播放结束或接自定义控件,就得用反射、按版本分支——这种脆弱性会在下一次系统更新时崩。

iOS 逼你全屏,否则静音

在 iOS 上,WKWebView 默认 allowsInlineMediaPlayback 为 false,于是即便写了 playsinline,视频一播放就被拽进系统全屏播放器。自动播放同样被门控:默认的 mediaTypesRequiringUserActionForPlayback 下,静音自动播放仍要手势,"视频当 banner" 的模式会悄悄卡住。画中画只有当内联播放器本就是 AVPlayerViewController 时才有效——而 App 切后台时它无法自动进入,因为 visibilitychange 不算用户交互。

媒体只接了一半时会崩什么

  • 全屏是个死按钮。 Android 上点了没反应,除非宿主接了 onShowCustomView。
  • 内联视频弹成全屏。 iOS 默认无视 playsinline,除非宿主在初始化阶段就设好开关——事后改会静默失败。
  • 自动播放卡住。 没手势就没播放,唯一的逃生通道是创建 WebView 前翻两个隐藏原生开关。
  • 后台音频死掉。 App 一进后台,WebView 媒体就暂停;画中画是唯一出路,且不会自动。
  • 跨版本混乱。 Android 的私有 surface 类与 iOS 的开关在每个系统版本都不同。

runtime 解法

宿主自有的 runtime 掌控媒体。宿主原生实现全屏交接,向页面暴露统一的播放 API,在配置阶段一次性设好内联与自动播放开关,并把后台音频桥接到系统媒体会话。一块播放面,所有设备、所有系统版本——而不是一个在工程师手机上能跑、到用户那就崩的网页。

维度WebView宿主自有 runtime
全屏除非宿主重写 onShowCustomView 否则失效宿主驱动的交接
iOS 内联播放默认无视 playsinline配置阶段设好开关
自动播放无手势即被拦可预期策略
后台音频进后台即暂停系统媒体会话桥
画中画不自动宿主可控
跨版本按构建各自崩稳定

原生 App 从不会失去对媒体的掌控。裸 WebView 却经常如此。runtime 把一块可预期的播放器交到页面手里——并在 App 进后台时让音频继续活。

参考来源