5

I am having issues of capturing when the youtube player will enter in fullscreen or exit fullscreen in iOS 8 because these notifications were removed UIMoviePlayerControllerDidEnterFullscreenNotification and UIMoviePlayerControllerWillExitFullscreenNotification for this version OS version.

Because my app project is set to be only in portrait mode the video won't rotate to landscape mode when is playing which is really not too user friendly when watching a video on your device.

Usually the user would like to watch the video either in portrait mode or landscape mode when the video enters in fullscreen.

These is the way I was doing it for iOS 7 which was working perfect but not in iOS 8.

First, I will set this function in my AppDelegate.m with boolean property in my AppDelegate.h which I called videoIsInFullscreen and function,

// this in the AppDelegate.h
@property (nonatomic) BOOL videoIsInFullscreen;


// This in my AppDelegate.m to allow landscape mode when the boolean property is set to yes/true.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    if(self.videoIsInFullscreen == YES)
    {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    else
    {
        return UIInterfaceOrientationMaskPortrait;
    }
}

Then within my ViewController.m First, I would #import "AppDelegate.h" after doing this, I will add some notifications in my viewDidLoad method..

-(void)viewDidLoad {

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerStarted) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerEnded) name:@"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];

}

Of course don't forget to remove them..

-(void)dealloc {

    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIMoviePlayerControllerWillExitFullscreenNotification" object:nil];

}

Then, I had my functions that will get call when these notifications get fires... Here is where I allow the landscape mode and then set it back to portrait. These is the case with my app because it's only set to portrait support but I don't want this for the youtube videos.

// first we set our property in the our AppDelegate to YES to allow landscape mode
- (void)playerStarted
{
    ((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = YES;

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
}

// Then I will set the property to NO and force the orientation to rotate to portrait.
- (void)playerEnded
{       
    ((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = NO;

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
}

But, these is not the case for iOS 8.. These notifications no longer work for iOS 8 so, I found something similar using these notifications but I am not too happy because they are not 100% accurate for the video player. UIWindowDidBecomeVisibleNotification and UIWindowDidBecomeHiddenNotification So, how can I do this correctly or at least that works properly for my youtube embedded video and allow landscape mode in iOS 8...?

valbu17
  • 4,034
  • 3
  • 30
  • 41

2 Answers2

3

So, after some research and looking more in-depth to this problem.. I came to a solution using the UIWebView delegates, plus I had to solve another issue in terms of my function - (void)playerEnded which it wasn't working properly in the new iPhone 6 devices..

This is how I did it.. First, in my webViewDidFinishLoad method I have added to my webview a javascript evaluation to check when this video player goes into fullscreen mode..

- (void)webViewDidFinishLoad:(UIWebView*)webView
{
    // adding listener to webView
    [_webView stringByEvaluatingJavaScriptFromString:@" for (var i = 0, videos = document.getElementsByTagName('video'); i < videos.length; i++) {"
                                                     @"      videos[i].addEventListener('webkitbeginfullscreen', function(){ "
                                                     @"           window.location = 'videohandler://begin-fullscreen';"
                                                     @"      }, false);"
                                                     @""
                                                     @"      videos[i].addEventListener('webkitendfullscreen', function(){ "
                                                     @"           window.location = 'videohandler://end-fullscreen';"
                                                     @"      }, false);"
                                                     @" }"
                                                     ];
}

Then, in my - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType method, I check when my request url matches the state of the youtube player, like this.. This will fire our function to allow landscape mode or force back to portrait mode.. or maybe any other type of work you might want to do..

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{
    // allows youtube player in landscape mode
    if ([request.URL.absoluteString isEqualToString:@"ytplayer://onStateChange?data=3"])
    {
        [self playerStarted];

        return NO;
    }
    if ([request.URL.absoluteString isEqualToString:@"ytplayer://onStateChange?data=2"])
    {
        [self playerEnded];

        return NO;
    }
}

And finally, I needed to adjust my playerEnded function to force back portrait mode for iPhone 6 devices..

- (void)playerEnded
{
    [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:@"orientation"];

    ((AppDelegate*)[[UIApplication sharedApplication] delegate]).videoIsInFullscreen = NO;

    [self supportedInterfaceOrientations];

    [self shouldAutorotate:UIInterfaceOrientationPortrait];

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
}

Almost, missed I also added these two other functions..

- (NSInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

- (BOOL)shouldAutorotate:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

So, finally I am able to catch the state of the actual player and fire my functions to do some work or whatever I want at the right moment, in my case changing the orientation..

I hope this helps someone else..

valbu17
  • 4,034
  • 3
  • 30
  • 41
  • tried it - not reaching -playerStarted and player ended. equest.URL.absoluteString is mainly about:blank and http://www.youtube.com/embed/..... - and that's before playing the video. When the video plays shouldStartLoadWithRequest is firing. any ideas? – Boaz Nov 05 '14 at 21:06
  • shouldStartLoadWithRequest will get fire when the video plays and you can catch the state as shown above.. I'm not sure if I'm understanding your question correctly. In there is no notifications involve.. this works if you are using the youtube embedded video within an iframe in a webview.. – valbu17 Nov 05 '14 at 21:45
  • well, it doesnt :( I've put NSLog(@"URL: %@",request.URL.absoluteString); in the beginning of the function and I get no prints when clicking play – Boaz Nov 05 '14 at 22:10
  • Mmm.. that's pretty interesting can you actually make a question for it with your code and more in details to see what's the problem.. I'm guessing it should be the configuration of the youtube player in your iframe... I have a javascript which creates the player and loads the video and so on... – valbu17 Nov 07 '14 at 18:58
  • hmm... js to load youtube? I'm just doing loadHTMLString with @"". Can you post your js init in a pastebin or something? – Boaz Nov 08 '14 at 07:41
  • please refer to the [youtube api](https://developers.google.com/youtube/iframe_api_reference) for that.. They have examples and so on.. The way you are doing it, youtube gets all the control of the player because you are not setting anything, so it gets set by youtube js api.. – valbu17 Nov 13 '14 at 18:05
0

I am working on swift, I my player runs movie in both portrait and landscape direction. First I checked three modes : portrait, landscapeleft, landscaperight. Second I wrote this function in all viewController:

 isFullScreen = false
override func shouldAutorotate() -> Bool {
    if isFullScreen == true {
        return true
    }else{
        return false
    }
}

Third I change the value of isFullScreen in this function:

func playerView(playerView: YTPlayerView!, didChangeToState state: YTPlayerState) {
    switch (state) {
        case  YTPlayerState.Playing:
                println("started to play")
        isFullScreen == true
        shouldAutorotate()
        case YTPlayerState.Paused:
                println("paused")
        default:
            println("non of sttate")
        break
    }
}

And video runs on both portrait and landscape mode! The interesting thing is that I dont set isFullScreen to false again when I pause video or move from fullscreen. However it doesnt rotate! Can somebody explain this?

Yestay Muratov
  • 1,338
  • 2
  • 15
  • 28