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.
Related
The Apple docs on windows say:
A window is considered the key window when it is currently receiving keyboard and non touch-related events. Whereas touch events are delivered to the window in which the touch occurred, events that don’t have an associated coordinate value are delivered to the key window. Only one window at a time can be key.
This means that the default window that Xcode provides us is the key window by default, but then our button taps are listened to by any other window which is not a key window. Which window is this, which is listening to the touch events? We do not generally add any other window. So from where did this window come?
UIWindow is just a UIView subclass that doesn't need to be added to any existing view hierarchy. While there's only one by default in an iOS application, it's not uncommon to use UIWindow instances for things like status bar overlays and full-screen overlays.
I want to detect when any notification of any app comes in.
I was looking for a sort of "window will open" event, to detect when the notification window pops up, but as far as I can see there is no such thing.
Would it be possible to use the "viewWillStartLiveResize" in some way or another for this purpose ?
Or is there any other way to detect a screen change event?
viewWillTransitionToSize:withTransitionCoordinator: or traitCollectionDidChange: should be enough to detect app screen size change (especially on an ipad split mode). But in your case that's not possible - you have an access to your and only your app views hierarchy. Push notification windows pops up over your app on a springboard view hierarchy. So as notification center, etc. They just don't resize your app's window, they overlap it.
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.
i have taken a .Storyboard Project and for video playing i am using separate .XIB file.
When i add a view player xib on my storyboard content view, it played video well
But, when i enter to fullscreen mode and come back, content of the previous view is getting clear/nil.
Can anybody help!
Thanks
it seems like you are loosing strong references to you view controller contents . make them strong to keep the reference.
example-
property(nonatomic, strong) UIImageView *imageView;// for example only
by this you will not loose this object(imageView) until the controller is present in memory.
i don't know without your code. so what you have mistaken. here is my guessing answer for you
fullscreen
A Boolean that indicates whether the movie player is in full-screen mode.
#property (nonatomic, getter=isFullscreen) BOOL fullscreen
Discussion
The default value of this property is NO. Changing the value of this property causes the movie player to enter or exit full-screen mode immediately. If you want to animate the transition to full-screen mode, use the setFullscreen:animated: method instead.
Whenever the movie player enters or exits full-screen mode, it posts appropriate notifications to reflect the change. For example, upon entering full-screen mode, it posts MPMoviePlayerWillEnterFullscreenNotification and MPMoviePlayerDidEnterFullscreenNotification notifications. Upon exiting from full-screen mode, it posts MPMoviePlayerWillExitFullscreenNotification and MPMoviePlayerDidExitFullscreenNotification notifications.
The value of this property may also change as a result of the user interacting with the movie player controls.
reference by apple doc
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.