Display one thing on iPad and another on Apple Tv? - ios

I have an app idea, but I'm not sure if it's possible.
I was wondering if I'm able to display one thing on the iPad ( or iPhone )
screen, and something totally different on the Apple Tv at the same time.
For example, a quiz app, where the question is displayed on the Apple Tv, and the multiple choices are listed on the iPad for the user to pick.
I'm not sure if this is possible or if you can only Mirror the iPad screen onto the Apple Tv.
If there is some "Proof of Concept" example code, I'd love to take a look.
Thank you so much.
Chris

Turns out that is is pretty simple to support two screens: the primary screen of the iOS device and a secondary screen (either an external display or mirroring on an Apple TV).
Based on information from the blog post Creating a Dual-Screen AirPlay Experience for iOS and Apple TV, you don't need to do much.
Basically you need to check the screens property from UIScreen. There are also notifications you should listen for (UIScreenDidConnectNotification and UIScreenDidDisconnectNotification) so you know if the number of screens changes while your app is running.
Once you have a second screen, you need to create a new window for it. Code like the following can be used:
if ([UIScreen screens].count > 1) {
if (!_secondWin) {
UIScreen *screen = [UIScreen screens][1];
_secondWin = [[UIWindow alloc] initWithFrame:screen.bounds];
_secondWin.screen = screen;
}
}
where _secondWin is a UIWindow ivar.
Once the window is setup, create a view controller, make it the window's root view controller, and show the window:
SomeViewController *vc = [[SomeViewController alloc] init...];
_secondWin.rootViewController = vc;
_secondWin.hidden = NO;
This is pretty much it other than proper handling of the notifications. Keep in mind that you can't get any touch events on the 2nd display so make sure whatever you show is basically display-only.
Depending on your app, you might have the 2nd screen/window being used throughout the lifetime of the app (as long as the 2nd screen is available any way). Or you might only create and use the 2nd window/screen under certain circumstances. When you don't setup the 2nd window/screen, your app will simply be mirrored to the 2nd display or Apple TV.
The last piece is to turn on mirroring to the Apple TV. This is done on the iOS device, not in the app.
The blog post I linked has a few more details worth reviewing.

Related

Get UIWindow of AirPlay mirroring screen

I'm trying to get the UIWindow object of the external screen (such as a television) when using AirPlay mirroring. The tricky part: it really is AirPlay mirroring, not a separate display, as we're using the built-in functionality of AirPlay rather than setting up a new UIWindow object and assigning it to the new screen. My boss wants the app to mirror the device in every way, but to be able to add subviews (tutorial overlays) to the external window exclusively, by adding them to the secondary screen's UIWindow.
What I've Tried:
I can get the secondary UIScreen object easily, either from UIScreenDidConnectNotification or [UIScreen screens], but as far as I know UIScreens don't have references to the UIWindow being shown.
Since we're just using the display that AirPlay auto-generates, I can't save a reference to the UIWindow during its creation.
I've checked [[UIApplication sharedApplication] windows], and it doesn't seem to include the UIWindow associated with the external display. (At least, none of the window.screen objects match the UIScreen object I get from UIScreenDidConnectNotification when the TV first connects, and while [[UIScreen screens] count] goes up by 1 when a TV is connected, the count of windows remains static.)
Is there a way to access the window for a secondary screen using AirPlay mirroring? Or alternatively, is there a way to efficiently implement app-wide mirroring of the device, that allows greater control of the UIWindow object associated with the TV?
This document from Apple:
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/WindowAndScreenGuide/UsingExternalDisplay/UsingExternalDisplay.html
states that:
To re-enable mirroring after displaying unique content, simply remove
the window you created from the appropriate screen object.
This means that when mirroring is active, there is no window linked to it, and the mirroring just uses the window of the main screen.
There is only a single window, and I don't think it's possible to show different content in this mode.
If you want to show different content, you'll have to create a new window and assign it to that screen.

Not able to push a custom view to external display using airplay (Apple TV)

