如何使用airplay以编程方式发现iOS设备列表和Connect for mirroring?

时间:2015-12-06 07:52:38

标签: ios airplay apple-tv

我想创建一个应用程序,用户不知道附近设备的发现(如iphone,ipad和appletv等),并选择唯一的appleTv,如果在附近可用,则自动连接并启动镜像。为此我读了 AirPlay

  

使用AirPlay,用户可以从iTunes或iTunes重定向音频和视频   基于iOS的设备可以是Apple TV(从那里到家庭)   剧院系统)或支持AirPlay的音响系统。 AirPlay可以   流媒体从互联网上传来,媒体已存储在其中   iTunes,或存储在基于iOS的设备上的媒体。 AirPlay可以流式传输   在iOS应用程序中,在Safari中播放基于Internet的媒体   基于iOS的设备上的浏览器,或任何平台上的iTunes

但我不需要airplay按钮,我想以编程方式发现设备并仅在启动镜像后与appleTv连接。

我阅读了许多博客并搜索了很多内容,但没有找到任何有用的内容。 http://spin.atomicobject.com/2012/04/23/ios-mirroring-and-programmatic-airplay-selection/给出了一些解释,但它出现了。

请给我一些建议,如何以一种伟大的方式实现这种东西。

1 个答案:

答案 0 :(得分:6)

对不起,这是一个非常优秀的duperdy迟到你可能已经实现了别的东西,但在 DAYS 的研究和反复试验之后,我终于得到了一些工作。

许多开发人员在他们的应用程序中拥有非常高级的UI,并使用大量自定义弹出窗口和控制器,为他们的应用程序提供非常独特的外观,然后必须使用库存AirPlay控制器UI,使用户完全脱离应用体验,可以是一个完整的眼睛。

其他人想要更好的用户体验;即。他们希望将两者结合起来,以便将人们的当前媒体流分开(一个用于AirPlay,一个用于其他所有媒体),而不是必须将菜单分开,以便用户拥有非常棒的体验。

不幸的是,使用今天提供的公共API,你真的无能为力。 Spotify试图让它在他们的应用程序中工作,虽然比大多数方法更好,但仍然有很多不足之处。 enter image description here enter image description here

但是,如果由于某种原因,您不想在应用程序商店中发布您的应用程序,那么您有一个很好的代码混淆器可以隐藏来自Apple的函数调用(极不可能),或者您希望将应用程序分发到另一个商店(Cydia等)有一个选项:私人API。

很多人在听到这两个词时都会回避,但是一旦你习惯了这种格式,它就会像普通的Cocoa编程一样减去Xcode代码的完成。

停止Blabbering并且只是GIMME DE CODEZ

我不打算向您介绍与私有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会自动为您处理(错误,缓存警报控制器等)。