iOS AirPlay: my app is only notified of an external display when mirroring is ON?

StackOverflow https://stackoverflow.com/questions/9023806

  •  14-11-2019
  •  | 
  •  

Question

I'm trying to enable AirPlay support in my app. I'm not doing video; I want to use the external display as a "second display".

Here's my problem: if I choose "AppleTV" from my AirPlay button, my app doesn't get notified. The only time my app -does- get notified is when I leave my app, go to the OS-level AirPlay button, choose "AppleTV" there and turn on Mirroring. If I turn mirroring off, my app is then told that the external display is gone.

So:

  1. Why doesn't my app get notified when I pick an external display from within my app?
  2. Why does my app get notified of the presence of an external display when I turn mirroring on...and not before? I'm obviously misunderstanding something, but it would seem like turning mirroring on should inform my app that the external display is gone (rather than now available, since the OS should now be using that external display for mirroring.)

Code sample below. Thanks in advance for any help!

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

     // Override point for customization after application launch.

     // Is there already an external screen?
     if (UIScreen.screens.count > 1)]
     {
          [self prepareExternalScreen:UIScreen.screens.lastObject];
     }

     // Tell us when an external screen is added or removed.
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(externalScreenDidConnect:) name:UIScreenDidConnectNotification object:nil];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(externalScreenDidDisconnect:) name:UIScreenDidDisconnectNotification object:nil];

     self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
     self.window.rootViewController = self.viewController;

     // Add AirPlay control to view controller.
     MPVolumeView* airplayButtonView = [[MPVolumeView alloc] init];
     airplayButtonView.frame = CGRectMake(300, 300, 50, 50);
     airplayButtonView.backgroundColor = [UIColor blackColor];
     airplayButtonView.showsVolumeSlider = NO;
     airplayButtonView.showsRouteButton = YES;

     [self.viewController.view addSubview:airplayButtonView];


    [self.window makeKeyAndVisible];

    return YES;
}

#pragma mark - External screen handling

- (void)externalScreenDidConnect:(NSNotification*)notification
{
     [self prepareExternalScreen:notification.object];
}

- (void)externalScreenDidDisconnect:(NSNotification*)notification
{
     // Don't need these anymore.
     self.externalWindow = nil;
}

- (void)prepareExternalScreen:(UIScreen*)externalScreen
{
     NSLog(@"PREPPING EXTERNAL SCREEN.");
     self.viewController.view.backgroundColor = [UIColor blueColor];
     CGRect frame = externalScreen.bounds;
     self.externalWindow = [[UIWindow alloc] initWithFrame:frame];
     self.externalWindow.screen = externalScreen;
     self.externalWindow.hidden = NO;
     self.externalWindow.backgroundColor = [UIColor redColor];
}
Was it helpful?

Solution

That's correct, unfortunately. The secondary display (the airplay screen) is only available with mirroring.

Here is an application that shows how to implement this: https://github.com/quellish/AirplayDemo

Looking at your code, you SHOULD be getting the UIScreenDidConnectNotification when a user goes to the airplay menu and turns on mirroring while your app is active. The "Airplay Button", wether a MPVolumeView or movie controller, does not control mirroring (and thus the external display functionality). Video and audio out are unfortunately separate from mirroring, and mirroring can only be turned on or off using the system wide mirroring UI.

Bottom line: You can't turn on that AirPlay screen from within your app.

OTHER TIPS

Finally found the answer, you must have mirroring enabled in order to get the new screen notification, but then you should overwrite the screen with your second screen content. Very confusing!

See this example:

UIScreen screens always return 1 screen

Now, the worst part. You can add an AirPlay button inside your app using this:

MPVolumeView *volumeView = [ [MPVolumeView alloc] init] ;
[view addSubview:volumeView];

However you cannot enable mirroring from this picker! And there is no programmatic way to turn on mirroring.

How can I turn on AirPlay Screen Mirroring on the iPhone 4S programmatically

So apparently the only way to have a second screen experience is to instruct your user how to turn on AirPlay from multitasking bar and make sure they turn mirror on.

It seems not possible from inside of app unfortunately. Only airplay sound can be turned on from inside app afaik. Here's an example app using the second screen with OpenGL and sounds http://developer.apple.com/library/ios/samplecode/GLAirplay/Introduction/Intro.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top