首页 文章 精选 留言 我的

精选列表

搜索[screen],共1022篇文章
优秀的个人博客,低调大师

iOS Airplay Screen Mirroring 同屏技术详解

投屏技术已经被大量用在身边的产品,比如电视投屏,投影仪,视频会议产品中。 在iOS平台外的其他平台中都已经有非常成熟的标准和实现。但在封闭的苹果iOS和Mac系统中,苹果使用私有的Airplay协议进行多屏互动,只开放给自己生态中的产品。对此相关技术限制比较严格,甚至在iOS9中加上了更严格的加密算法,直接导致很多投屏的产品不可用。本文转自刘连响知乎的文章。 文 / 刘连响 iOS中的投屏方案 1.ReplayKit iOS9中引入了ReplayKit, 让开发者有了一定的获取屏幕数据的能力. 并在iOS10和iOS11中继续扩展了ReplayKit的能力. 但还是有很大的限制, 比如在使用ReplayKit的api时只能录制当前应用的应用, 无法在应用进入后台之后继续录屏. 如果使用系统级别的屏幕录制,又无法获得每一帧的数据,只能获得最后录取的单个视频. 这样对第三方的开发有了非常大的限制. 2.Airplay Airplay是苹果提供的一种多屏互动技术, 可以将音频照片,视频, 屏幕从iOS设备或者Mac电脑上投射到支持airplay接受的设备上,如Apple TV。这样可以将小屏映射到大屏,可以无线音乐,可以图片分享等等. 但是Airplay属于苹果私有协议方案,设备间的协商与传输过程都进行了加密处理,并不能用于其他平台中。我们已经完整的逆向了Airplay的全部协议栈,并破解了其加密方案,可以提供跨平台Airplay接收方案。这样可以方便实现跨平台的多屏共享。 同时,通过研究,我们也可以通过Airplay Mirroring技术,做到在iPhone上把自己的屏幕的内容投送给当前iPhone,在某些情况下这种airplay的破解却非常有用处,比如手游直播。这中投屏方案使用了iOS原生的投屏能力,并且是完全的软件方案,非常方便进行集成和使用。 Airplay Mirroring实现原理 下面将介绍Airplay Mirroring接收端的实现原理,并揭示相关协议交互过程。 Airplay Mirroring客户端的同屏交互过程,分为三个主要步骤: 设备广播与发现 信息交互与能力协商 音视频数据接收与解扰 设备广播与发现 Airplay设备间的广播与发现通过Bonjour协议进行。Bonjour也被称为ZeroConf, mDNS等,可以用来在局域网内进行数据记录广播与发现。该协议比较成熟,网上可以找到诸多介绍。对于实现的Airplay(包括Mirroring)接收端而言,首先需要注册两类服务,即airtunes和airplay。 Airtunes服务主要用来处理广播视音频接收能力协商,是最为重要的服务内容,对应Bonjour记录名称为'_raop._tcp',注册服务端口不限,一般为了避免冲突,建议采用较高的端口数;Airplay服务主要用来兼容传统的streaming等服务,对应记录名称为'_airplay._tcp',注册端口一般为7000。 具体的服务广播内容,可以进行局域网抓包,找到对应记录内容。 当接收端通过Bonjour广播器服务能力后,发送端(如iPhone等各类iOS设备)就可以发现该接收端。 信息交互与能力协商 当发送端发现接收端后,可以开始信息交互与能力协商过程。该部分协议协议格式类似rtsp协议格式。主要分为两个阶段,设备匹配与和能力协商。 当发送端链接服务端后,设备匹配过程即开始。通信双方会进行fairplay加密协议进行信息交换,当完成信息交换后,客户端后续必须使用这部分信息来处理加密过的密钥,才能获得进一步视音频解密密钥。在iOS9之后,在fairplay过程之前,增加一个设备匹配过程,即pair-setup、pair-verify过程,其主要算法是较为标准的非对称公钥交换算法。 当两端成功匹配后,开始进行能力协商与信息交换,这些信息包括,设备名称、代号,音视频接收相关端口配置,视频接收能力以及加密密钥等,相关信息使用binary plist格式进行封装。 可以参考https://github.com/espes/Slave-in-the-Magic-Mirror找到相关协议交互的一些细节。 音视频数据接收与解密 双方协商成功后,发送端开始向接收端发送视音频数据,mirroring数据是通过TCP进行发送,为h.264 ES流格式。音频是通过RTP协议进行发送,根据内容的不同音频编码为ALAC或者AAC-ELD。 音视频流都是通过AES进行了加密处理,密钥需要通过上面一步的进过信息交互后的fairplay模组对setup过程中接收到的加密密钥进行解密,获得的AES解密需要的IV和KEY,然后经过AES解扰,即可以获得最终的视音频清流。 其他需要注意的地方 Airplay没过Session传送过来的视频h264码流,只有开头一个关键帧. 因此这种情况并不适合直播这种需要固定GOP的场景. 还需要做进一步的转码的工作,或者直接在压缩域进行处理,获得合理的GOP结构。 我们对Airplay相关协议的逆向工程已经封装成了跨平台的类库和框架, 支持windows/Mac/Android/iOS/linux, 在自己内部产品中使用已经非常稳定, 如果有需要可以联系我们. 也欢迎各类技术与应用场景讨论。我的邮箱leeoxiang#http://gmail.com 相关链接 AirCast:http://link.zhihu.com/?target=https%3A//github.com/AirCastLab Airplay Protocol:http://link.zhihu.com/?target=https%3A//nto.github.io/AirPlay.html AirCast website:https://aircast.cc/

