屏幕共享
RTCLib SDK 为开发者提供了屏幕共享插件,屏幕共享功能以插件库形式提供。开发者可自行选择是否向项目中集成 RongRTCReplayKitExt 插件库来实现屏幕共享功能。RongRTCReplayKitExt 插件用于扩展 target 上使用。
环境要求
- iOS 系统版本 12 及以上
- 屏幕共享功能在 RTCLib SDK 5.1.8.1 及以后支持
- 屏幕共享库 RongRTCReplayKitExt 依赖的 RTCLib SDK 版本必须大于等于 5.1.8.1
实现方式
我们可以通过苹果的 Extension 来实现屏幕共享技术。这里将通过使用 iOS 11 之后新增的系统级别的录屏能力,来实现录制自身 App 以外手机屏幕内容的效果。
受 iOS 系统的 ReplayKit 库限制,iOS 12 前在 App 中调用 Extension 启动屏幕共享时,只能作用于 App 内,如果退出 App 则无法得到屏幕内容。
iOS 端的屏幕共享是通过在 Extension 中使用 RongRTCReplayKitExt 框架实现录制屏幕流的接收,然后将屏幕共享流传输到 RTCLib 实现的。由于 Apple 不支持 Extension 进程与主 App 进程通信,因此您需要为屏幕共享流单独创建一个进程。

实现流程
实现屏幕共享的主要步骤如下:
- 创建 App Group:在 Xcode 中进行配置,让 Extension 录屏进程可以与主 App 进程进行跨进程通信
- 创建 Broadcast Upload Extension:用于开启屏幕共享的进程
- 宿主 App 开启屏幕共享:发布屏幕共享流
- 屏幕共享 Extension 处理:收到消息后,初始化 RongRTCReplayKitExt 库,接收系统录制数据
集成说明
创建 App Group
- 新版本 Xcode 支持在 Target 下 Signing & Capabilities 页面中 App Groups 进行创建并关联 AppGroup,可以直接跳过如下 1-5 步。
- 老版本 Xcode 可能无法直接使用 Xcode 创建 AppGroup,需要使用您的帐号登录 苹果开发者后台 ,进行以下 1-5 步操作来创建 AppGroup,然后再关联 AppGroup。
-
单击 Certificates, IDs & Profiles,在右侧的界面中单击加号。

-
选择 App Groups,单击 Continue。

-
在弹出的表单中填写 Description 和 Identifier, 其中 Identifier 需要传入接口中的对应的 AppGroup 参数。完成后单击 Continue。

-
回到 Identifier 页面,然后单击您的 App ID,进入 Edit your App ID Configuration 页面,选中 App Groups 并单击 Edit。

-
在弹出的表单中选 择您之前创建的 App Group,单击 Continue 返回 Edit your App ID Configuration 页面,单击 Save 保存。

-
打开 Xcode,选中屏幕共享 Target(Broadcast Upload Extension) 点击 App Groups 的 + 按钮。

-
输入的 AppGroup,然后点击 OK 按钮,如果输入的 AppGroup 的已经创建过,则直接关联上;如果输入的 AppGroup 没有被创建过,则创建的同时进行关联。

创建 Broadcast Upload Extension:
-
在 Xcode 菜单依次单击 File、New、Target...,选择 Broadcast Upload Extension,创建类型为
Broadcast Upload Extension的新 target。
-
在弹出的对话框中填写相关信息,不用勾选 Include UI Extension,单击 Finish 完成创建。
-
在您的屏幕共享 Target - Build Phases - Compile Sources 中添加您可能在屏幕共享 Extension 里引用类的 .m 文件名
-
受限于
RongIMLib库中的默认 2 分钟断开连接的限制,需要修改如下 Pod 路径下的 .plist 配置文件:您的工程名/Pods/RongCloudIM/IMLibCore/RCConfig.plist在此文件中添加:
xml<key>Connection</key>
<dict>
<key>ForceKeepAlive</key>
<true/>
</dict>其中:
Connection和ForceKeepAlive类型为 Key 值,true的类型为 Bool -
选中新增加的 Target,依次单击 + Capability,双击 App Groups,如下图:

