在Objective-C中检测AirPlay是否有通知?

21

我正在使用MPVolumeView来显示Airplay图标,并且它运行正常。

但是当Airplay网络出现时,我需要展示一个动画,并在Airplay网络隐藏时隐藏该动画。

是否存在通知可让我知道何时开始和结束Airplay?


请查看这个答案,它提供了一种不错的方法 - https://dev59.com/72jWa4cB1Zd3GeqPoC6l - amergin
这个问题的日期一年后,真的没有苹果通知吗? - Morkrom
6个回答

18

这正是您所需要的 - https://github.com/StevePotter/AirPlayDetector

它是一个单一的类,提供了一个属性来确定Airplay设备是否处于活动状态,并在可用性发生变化时通知。

使用它很简单。例如,要确定可用性,您可以编写:

[AirPlayDetector defaultDetector].isAirPlayAvailable

享受吧!


不错的技巧。显然,它需要在每个iOS版本中进行测试。这在App Store中可行吗?我知道它没有使用私有API,但仍然想知道是否可以接受? - mttrb
顺便提一下,这里有一个兼容ARC的版本。https://github.com/MobileVet/AirPlayDetector - Morkrom
它在我的iOS 7和8上都能正常工作。观察alpha值是一个好主意! - RayChen
大家好,我在存储库中更新了 readme。由于我不再进行 ios 开发,所以无法管理该项目。欢迎 Fork。 - Steve Potter
@RayChen,这并不保证在无线路由可用的情况下是正确的,这意味着蓝牙设备可用,但Airplay设备不可用。它将完全执行与volumeView.areWirelessRoutesAvailable相同的操作; - ambientlight
显示剩余3条评论

8

确切地说: 使用公共API精确检查Airplay: 不行

你能用公共API做的只是检查可用的无线路由,其中包括了Airplay: (在一个简单的情况下,当你在某处连接了MPVolumeView实例到你的视图上时,你可以直接调用volumeView.areWirelessRoutesAvailable;)

如果你好奇如何使用私有API来检查是否确切可用Airplay:

- (BOOL)isAirplayAvailable
{
    Class MPAVRoutingController = NSClassFromString(@"MPAVRoutingController");
    id routingController = [[MPAVRoutingController alloc] init];

    NSArray* availableRoutes = [routingController performSelector:@selector(availableRoutes)];
    for (id route in availableRoutes) {
        NSDictionary* routeDescription = [route performSelector:@selector(avRouteDescription)];
        if ([routeDescription[@"AVAudioRouteName"] isEqualToString:@"AirTunes"])
            return true;
    }

    return false;
}

(实际上,MPVolumeView具有一个MPAVRoutingController实例作为其成员变量, 所以-areWirelessRoutesAvailable只是一个访问器, 正好对应于[volumeView->_routingController wirelessDisplayRoutesAvailable]

AVAudioSession也向您公开了currentRoute,因此您可以轻松检查是否激活了AirPlay:

- (BOOL)isAudioSessionUsingAirplayOutputRoute
{
    AVAudioSession* audioSession = [AVAudioSession sharedInstance];
    AVAudioSessionRouteDescription* currentRoute = audioSession.currentRoute;
    for (AVAudioSessionPortDescription* outputPort in currentRoute.outputs){
        if ([outputPort.portType isEqualToString:AVAudioSessionPortAirPlay])
            return true;
    }

    return false;
}

关于AirPlayDetector的答案并不能保证Airplay可用 - 它只是检查MPVolumeView的routeSelection按钮的alpha值,当无线路由可用时(例如蓝牙),该按钮将在任何情况下显示。它将与volumeView.areWirelessRoutesAvailable;完全相同。


当AVPlayer的方法isExternalPlaybackActive与AVPlayerItem一起加载时,对我来说非常完美。谢谢! - iGranDav
那就意味着,如果蓝牙关闭了,MPVolumeView实例将不会显示? - KarenAnne
你是指 volumeView.areWirelessRoutesAvailable 吗?AVAudioSession 对蓝牙和Airplay音频设备的处理方式相似。只要任何可用的无线设备(蓝牙或Airplay)可用 -> 它将返回true。 - ambientlight

7
自iOS 7以来,您可以注册一个名为MPVolumeViewWirelessRoutesAvailableDidChangeNotification的通知,此通知涉及无线路由器的可用性。

3

使用ReactiveCocoa可以更轻松地完成。快来看看吧:

MPVolumeView *myVolumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(0, 0, 180, 22)];
for (UIView *view in myVolumeView.subviews) {
    if ([view isKindOfClass:[UIButton class]]) {
        [[RACAbleWithStart(view, alpha) distinctUntilChanged] subscribeNext:^(id x) {
            NSLog(@"airplay button visibility changed %@", x);
        }];
        [[RACAbleWithStart(view, frame) distinctUntilChanged] subscribeNext:^(id x) {
            NSLog(@"airplay button connection changed %@", x);
        }];
    }
}

我不会这样做。如果苹果决定AirPlay按钮不再是MPVolumeView的顶级子视图,或者他们决定AirPlay视图不再是UIButton,那么这个解决方案随时可能出现问题。 - Alexander
@Alexander 是的,但这个变化不会导致崩溃,所以假设没有可用的公共API,这是可以接受的。 - Roman B.

0

如果你想要通知,这里是实现方式

[[NSNotificationCenter defaultCenter]
    addObserver:self
    selector: @selector(deviceChanged:)
    name:AVAudioSessionRouteChangeNotification
    object:[AVAudioSession sharedInstance]];

- (void)deviceChanged:(NSNotification *)sender {
      NSLog(@"Enters here when connect or disconnect from Airplay");
}

0

六年后。 我认为 Sankar Siva 并没有要求检测,而是要求激活 airplay 路线。

我提到了 @Alf,因为他引导了我的方向,但他并没有回答问题。

MPVolumeViewWirelessRoutesAvailableDidChangeNotification 在 MPVolumeView 检测到新路线时触发。

另一方面,MPVolumeViewWirelessRouteActiveDidChangeNotification 在选取新路线时触发,例如:当你选择你的 Apple TV 时。

不需要私有 API。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接