Автоматическое воспроизведение видео vimeo в веб-просмотре Android

Мне удалось загрузить и воспроизвести видео vimeo, используя следующее. Однако autoplay=1, как указано в документации vimeo oembed, не воспроизводится автоматически при загрузке. Кто-нибудь нашел способ автоматического воспроизведения (также нужно поймать событие, когда видео заканчивается)

mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setAppCacheEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);

// how plugin is enabled change in API 8
if (Build.VERSION.SDK_INT < 8) {
  mWebView.getSettings().setPluginsEnabled(true);
} else {
  mWebView.getSettings().setPluginState(PluginState.ON);
}
mWebView.loadUrl("http://player.vimeo.com/video/24577973?player_id=player&autoplay=1&title=0&byline=0&portrait=0&api=1&maxheight=480&maxwidth=800");

person scottyab    schedule 27.01.2012    source источник
comment
приведенный выше код работает без автозапуска??   -  person Venkat    schedule 10.04.2013
comment
Да, я также установил WebViewClient, который показывает/скрывает индикатор выполнения, не уверен, влияет ли на него настройка пользовательского WebViewClient?   -  person scottyab    schedule 11.04.2013
comment
но я много пробовал, используя ваш код. Но это не работает. поэтому я использую пользовательский веб-просмотр   -  person Venkat    schedule 22.04.2013


Ответы (5)


Этот ответ относится только к Vimeo. После примерно дюжины неудачных попыток вот что у меня работает. Возможно, это поможет кому-то еще. Тысяча извинений первоначальным авторам других ответов SO. Я «позаимствовал» несколько шаблонов ниже — просто подумал, что было бы удобно иметь все это в одном месте и не требовать их для своего собственного кода.

Во-первых, я не нашел способа встроить проигрыватель Vimeo (т. е. вы не можете получить доступ к потоку mp4 напрямую — по крайней мере, не легко и надежно — я почти уверен, что это сделано намеренно). Во-вторых, Vimeo предлагает библиотеку javascript для инструментов своего проигрывателя, и ее использование неизбежно. Осторожно, для этого требуется передача сообщений, что является новой функцией браузера. Это задокументировано на их странице API. В-третьих, как описано в другом месте на SO, вам нужно быть очень осторожным, чтобы дождаться готовности частей стека и не прыгать с пистолета. В-четвертых, проигрыватель Vimeo включает в себя особенно бесполезное фоновое изображение, означающее, что плагин отсутствует или сломан (небольшой кадр фильма, общий значок для этого). Что на самом деле означает, так это то, что ваш javascript где-то взорвался, и вообще ничего не работает. Если вы видите небольшой фрагмент пленки на пустом экране, проверьте свой javascript.

Шаг 1. Настройте WebView. У вас это правильно выше. Для справки, вот что я использовал.

mWebView = new WebView((Context) this);
mWebView.setLayoutParams(new LayoutParams(windowWidth, windowHeight));

mWebView.getSettings().setJavaScriptEnabled(true);
 // Watch the sdk level here, < 12 requires 'false
 // Wanted to force HTML5/264/mp4, you may want flash
 //    where still available
mWebView.getSettings().setPluginState(PluginState.OFF);
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setUserAgentString("Android Mozilla/5.0 AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");

wcc = new MyWebChromeClient();
mWebView.setWebChromeClient(wcc);

wvc = new MyWebViewClient();
mWebView.setWebViewClient(wvc);

Шаг 2. Вам нужен WebChromeClient, если вы хотите, чтобы видео работало в WebView. Это задокументировано здесь: http://developer.android.com/reference/android/webkit/WebView.html (см. Поддержка HTML-видео).

Опять же, для справки вот то, что я использовал.

private class MyWebChromeClient extends WebChromeClient {
    @Override
    public void onProgressChanged(WebView view, int progress) {
        if(progress == 100) {
          // Your page is loaded, but not visible,
          // add whatever navigation elements you plan to use here.
          // N.B. these are JAVA, not JS nav elements
        }
    }

