Detect when a webview video becomes fullscreen on ios8

11,432

Solution 1

This is the work around I found for this..

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(VideoExitFullScreen:)
                                                 name:UIWindowDidBecomeVisibleNotification
                                               object:self.view.window];

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(VideoEnterFullScreen:)
                                                 name:UIWindowDidBecomeHiddenNotification
                                               object:self.view.window];

Solution 2

Swift 5.1:

NotificationCenter.default.addObserver(
    forName: UIWindow.didResignKeyNotification,
    object: self.view.window,
    queue: nil
) { notification in
    print("Video is now fullscreen")
}

NotificationCenter.default.addObserver(
    forName: UIWindow.didBecomeKeyNotification,
    object: self.view.window,
    queue: nil
) { notification in
    print("Video stopped")
}

Solution 3

update for Swift 4.2, iOS 12.1 and WKWebView:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    // listen for videos playing in fullscreen
    NotificationCenter.default.addObserver(self, selector: #selector(onDidEnterFullscreen(_:)), name: UIWindow.didBecomeVisibleNotification, object: view.window)

    // listen for videos stopping to play in fullscreen
    NotificationCenter.default.addObserver(self, selector: #selector(onDidLeaveFullscreen(_:)), name: UIWindow.didBecomeHiddenNotification, object: view.window)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    // remove video listeners
    NotificationCenter.default.removeObserver(self, name: UIWindow.didBecomeVisibleNotification, object: view.window)
    NotificationCenter.default.removeObserver(self, name: UIWindow.didBecomeHiddenNotification, object: view.window)
}

@objc func onDidEnterFullscreen(_ notification: Notification) {
    print("video is now playing in fullscreen")
}

@objc func onDidLeaveFullscreen(_ notification: Notification) {
    print("video has stopped playing in fullscreen")
}

Solution 4

@NorthBlast's answer works well for detecting any UIWindow appearing on top of the UIViewController that holds the UIWebView. Unfortunately, it's hard to filter what kind of UIWindow is (since, well... you can't really know if it is a video or some other kind of window).

There are 3 special cases I prefer to filter, in which you're sure they are NOT video player windows, those are:

1) _UIAlertControllerShimPresenterWindow, which is a kind of window that appears when using alerts (like UIAlertView).

2) UITextEffectsWindow, which appears when presenting special iOS windows (like the share window, UIActivityViewController).

3) UIRemoteKeyboardWindow which appears when presenting the keyboard (for some reason, this class only appeared to me when using Swift, but on Objective-C it didn't... no clue why is that).

So to subscribe to notifications, I use (just like @NorthBlast said):

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(windowDidBecomeActive:)
                                             name:UIWindowDidBecomeVisibleNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(windowDidBecomeHidden:)
                                             name:UIWindowDidBecomeHiddenNotification
                                           object:nil];

Then the implementations:

- (void)windowDidBecomeActive:(NSNotification *)notification {
    if ( [self isVideoPlayerWindow:notification.object] ) {
        // Do what's needed if it is a video
        // For example, on a live streaming radio app, I would stop the audio if a video is started
    }
}

- (void)windowDidBecomeHidden:(NSNotification *)notification {
    if ( [self isVideoPlayerWindow:notification.object] ) {
        // Do what's needed if it is a video
    }
}

- (BOOL)isVideoPlayerWindow:(id)notificationObject {
    /*
     Define non video classes here, add more if you need it
    */
    static NSArray *nonVideoClasses = @[
        @"_UIAlertControllerShimPresenterWindow",
        @"UITextEffectsWindow",
        @"UIRemoteKeyboardWindow"
    ];

    BOOL isVideo = YES;
    for ( NSString *testClass in nonVideoClasses ) {
        isVideo = isVideo && ! [notificationObject isKindOfClass:NSClassFromString(testClass)];
    }

    return isVideo;
}
Share:
11,432
eiprol
Author by

eiprol

Updated on June 05, 2022

Comments

  • eiprol
    eiprol about 2 years

    I have an app where users can open videos from UIWebview, including Youtube ones. In iOS7, I was able to get a notification when it started playing, or when it became full screen, which is vital for me to show certain options to the user and modify the interface.

    I used to use this:

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(VideoExitFullScreen:) name:@"UIMoviePlayerControllerDidExitFullscreenNotification" object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(VideoEnterFullScreen:) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
    

    However, since iOS8, I can't achieve this. It is like the notification is no longer triggered from UIWebview videos. However, it is still triggered from normal videos, non-Webview, as I've tested.

    Any idea of what have changed?

  • Igor Kulagin
    Igor Kulagin over 9 years
    I've found that UIWindowDidBecomeVisibleNotification is called when video starts to play fullscreen. And UIWindowDidBecomeHiddenNotification is called when video disappears.
  • Tobonaut
    Tobonaut over 7 years
    This will no longer work for iOS 9, etc. It's now deprecated.
  • Berry Blue
    Berry Blue over 7 years
    I'm trying this in iOS 10 but these notifications never get called for me. Anyone else with the same problem?
  • jeffctown
    jeffctown about 7 years
    @BerryBlue yep. Same problem. Did you ever find another way?
  • Pranav Kasetti
    Pranav Kasetti over 5 years
    The object: view.window sometimes will mean the notification will not be observed. We can pass nil for the object param, to always receive notifications.
  • Pranav Kasetti
    Pranav Kasetti over 5 years
    @BerryBlue remove the object:self.view.window, and replace with object: nil]
  • user25
    user25 over 5 years
    Well it doesn't work ok for YouTube iFrame inside UIWebView. It always calls both events where it becomes fullscreen or exists fullscreen
  • user25
    user25 over 5 years
    because we should use didBecomeVisibleNotification and didBecomeHiddenNotification
  • palmi
    palmi over 4 years
    Swift 5 ``` NotificationCenter.default.addObserver(forName: UIWindow.didResignKeyNotification, object: self.view.window, queue: nil) { _ in print("Video is now fullscreen") } NotificationCenter.default.addObserver(forName: UIWindow.didBecomeKeyNotification, object: self.view.window, queue: nil) { _ in print("Video stopped") } ```
  • Tieme
    Tieme over 4 years
    Updated for swift 5