Search code examples
objective-cipadyoutubeuiwebview

Detecting UIWebView finish to play youtube video on iPad


I'm using UIWebView to play YouTube videos in an iPad.

How can I detect when a YouTube video is finished playing? I see the play icon in the status bar and I tried to use MPMusicPlayerController notifications to detect playbackStateDidChange, but it didn't work.

Any ideas how to detect this event? Again, I'm talking about iPad not iPhone.

Thanks in advance.

Update:

If you use zero solution to detect the end of playing and also want the Youtube video to start automatically set the UIWebView to :

self.webView.mediaPlaybackRequiresUserAction = NO ;

I just want to clarify about the YouTube frame API:

"Important: This is an experimental feature, which means that it might change unexpectedly" (08/05/2012)


Solution

  • No, there's no way to directly get web page event from UIWebView. But we can accomplish this by using Javascript.

    • First you use embed Javascript in your custom HTML, to detect video ending play event.
    • Then you try to load a scheme-customized request using JavaScript, and UIWebView could catch the request.

    These links may help:

    1. Calling Objective-C from JavaScript in an iPhone UIWebView

    2. Javascript callback in Objective-C

    3. YouTube iFrame API

    updated with an example:

    in UIWebView's delegate, i put:

    #pragma - mark WebView Delegate
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    
    
    if ( [[[request URL] scheme] isEqualToString:@"callback"] ) {
    
        NSLog(@"get callback");
    
        return NO;
    }
    
    return YES;
    

    }

    the web page is load when viewDidLoad:

    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle       mainBundle] pathForResource:@"youtube" ofType:@"html" ]]]];
    

    and in youtube.html i put:

    <html>
    <body>
    <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
    <div id="player"></div>
    
    <script>
    
      // 2. This code loads the IFrame Player API code asynchronously.
      var tag = document.createElement('script');
      tag.src = "http://www.youtube.com/player_api";
      var firstScriptTag = document.getElementsByTagName('script')[0];
      firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    
      // 3. This function creates an <iframe> (and YouTube player)
      //    after the API code downloads.
      var player;
      function onYouTubePlayerAPIReady() {
        player = new YT.Player('player', {
          height: '390',
          width: '640',
          videoId: 'u1zgFlCw8Aw',
          events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });
      }
    
      // 4. The API will call this function when the video player is ready.
      function onPlayerReady(event) {
        event.target.playVideo();
      }
    
      // 5. The API calls this function when the player's state changes.
      //    The function indicates that when playing a video (state=1),
      //    the player should play for six seconds and then stop.
      var done = false;
      function onPlayerStateChange(event) {
    
        if (event.data == YT.PlayerState.PLAYING && !done) {
          setTimeout(stopVideo, 6000);
          done = true;
        }
        if (event.data == YT.PlayerState.ENDED) {
          window.location = "callback:anything"; //here's the key
        };
      }
      function stopVideo() {
        player.stopVideo();
      }
    </script>
    </body>
    </html>
    

    you can see i add

    if (event.data == YT.PlayerState.ENDED) {
          window.location = "callback:anything";
        };
    

    to YouTube's iFrame API demo, and it catches the player end playing event and try to load a request with scheme "callback", then the UIWebView Delegate could catch it.

    You can use this method to trigger any event using JavaScript;