2012-02-27 18 views
10

Sto utilizzando UIWebView per riprodurre video di YouTube in un iPad.Rilevamento della finitura di UIWebView per riprodurre i video di YouTube su iPad

Come posso rilevare quando un video di YouTube è finito? Vedo l'icona di riproduzione nella barra di stato e ho provato a utilizzare le notifiche MPMusicPlayerController per rilevare playbackStateDidChange, ma non ha funzionato.

Qualche idea su come rilevare questo evento? Ancora una volta, sto parlando di iPad non iPhone.

Grazie in anticipo.

Aggiornamento:

Se si utilizza una soluzione a zero per rilevare la fine del gioco e vogliono anche il video di YouTube per avviare impostare automaticamente la UIWebView a:

self.webView.mediaPlaybackRequiresUserAction = NO ; 

Voglio solo chiarire su l'API della cornice YouTube:

"Importante: questa è una funzione sperimentale, il che significa che potrebbe cambiare in modo imprevisto"(08/05/2012)

risposta

15

No, non c'è alcun modo per ottenere direttamente evento pagina web da UIWebView. Ma possiamo farlo usando Javascript.

  • Per prima cosa si utilizza il codice JavaScript incorporato nel codice HTML personalizzato, per rilevare il video che termina l'evento di riproduzione.
  • Quindi si tenta di caricare una richiesta personalizzata di schema utilizzando JavaScript e UIWebView potrebbe ricevere la richiesta.

Questi link possono aiutare:

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

  2. Javascript callback in Objective-C

  3. YouTube iFrame API

aggiornato con un Esempio:

nella delegato di UIWebView, ho messo:

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

}

la pagina web è carico quando viewDidLoad:

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

e youtube.html ho messo:

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

si può vedere aggiungo

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

al di YouTube iFrame API demo, e cattura la fine giocatore che gioca eventi e cercare di caricare una richiesta con schema "callback", allora il Delegato di UIWebView potrebbe prenderlo.

È possibile utilizzare questo metodo per attivare qualsiasi evento utilizzando JavaScript;

+0

Ma dipende se il player di youtube supporta tale evento, no? Hai avuto successo? – user1105951

+0

@ user1105951 sì, evento finale di supporto giocatore youtube denominato "onStateChange", e dovrai aggiungere un listener che segua l'API di YouTube JavaScript [API JavaScript di YouTube - Eventi] (https://developers.google.com/youtube/js_api_reference#Events – ZeR0

+0

@ Zero, controllo il tuo link e ricordo di averlo provato. prova a eseguire questa dimostrazione https://developers.google.com/youtube/youtube_player_demo -UN IL browser web IPAD- safari, e vedrai: "hai bisogno di Flash Player 9+ e javascript abilitato per vedere questo video". Il safari – user1105951

3

Ecco @ risposta fantastica a zero di come una classe a tutti gli effetti per l'uso:

@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; 
} 

Basta utilizzare questa versione di youtube.html, che ha un codice di sostituzione (%@) al posto del video 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> 

l'unico ostacolo maggiore ho dovuto superare per implementare questo stava caricando il file come una stringa per effettuare la sostituzione. Sfortunatamente deve essere scritto di nuovo come file per il funzionamento automatico. Se questo non è necessario per il tuo caso d'uso, sentiti libero di caricare l'HTML nella vista web direttamente come una stringa.

+0

perché non si passa l'id del video come parametro alla funzione javascript e si chiama quella funzione per caricare il video? –

11

Riferirsi ai:

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

c'è una notifica disponibile iOS 4.0, che può essere utilizzato per rilevare youtube finitura riproduzione video

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

è buono ricaricare la pagina di youtube quando il video finisce, altrimenti, mostrerà i video correlati forniti da youtube – chings228

+3

Non perdere tempo a provare altre soluzioni. Questo funziona come un fascino ed è solo una linea di codice. Comunque, questo è l'osservatore che viene chiamato, solo per riferimento - (void) youTubePlayed: (id) mittente –

+0

Works in iOS 8 .. –

0

Ecco uno Swift 3 risposta

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


} 

func videoEnded(){ 
    print("video ended") 
} 
Problemi correlati