【问题标题】:YouTube video playback broken on iOS6 (works fine on iOS5)iOS6 上的 YouTube 视频播放中断(在 iOS5 上运行良好)
【发布时间】:2012-09-09 20:01:13
【问题描述】:

在我的应用程序中,我有一个按钮,按下该按钮后,您可以观看 youtube 视频(电影预告片)。在应用程序内,无需启动 safari。下面你可以看到一个代码sn-p。此代码在 iOS5 下运行良好。但是,在 iOS 6 中,findButtonInView 中的 UIButton 始终为 nil。任何想法可能是什么原因?

youtubeWebView.delegate = self;
youtubeWebView.backgroundColor = [UIColor clearColor];

NSString* embedHTML = @" <html><head> <style type=\"text/css\"> body {background-color: transparent;  color: white; }</style></head><body style=\"margin:0\"><embed id=\"yt\" src=\"%@?version=3&app=youtube_gdata\" type=\"application/x-shockwave-flash\"width=\"%0.0f\" height=\"%0.0f\"></embed></body></html>";

NSURL *movieTrailer;

if(tmdbMovie) movieTrailer = tmdbMovie.trailer;

else movieTrailer = [NSURL URLWithString:movie.trailerURLString];

NSString *html = [NSString stringWithFormat:embedHTML,
                                            movieTrailer,
                                            youtubeWebView.frame.size.width,
                                            youtubeWebView.frame.size.height];

[youtubeWebView loadHTMLString:html baseURL:nil];

[self addSubview:youtubeWebView];


- (void)webViewDidFinishLoad:(UIWebView *)_webView {

    isWatchTrailerBusy = NO;

    [manager displayNetworkActivityIndicator:NO];

    //stop the activity indicator and enable the button

     UIButton *b = [self findButtonInView:_webView];

    //TODO this returns null in case of iOS 6, redirect to the youtube app

    if(b == nil) {

        NSURL *movieTrailer;

        if(tmdbMovie) {
            movieTrailer = tmdbMovie.trailer;
        } else {
            movieTrailer = [NSURL URLWithString:movie.trailerURLString];
        }

        [[UIApplication sharedApplication] openURL:movieTrailer];

    } else {
        [b sendActionsForControlEvents:UIControlEventTouchUpInside];
    }
}


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

【问题讨论】:

  • 我正在使用新的 HTML iFrame API(这是 BTW 推荐的方式)来嵌入 youtube 视频,而这种自动播放技术 findButtonInView 从来没有为我工作过(返回 null)。
  • @MSK 您是否有一个教程链接或使用 iframe 的代码 sn-p?谢谢
  • 看我的问答here
  • 谢谢。所以这意味着不可能在应用内按下按钮来观看 youtube 视频?
  • 它从来没有为我工作过,而且它是一种黑客,不能保证它会在下一次操作系统更新时工作。

标签: iphone ios youtube ios6


【解决方案1】:

Apple 更改了 iOS6 中处理 YouTube 视频的方式。我也在使用 findButtonInView 方法,但它不再有效。

我发现以下似乎可行(在 iOS

- (void)viewDidLoad 
{
    [super viewDidLoad];
    self.webView.mediaPlaybackRequiresUserAction = NO;
}

- (void)playVideo
{
    self.autoPlay = YES;
    // Replace @"y8Kyi0WNg40" with your YouTube video id
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@", @"http://www.youtube.com/embed/", @"y8Kyi0WNg40"]]]];
}

// UIWebView delegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (self.autoPlay) {
        self.autoPlay = NO;
        [self clickVideo];
    }
}

- (void)clickVideo {
    [self.webView stringByEvaluatingJavaScriptFromString:@"\
        function pollToPlay() {\
            var vph5 = document.getElementById(\"video-player\");\
            if (vph5) {\
                vph5.playVideo();\
            } else {\
                setTimeout(pollToPlay, 100);\
            }\
        }\
        pollToPlay();\
     "];
}

【讨论】:

  • 我修改了 javascript 代码以轮询元素,直到它在发送点击事件之前可用。当我在某些设备上看到它时,这解决了这个问题。如果这有帮助,请告诉我!
  • 嗯,嗯,它适用于我的 iPhone 4s、iPhone 5 和 iPad。如果我找到更好的方法,我会更新。
  • 我可以确认这在我的 iPhone4S 上的 iOS6 上对我有效!唯一的问题是,您必须等待几秒钟才能工作,但它确实有效!
  • 我可以确认它也适用于我。两者,在 iPad 和 iPhone(运行 iOS6)上
  • 当我们观看第一个视频时,它正在工作。当我点击第二个视频时,上面的代码对我不起作用。我需要添加任何额外的参数吗?