操作完成后,会在文件列表中生成一个以您自己创建的 Target 命名的 Target名.entitlements 的文件,如下图所示,选中该文件并单击 + 号填写上述步骤中的 App Group 即可

-
选中宿主 App 的 Target,并按照上述步骤对宿主 App 的 Target 做同样的 处理
导入 SDK
融云支持使用 CocoaPods 和本地手动导入两种方式,将 RTCLib SDK 和屏幕共享扩展导入到您的应用工程中。
CocoaPods 导入(推荐)
-
如果您的项目中没有
Podfile文件,您需要打开终端并进入到项目的根目录,在终端中运行pod init命令,之后系统会自动创建一个默认的Podfile文件。 -
在项目中的
Podfile文件中添加如下内容:rubytarget '主进程APP Target' do
use_frameworks!
pod 'RongCloudRTC/RongRTCLib', '~> x.y.z'
end
target '您的屏幕共享的 target' do
use_frameworks!
pod 'RongCloudRTC/RongRTCReplayKitExt', '~> x.y.z'
end -
打开终端并进入到
Podfile文件所在的目录,在终端中运行以下命令:shellpod install提示如果终端中出现类似
CocoaPods could not find compatible versions for等找不到相关版本的报错,可先在终端中执行pod repo update命令,再执行pod install命令。 -
通过 Xcode 打开项目目录下的
xcworkspace文件加载工程。
手动集成
-
您可以前往融云官网 SDK 下载页面,将音视频通话(无 UI)SDK 下载到本地。
-
使用 Xcode 打开您的工程,然后将下载下来的 SDK 手动拖入到您的项目中:
主进程 App Target 所需的 SDK:
Framework - RongRTCLib.xcframework
- RongIMLibCore.xcframework
- RongRTCReplayKitExt.xcframework
屏幕共享 Extension Target 所需的 SDK:
Framework - RongRTCReplayKitExt.xcframework