    @Override
    public boolean onConsoleMessage(ConsoleMessage cm) {

     // I like to watch in the console. And, since it was
     // a very convenient way to monitor the javascript, I
     // use it for that too. Purists will object, no doubt

       if(cm.message().equalsIgnoreCase("EVENT -- Finish")) {
            Log.i(TAG, "---> Finishing . . .");
            // Depart the activity
            finish();
       } else {
            Log.d(TAG, " **Console ["+cm.sourceId()+"] ("+cm.lineNumber()+") ["+cm.message()+"]");
       }
       return(true);
   }

       @Override
       public View getVideoLoadingProgressView() {
                        // Something entertaining while the bytes arrive
            Log.i(TAG, " -------------> Loading Progress . . . ");
            LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            return(inflater.inflate(R.layout.loading_video, null));
       }

       @Override
       public void onShowCustomView(View v, WebChromeClient.CustomViewCallback callback) {
                       // With great sadness, I report that this never fires.
                       // Neither does the 'hide'.
       }

       @Override
       public void onHideCustomView() {
       }

}

WebViewClient выглядит так:

private class MyWebViewClient extends WebViewClient {

    @Override
    public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            String injection = injectPageMonitor();
            if(injection != null) {
            Log.d(TAG, " ---------------> Page Loaded . . .");
                Log.d(TAG, "  Injecting . . . ["+injection+"]");
                view.loadUrl(injection);
            }
    }

}

Шаг 3. Вам нужно создать небольшой фрагмент Javascript, чтобы запустить проигрыватель. Я использовал это:

public String injectPageMonitor() {
   return( "javascript:" +
               "jQuery(document).ready( function() { " +
               "console.log(' === Page Ready ===> Setting up');" +
               "console.log(' ==== Sending PLAY Command ===');" +
               "var froogaloop = $f('froog');" +
               "setTimeout(function() {  froogaloop.api('play'); }, 3000);" +
  "});");
}

Быстрое объяснение. . . Я использую jQuery в своем JS, это будет ниже. Это только для удобства, вы можете сделать прямой JS, если хотите облегчить нагрузку. Обратите внимание, что после того, как все остальное будет готово, скрипт ждет еще 3 секунды, прежде чем сработает. В моменты моей слабости я представляю, что у добрых людей в Vimeo есть неработающий обратный вызов «готово». 3 секунды, кажется, делают это.

Шаг 4. Вам нужно немного HTML и JavaScript на странице. Я поместил его в текстовый файл внутри ресурсов (raw/vimeo_frame.html). Файл выглядит так:

<!DOCTYPE html>
<html>
<head>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">jQuery.noConflict();</script>
<script src="http://a.vimeocdn.com/js/froogaloop2.min.js"></script>

<script type="text/javascript">

   jQuery(document).ready( function() { 
       var showing_player = false;
       var froogaloop = $f('froog');

           console.log(' === Page Ready ===> Setting up');
       jQuery('.froog_container_class').hide();
       jQuery('.console').css('height', '100%');

       froogaloop.addEvent('ready', function() { 

             console.log('====  PLAYER READY ====> Setting Play Callback');
                froogaloop.addEvent('play', function(data) { 
                console.log('EVENT -- Play');
                /* No idea why, but if the player isn't displayed, it goes
                   straight to 'pause'. Probably a feature. So I give it 4x4px
                   to do it's thing during setup */
                jQuery('.froog_container_class').show();
                jQuery('.froog_container_class').css('height', '4px');
                jQuery('.froog_container_class').css('width', '4px');
                jQuery('.froog_container_class').css('overflow', 'hidden');
            });

           /* I don't want to reveal the video until it is actually
              playing. So I do that here */
           var showingPlayer = false;
           froogaloop.addEvent('playProgress', function(data) {
               if(!showingPlayer && data.percent > 0) {
                  showingPlayer = true;
                  jQuery('.froog_container_class').show();
                  jQuery('.froog_container_class').css('height', '_windowHeight');
                  jQuery('.froog_container_class').css('width', '_windowWidth');
                  /* Most tablets I tested aren't quick enough to make this work
                     but one can still hope */
                  jQuery('#loading').fadeOut('slow');
               }
           });

       });
});
</script>
</head>
<body>
<style>
  body {
     background-image: url('http://<SomethingEntertainingToWatch>.png');
     background-size: contain;
  }
  .mask {
     float: left;
     height: _windowHeight;
     width: _windowWidth;
     z-index: 100;
     background: transparent;
     display: inline;
     position: absolute;
     top: 0;
     left: 0;
   }
   .froog_container_class {
      position: absolute;
      height: _windowHeight;
      width: _windowWidth;
      left: 0;
      top: 0;
      display: inline;
      z-index: 1;
    }
    #froog {
      display: inline;
      height: _windowHeight;
      width: _windowWidth;
      postion: absolute;
      top: 0;
      left: 0;
    }
