MPVolumeView Airplay 仅在镜像时触摸

Posted

技术标签:

【中文标题】MPVolumeView Airplay 仅在镜像时触摸【英文标题】:MPVolumeView Airplay only touches when mirroring 【发布时间】:2017-09-02 03:04:04 【问题描述】:

我正在使用自定义AVPlayerLayer 来显示一个简单的视频。我正在尝试添加 Airplay 支持,但点击该按钮时,不显示任何内容。

self.player.allowsExternalPlayback = true
...
let airplayButton = MPVolumeView(frame: self.airplayButtonPlaceholder!.bounds)
airplayButton.showsRouteButton = true
airplayButton.showsVolumeSlider = false

self.airplayButtonPlaceholder?.addSubview(airplayButton)
self.airplayButtonPlaceholder?.backgroundColor = UIColor.clear

当我(在真实设备上)运行我的代码时,我看到了按钮,但是当我点击它时,什么也没有发生。这可能是什么原因造成的?是不是因为我使用的是自定义AVPlayerLayerAVPlayer

编辑:

当我通过控制中心打开镜像时,我可以触摸按钮并显示弹出窗口。怎么回事?

【问题讨论】:

【参考方案1】:

没有任何反应,因为您没有正确配置这个“新窗口”。

使用 Airplay 显示内容有两种方式。

镜像

不需要任何配置。

注意:您无需执行任何操作即可进行镜像。在 ios 中 5.0 及更高版本,镜像(即在主机设备和外部显示器上显示相同的内容)默认情况下发生 用户选择 AirPlay 视频输出设备。

额外窗口

(check apple guide here)

苹果描述的步骤是:

    在应用启动时,检查是否存在外部显示器并注册屏幕连接和断开通知。 当外部显示器可用时(无论是在应用启动时还是在您的应用运行时)为其创建和配置一个窗口。 将窗口与适当的屏幕对象关联,显示第二个窗口,并正常更新。

这里是摘自苹果文档的代码供快速参考。


- 如果外部显示器已经存在,则创建一个新窗口

- (void)checkForExistingScreenAndInitializeIfPresent

    if ([[UIScreen screens] count] > 1)
    
        // Get the screen object that represents the external display.
        UIScreen *secondScreen = [[UIScreen screens] objectAtIndex:1];
        // Get the screen's bounds so that you can create a window of the correct size.
        CGRect screenBounds = secondScreen.bounds;

        self.secondWindow = [[UIWindow alloc] initWithFrame:screenBounds];
        self.secondWindow.screen = secondScreen;

        // Set up initial content to display...
        // Show the window.
        self.secondWindow.hidden = NO;
    


- 注册连接和断开通知

- (void)setUpScreenConnectionNotificationHandlers

    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];

    [center addObserver:self selector:@selector(handleScreenDidConnectNotification:)
            name:UIScreenDidConnectNotification object:nil];
    [center addObserver:self selector:@selector(handleScreenDidDisconnectNotification:)
            name:UIScreenDidDisconnectNotification object:nil];


- 处理连接和断开通知

- (void)handleScreenDidConnectNotification:(NSNotification*)aNotification

    UIScreen *newScreen = [aNotification object];
    CGRect screenBounds = newScreen.bounds;

    if (!self.secondWindow)
    
        self.secondWindow = [[UIWindow alloc] initWithFrame:screenBounds];
        self.secondWindow.screen = newScreen;

        // Set the initial UI for the window.
    


- (void)handleScreenDidDisconnectNotification:(NSNotification*)aNotification

    if (self.secondWindow)
    
        // Hide and then delete the window.
        self.secondWindow.hidden = YES;
        self.secondWindow = nil;

    



编辑:

当使用 AVPlayerViewController 时,它已经按照文档here 中的描述自动实现。

AVPlayerViewController 自动支持 AirPlay,但你需要 执行一些项目和音频会话配置,然后才可以 在您的应用程序中启用。

【讨论】:

真的这么复杂吗?我记得我在股票 avplayerviewcontroller 上使用了我的方法,效果很好。我已经很晚了,所以我明天试试你的解决方案 实现并不复杂,但它确实会发生变化,因为您使用的是自定义播放器。如果您要使用默认的 AVPlayerViewController,它将是自动的。事实上,它写在类描述上。 (检查编辑) checkForExistingScreenAndInitializeIfPresent 中,您有一个评论// Set up initial content to display...,在handleScreenDidConnectNotification 中有类似的评论。最初的 UI 是什么?另外,如果我错了,请纠正我,但这是在 AppDelegate 中完成的,对吗? 至于在哪里完成,我建议在 AppDelegate 或 SingletonManager 中进行,您也可以在应用程序委托中初始化。这样做的目的是 1,尽快检测屏幕,2 持续监控连接的新屏幕。至于 cmets,是的,它就是你想在那里展示的任何东西。但简单地说,您创建一个根视图控制器并将其设置在该窗口上,如下所示: secondWindow!.rootViewController = rootVC

以上是关于MPVolumeView Airplay 仅在镜像时触摸的主要内容,如果未能解决你的问题,请参考以下文章

iOS AirPlay:我的应用程序仅在镜像打开时才收到外部显示器通知?

AVPlayer / Airplay 按钮

音频路由按钮 - AirPlay

MPMusicPlayerController 与 AirPlay?

列出并连接到没有 MPVolumeView 的播放设备

是否有任何公共 api 来检测可用的 AirPlay