优秀的个人博客,低调大师

Keep the Screen from Locking(阻止屏幕自动上锁)

在ios设备中,如果ios设备一段时间中没收到touch事件,ios设备就会自动锁定,但是在玩游戏时候可能会某段时间不触发touch时间,这时候就会锁定,而这并不是我们所想要的,那么我们可以设置 [[UIApplication sharedApplication] setIdleTimerDisabled: YES]; // Or for those who prefer dot syntax: [UIApplication sharedApplication].idleTimerDisabled = YES; swift // 保持常亮 UIApplication.shared.isIdleTimerDisabled = true

优秀的个人博客,低调大师

浅谈3D Touch(1) -- Home screen quick action

1. 背景: 随着iOS9 和 iPhone 6s的普及,苹果官方提供的3D Touch将带给我们更好玩,更便捷的操作习惯,桌面快捷菜单可谓是3D Touch功能中最实用的一个,有了它,用户不再需要进入app后做额外的操作,便能快速进入指定的页面。 2. 前期工作: 由于手头“并(wo)没(xiang)有(yao)”iPhone 6s 的设备,很多人说,那我怎么开发这个功能呢?不怕,github上早有大神写好了模拟器的解决方案。按照这个文档上的方法依次执行,你的模拟器也能唤出快捷菜单。 3. 正式接入 ①.创建UIApplicationShortcutItem 我们先来看一下每个UIApplicationShortcutItem中能够包含哪些信息 key Description required UIApplicationShortcutItemType 事件的唯一标识,可以通过这个标识来辨别你具体点击了哪个事件 Y UIApplicationShortcutItemTitle 标题,在没有子标题的情况下如果标题太长能自动换行 Y UIApplicationShortcutItemSubtitle 子标题,在标题的下方 N UIApplicationShortcutItemIconType 枚举选取系统中的一个图标类型 N UIApplicationShortcutItemIconFile 自定义一个图标,以单一颜色35x35的大小展示,如果设置这个,UIApplicationShortcutItemIconType将不起作用 N UIApplicationShortcutItemUserInfo 字典,里面可以添加各种key、value对 N UIApplicationShortcutItem 的创建有2种方式 第一种是在info.plist里面静态添加: <key>UIApplicationShortcutItems</key> <array> <dict> <key>UIApplicationShortcutItemType</key> <string>3dtouch.homePage</string> <key>UIApplicationShortcutItemTitle</key> <string>首页</string> <key>UIApplicationShortcutItemSubtitle</key> <string>这是首页</string> <key>UIApplicationShortcutItemIconFile</key> <string>shouye.png</string> <key>UIApplicationShortcutItemUserInfo</key> <dict> <key>url</key> <string>index</string> </dict> </dict> <dict> <key>UIApplicationShortcutItemType</key> <string>3dtouch.guanzhupage</string> <key>UIApplicationShortcutItemTitle</key> <string>关注</string> <key>UIApplicationShortcutItemSubtitle</key> <string>这是关注</string> <key>UIApplicationShortcutItemIconFile</key> <string>guanzhu.png</string> <key>UIApplicationShortcutItemUserInfo</key> <dict> <key>url</key> <string>guanzhu</string> </dict> </dict> </array> 第二种是在程序初始化的时候用代码动态添加: 我们先看一下UIApplicationShortcutItem.h,发现它的使用非常简单,习惯完全符合官方API固有方式,而且和之前那种方式所构建的包含的信息是一一对应的,其中有3个@interface分别是: UIApplicationShortcutIcon UIApplicationShortcutItem UIMutableApplicationShortcutItem //创建快捷item的icon 即UIApplicationShortcutItemIconFile UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"money"]; UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"gouwuche"]; UIApplicationShortcutIcon *icon3 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"wode"]; //创建快捷item的userinfo 即UIApplicationShortcutItemUserInfo NSDictionary *info1 = @{@"url":@"money"}; NSDictionary *info2 = @{@"url":@"gouWuche"}; NSDictionary *info3 = @{@"url":@"wode"}; //创建ShortcutItem UIMutableApplicationShortcutItem *item1 = [[UIMutableApplicationShortcutItem alloc]initWithType:@"3dtouch.moneyPage" localizedTitle:@"资产" localizedSubtitle:@"这是资产" icon:icon1 userInfo:info1]; UIMutableApplicationShortcutItem *item2 = [[UIMutableApplicationShortcutItem alloc]initWithType:@"3dtouch.shopPage" localizedTitle:@"购物车" localizedSubtitle:@"这是购物车" icon:icon2 userInfo:info2]; UIMutableApplicationShortcutItem *item3 = [[UIMutableApplicationShortcutItem alloc]initWithType:@"3dtouch.mypage" localizedTitle:@"我的" localizedSubtitle:@"这是我的" icon:icon3 userInfo:info3]; //把原有的shortcutItems拿出来,把动态的放进去 NSArray *items = @[item1, item2, item3]; NSArray *existingItems = [UIApplication sharedApplication].shortcutItems; NSArray *updatedItems = [existingItems arrayByAddingObjectsFromArray:items]; //塞回去 [UIApplication sharedApplication].shortcutItems = updatedItems; 最后我们来看一下效果: 看上去是不是非常和谐?其实我告诉你,我们已经踩到了坑里了 我在运行中发现: NSArray *existingItems = [UIApplication sharedApplication].shortcutItems; 所获得的existingItems并不是我们之前设置在info.plist里面的,而是上一次 [UIApplication sharedApplication].shortcutItems = updatedItems; 赋值给他的,又因为我自作聪明的做了一次 NSArray *updatedItems = [existingItems arrayByAddingObjectsFromArray:items]; 所以我们每运行一次,shortcutItems中的元素个数就会多3个, 那为什么展示出来没有问题呢? 仔细看刚刚发的那张效果图,我擦,只有4个,对了,这个就是表象上不出错的原因,在API上并没有写shortcutItems有任何个数限制,也没有写快捷窗口的个数,但是实际上,最多只能显示4个,而且shortcutItems这个里面的对象恐怕是早已被系统默默的存到了某个plist里了,每当程序启动时,会向系统要app的Bundle Identifier对应的shortcutItems,并非我们事先想要的info.plist中的items,当然以上只是我从现象做出的合理猜测,我们并不需要关心info.plist中的那些静态item,只需要动态创建的item直接打包赋值过去 [UIApplication sharedApplication].shortcutItems = @[item1, item2, item3]; 至于只展示4个的问题,这个我们无能为力了,系统做了限制。 ②.Item点击回调 当app在后台的时候UIApplication提供了一个回调方法 - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0); 我们依据这个回调中的shortcutItem的type和userinfo来做出不同的事件处理,而最后的completionHandler在API的说明中我们看到当应用并非在后台,而是直接重新开进程的时候,直接返回No,那么这个时候,我们的回调会放在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions UIApplication又给我们一个从launchOptions中获取这个shortcutItem的key–UIApplicationLaunchOptionsShortcutItemKey,所以在这2个都进行对shortcutItem的操作后,我们这个功能算是完成了 在didFinishLaunchingWithOptions中,由于某些客户端会有启动动画,所以这边加了3秒,具体因程序而异 UIApplicationShortcutItem *item = [launchOptions valueForKey:UIApplicationLaunchOptionsShortcutItemKey]; __weak typeof(self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ __strong typeof(weakSelf) strongSelf = weakSelf; if (strongSelf) { [strongSelf actionWithShortcutItem:item]; } }); 在performActionForShortcutItem回调中 - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void(^)(BOOL succeeded))completionHandler { if (shortcutItem) { [self actionWithShortcutItem:shortcutItem]; } if (completionHandler) { completionHandler(YES); } } 最后就是统一处理actionWithShortcutItem的地方,由于我这个demo中所有的type对应的行为都一样的,所以我这边没有对type做区分,甚至所以的item可以用同一个type -(void)actionWithShortcutItem:(UIApplicationShortcutItem *)item { if (item.userInfo) { NSLog(@"%@",item.userInfo[@"url"]); } } 好了,3D Touch的第一个功能就介绍到这里Demo。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册