【问题标题】:Is there any notification for detecting AirPlay in Objective-C?在 Objective-C 中是否有检测 AirPlay 的通知?
【发布时间】:2022-03-09 00:11:07
【问题描述】:

我正在使用 MPVolumeView 来显示 Airplay 图标,它工作正常。

但我需要在 Airplay 网络到来时显示动画,并在 Airplay 网络隐藏时隐藏该动画。

是否有通知让我知道 Airplay 的开始和结束时间?

【问题讨论】:

标签: iphone objective-c ios


【解决方案1】:

这正是您正在寻找的 - https://github.com/StevePotter/AirPlayDetector

它是一个单一的类,它提供一个属性来确定播放设备是否处于活动状态。以及可用性变化时的通知。

使用起来很简单。比如,要确定你写的可用性:

[AirPlayDetector defaultDetector].isAirPlayAvailable

享受吧!

【讨论】:

  • 不错的技巧。显然,每个 iOS 版本都需要对其进行测试。这在 App Store 中是否可以接受,我意识到它没有使用私有 API 但仍然想知道?
  • 这是苹果的说法,不是我们。我们不能代表他们或他们的政策。但我的直觉告诉我这是可以接受的。
  • 我们接受它没有问题。 MPVolumeView 是一个公共类。唯一值得怀疑的事情是遍历它的子视图。但它不使用任何私有 API。
  • 顺便说一下,这是一个 ARC 兼容的版本。 github.com/MobileVet/AirPlayDetector
  • 这并不保证airplayIsAvailable。如果有任何可用的无线路由,则将设置 volumeView 的 routeSelection 按钮的 alpha 值。它只是和 MPVolumeView 的 volumeView.areWirelessRoutesAvailable 一样
【解决方案2】:

准确地说: 使用公共 API 准确检查播放:NO

您可以使用公共 API 做的所有事情就是检查 可用的无线路由,其中包括空中播放:(在简单的情况下,当您有一个 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 实例作为它的ivar,所以-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 时,它对我来说是完美的。谢谢!
  • 也就是说,如果蓝牙关闭,MPVolumeView 实例将不会显示?
  • 你的意思是volumeView.areWirelessRoutesAvailable? AVAudioSession 对蓝牙和无线播放音频设备的处理方式类似。只要任何可用的无线设备可用(蓝牙或无线播放)-> 它将返回 true。
【解决方案3】:

从 iOS 7 开始,您可以注册 MPVolumeViewWirelessRoutesAvailableDidChangeNotification。

【讨论】:

    【解决方案4】:

    使用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);
            }];
        }
    }
    

    【讨论】:

    • 我不会这样做。如果 Apple 决定 AirPlay 按钮不是 MPVolumeView 的顶级子视图,此解决方案可能随时中断。或者如果他们决定 AirPlay 视图不再是 UIButton。
    • @Alexander true,但更改不会导致崩溃,因此假设没有可用的公共 api 就可以了
    【解决方案5】:

    6 年后。 我认为 Sankar Siva 并没有要求检测,而是要求激活一条播放路线。

    我提高了@Alf,因为他把我放在了正确的方向上,但他没有回答这个问题。

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

    另一方面,MPVolumeViewWirelessRouteActiveDidChangeNotification 在采用新路线时触发,例如:当您选择 Apple TV 时。

    不需要私有 API。

    【讨论】:

      【解决方案6】:

      如果你想要一个通知,这里就是这样做的方法

      [[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");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-22
        • 1970-01-01
        相关资源
        最近更新 更多