2012-02-27 109 views
10

我使用UIWebView在iPad中播放YouTube視頻。檢測UIWebView完成在iPad上播放YouTube視頻

如何檢測YouTube視頻播放完畢? 我在狀態欄中看到播放圖標,我試圖使用MPMusicPlayerController通知來檢測playbackStateDidChange,但它不起作用。

任何想法如何檢測此事件?再次,我談論的不是iPhone。

在此先感謝。

更新:

如果使用零解決方案來檢測的演奏結束,也希望Youtube視頻開始自動設置UIWebView到:

self.webView.mediaPlaybackRequiresUserAction = NO ; 

我只是想澄清有關YouTube框架API:

「重要提示:這是一個實驗性功能,這意味着它可能會 意外更改」(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"; 
    }; 

到YouTube的iframe API演示,並捕捉玩家打到底的事件並嘗試加載使用方案「回調」的要求,那麼UIWebView委託可以抓住它。

您可以使用此方法來使用JavaScript的任何事件;

+0

但它取決於如果YouTube播放器支持這樣的事件,不是嗎? 你成功了嗎? – user1105951 2012-05-07 12:53:22

+0

@ user1105951是,YouTube播放器支持結束事件稱爲「onStateChange」,你要添加一個偵聽它符合YouTube的JavaScript API [YouTube上的JavaScript API - 活動(https://developers.google.com/youtube/js_api_reference#Events ) – ZeR0 2012-05-07 15:46:32

+0

@Zero,我檢查你的鏈接,我記得alreay測試它。 嘗試運行這個演示https://developers.google.com/youtube/youtube_player_demo-ON THE IPAD- Safari網絡瀏覽器,你會看到:「您需要Flash Player 9+並啓用javascript才能觀看此視頻」。 – user1105951 2012-05-07 19:43:25

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的,它取代視頻ID的有一個替換代碼(%@) :

<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直接作爲字符串加載到Web視圖來代替。

+0

你爲什麼不傳視頻ID作爲參數傳遞給javascript函數,並調用該函數加載視頻? – 2015-07-21 13:27:11

11

請參考,以:

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 2013-05-10 02:43:16

+3

不要浪費時間去嘗試其他的解決方案相關的視頻。這個作品像魅力一樣,只是一行代碼。無論如何,這是被稱爲,僅供參考觀察者 - (空)youTubePlayed:(ID)發送 – 2013-09-06 10:23:33

+0

作品中的iOS 8 .. – 2014-11-07 10:38:18

0

這裏的斯威夫特3回答

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


} 

func videoEnded(){ 
    print("video ended") 
} 
相關問題