本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。
通过阅读本文,您可以了解 iOS 如何实现屏幕共享。DingRTC 的屏幕共享方案是基于 iOS 系统的 ReplayKit,能够分享整个系统的屏幕内容,但需要在您的 App 里额外创建一个 Extension 扩展组件。
一、创建 Broadcast Upload Extension
在 Xcode 菜单依次单击 File -> New -> Target,选择 Broadcast Upload Extension。
选中新建的 Target,单击 Capability,添加 App Groups,如下图:
3. 填写 App Group Id,如下图。这一步要求您需要持有 Apple 的开发证书或个人账号。如果开发证书和应用的发布证书不同,那么发布证书也需要注册App Group(参考官方说明)。
选中主 App 的 Target ,并按照上述的步骤 2、3 对主 App 的 Target 做同样的处理。
选中新建的 Target,添加 DingRTC.framework 到 Framework and Libraries,如下图:
6. 在新建的 Target 中,Xcode 会自动创建一个名为 SampleHandler.m 的文件,用如下代码进行替换。需将代码中的 kAppGroup 修改为上文中您填写的 App Group Id。
#import "SampleHandler.h"
#import <DingRtc/DingRTC.h>
static NSString * _Nonnull kAppGroup = @"group.com.dingtalk.DingRTCSample";
@interface SampleHandler() <DingScreenShareExtDelegate>
@end
@implementation SampleHandler
- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
[[DingRtcScreenShareExt sharedInstance] setupWithAppGroup:kAppGroup delegate:self];
}
- (void)broadcastPaused {
// User has requested to pause the broadcast. Samples will stop being delivered.
}
- (void)broadcastResumed {
// User has requested to resume the broadcast. Samples delivery will resume.
}
- (void)broadcastFinished {
// User has requested to finish the broadcast.
}
- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
@autoreleasepool {
[[DingRtcScreenShareExt sharedInstance] sendSampleBuffer:sampleBuffer type:sampleBufferType];
}
}
#pragma mark - DingRtcScreenShareExtDelegate
- (void)finishBroadcastWithError:(DingRtcScreenShareExt *)broadcast error:(NSError *)error {
[self finishBroadcastWithError:error];
}
@end
二、主 App 接收来自 Broadcast Upload Extension 进程的录屏数据
1. 在主 App 调用 -startScreenShare:mode: 传入上文的 App Group Id 来启动屏幕共享。
[DingRTCClient.instance.rtcEngine startScreenShare:@"group.com.dingtalk.DingRTCSample" mode:DingRtcScreenShareAll];
2. 等待用户触发屏幕分享(一般需要用户在 iOS 系统的控制中心,长按录屏按钮来触发),此外您也可以参考如下代码,在主 App 通过 RPSystemBroadcastPickerView 实现弹出一个启动器供用户确认启动屏幕分享。
苹果在 iOS 12.0 中增加了 RPSystemBroadcastPickerView 可以在应用中弹出启动器供用户确认启动屏幕分享。到目前为止 RPSystemBroadcastPickerView 尚不支持自定义界面,也没有官方的唤起方法。
示例代码的原理是通过遍历 RPSystemBroadcastPickerView 的 Subviews 寻找 UIButton 并触发其点击事件。
该方案不被苹果官方推荐,并可能在新一轮的系统更新中失效,因此仅供您参考,您需要自行承担选用此方案带来的风险。
@property (strong, nonatomic) RPSystemBroadcastPickerView *broadcastPickerView;
- (void)launchBroadcastPickerView {
if (@available(iOS 12.0, *)) {
RPSystemBroadcastPickerView *pickerView = [[RPSystemBroadcastPickerView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
pickerView.showsMicrophoneButton = NO;
pickerView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin;
NSString *pluginPath = [NSBundle mainBundle].builtInPlugInsPath;
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pluginPath error:nil];
for (NSString *content in contents) {
if (![content hasSuffix:@".appex"]) {
continue;
}
NSBundle *bundle = [NSBundle bundleWithPath:[[NSURL fileURLWithPath:pluginPath] URLByAppendingPathComponent:content].path];
if (bundle) {
NSString *identifier = [bundle.infoDictionary valueForKeyPath:@"NSExtension.NSExtensionPointIdentifier"];
if ([identifier isEqualToString:@"com.apple.broadcast-services-upload"]) {
pickerView.preferredExtension = bundle.bundleIdentifier;
}
}
}
self.broadcastPickerView = pickerView;
for (UIView *view in self.broadcastPickerView.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
[(UIButton *)view sendActionsForControlEvents:UIControlEventAllEvents];
}
}
}
}
3. 调用 -stopScreenShare 可以随时停止屏幕共享。
[DingRTCClient.instance.rtcEngine stopScreenShare];