如何在使用 AVPlayer 播放视频之前检测 AirPlay 是否处于活动状态?
How to detect if AirPlay is active before playing a video with AVPlayer?
我使用下面的代码来检测 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 相关的东西:
如果我在视图控制器 B 上激活 AirPlay 然后关闭它,AirPlay 将被停用。现在当前 portType
再次变为 .builtInSpeaker
。因此,在重新打开 B(播放视频)之前,我无法判断 AirPlay 是否处于活动状态。
即使 portType
在关闭 B 后是 .builtInSpeaker
,如果我调用 MPVolumeView().isWirelessRouteActive
,它告诉我无线路由处于活动状态,但这不一定是 AirPlay(例如,它可能是蓝牙耳机)。
如果我重新打开 B,portType
会在视频开始播放后从 .builtInSpeaker
变为 .airPlay
。
音频路由更改通知也停止正常工作。观察AVAudioSession.routeChangeNotification
时,有时不触发,触发时,AVAudioSessionRouteChangeReasonKey
的用户信息大部分时间是.unknown
.
对我来说,这显然是 Apple 方面的一个错误,但是你们中有人碰巧知道替代方案吗?在播放视频之前,我基本上需要知道 AirPlay 是否处于活动状态。
谢谢!
好吧,我找到了解决方法。它和问题本身一样奇怪,但它正在工作...
我刚刚在视图控制器上播放视频之前向远程命令添加了一个目标 B。然后我只是等待音频路由更改通知(或者在不活动的情况下超时)。这表明 "safe" 可以播放视频。
我使用下面的代码来检测 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 相关的东西:
如果我在视图控制器 B 上激活 AirPlay 然后关闭它,AirPlay 将被停用。现在当前
portType
再次变为.builtInSpeaker
。因此,在重新打开 B(播放视频)之前,我无法判断 AirPlay 是否处于活动状态。即使
portType
在关闭 B 后是.builtInSpeaker
,如果我调用MPVolumeView().isWirelessRouteActive
,它告诉我无线路由处于活动状态,但这不一定是 AirPlay(例如,它可能是蓝牙耳机)。如果我重新打开 B,
portType
会在视频开始播放后从.builtInSpeaker
变为.airPlay
。音频路由更改通知也停止正常工作。观察
AVAudioSession.routeChangeNotification
时,有时不触发,触发时,AVAudioSessionRouteChangeReasonKey
的用户信息大部分时间是.unknown
.
对我来说,这显然是 Apple 方面的一个错误,但是你们中有人碰巧知道替代方案吗?在播放视频之前,我基本上需要知道 AirPlay 是否处于活动状态。
谢谢!
好吧,我找到了解决方法。它和问题本身一样奇怪,但它正在工作...
我刚刚在视图控制器上播放视频之前向远程命令添加了一个目标 B。然后我只是等待音频路由更改通知(或者在不活动的情况下超时)。这表明 "safe" 可以播放视频。