【解决方案2】:
- (void) performTapInView: (UIView *) view {
    BOOL found = NO;
    if ([view gestureRecognizers] != nil) {
        for (UIGestureRecognizer *gesture in  [view gestureRecognizers]) {
            if ([gesture isKindOfClass: [UITapGestureRecognizer class]]) {
                if ([gesture.view respondsToSelector: @selector(_singleTapRecognized:)]) {
                    found = YES;
                    [gesture.view performSelector: @selector(_singleTapRecognized:) withObject: gesture afterDelay: 0.07];
                    break;
                }
            }
        }
    }

    if (!found) {
        for (UIView *v in view.subviews) {
            [self performTapInView: v];
        }
    }
}
#pragma mark - UIWebViewDelegate methods
- (void) webViewDidFinishLoad: (UIWebView *) webView {
    if (findWorking) {
        return;
    }
    findWorking = YES;
    [self performTapInView: webView];
}

【讨论】:

  • iOS 6.0 现在使用手势检测用户点击,检测到点击后使用html5自动播放。
  • 我不知道苹果是否会批准这个,今天会尝试提交一个带有这个代码的版本。会及时通知你们。
  • 史蒂夫你很幸运,我的应用程序刚刚使用此代码被拒绝。它说我使用了一个名为 _singleTapRecognized 的非公共 API:所以我可以建议人们不要使用这段代码!
  • 我们的应用也被拒绝了!这是苹果的推理:我们发现您的应用使用了一个或多个非公共API,这不符合应用商店审查指南。不允许使用非公共 API,因为如果这些 API 发生变化,可能会导致糟糕的用户体验。我们在您的应用中发现了以下非公共 API:_singleTapRecognized:
  • 有人在
【解决方案3】:

未经测试,不确定这是否是这里的问题,因为我不知道您使用的 URL。但是我偶然发现了以下内容:

从 iOS 6 开始,http://www.youtube.com/watch?v=oHg5SJYRHA0 形式的嵌入式 YouTube URL 将不再有效。这些 URL 用于查看 YouTube 网站上的视频,而不是用于嵌入网页。相反,这里描述了应该使用的格式:https://developers.google.com/youtube/player_parameters。

来自http://thetecherra.com/2012/09/12/ios-6-gm-released-full-changelog-inside/

