我使用以下代码来检测AirPlay是否是当前选定的路线:
let airPlayActive = AVAudioSession
.sharedInstance()
.currentRoute
.outputs
.first?
.portType == .airPlay
print("AirPlay active: \(airPlayActive)")
但是,这在非常具体的情况下不起作用。我的用例是知道在播放视频之前选择了播放。我有两个视图控制器,比如A和B.出于测试目的,我在A上有一个计时器,如果AirPlay每秒使用上面的代码激活,它就会打印出来。
从A,我提出模态视图控制器B,它基本上使用AVPlayer
播放视频并使用MPVolumeView
控制当前选定的路线。如果我出现B,等待视频播放,然后改变路线到AirPlay,我可以看到更改反映在A(它将开始打印true
)。然后,如果我关闭B然后重新打开它,即使在播放视频之前,也可以判断AirPlay是否处于活动状态,这正是我想要的。
但是,有一种情况是这种情况不起作用。
场景是(看起来很奇怪),如果我使用MPRemoteCommandCenter
向远程命令添加目标,我上面描述的那种行为只会改变!这是我添加目标的方法(在视图控制器B中):
let center = MPRemoteCommandCenter.shared()
let pauseCommand = center.pauseCommand
pauseCommand.isEnabled = true
pauseCommand.addTarget(handler: { _ -> MPMPRemoteCommandHandlerStatus in
// ... doing some business logic
return .success
})
我也在B的deinit
中移除了该目标:
let center = MPRemoteCommandCenter.shared()
let pauseCommand = center.pauseCommand
pauseCommand.isEnabled = false
pauseCommand.addTarget(nil)
好吧,这只是与所有AirPlay相关的东西完全混淆:
portType
再次成为.builtInSpeaker
。因此,在重新打开B(播放视频)之前,我无法判断AirPlay是否处于活动状态。portType
在关闭B之后是.builtInSpeaker
,但如果我打电话给true
,我仍然会得到MPVolumeView().isWirelessRouteActive
,这告诉我无线路由是活跃的,但这不一定是AirPlay(例如它可能是蓝牙耳机)。portType
会在视频开始播放后从.builtInSpeaker
转到.airPlay
。AVAudioSession.routeChangeNotification
时,它有时不触发,当它发生时,AVAudioSessionRouteChangeReasonKey
的用户信息大部分时间都是.unknown
。对我来说,这显然是苹果方面的一个错误,但是你们中的任何一个都会碰巧知道另一种选择吗?在播放视频之前,我基本上需要知道AirPlay是否处于活动状态。
谢谢!
好吧,我找到了一个解决方法。它与问题本身一样奇怪,但它的工作......
我刚刚在视图控制器B上播放视频之前就向远程命令添加了目标。然后我只是等待音频路由更改通知(或者在没有激活的情况下超时)。这表明播放视频是“安全的”。