我想创建一个应用程序,用户不知道附近设备的发现(如iphone,ipad和appletv等),并选择唯一的appleTv,如果在附近可用,然后原子连接并启动镜像.为此我读了AirPlay:
使用AirPlay,用户将音频和视频从iTunes或基于iOS的设备重定向到Apple TV(从那里到家庭影院系统)或AirPlay启用的音响系统.AirPlay可以流式传输来自互联网的媒体,已存储在iTunes中的媒体或存储在基于iOS的设备上的媒体.AirPlay可以在iOS应用程序,基于iOS的设备上的Safari浏览器或任何平台的iTunes中播放基于Internet的媒体
但我不需要airplay按钮,我想以编程方式发现设备并仅与appleTv连接,然后开始镜像.
我阅读了很多博客并搜索过很多东西,但没有找到任何有用的东西.http://spin.atomicobject.com/2012/04/23/ios-mirroring-and-programmatic-airplay-selection/ 给出了一些解释,但它出现了.
请给我一些建议,如何以一种伟大的方式实现这种东西.
对不起,这是超级duperdy迟到,你可能已经实现了别的东西,但经过DAYS的研究和试验,我终于得到了一些工作.
许多开发人员在他们的应用程序中拥有非常高级的UI,并使用大量自定义弹出窗口和控制器,为他们的应用程序提供非常独特的外观,然后必须使用股票AirPlay控制器UI,这使用户完全脱离应用程序体验和可以是一个完整的眼睛.
其他人想要更好的UX; 即.他们希望将两者结合起来,以便将人们的当前媒体流分开(一个用于AirPlay,一个用于其他所有媒体),而不是必须将菜单分开,以便用户拥有非常棒的体验.
不幸的是,使用今天可用的公共API,你真的无能为力.Spotify试图让它在他们的应用程序中工作,虽然比大多数方法更好,但仍然有很多不足之处.
但是,如果由于某种原因,您不想在应用程序商店中发布您的应用程序,那么您有一个很好的代码混淆器可以隐藏您的函数来自苹果(极不可能),或者您想要将您的应用程序分发到另一个商店(Cydia)等等.有一个选项:私人API.
很多人在听到这两个词时都会回避,但是一旦你习惯了这种格式,它就会像普通的Cocoa编程减去Xcode代码的完成一样.
我不打算向您介绍与Private API的交互; 你可以阅读其他文章,这些文章将比我愿意深入研究更深入.没有任何进一步的麻烦,这就是我提出的.
第1步:阅读其他更聪明的人在github上发布的反向工程头文件(https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/).这真的值得阅读所有的头文件,因为你可以做的一些事情真的很有趣.
第2步: 开展业务.现在,我将在Swift中执行此操作,但我将在下面提供Objective-C链接.我建议Objective-C执行此操作,因为大多数这些类都是用Objective-C编写的,许多方法都以iVars的"_"快速错误开头,而且它变得非常混乱.但如果你必须,那就是你的意思.
因此,不是传统的[class performSelector:methodName]
方法和[instance valueForKey:_iVar]
访问实例变量的方式,而是在Swift中使用协议更容易; 主要是因为在Swift中执行选择器SUCKS.
因此,我们将基本上创建我们稍后需要使用的类的本地表示.
@objc protocol MPAVRoutingControllerProtocol { optional func fetchAvailableRoutesWithCompletionHandler(completion: (routes: [MPAVRouteProtocol]) -> Void) optional func pickRoute(route: MPAVRouteProtocol) -> Bool optional func setDelegate(delegate: NSObject) } @objc protocol MPAVRouteProtocol { optional func routeName() -> String optional func routeUID() -> String optional func isPicked() -> Bool optional func wirelessDisplayRoute() -> MPAVRouteProtocol } @objc protocol MPAudioDeviceControllerProtocol { optional func setRouteDiscoveryEnabled(enabled: Bool) optional func routeDescriptionAtIndex(index: Int) -> [String: AnyObject] } extension NSObject : MPAVRoutingControllerProtocol, MPAVRouteProtocol, MPAudioDeviceControllerProtocol { }
现在这真是神奇发生的地方.在视图控制器的某个地方,我们使用创建类NSClassFromString()
let MPAudioDeviceControllerClass: NSObject.Type = NSClassFromString("MPAudioDeviceController") as! NSObject.Type let MPAVRoutingControllerClass: NSObject.Type = NSClassFromString("MPAVRoutingController") as! NSObject.Type
然后,我们从这些类创建对象,并通过调用我们的协议函数与它们进行交互.
let routingController = MPAVRoutingControllerClass.init() as MPAVRoutingControllerProtocol let audioDeviceController = MPAudioDeviceControllerClass.init() as MPAudioDeviceControllerProtocol
现在我们已经完全初始化了对象,我们可以做很酷的事情.所以我们首先需要做的是启动守护进程来搜索airplay设备.
audioDeviceController.setRouteDiscoveryEnabled!(true)
此步骤是可选的,但建议使用.我们可以为自己分配MPAVRoutingController的委托,并在设备变为活动状态时获得委托调用,而不是更新您的UI以查找可能存在或可能不存在的更改.
routingController.setDelegate!(self)
然后我们实现该功能.
func routingControllerAvailableRoutesDidChange(controller: MPAVRoutingControllerProtocol) { }
然后在这个函数里面我们可以填充UI的数据源.
routingController.fetchAvailableRoutesWithCompletionHandler! { (routes) in }
首先,我们调用的routingController
方法将返回一个MPAVRoute对象数组,我们可以提取有关的信息.您需要的所有信息都在MPAVRouteProtcol中,但是您需要更多信息才能打电话audioDeviceController.routeDescriptionAtIndex!(an Index)
.这将返回详细信息,例如airplay设备的类型,mac地址,是否支持视频等等.
然后当你需要选择路线时,你会打电话routingController.pickRoute!(selectedRoute)
.您无需担心密码,iOS会自动为您处理(错误,缓存警报控制器等).