####习惯性的开始前先叙个旧,感慨下,距离上次写博客已经很久时间了,感觉要学的东西很多,学的也很杂乱,今天难得感觉心情比较轻松,想着写写以前弄的东西,慢慢回忆一下,所以先从现在这个开始吧,
replaykit在ios9时已经出来了,那是还只允许在app内录制,还不支持录制桌面及其他应用,我之前的博客中有详细的介绍如何使用replaykit实现app内的录制,这里不再赘述了replaykit app内录制
特点
- replaykit2在replaykit的基础上增加了能录制桌面,退到后台打开其他应用同样能录制当前屏幕显示的内容,
- 使用socket完成进程间的通信,
- 负责录制的屏幕数据的进程占用内存最大只能50M,大于则会被系统杀掉
系统版本下的区别
ios12新出了一个api用于在app内能直接调起录屏功能的UI
RPSystemBroadcastPickerView
具体实现
申明
@property (nonatomic,strong)RPSystemBroadcastPickerView API_AVAILABLE(ios(12.0)) *broadPickerView;
初始化
- (RPSystemBroadcastPickerView *)broadPickerView API_AVAILABLE(ios(12.0)){
if(!_broadPickerView){
_broadPickerView = [[RPSystemBroadcastPickerView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
//是否显示音频按钮
_broadPickerView.showsMicrophoneButton = NO;
这个是决定调起某一个特定的extensionUpload,这里就写自己创建的upload的bundleID
_broadPickerView.preferredExtension = @"extensionbundleID";
}
return _broadPickerView;
}
app内调用录制按钮的方法
if (@available(iOS 12.0, *)) {
//首先判断是否在录制中
if (![UIScreen mainScreen].isCaptured) {
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication].keyWindow addSubview:self.broadPickerView];
for (UIView *view in self.broadPickerView.subviews)
{
if ([view isKindOfClass:[UIButton class]])
{
// UIControlEventAllTouchEvents这个属性需要特别注意,网上很多说使用的是别的类型,在ios13下都会不起作用,ios13以后必须使用UIControlEventAllTouchEvents,调用事件才有效,所以直接使用UIControlEventAllTouchEvents,在ios9以上都支持
[(UIButton*)view sendActionsForControlEvents:UIControlEventAllTouchEvents];
}
}
});
}
}
看了上面的特定api,先看下创建ExtensionUpload的方式
选中工程的 Targets —> editor —>addTarget —>Broadcast Upload Extension—>Next
next 如下
1.输入名称
2.选择语言
3.Include UI Extension 可选可不选,后期也用不到
确定后会在工程中多几个文件
1.SampleHandler
2.BroadcastSetupViewController
其中SampleHandler就是我们获取录屏数据处理的类,这个类相当于一个单独的应用,想要调制需要运行extension的才能打印或者断点调试
//这个代码是我们获取数据并处理的方法
- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
switch (sampleBufferType) {
case RPSampleBufferTypeVideo:
// Handle video sample buffer
break;
case RPSampleBufferTypeAudioApp:
// Handle audio sample buffer for app audio
break;
case RPSampleBufferTypeAudioMic:
// Handle audio sample buffer for mic audio
break;
default:
break;
}
}
这里面的难点在于,如果你有单独的类来处理视频数据的上传,直接上传就可以了,如果你需要把数据传回住app在处理,就需要用到进程间的通信了,进程间的通信有很多种,不再叙述,感兴趣可以网上查查,这里只讲使使用socket进行进程间的通信
这里还涉及到一个进程间的通知的问题,用于状态标记的回传
socket 使用GCDAsysocket
处理数据视频数据使用一个第三方的对视频进行裁剪封装为nsdata数据,socket使用nsadata类型的数据
下面的代码其实可以是一个固定写法,就这样写,变动也是在个别参数的调试
//
// SampleHandler.m
// ClairEye
//
// Created by AmpleSky on 2020/3/31.
// Copyright © 2020年 Facebook. All