iOS悬浮窗通话怎么做?react-native-agora画中画(PiP)完整实现指南
【免费下载链接】react-native-agoraReact Native around the Agora RTC SDKs for Android and iOS agora项目地址: https://gitcode.com/gh_mirrors/re/react-native-agora
react-native-agora是 Agora RTC SDK 的 React Native 封装库,帮你在移动 App 中快速搭建音视频通话。本文以iOS 悬浮窗通话为例,讲解如何用它的**画中画(Picture-in-Picture,PiP)**能力,让用户在 App 切到后台时仍保留一个视频小窗继续通话——看完即可跑通一套完整、合规的 PiP 悬浮通话方案。
一、为什么通话类 App 需要画中画(PiP)悬浮窗?
- 📱 用户切出去回消息、刷其他 App,通话不断线、小窗常亮
- 🧩 悬浮窗由系统托管,不占用你的 App 界面,拖拽/缩放/恢复都开箱即用
- 🚀 平台支持广:iOS 15.0+、Android 8.0+,且 react-native-agorav4.6.2+已把两端 API 统一封装,一套 TS 代码写双端
二、快速认识 PiP 核心 API
react-native-agora 的 PiP 能力集中在engine.getAgoraPip()返回的控制器上:
| 方法 | 作用 |
|---|---|
pipIsSupported() | 当前设备是否支持画中画 |
pipIsAutoEnterSupported() | 是否支持应用切后台自动进入 PiP |
pipSetup(options) | 配置悬浮窗(尺寸、内容、布局、控件) |
pipStart()/pipStop() | 启动 / 停止画中画 |
pipDispose() | 释放 PiP 控制器资源(防内存泄漏) |
registerPipStateChangedObserver() | 监听 PiP 状态变化 |
状态枚举共三种:pipStateStarted(已启动)、pipStateStopped(已停止)、pipStateFailed(失败)。完整定义见 src/IAgoraPip.ts。
三、iOS 前置配置:这 3 步不做,悬浮窗出不来 ⚠️
1️⃣ 开启 Background Modes 能力(必须)
在 Xcode 中选择 App Target →Signing & Capabilities→ 点+ Capability→ 添加Background Modes→ 勾选“Audio, AirPlay, and Picture in Picture”。
2️⃣ 在 Info.plist 中声明后台音频模式(必须)
在UIBackgroundModes中加入audio,示例工程的配置如下:Info.plist
3️⃣ 多任务下保留摄像头(可选)
如果你希望在悬浮窗里显示本地摄像头画面,iOS 处于多任务(PiP)模式时需要com.apple.developer.avfoundation.multitasking-camera-accessentitlement(iOS 16 以下需向 Apple 申请;iOS 16+ 可将捕获会话的multitaskingCameraAccessEnabled设为 true)。不展示本地流可跳过此步。
四、5 步实现 iOS 悬浮窗通话(核心代码不到 30 行)
// Step 1: 创建引擎 + 注册 PiP 状态监听器 const engine = createAgoraRtcEngine(); engine.initialize({ appId, channelProfile: ChannelProfileType.ChannelProfileLiveBroadcasting }); engine.registerEventHandler(this); engine.getAgoraPip().registerPipStateChangedObserver(this); // Step 2: 入会(广播者角色,发送视频流) await engine.joinChannel(token, channelId, uid, { clientRoleType: ClientRoleType.ClientRoleBroadcaster, }); // Step 3: 配置画中画(iOS) const options: AgoraPipOptions = { preferredContentWidth: 960, // 悬浮窗首选宽度 preferredContentHeight: 540, // 悬浮窗首选高度 sourceContentView: 0, // 0 = 根视图,用于进出场动画 contentView: 0, // 0 = SDK 自动托管视频流(推荐) contentViewLayout: { row: 1, column: 0, spacing: 2 }, // 网格布局 videoStreams, // 要显示的本地/远端视频流 controlStyle: 2, // 只保留“关闭”和“恢复”按钮 }; engine.getAgoraPip().pipSetup(options); // Step 4: 启动画中画(⚠️ iOS 必须由用户点击触发) engine.getAgoraPip().pipStart(); // Step 5: 离开频道 / 页面卸载时释放,防止内存泄漏 engine.getAgoraPip().pipDispose(); engine.getAgoraPip().release();💡 本地流和远端流都要显示时,把它们都放进
videoStreams数组即可,SDK 会按网格自动排布并管理原生视图。
五、iOS 专属参数详解:controlStyle 到底选几?
| 参数 | 说明 | 推荐值 |
|---|---|---|
preferredContentWidth/Height | 悬浮窗初始尺寸,建议与视频视图一致 | 960 × 540 |
sourceContentView | 进出场动画源视图,0 = App 根视图 | 0 |
contentView | 0 = SDK 自动托管视频流;传自定义视图 ID 则需自己管理内容 | 0 |
contentViewLayout | 网格布局:row行数、column每行列数、spacing间距 | 单流1×0 |
controlStyle | 系统控件样式,见下表 | 2 |
controlStyle四档可选:
| 值 | 效果 |
|---|---|
| 0 | 显示全部系统控件(默认) |
| 1 | 隐藏快进/快退按钮 |
| 2 | 隐藏播放/暂停与进度条,仅保留关闭和恢复(视频会议场景推荐 ✅) |
| 3 | 隐藏所有控件 |
六、状态监听:通话悬浮窗的“保险丝” 🔌
实现onPipStateChanged回调,是生产环境必备的一步:
onPipStateChanged(state: AgoraPipState, error: string | null) { if (state === AgoraPipState.pipStateFailed) { // 失败时立即释放控制器,避免后续操作报错 this.engine?.getAgoraPip().pipDispose(); } this.setState({ pipState: state }); }两个易被忽略的细节(示例工程中的真实做法,见 PictureInPicture.tsx):
- 🧠远端用户加入/退出后要重新
pipSetup:窗口渲染是异步的,示例用setTimeout等渲染完成后再 setup; - 🧹离开频道时主动
pipDispose():onLeaveChannel回调和组件卸载时都要释放,失败态同理。
七、常见坑点自查清单 ✅
- iOS 上 PiP 必须由用户操作发起——程序自动启动可能被 App Store 拒审,务必绑在按钮点击上;
- 忘记加 Background Modes是“悬浮窗不出来”的头号原因,Xcode 能力 + Info.plist 缺一不可;
- iOS 的悬浮窗由原生
UIView托管,无需自己画 UI;而 Android 走 Activity,需自行处理界面(详见官方说明 PictureInPicture.md); - 不
pipDispose()会造成内存泄漏; - 想跑通全流程,克隆仓库后直接看示例:
git clone https://gitcode.com/gh_mirrors/re/react-native-agora
八、相关模块路径速查
| 模块 | 路径 |
|---|---|
| 完整 PiP 示例(双端) | examples/expo/app/examples/advanced/PictureInPicture/PictureInPicture.tsx |
| PiP 功能说明文档 | examples/expo/app/examples/advanced/PictureInPicture/PictureInPicture.md |
| PiP 类型定义 | src/IAgoraPip.ts |
| PiP TS 层实现 | src/internal/AgoraPipInternal.ts |
| iOS 原生模块(PiP 桥接) | ios/AgoraRtcNg.mm |
小结:iOS 悬浮窗通话 = 后台音频能力 + 5 步 API 调用 + 状态监听兜底。照着本文配置 Background Modes、设置contentView: 0让 SDK 托管视频流、controlStyle: 2精简控件,你就能得到一个既流畅又符合审核规范的画中画通话体验。🎬
【免费下载链接】react-native-agoraReact Native around the Agora RTC SDKs for Android and iOS agora项目地址: https://gitcode.com/gh_mirrors/re/react-native-agora
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考