Подтвердить что ты не робот

Воспроизведение видео на YouTube на iOS6 (отлично работает на iOS5)

В моем приложении у меня есть кнопка, которая при нажатии позволяет смотреть видео с YouTube (трейлер фильма). В приложении, без запуска сафари. Ниже вы можете увидеть фрагмент кода. Этот код работает правильно под iOS5. Однако в iOS 6 UIButton в findButtonInView всегда равен нулю. Какие идеи могут быть причиной?

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

Ответ 1

Apple изменила обработку видео YouTube в iOS6. Я также использовал метод findButtonInView, но это больше не работает.

Я обнаружил, что, похоже, работает (непроверено в iOS < 6):

- (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();\
     "];
}

Ответ 2

Решение 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();\
     "];
}

Ответ 3

Я решил проблемы с 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;
}

Ответ 4

Неподтвержденный и не уверен, что это проблема, потому что я не знаю URL, который вы используете. Но я сразу споткнулся о следующем:

Как и в iOS 6, встроенные URL-адреса YouTube в форме http://www.youtube.com/watch?v=oHg5SJYRHA0 больше не будут работать. Эти URL-адреса предназначены для просмотра видео на сайте YouTube, а не для встраивания в веб-страницы. Вместо этого здесь описывается формат, который должен использоваться: https://developers.google.com/youtube/player_parameters.

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

Ответ 5

Я работаю над этой же общей проблемой, и я поделюсь подходом, который я придумал. У меня есть некоторые оставшиеся изломы, чтобы разобраться в моей конкретной ситуации, но общий подход может работать для вас, в зависимости от требований к пользовательскому интерфейсу.

Если вы структурируете код встраивания HTML, чтобы игрок YouTube покрывал все границы UIWebView, UIWebView фактически становится большой кнопкой воспроизведения - прикосновение в любом месте на поверхности приведет к запуску видео в собственный медиаплеер. Чтобы создать свою кнопку, просто закройте UIWebView с UIView, у которого userInteractionEnabled установлено значение NO. Неважно, какой размер UIWebView находится в этой ситуации? Не совсем так, потому что видео все равно откроется в родном проигрывателе.

Если вы хотите, чтобы пользователь воспринимал область вашего пользовательского интерфейса как место, где будет воспроизводиться видео, вы можете взять миниатюру для видео с YouTube и поместить его где угодно. Если нужно, вы можете поместить второй UIWebView за этот вид, поэтому, если пользователь коснется этого представления, видео также запустится или просто распространит другой UIWebView, чтобы он "отставал" от обоих этих видов.

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

Ответ 6

Я обнаружил, что приведенный ниже код работает как для iOS5, так и для iOS6. В моем примере у меня есть текстовое поле, содержащее URL-адрес видео. Сначала я конвертирую форматы в одну и ту же начальную строку "http://m...". Затем я проверяю, является ли формат старым форматом с "watch? V =", а затем заменяет его новым форматом Я тестировал это на iPhone с iOS5 и в симуляторах 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];
}

Ответ 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]; }

Мне пришлось использовать url http://www.youtube.com/watch?v=videoid, это единственный способ, которым он будет работать для меня

Ответ 8

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