iOS录屏直播(四)主App和宿主App数据共享,通信功能实现
文章目录
- CFNotificationCenterGetDarwinNotifyCenter
- 发送通知
- 接收通知
- 注意事项
- 遗留问题
- 补充
Morris_
2019.06.17
上一篇总结了一下AppGroup相关的基础知识,通过AppGroup组即可实现App之间共享同一块存储区,以达到数据共享的目的。
在录屏直播中,我们采用AppGroup这种方式可以实现宿主App和Extention的数据传递。在App中写入数据,然后在Extention中读取数据,反之也可以。
这里主要总结一下跨进程在两个App中事件传递,从Extention发送通知到宿主App。
CFNotificationCenterGetDarwinNotifyCenter
平时开发中发送通知我们使用NSNotificationCenter这个单例类,这个类仅限在一个App内部发送通知,如果跨进程发通知的话就不能使用它了。
CFNotificationCenterGetDarwinNotifyCenter,是CoreFundation中的一个类,它可以实现跨进程发送通知,将通知从Extention App发送到宿主App中。
如果我们的App要实现录屏直播功能,需要添加Broadcast Upload Extension,这子App是负责采集、传输数据的,创建后会自动生成一个类SampleHandler。系统将采集到的录屏数据,通过SampleHandler中的Api输出,同时有一些其他Api:
- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {[self sendNotificationForMessageWithIdentifier:@"broadcastStartedWithSetupInfo" userInfo:setupInfo];
}- (void)broadcastPaused {[self sendNotificationForMessageWithIdentifier:@"broadcastPaused" userInfo:nil];
}- (void)broadcastResumed {[self sendNotificationForMessageWithIdentifier:@"broadcastResumed" userInfo:nil];
}- (void)broadcastFinished {[self sendNotificationForMessageWithIdentifier:@"broadcastFinished" userInfo:nil];
}- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {}
打开手机桌面,然后长按录屏,选择录屏的App为我们自己的App,这时候就开始录制了。以上的接口就会被执行。开始录屏执行broadcastStartedWithSetupInfo,暂停录制执行broadcastPaused…
如果我们要将开始、暂停、结束这些事件以消息的形式发送到宿主App中,需要使用CFNotificationCenterGetDarwinNotifyCenter。
发送通知
写一个发送通知的方法:
- (void)sendNotificationForMessageWithIdentifier:(nullable NSString *)identifier userInfo:(NSDictionary *)info {CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();CFDictionaryRef userInfo = (__bridge CFDictionaryRef)info;BOOL const deliverImmediately = YES;CFStringRef identifierRef = (__bridge CFStringRef)identifier;CFNotificationCenterPostNotification(center, identifierRef, NULL, userInfo, deliverImmediately);
}
这里的identifier是发送此条通知的标识,每个通知定义一个唯一的标识,以便接收端辨认是哪一条通知。
接收通知
在Extension中发送通知后,在宿主App中接收消息。
需要接收通知,首先需要注册该条通知,这里写了注册和移除注册通知的方法。这里的identifier需要和发送端保持一致。
- (void)registerForNotificationsWithIdentifier:(nullable NSString *)identifier {[self unregisterForNotificationsWithIdentifier:identifier];CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();CFStringRef str = (__bridge CFStringRef)identifier;CFNotificationCenterAddObserver(center,(__bridge const void *)(self),MyHoleNotificationCallback,str,NULL,CFNotificationSuspensionBehaviorDeliverImmediately);
}
- (void)unregisterForNotificationsWithIdentifier:(nullable NSString *)identifier {CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();CFStringRef str = (__bridge CFStringRef)identifier;CFNotificationCenterRemoveObserver(center,(__bridge const void *)(self),str,NULL);
}
这里我们需要接收多个通知消息,需要一一注册才能收到消息:
注册对应事件的通知
- (void)addUploaderEventMonitor {NSLog(@"addUploaderEventMonitor");[self registerForNotificationsWithIdentifier:@"broadcastStartedWithSetupInfo"];[self registerForNotificationsWithIdentifier:@"broadcastPaused"];[self registerForNotificationsWithIdentifier:@"broadcastResumed"];[self registerForNotificationsWithIdentifier:@"broadcastFinished"];[self registerForNotificationsWithIdentifier:@"processSampleBuffer"];//这里同时注册了纷发消息的通知,在宿主App中使用[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(broadcastInfo:) name:ScreenHoleNotificationName object:nil];
}
移除注册的通知
- (void)removeUploaderEventMonitor {NSLog(@"removeUploaderEventMonitor");[self unregisterForNotificationsWithIdentifier:@"broadcastStartedWithSetupInfo"];[self unregisterForNotificationsWithIdentifier:@"broadcastPaused"];[self unregisterForNotificationsWithIdentifier:@"broadcastResumed"];[self unregisterForNotificationsWithIdentifier:@"broadcastFinished"];[self unregisterForNotificationsWithIdentifier:@"processSampleBuffer"];[[NSNotificationCenter defaultCenter] removeObserver:self name:ScreenHoleNotificationName object:nil];
}
MyHoleNotificationCallback是一个回调block,当收到通知时,就会回调这个block。它的实现如下:
static NSString * const ScreenHoleNotificationName = @"ScreenHoleNotificationName";void MyHoleNotificationCallback(CFNotificationCenterRef center,void * observer,CFStringRef name,void const * object,CFDictionaryRef userInfo) {NSString *identifier = (__bridge NSString *)name;NSObject *sender = (__bridge NSObject *)observer;//NSDictionary *info = (__bridge NSDictionary *)userInfo;NSDictionary *info = CFBridgingRelease(userInfo);NSLog(@"userInfo %@ %@",userInfo,info);NSDictionary *notiUserInfo = @{@"identifier":identifier};[[NSNotificationCenter defaultCenter] postNotificationName:ScreenHoleNotificationNameobject:senderuserInfo:notiUserInfo];
}
这里收到通知后,做了一步转发,将消息转发出去,在在宿主App中发送通知。
在宿主App中收到MyHoleNotificationCallback这个回调后,我们将此条通知通过NSNotificationCenter纷发出去,App中其他地方如果需要监听这些事件就可以注册ScreenHoleNotificationName接收消息了。
如果其他地方不需要接收通知消息,则收到MyHoleNotificationCallback后直接处理就行,也不必再转发了。
这样事件传递,实现了宿主App和主App之间的事件通信。
- (void)broadcastInfo:(NSNotification *)noti {NSDictionary *userInfo = noti.userInfo;NSString *identifier = userInfo[@"identifier"];if ([identifier isEqualToString:@"broadcastStartedWithSetupInfo"]) {}if ([identifier isEqualToString:@"broadcastPaused"]) {}if ([identifier isEqualToString:@"broadcastResumed"]) {}if ([identifier isEqualToString:@"broadcastFinished"]) {}if ([identifier isEqualToString:@"processSampleBuffer"]) {}
}
这块只是在录屏直播中是否有用,得根据具体的业务需求来看,有时候不需要将事件传递给宿主App,也就不用发送通知了。
注意事项
不要在- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType这个方法里发通知,这几方法是采集到数据就会回调,录屏过程中一直被执行,如果一直发送通知的话,会造成主线程卡顿,因为通知是同步进行的。
遗留问题
在发送通知的时候,可以传递一个参数userInfo,即CFNotificationCenterPostNotification(center, identifierRef, NULL, userInfo, deliverImmediately);
这个userInfo的传值问题我没有解决,应该是可以转值的,可能是转化问题,不知道怎么弄,有知道的可以一起探讨一下,或者直接在品论了告知,谢谢先。
补充
这里是之后补充的内容
以下是别人的处理思路,出处
App 与 Extension 的代码共用iOS 10 新增了很多种 Extension,包括本文提到的两种 Broadcast Extension。主 App 与 Extension 属于不同的两个进程,代码逻辑也是分离的,而实际情况中,主 App 与 Extension 往往会包含相同的逻辑,需要共用代码。
主 App 与 Extension 属于两个不同的 target,共用代码,有以下几种方式:
一份代码创建两个副本,分别加到 App 和 Extension 两个 target 中。这种方法简单粗暴而有效,只是,如果需要改动逻辑,则需要改两份代码,想象一下,假如这种改动很频繁,世界上又有几个程序员能受得了?
抽离公共代码,放到独立的 framework,然后两个 target 都依赖该 framework,这是标准而方便的做法。
使用 CocoaPods,只需要在 Podfile 中分别写两个 target 所依赖的 pod 即可,最简洁。
我觉得 使用 CocoaPods,只需要在 Podfile 中分别写两个 target 所依赖的 pod 即可,最简洁。
这个也是一个可考虑的思路。
iOS录屏直播(四)主App和宿主App数据共享,通信功能实现相关推荐
- iOS录屏直播(二)Broadcast Upload Extension和Broadcast Setup UI Extension
Morris_2019.06.13 上一篇总结了ReplayKit相关的知识点,实现了应用内的录屏功能,同时涉及到了很少一部分Broadcast Upload Extension和Broadcast ...
- iOS录屏直播(一)初识ReplayKit
Morris_2019.05.08 本篇主要功能: 认识ReplayKit框架 RPScreenRecorder实现在应用内录屏功能 RPPreviewViewController查看录屏内容 RPB ...
- iOS录屏直播(三)AppGroup
Morris_2019.06.14 AppGroup是什么 App Groups Entitlement AppGroup是一个App组,里面可以有若干个App,AppGroup组是个虚无的存在,若干 ...
- iOS rtmp 摄像头/录屏直播以及观看
之前讲过如何在centos上使用nginx搭建rtmp服务器(链接),本文介绍一下iOS 端如何通过rtmp录屏直播以及观看,完整的工程代码地址(https://github.com/zxm006/R ...
- 手游录屏直播技术详解 | 直播 SDK 性能优化实践
直播无疑是 2016 年的大热话题,七牛云在 6 月底发布了实时流网络 LiveNet 和直播云解决方案后,我们用<直播技术详解>系列文章系统地介绍了直播各个环节的关键技术,帮助视频直播创 ...
- 如何做电脑游戏桌面录屏直播实现手机直接观看
原创教程 ( 转载请注明出处 ) 2017-6-26,今天来做一下是电脑游戏桌面录屏直播的教程,就是把桌面的游戏直播出去,加上话筒做讲解.最终实现在电脑.手机.微信中都可以观看到游戏的直播和讲解画面. ...
- 直播源码:游戏录屏直播的基本实现方式
移动端设备性能的提升,和手机直播行业的发展,催生了一大批直播细分行业,今天我们总结的是基于直播源码的手游录屏直播技术的基本实现方式. 大致的流程是手机申请录屏权限,手机录屏,开启手机实时将数据推向网络 ...
- Android实现录屏直播(二)需求才是硬道理之产品功能调研
请尊重分享成果,转载请注明出处,本文来自Coder包子哥,原文链接:http://blog.csdn.net/zxccxzzxz/article/details/54254244 Android实现录 ...
- Android PC投屏简单尝试(录屏直播)2—硬解章(MediaCodec+RMTP)
代码地址 :https://github.com/deepsadness/MediaProjectionDemo 想法来源 上一边文章的最后说使用录制的Api进行录屏直播.本来这边文章是预计在5月份完 ...
最新文章
- android button背景图片自适应,Android开发之给你的Button加个背景
- 人工智能创业指南:AI 产品未来的发展模式及策略
- vsphere服务器虚拟化流程,VMware vSphere服务器虚拟化实验
- 高斯消元处理无解|多解情况 poj1830
- Exchange企业实战技巧(15)启用向外部联系人发送邮件时的提醒
- 【最优解法】1087 有多少不同的值 (20分)_17行代码AC
- Linux下备份cisco路由配置
- 【月径流预测】基于matlab人工生态系统算法优化BP神经网络月径流预测【含Matlab源码 2000期】
- win10连接校园网(wifi)开热点手机连接显示“已连接但无法访问互联网”解决办法
- c语言中eof的作用,eof在c语言中表示什么
- Base理论是什么?之前也聊到过CAP理论
- python爬取豆瓣Top250完整代码
- AS问题解决系列3—iCCP: Not recognizing known sRGB profile
- 用计算机管理员同步一下文件,《计算机应用基础(Windows 7 Office 2010)同步训练》0711.docx...
- 子网掩码 与同一网段
- 使用Qpaint在图片上写文字
- 中小项目敏捷实践之一(关于项目所有者和责任人)
- 基于java的项目总结
- java从零开发贪吃蛇游戏全流程
- Cocos2d-x12和NDK-r8编译android
热门文章
- bt服务器搭建 linux_CentOS 4.5 下搭建BT下载服务器安装笔记
- IT项目经理必须清楚和把握IT项目管理的弹性特点
- Eclipse IDE for Java Developers与Eclipse IDE for Java EE Developers的区别
- antd vue表单上传文件_AntDesign vue学习笔记-自定义文件上传
- 一些前端模拟接口工具和相关文章
- oracle数据库短期培训,Oracle数据库培训课件.ppt
- python框架-Django-02-相知.模型
- 加速度传感器安装注意事项
- 智能温湿度计原型设计-BLE 模组 SDK 开发
- ABB机器人学习笔记(十)-ABB机器人常用指令详解(2)