How to receive NSNotifications from UIWebView embedded YouTube video playback How to receive NSNotifications from UIWebView embedded YouTube video playback ios ios

How to receive NSNotifications from UIWebView embedded YouTube video playback


There are no documented notifications sent by the UIWebView embedded movie player.

In fact, the closed implementation used within the UIWebView does differ from the public MPMoviePlayerController in many aspects (e.g. DRM).

The most important classes used for playing video content within that UIWebView are called MPAVController and UIMoviePlayerController. The latter one makes the player appear like the MPMoviePlayerController fullscreen interface.

In case you dare to risk a rejection by Apple, there are actually ways to still achieve what you are looking for.

NOTE This is not documented and is subject to break on each and every new iOS release. It does however work on iOS4.3, 5.0 and 5.01, 5.1 and 6.0 and it may work on other versions as well.

I am not able to test this solution on iOS 4.1 and 4.2, so that is up to you to do. I highly suspect that it will work.


Fullscreen State

If, for example you are intending to react upon the user tapping the DONE button, you may be able to do it this way:

UPDATE The old version of this answer recommended to use UIMoviePlayerControllerDidExitFullscreenNotification whereas this new version (updated for iOS6) recommends using UIMoviePlayerControllerWillExitFullscreenNotification.

C-Language Level:

void PlayerWillExitFullscreen (CFNotificationCenterRef center,                 void *observer,                 CFStringRef name,                 const void *object,                 CFDictionaryRef userInfo){    //do something...}CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),     NULL,     PlayerWillExitFullscreen,     CFSTR("UIMoviePlayerControllerWillExitFullscreenNotification"),     NULL,      CFNotificationSuspensionBehaviorDeliverImmediately);

Objective-C Level:

- (void)playerWillExitFullscreen:(NSNotification *)notification{    //do something...}[[NSNotificationCenter defaultCenter] addObserver:self                                         selector:@selector(playerWillExitFullscreen:)                                             name:@"UIMoviePlayerControllerWillExitFullscreenNotification"                                            object:nil];

I did draft both, C-Level and Objective-C-Level options because the best way to actually find out about all of this is to use C-Level (CoreFoundation) functions as shown at the end of my answer. If the sender of a notification does not use Objective-C (NSNotifications), you may actually not be able to trap them using the NSNotification-mechanics.


Playback State

For examining the playback state, look out for "MPAVControllerPlaybackStateChangedNotification" (as drafted above) and examine the userInfo which may look like this:

{    MPAVControllerNewStateParameter = 1;    MPAVControllerOldStateParameter = 2;}

Further Reverse Engineering

For reverse engineering and exploring all the notifications sent, use the following snippet.

void MyCallBack (CFNotificationCenterRef center,                 void *observer,                 CFStringRef name,                 const void *object,                 CFDictionaryRef userInfo){    NSLog(@"name: %@", name);    NSLog(@"userinfo: %@", userInfo);}CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(),     NULL,     MyCallBack,     NULL,     NULL,      CFNotificationSuspensionBehaviorDeliverImmediately);


In iOS 4.3+ you can use the UIMoviePlayerControllerDidEnterFullscreenNotification and UIMoviePlayerControllerDidExitFullscreenNotification notifications:

-(void)viewDidLoad{    ...    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(youTubeStarted:) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil];    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(youTubeFinished:) name:@"UIMoviePlayerControllerDidExitFullscreenNotification" object:nil];}-(void)youTubeStarted:(NSNotification *)notification{    // your code here}-(void)youTubeFinished:(NSNotification *)notification{    // your code here}


As far as I know, the implementation details of UIWebView (and all system classes made by Apple) are not to be relied upon when making a Cocoa Touch application. Maybe it's the case that an UIWebView's video player is not a standard MPMoviePlayerController class and it might have a totally different delegation/notification system, which is not supposed to be accessible by the user.

I suggest you to use the HTML5 element and detect the "onended" event of this tag:

<html>    <body>        <script>function endMovie() {    // detect the event here    document.location.href="somefakeurlscheme://video-ended";}        </script>        <video src="http://youtube.com/watch?v=aiugvdk755f" onended="endMovie()"></video>    </body></html>

In fact, from the endMovie JavaScript function, you can redirect to a bogus URL which you can catch in your -webView:shouldStartLoadWithRequest: (UIWebViewDelegate) method thus get notified that the video has ended:

- (BOOL) webView:(UIWebView *)wv shouldStartLoadWithRequest:(NSURLRequest *)req {    if ([[[req URL] absoluteString] hasPrefix:@"somefakeurlscheme://video-ended"]) {        [self someMethodSupposedToDetectVideoEndedEvent];        return NO; // prevent really loading the URL    }    return YES; // else load the URL as desired}

Hope this helps.