【讨论】:

    【解决方案4】:

    我正在解决同样的一般问题,我将分享我提出的方法。对于我的特殊情况,我还有一些问题需要解决,但一般方法可能适合您,具体取决于您的 UI 要求。

    如果您构建 HTML 嵌入代码以使 YouTube 播放器覆盖 UIWebView 的整个边界,则 UIWebView 有效地成为一个大播放按钮 - 触摸其表面上的任何位置都会使视频启动到本机媒体播放器。要创建您的按钮,只需使用将 userInteractionEnabled 设置为 NO 的 UIView 覆盖 UIWebView。在这种情况下 UIWebView 的大小是否重要?不是真的,因为无论如何视频都会在本机播放器中打开。

    如果您希望用户将 UI 的某个区域视为视频将要“播放”的位置,那么您可以从 YouTube 获取视频的缩略图并将其放置在任何位置。如果需要,您可以在该视图后面放置第二个 UIWebView,因此如果用户触摸该视图,视频也会启动 - 或者只是将另一个 UIWebView 展开,使其位于这两个视图的“后面”。

    如果您发布您的 UI 屏幕截图,我可以提出一些更具体的建议,但基本想法是通过在 UIWebView 前面放置一个禁用用户交互的视图来将其变成一个按钮。

    【讨论】:

      【解决方案5】:

      我发现下面的代码适用于 iOS5 和 iOS6。在我的示例中,我有一个包含视频 url 的文本字段。我首先将格式转换为相同的起始字符串“http://m...”。然后我检查格式是否是带有 'watch?v=' 的旧格式,然后用新格式替换它. 我已经在 iOS5 的 iPhone 和 iOS5 和 iOS6 的模拟器上测试过:

      -(IBAction)loadVideoAction {
          [activityIndicator startAnimating];
      
          NSString *urlString = textFieldView.text;
          urlString = [urlString stringByReplacingOccurrencesOfString:@"http://www.youtube" withString:@"http://m.youtube"];
          urlString = [urlString stringByReplacingOccurrencesOfString:@"http://m.youtube.com/watch?v=" withString:@""];
          urlString = [NSString stringWithFormat:@"%@%@", @"http://www.youtube.com/embed/", urlString];
          [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];
      }
      
      - (void)webViewDidFinishLoad:(UIWebView *)webView
      {
          [activityIndicator stopAnimating];
      }
      

      【讨论】:

        【解决方案6】:

        dharmabruce 解决方案在 iOS 6 上运行良好,但为了使其在 iOS 5.1 上运行,我不得不将 javascript click() 替换为 playVideo(),并且我必须将 UIWebView 的 mediaPlaybackRequiresUserAction 设置为 NO

        这是修改后的代码:

        - (void)viewDidLoad 
        {
            [super viewDidLoad];
            self.webView.mediaPlaybackRequiresUserAction = NO;
        }
        
        - (void)playVideo
        {
            self.autoPlay = YES;
            // Replace @"y8Kyi0WNg40" with your YouTube video id
            [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@", @"http://www.youtube.com/embed/", @"y8Kyi0WNg40"]]]];
        }
        
        // UIWebView delegate
        - (void)webViewDidFinishLoad:(UIWebView *)webView {
            if (self.autoPlay) {
                self.autoPlay = NO;
                [self clickVideo];
            }
        }
        
        - (void)clickVideo {
            [self.webView stringByEvaluatingJavaScriptFromString:@"\
                function pollToPlay() {\
                    var vph5 = document.getElementById(\"video-player-html5\");\
                    if (vph5) {\
                        vph5.playVideo();\
                    } else {\
                        setTimeout(pollToPlay, 100);\
                    }\
                }\
                pollToPlay();\
             "];
        }
        

        【讨论】:

        • 这是第一次工作。如果我想观看另一个视频,上面的代码不起作用。为什么?
        【解决方案7】:

        我认为问题是当 webViewDidFinishLoad 被触发时,UIButton 还没有添加到视图中。在回调返回后,我实现了一个小的延迟来找到按钮,它适用于我在 ios5 和 ios6 上。缺点是延迟后无法保证 UIButton 已准备好被找到。

        - (void)autoplay {
            UIButton *b = [self findButtonInView:webView];
            [b sendActionsForControlEvents:UIControlEventTouchUpInside]; }
        
        - (void)webViewDidFinishLoad:(UIWebView *)_webView {
            [self performSelector:@selector(autoplay) withObject:nil afterDelay:0.3]; }
        

        我必须使用网址 http://www.youtube.com/watch?v=videoid 这是唯一适合我的方法

        【讨论】:

          【解决方案8】:

          我已经解决了 dharmabruce 和 JimmY2K 的问题。解决方案,事实上它只在第一次播放视频时才有效,正如 Dee

          所述

          这是代码(包括视频结束时的事件):

          - (void)embedYouTube:(NSString *)urlString frame:(CGRect)frame {
              videoView = [[UIWebView alloc] init];
              videoView.frame = frame;
              videoView.delegate = self;
          
              [videoView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]];// this format: http://www.youtube.com/embed/xxxxxx
              [self.view addSubview:videoView];
          
              //https://github.com/nst/iOS-Runtime-Headers/blob/master/Frameworks/MediaPlayer.framework/MPAVController.h
              [[NSNotificationCenter defaultCenter] addObserver:self
                                                       selector:@selector(playbackDidEnd:)
                                                           name:@"MPAVControllerItemPlaybackDidEndNotification"//@"MPAVControllerPlaybackStateChangedNotification"
                                                         object:nil];
          
          }
          
          
          - (void)webViewDidFinishLoad:(UIWebView *)webView {
              //http://stackoverflow.com/a/12504918/860488
              [videoView stringByEvaluatingJavaScriptFromString:@"\
                                              var intervalId = setInterval(function() { \
                                                  var vph5 = document.getElementById(\"video-player\");\
                                                  if (vph5) {\
                                                      vph5.playVideo();\
                                                      clearInterval(intervalId);\
                                                  } \
                                              }, 100);"];
          }
          
          - (void)playbackDidEnd:(NSNotification *)note
          {
              [videoView removeFromSuperview];
              videoView.delegate = nil;
              videoView = nil;
          }
          

          【讨论】:

          • 请写下你的地址,我想送你一份礼物!
          • 在这里不起作用。它可能工作过一次,但由于某种原因它不再工作了。我有你的确切代码! ios 6.1.x 在 iphone 和模拟器上试过了
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-01-29
          • 2013-02-09
          • 2011-06-26
          • 2013-11-19
          • 1970-01-01
          • 1970-01-01
          • 2017-12-23
          相关资源
          最近更新 更多