</style>
<div id="loading" class="loading"><h1>Loading</h1><img class="loading_anim" src="http://foo.bar.com/assets/global/loading.gif"/>
</div>
<!-- Completely optional, I put a div in front of the player to block controls -->
<div id="mask" class="mask">
</div>
<div id="froog_container" class="froog_container_class">
   <iframe id="froog" src="_targetUrl?api=1&title=0&byline=0&portrait=0&player_id=froog" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen>
   </iframe>
</div>
</body>
</html>

И я загружаю этот html-файл так:

public String genMainHTML() {
    String code = null;
    try {
        Resources res = getResources();
        InputStream in_s = res.openRawResource(R.raw.vimeo_frame);

        byte[] b = new byte[in_s.available()];
        in_s.read(b);
        code = new String(b);
    } catch (Exception e) {
        e.printStackTrace();
    }
    if(code != null) {
            code = code.replaceAll("_windowHeight", "" + windowHeight + "px");
            code = code.replaceAll("_windowWidth", "" + windowWidth + "px");
            code = code.replaceAll("_targetUrl", targetUrl);
            return(code);
    }  else  {
            return(null);
    }
}

И введите его так:

mDomain = "http://player.vimeo.com";
mWebView.requestFocus(View.FOCUS_DOWN);
targetUrl = extras.getString("URL");
String meat = genMainHTML();
mWebView.loadDataWithBaseURL(mDomain, meat, "text/html", "utf-8", null);

setContentView(mWebView);

Вау! Когда WebView готов, идут html и js, включая iframe с проигрывателем Vimeo. Когда документ загрузится, то ждем готовности плеера. Когда проигрыватель готов, мы добавляем слушателей. И через 3 секунды мы запускаем метод API play.

Полировщики яблок в зале могут задаться вопросом, для полноты картины, как можно остановить видео? Два бита. Во-первых, когда он заканчивается, я останавливаю его, наблюдая за выводом консоли сообщения, которое я отображаю. Таким образом:

public String injectPageFinisher() {
    return( "javascript:" +
            "jQuery(document).ready( function() { " +
              "console.log(' === Page Ready ===> Tearing down');" +
              "console.log(' ==== Sending PAUSE Command ===');" +
              "var froogaloop = $f('froog');" +
          "froogaloop.api('pause');" +
              "jQuery('#froog_container').html('');" +
            "});");
    }

Который можно вставить так:

@Override
public void onPause() {
    super.onPause();
    if(isFinishing()){
        // Unload the page
        if(mWebView != null) {
            Log.i(TAG, " ------> Destroying WebView");
            mWebView.destroy();
        }
    }
    finish();
}

Во втором бите видео завершает свое маленькое «я». Таким образом, в вышеприведенном файле vimeo_frame.html сразу после обратного вызова play я добавил:

froogaloop.addEvent('finish', function(data) { 
    console.log('EVENT -- Finish');
});

И в Activity я немного понаблюдал за этим — см. выше в переопределении onConsoleMessage.