-
修改您的项目配置。在
General→Frameworks, Libraries, and Embedded Binaries中,将手动导入的 RTCLib SDK 所有的 Framework 全部改为Embed & Sign。
工程配置
-
音视频通话需要用到摄像头和麦克风权限,请在工程的 Info.plist 中添加如下键值:
- Privacy - Microphone Usage Description
- Privacy - Camera Usage Description
-
请将工程中 Target → Signing & Capabilities → Background Modes 如下内容勾选:
- Audio, AirPlay, and Picture in Picture
导入头文件
在需要使用的业务层导入 RTCLib 头文件,即可使用 SDK 的方法来实现屏幕共享相关业务。
主进程 App 导入:
#import <RongRTCLib/RongRTCLib.h>
屏幕共享 Extension 导入:
#import <RongRTCReplayKitExt/RongRTCReplayKitExt.h>
共享实现
iOS 系统上的跨应用屏幕分享,需要增加 Extension 录屏进程以配合宿主 App 进程进行推流。Extension 录屏进程由系统在需要录屏的时候创建,并负责接收系统采集的 CMSampleBufferRef 数据。
宿主 App
宿主 App 在加入房间后在需要屏幕共享时,通过点击录制按钮通知屏幕共享 target、并发布屏幕共享流。
添加系统录制按钮
此按钮需 iOS 12 及以上可用。
代码示例
#import <ReplayKit/ReplayKit.h>
// 添加录制按钮
RPSystemBroadcastPickerView *systemBroadcastPickerView = [[RPSystemBroadcastPickerView alloc] initWithFrame:CGRectMake(0, 64, 50, 80)];
systemBroadcastPickerView.preferredExtension = @"您的屏幕共享 target 的 Bundle Identifier";
systemBroadcastPickerView.backgroundColor = [UIColor colorWithRed:53.0/255.0 green:129.0/255.0 blue:242.0/255.0 alpha:1.0];
systemBroadcastPickerView.showsMicrophoneButton = NO;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:systemBroadcastPickerView];
初始化并连接
初始化 SDK 并连接融云服务器。
代码示例
#import <RongRTCLib/RongRTCLib.h>
[[RCCoreClient sharedCoreClient] initWithAppKey:@"您的AppKey"];
// 连接 IM
[[RCCoreClient sharedCoreClient] connectWithToken:@"您的token" dbOpened:^(RCDBErrorCode code) {
} success:^(NSString *userId) {
// 可以在此处加入房间
} error:^(RCConnectErrorCode errorCode) {
}];
监听屏幕共享流的发布与取消
在发布屏幕共享流之前,可以先设置 RCRTCEngine 的代理,通过对应的代理方法来获取发布与取消屏幕共享流的时机。
屏幕共享扩展结束
接口原型
- (void)screenShareExtentionFinished;
屏幕共享扩展开始
接口原型
- (void)screenShareExtentionStarted;
代码示例
#import <RongRTCLib/RongRTCLib.h>
[RCRTCEngine sharedInstance].delegate = self;
// 屏幕共享扩展结束消息回调 Added from 5.1.8
- (void)screenShareExtentionFinished {
NSLog(@"屏幕共享扩展结束");
}
// 屏幕共享扩展开始消息回调 Added from 5.2.0
- (void)screenShareExtentionStarted {
NSLog(@"屏幕共享扩展开始");
}
加入房间
连接 SDK 成功后,配置房间信息并加入房间。
代码示例
#import <RongRTCLib/RongRTCLib.h>
[[RCRTCEngine sharedInstance] joinRoom:@"您的房间号" completion:^(RCRTCRoom * _Nullable room, RCRTCCode code) {
room.delegate = self;
// 发布资源
[self publishScreenStream];
}];
发布资源
加入房间成功后可以发布 RCRTCScreenShareOutputStream 流。直播与会议场景发布流的方法不同,请注意区分。
获取屏幕共享流
接口原型
- (RCRTCScreenShareOutputStream *)getScreenShareVideoStreamWithGroupId:(NSString *)groupId;
参数说明
| 参数 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
| groupId | NSString * | 是 | 苹果开发者账号后台申请的 Group ID |
返回值
| 类型 | 说明 |
|---|---|
| RCRTCScreenShareOutputStream | 屏幕共享输出流 |
代码示例
会议场景
在会议场景下,请使用 publishStream:completion 方法。
#import <RongRTCLib/RongRTCLib.h>
RCRTCScreenShareOutputStream *videoOutputStream = [[RCRTCEngine sharedInstance] getScreenShareVideoStreamWithGroupId:@"您的屏幕共享 Extension 的 Group ID"];
RCRTCVideoStreamConfig *videoConfig = videoOutputStream.videoConfig;
videoConfig.videoSizePreset = RCRTCVideoSizePreset1280x720;
videoConfig.videoFps = RCRTCVideoFPS24;
[videoOutputStream setVideoConfig:videoConfig];
[self.room.localUser publishStream:videoOutputStream completion:^(BOOL isSuccess, RCRTCCode desc) {
}];
直播场景
在直播场景下,请使用 publishLiveStream:completion 方法。
#import <RongRTCLib/RongRTCLib.h>
RCRTCScreenShareOutputStream *videoOutputStream = [[RCRTCEngine sharedInstance] getScreenShareVideoStreamWithGroupId:@"您的屏幕共享 Extension 的 Group ID"];
RCRTCVideoStreamConfig *videoConfig = videoOutputStream.videoConfig;
videoConfig.videoSizePreset = RCRTCVideoSizePreset1280x720;
videoConfig.videoFps = RCRTCVideoFPS24;
[videoOutputStream setVideoConfig:videoConfig];
[self.room.localUser publishLiveStream:videoOutputStream completion:^(BOOL isSuccess, RCRTCCode code, RCRTCLiveInfo *_Nullable liveInfo) {
}];
屏幕共享 Extension
屏幕共享 target 在收到录制通知后,需要初始化 RongRTCReplayKitExt 库,并接收系统源数据。
SampleHandler 文件处理
在系统对应函数中初始化 SDK,接收系统 CMSampleBufferRef 源数据。