You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android/iOS设备启用控制JavaScript Picture-in-Picture模式

问题核心原因

Cordova 打包的App本质是调用系统原生WebView加载页面,标准Web Picture-in-Picture API的移动端支持存在明显断层:

  • Android 系统WebView 仅在Android 12(API 31)及以上版本开放了部分PiP能力,低版本完全不支持
  • iOS 端WKWebView 至今未实现标准requestPictureInPicture 接口,纯前端调用必然报错
    直接复用Web端的PiP逻辑无法在移动端App生效,需要结合Cordova原生能力+前端兼容判断实现。
Android 端适配步骤
  1. 配置项目权限与Activity属性
    在项目的config.xml中添加画中画相关配置,声明权限同时让主Activity支持PiP模式:
    <platform name="android">
        <config-file target="AndroidManifest.xml" parent="/manifest/application/activity">
            <attr name="android:supportsPictureInPicture" value="true" />
            <attr name="android:configChanges" value="screenSize|smallestScreenSize|screenLayout|orientation" />
        </config-file>
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    </platform>
    
  2. 实现原生PiP调用逻辑
    可以直接使用现成的Cordova PiP插件,也可以自行开发简单插件:核心逻辑是收到前端的PiP切换请求时,判断当前PiP状态,调用Activity原生的enterPictureInPictureMode()方法进入PiP,或调用exitPictureInPictureMode()退出PiP。系统进入PiP模式后会自动将当前前台渲染的WebRTC视频层悬浮显示,不需要前端额外调整DOM。
  3. 注意适配低版本:Android 11及以下版本的系统WebView完全不支持标准Web PiP API,必须走原生调用逻辑。
iOS 端适配步骤

iOS端的系统限制更严格,无法直接复用Web或Android的逻辑:

  1. 开启系统能力
    在Xcode项目配置中开启Background Modes,勾选Audio, AirPlay, and Picture in Picture选项,否则PiP启动后应用切后台会被系统直接终止。
  2. 实现原生PiP调用逻辑
    iOS 不支持将整个WebView页面压缩为悬浮窗,必须通过Cordova插件获取WebRTC视频对应的原生渲染层(即RTCVideoRenderer绑定的AVSampleBufferDisplayLayer),为其创建AVPictureInPictureController实例,再调用控制器的startPictureInPicture()/stopPictureInPicture()方法实现PiP切换。
  3. 版本限制:仅iOS 14及以上系统支持画中画能力,低版本需要做降级提示。
全端兼容调用代码

将原有纯Web逻辑改造为三端兼容的判断逻辑,优先使用标准Web API,不支持时自动降级为Cordova原生调用:

async function videoShrink(video){
    const videoEl = video || document.getElementsByTagName("video")[0];
    if (!videoEl) return;

    try {
        // 标准Web PiP API可用场景:普通移动端/桌面端浏览器、高版本Android WebView
        if (document.pictureInPictureEnabled && typeof videoEl.requestPictureInPicture === 'function') {
            if (videoEl !== document.pictureInPictureElement) {
                await videoEl.requestPictureInPicture();
            } else {
                await document.exitPictureInPicture();
            }
            return;
        }

        // Cordova 环境降级走原生桥接
        if (window.cordova) {
            const currentPlatform = cordova.platformId;
            const isInPip = document.pictureInPictureElement === videoEl;
            // 插件名、方法名可根据自己集成的插件调整
            const pluginName = 'PiPPlugin';
            
            if (currentPlatform === 'android') {
                cordova.exec(
                    (result) => console.log('PiP操作成功', result),
                    (err) => console.log('PiP操作失败', err),
                    pluginName,
                    isInPip ? 'exitPip' : 'enterPip',
                    []
                );
            }

            if (currentPlatform === 'ios') {
                // iOS端需要传入video元素标识,方便原生层定位对应的视频渲染层
                cordova.exec(
                    (result) => console.log('PiP操作成功', result),
                    (err) => console.log('PiP操作失败', err),
                    pluginName,
                    'togglePip',
                    [{ videoDomId: videoEl.id }]
                );
            }
        }
    } catch (error) {
        console.log(error);
    }   
}
避坑提示
  • 不要尝试用CSS固定定位+全局悬浮层模拟PiP:这种方案仅能在App前台时生效,一旦应用切到后台就会被系统暂停,无法实现跨应用悬浮的系统级PiP效果。
  • Android端从PiP切回全屏时,需要监听原生PiP生命周期回调,通知前端调整WebRTC视频的渲染尺寸,避免画面拉伸、变形。
  • iOS端启动PiP前需要确保音频会话类别设置为AVAudioSessionCategoryPlayback,否则应用切后台时音频会被系统中断,直接导致PiP窗口关闭。

内容的提问来源于stack exchange,提问作者R sukumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:51:26