ОДНАКО -- на момент написания этой статьи я так и не решил одну надоедливую проблему. MediaPlayer продолжает жить после того, как WebView и все его потомки исчезли. Я уверен, что это создает некоторые проблемы, но я еще не определил их.

person Ted Collins    schedule 14.09.2012
comment
Я заметил, что ready также не увольняется. ЭТО СЛОМАН ИЛИ ЭТО ПРОСТО ВЕБ-ПРОСМОТР ANDROID UUUUUUHHHHGGGGHHHH. - person Jon Willis; 08.10.2013
comment
Я почти уверен, что он сломан, хотя у WebView, безусловно, есть свои проблемы. Vimeo просто незаметно переработали свой плеер (может быть, четыре недели назад?). Нам потребовалось некоторое время, чтобы приспособиться к этому, но приведенное выше решение все еще работает. - person Ted Collins; 09.10.2013
comment
Я заставил Vimeo работать (принимать внешние команды воспроизведения/паузы/поиска) с гораздо меньшим количеством кода, чем этот, я опубликую здесь еще один ответ после того, как немного подчищу код. - person Jon Willis; 09.10.2013
comment
@JonWillis, не могли бы вы поделиться своим кодом, пожалуйста? Большое спасибо! - person Pelanes; 30.10.2014
comment
Это очень долгий процесс. Можете ли вы опубликовать краткий процесс для него? - person Anand Savjani; 07.06.2016
comment
Эй, приятель, этот хак все еще работает сегодня? (2018) - person Fo Nko; 27.04.2018
comment
Будет ли отображаться URL-адрес видео Vimeo, если произойдет какая-либо ошибка? - person Bhaskar Jyoti Dutta; 06.07.2020

Мы столкнулись с той же проблемой, и кажется, что Android WebView (а также устройства на iOS) не запрограммированы на автоматический запуск видео, поскольку вполне возможно, что это поглотит чей-то тарифный план. Вы должны на самом деле нажать на него, если вы не хотите взять Google WebView в качестве отправной точки и свернуть свой собственный. Это не так просто, как кажется, мы старались!

person CaseyB    schedule 06.02.2012
comment
Звучит правдоподобно, что веб-просмотры не запрограммированы для этого. Вы нашли конкретный код в классе веб-просмотра Android, который привел вас к такому выводу? - person scottyab; 09.02.2012
comment
Дело не в том, что есть код, чтобы остановить это, а в том, что нет кода, чтобы это произошло. - person CaseyB; 09.02.2012
comment
@CaseyB этот ответ от 2012 года, он все еще верен? - person Khizar; 29.09.2014
comment
Понятия не имею, с тех пор многое изменилось. - person CaseyB; 07.10.2014

Вот простое решение

Шаг 1. Убедитесь, что у вас есть minSdkVersion 17

Шаг 2- mWebView.getSettings().setMediaPlaybackRequiresUserGesture(false); Вставьте эту строку в класс Vimeo.

person shyam    schedule 12.09.2018

У меня была такая же проблема, я думаю, что вы могли бы использовать это, чтобы это произошло:

public abstract void setMediaPlaybackRequiresUserGesture (логическое требование)

Добавлено на уровне API 17. Определяет, требует ли WebView жест пользователя для воспроизведения мультимедиа. Значение по умолчанию верно.

Параметры требуют, требует ли WebView жест пользователя для воспроизведения мультимедиа.

Надеюсь помочь вам хоть немного!

person M. Mariscal    schedule 26.01.2016

Надеюсь, это может помочь кому-то новому в этом. Пожалуйста, попробуйте следующие настройки для вашего веб-просмотра.

WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setAllowFileAccess(true);
webSettings.setAppCacheEnabled(true);
webSettings.setMediaPlaybackRequiresUserGesture(false);

И добавьте autoplay=1 к URL вашего видео Vimeo.

webView.loadUrl(resLink + "?autoplay=1");

Здесь resLink будет выглядеть как https://player.vimeo.com/video/your_video_id.

person Surendar D    schedule 03.12.2020