Trying to show a custom screen on an external display connected to apple tv using airplay. We are also trying to stream audio via AppleTV after the pairing. (Audio is optional here, it's good to have but not required).
The problem is, if we do audio playback (using AVAudioPlayer), it works fine as expected, but cannot display the custom screen. On the other hand, selecting it from the Control Center makes it work fine except that we don't want to mirror the screen, we want to display a custom view.
Any help in this regard is much appreciated.
Uploaded a sample code for the AirPlay issue in dropbox - https://dl.dropboxusercontent.com/u/1307156/AirplayDemo.zip
What you're trying to do is actually quite simple:
Once an external screen has been added you can create a new UIWindow, a new UIViewController, which will be controlling your custom view displayed to the external screen, and set that just created window to the external UIScreen.
// new window binding
newWindow.screen = externalScreen;
[newWindow makeKeyAndVisible];
You can observe changes over external screens (a screen added, removed, changes over screenModes) through the NSNotificationCenter and do something accordingly for your purposes.

Airplay mirroring in iOS apps

I have looked several links and read the Apple Documentation but I don't get any step-wise instructions to mirror the content of app on an external device. All they explain is how to display a new window for an external screen if recognized.
In my app, I just need to display the current screen being shown in the app on an airplay enabled device. There is a airplay button, clicking on which will check for available external screens and display the content present on the device on that screen.
Well the reason is simple. AirPlay mirroring is enabled by the user from the settings as #Meera mentioned below. The idea to use in code app is to either display selective things (audio/video) on the TV via AirPlay or to use it as a second Window, where the user does see other things. However if you want you can simply send the whole view to the external screen using this code:
// Check for external screen and if found send output there
if ([[UIScreen screens] count] > 1) {
UIScreen *externalScreen = [[UIScreen screens] objectAtIndex:1];
NSArray *screenModes = externalScreen.availableModes;
//set max resolution
externalScreen.currentMode = [screenModes lastObject];
self.window.screen = externalScreen;
}

For iOS when would an App use more than one Window?

In the view programming guide for iOS, it states "Every iOS application needs at least one window—an instance of the UIWindow class—and some may include more than one window."
What are some examples Apps that would need more than one window?
Thanks
Apps that require to output video to a second screen might use more than one window.
Here you have a question about that particular topic.
You could also use more than one window to achieve other objectives, but that is not recommended by Apple. In general if you see that you need 2 windows or more, I'd suggest that something is wrong with your approach.
I've played around with 2 windows to integrate cocos2d and uikit in a test project, the code was pretty clean and the idea was to switch between windows, using the visibility and the key window, as necessary. It worked, but sometimes when sending the app to background, for some magical reason the active, key window would be made invisible.
Afaik the only case you'd need more than one window is if you connect another screen like a TV to your device. In that case you could provide a totally independent UI for the second screen. F.e. the Keynotes app on iPad does that when you connect another screen to the device.
You could register for the UIScreenDidConnectNotification and handle it like this:
- (void)screenDidChange:(NSNotification *)notification
{
if ([UIScreen screens] count] > 1)
{
UIScreen *extScreen = [[UIScreen screens] objectAtIndex:1];
UIWindow *extWindow = [[UIWindow alloc] initWithFrame:[extScreen bounds]];
//add some subviews to the window
extWindow.screen = extScreen;
[extWindow makeKeyAndVisible];
}
}

ads in universal app + ad persisting even when viewController changes

I'm implementing ads for the first time in an app that will be universal. I've followed a few tutorials and sorta|kinda have it working - using adWhirl, iAd, adMob. The tutorials were a bit simplistic though and I'm wondering if there are any open source universal ad template/library projects out there.
I've seen this and while helpful, the tutorial code is kind of broken/limited.
The specific questions I have (iOS5+ universal app):
In an app with a navController where the UIViewController can segue
multiple times to other controllers and then back again, do I need to
set up the ad stuff in each viewController or is there some way I
can have the ad layer/view persist across multiple VC views?
Ad sizes - In my test app, running on iPad I am getting ads but the
size is for iPhone. In adWhirl it didn't seem possible to specify
universal - only iPhone or Android. I've seen other iPad apps that seem to have a problem presenting ads because of the size - ads
appear in weird places, etc. Is there some universal solution to
the issue of ad sizes in universal apps?
For your first question, I would recommend that you use a singleton approach for your adView. You can find a similar singleton approach for an AdMob adView here. Tweaking that with your AdWhirl view instead shouldn't be bad at all. For each view that is displayed then, you could just do something like:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
shared = [AdWhirlMasterViewController singleton];
[shared resetAdView:self];
}
For your second question, I wonder if you can't just make some minor modifications to your adapter code to get iPad ads to show. So, for example, for AdMob adapter's getAd: method, you'd probably have something that looks like:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
adSize = kGADAdSizeLeaderboard;
} else {
adSize = kGADAdSizeBanner;
}
Then create your GADBannerView doing something similar to:
GADBannerView *view =
[[GADBannerView alloc] initWithAdSize:adSize];

Resources