如何从 UIWebView 嵌入式 YouTube 视频播放接收 NSNotifications [英] How to receive NSNotifications from UIWebView embedded YouTube video playback

查看:15
本文介绍了如何从 UIWebView 嵌入式 YouTube 视频播放接收 NSNotifications的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有收到关于 MPMoviePlayerController 的任何通知.我做错了什么?

I didn't received any notifications for MPMoviePlayerController. What am I doing wrong?

我使用以下逻辑.

我开始在 UIWebView 中播放 youtube 视频.UIWebView 调用标准的 MPMoviePlayerController.我不控制 MPMoviePlayerController 因为我没有实例化 MPMoviePlayerController.

I'm begining to play youtube video in UIWebView. UIWebView calls a standard MPMoviePlayerController. I don't control MPMoviePlayerController because I didn't instantiate MPMoviePlayerController.

我使用自动播放(1 秒延迟)运行 youtube 的剪辑:

I run youtube's clip with autoplay (1 second delay):

[self performSelector:@selector(touchInView:) withObject:b afterDelay:1];

我的代码是:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadStateDidChange:) name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidFinish:) name:MPMoviePlayerDidExitFullscreenNotification object:nil];

    [self embedYouTube];
}

- (void)loadStateDidChange:(NSNotification*)notification
{
    NSLog(@"________loadStateDidChange");
}

- (void)playbackDidFinish:(NSNotification*)notification
{
    NSLog(@"________DidExitFullscreenNotification");
}

- (void)embedYouTube
{
    CGRect frame = CGRectMake(25, 89, 161, 121);
    NSString *urlString = [NSString stringWithString:@"http://www.youtube.com/watch?v=sh29Pm1Rrc0"];

    NSString *embedHTML = @"<html><head>
    <body style="margin:0">
    <embed id="yt" src="%@" type="application/x-shockwave-flash" 
    width="%0.0f" height="%0.0f"></embed>
    </body></html>";
    NSString *html = [NSString stringWithFormat:embedHTML, urlString, frame.size.width, frame.size.height];
    UIWebView *videoView = [[UIWebView alloc] initWithFrame:frame];
    videoView.delegate = self;

    for (id subview in videoView.subviews)
        if ([[subview class] isSubclassOfClass: [UIScrollView class]])
            ((UIScrollView *)subview).bounces = NO;

            [videoView loadHTMLString:html baseURL:nil];
    [self.view addSubview:videoView];
    [videoView release];
}

- (void)webViewDidFinishLoad:(UIWebView *)_webView 
{
    UIButton *b = [self findButtonInView:_webView];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(touchInView:) object:b];
    [self performSelector:@selector(touchInView:) withObject:b afterDelay:1];
}

- (UIButton *)findButtonInView:(UIView *)view 
{
    UIButton *button = nil;

    if ([view isMemberOfClass:[UIButton class]]) {
        return (UIButton *)view;
    }

    if (view.subviews && [view.subviews count] > 0) 
    {
        for (UIView *subview in view.subviews) 
        {
            button = [self findButtonInView:subview];
            if (button) return button;
        }
    }
    return button;
}

- (void)touchInView:(UIButton*)b
{
    [b sendActionsForControlEvents:UIControlEventTouchUpInside];
}

更新:我正在创建播放 youtube 视频的应用程序.您可以运行播放列表,您将看到第一个视频.当第一个视频结束时,第二个视频开始自动播放,依此类推.

UPDATE: I'm creating application that plays youtube's video. You can run playlist and you will see first video. When first video has ended, second video begins play automatically and so on.

我需要支持 ios 4.1 及更高版本.

I need to support ios 4.1 and above.

UPDATE2: @H2CO3 我正在尝试使用您的 url-scheme,但它不起作用.没有在退出事件上调用委托方法.我添加了我的 html url 来记录.它是:

UPDATE2: @H2CO3 I'm trying to use your url-scheme, but it don't works. Delegate method didn't called on exit event. I added my html url to log. It is:

<html><head>    <body style="margin:0">    
<script>function endMovie() 
{document.location.href="somefakeurlscheme://video-ended";} 
 </script>      <embed id="yt" src="http://www.youtube.com/watch?v=sh29Pm1Rrc0"        
 onended="endMovie()" type="application/x-shockwave-flash"  
 width="161" height="121"></embed>  
 </body></html>

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

更新3@Till,我无法捕捉到 UIMoviePlayerControllerDidExitFullscreenNotification,但我发现了 MPAVControllerItemPlaybackDidEndNotification.MPAVControllerItemPlaybackDidEndNotification 在播放视频结束时出现.

UPDATE3 @Till, I cann't caught UIMoviePlayerControllerDidExitFullscreenNotification, but I found MPAVControllerItemPlaybackDidEndNotification. MPAVControllerItemPlaybackDidEndNotification appears when playback video is ended.

但我不明白如何接收 onDone 通知?

But I don't understand how do I catch onDone notifications?

推荐答案

UIWebView 嵌入式电影播放器​​没有发送记录的通知.

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

事实上,UIWebView 中使用的封闭实现在许多方面(例如 DRM)与公共 MPMoviePlayerController 不同.

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

用于在该 UIWebView 中播放视频内容的最重要的类称为 MPAVControllerUIMoviePlayerController.后者使播放器看起来像 MPMoviePlayerController 全屏界面.

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.

如果您敢冒被 Apple 拒绝的风险,实际上仍有办法实现您的目标.

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

注意这没有记录,并且可能会在每个新的 iOS 版本中中断.然而,它确实适用于 iOS4.3、5.0 和 5.01、5.1 和 6.0,并且它可能也适用于其他版本.

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.

我无法在 iOS 4.1 和 4.2 上测试此解决方案,所以这取决于您.我非常怀疑它会起作用.

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.

全屏状态

例如,如果您打算对用户点击完成按钮做出反应,您可以这样做:

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 建议使用此答案的旧版本 UIMoviePlayerControllerDidExitFullscreenNotification 而此新版本(针对 iOS6 更新)建议使用 UIMoviePlayerControllerWillExitFullscreenNotification.

C 语言级别:

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 级别:

Objective-C Level:

- (void)playerWillExitFullscreen:(NSNotification *)notification
{
    //do something...
}

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(playerWillExitFullscreen:)
                                             name:@"UIMoviePlayerControllerWillExitFullscreenNotification" 
                                           object:nil];

我确实起草了 C-Level 和 Objective-C-Level 选项,因为真正了解所有这些的最佳方法是使用 C-Level (CoreFoundation) 函数,如我的答案末尾所示.如果通知的发送者不使用 Objective-C (NSNotifications),您可能实际上无法使用 NSNotification-mechanics 捕获它们.

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.

播放状态

要检查播放状态,请注意 "MPAVControllerPlaybackStateChangedNotification"(如上所示)并检查 userInfo,它可能如下所示:

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

<小时>

进一步逆向工程

对于逆向工程和探索发送的所有通知,请使用以下代码段.

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

这篇关于如何从 UIWebView 嵌入式 YouTube 视频播放接收 NSNotifications的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