2012-02-27 4 views
10

Я использую UIWebView для воспроизведения видео на YouTube в iPad.Обнаружение UIWebView для воспроизведения youtube видео на iPad

Как определить, когда видеоролик YouTube закончен? Я вижу значок воспроизведения в строке состояния, и я пытался использовать MPMusicPlayerController уведомления для обнаружения playbackStateDidChange, но это не сработало.

Любые идеи, как обнаружить это событие? Опять же, я говорю о iPad, а не о iPhone.

Заранее спасибо.

Update:

Если вы используете нулевое решение для обнаружения конца игры, а также хотят видео Youtube, чтобы начать автоматически установить UIWebView на:

self.webView.mediaPlaybackRequiresUserAction = NO ; 

Я просто хочу уточнить, о API-интерфейс YouTube:

Важно: Это экспериментальная функция, что означает, что она может быть неожиданно измениться»(08/05/2012)

ответ

15

Нет, нет никакого способа, чтобы непосредственно получить событие веб-страницы из UIWebView. Но мы можем это сделать, используя Javascript.

  • Сначала вы используете встроенный Javascript в свой собственный HTML-код, чтобы обнаружить событие окончания видео.
  • Затем вы пытаетесь загрузить запрограммированный по схеме запрос с использованием JavaScript, и UIWebView может поймать запрос.

Эти ссылки могут помочь:

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

  2. Javascript callback in Objective-C

  3. YouTube iFrame API

обновляется с Пример:

в делегатом UIWebView, я поставил:

#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; 

}

веб-страницы нагрузки при viewDidLoad:

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

и в YouTube.HTML я поставил:

<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> 

вы можете увидеть я добавить

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

для IFrame API демо на YouTube, и он ловит конец игрок играет событие и попытаться загрузить запрос со схемой «обратного вызова», то делегат UIWebView может его поймать.

Вы можете использовать этот метод для запуска любого события с использованием JavaScript;

+0

Но это зависит от того, поддерживает ли youtube плеер такое событие, нет? Вам это удалось? – user1105951

+0

@ user1105951 yes, youtube player end end event, называемый onStateChange, и вы должны добавить слушателя к нему, следуя API YouTube JavaScript [JavaScript JavaScript API - События] (https://developers.google.com/youtube/js_api_reference#Events) – ZeR0

+0

@Zero, я проверяю вашу ссылку, и я помню, как он тестировал ее. попробуйте запустить эту демонстрационную версию https://developers.google.com/youtube/youtube_player_demo -ON В веб-браузере IPAD-safari, и вы увидите: «вам нужен флеш-плеер 9+, а javascript включен для просмотра этого видео». – user1105951

3

Вот @ фантастический ответ нуля в качестве полноценного класса для вашего использования:

@interface YouTubeWebView() <UIWebViewDelegate> 

@end 


@implementation YouTubeWebView 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self == nil) return nil; 

    self.mediaPlaybackRequiresUserAction = NO; 
    self.delegate = self; 
    self.alpha = 0; 

    return self; 
} 

- (void)loadVideo:(NSString *)videoId 
{ 
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"youtube" ofType:@"html"]; 
    // if (filePath == nil) 

    NSError *error; 
    NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error]; 
    // TODO: error check 

    string = [NSString stringWithFormat:string, videoId]; 

    NSData *htmlData = [string dataUsingEncoding:NSUTF8StringEncoding]; 
    // if (htmlData == nil) 

    NSString *documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; 
    NSString *targetPath = [documentsDirectoryPath stringByAppendingPathComponent:@"youtube.html"]; 
    [htmlData writeToFile:targetPath atomically:YES]; 

    [self loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:targetPath]]]; 
} 

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{ 
    if ([[[request URL] scheme] isEqualToString:@"callback"]) { 
     [self removeFromSuperview]; 

     NSString *documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; 
     NSString *targetPath = [documentsDirectoryPath stringByAppendingPathComponent:@"youtube.html"]; 
     NSError *error; 
     [[NSFileManager defaultManager] removeItemAtPath:targetPath error:&error]; 
//  TODO: error check 
    } 

    return YES; 
} 

Просто использовать эту версию youtube.html, которая имеет код замещения (%@) вместо видео ид :

<html> 
<head><style>body{margin:0px 0px 0px 44px;}</style></head> 
<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: '320', 
     width: '480', 
     videoId: '%@', 
     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"; 
    }; 
    } 
    function stopVideo() { 
    player.stopVideo(); 
    } 
</script> 
</body> 
</html> 

Единственное серьезное препятствие, которое мне пришлось преодолеть для реализации этого, это загрузить файл в виде строки, чтобы сделать замену. К сожалению, его нужно снова записать в качестве файла для автоматического запуска. Если это не обязательно для вашего случая использования, не стесняйтесь загружать HTML в веб-представление непосредственно в виде строки.

+0

Почему вы не передаете идентификатор видео в качестве параметра функции javascript и не вызываете эту функцию для загрузки видео? –

11

пожалуйста refere к:

https://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVPlayerItem_Class/Reference/Reference.html

есть уведомление доступны IOS 4.0, который можно использовать для обнаружения Youtube видео доиграть

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(youTubePlayed:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 
+0

полезно перезагрузить страницу youtube при завершении видео, иначе будет показано связанное видео, предоставленное youtube. – chings228

+3

Не тратьте время на поиск других решений. Это работает как шарм, и это всего лишь строка кода. Во всяком случае, это вызов наблюдателя, только для справки - (void) youTubePlayed: (id) sender –

+0

Работает в iOS 8 .. –

0

Вот Swift 3 ответ

NotificationCenter.default.addObserver(
    self, 
    selector: #selector(self.videoEnded), 
    name: .AVPlayerItemDidPlayToEndTime, 
    object: nil) 


} 

func videoEnded(){ 
    print("video ended") 
} 
Смежные вопросы