Автоматическое воспроизведение видео Vimeo в веб-браузере Android - PullRequest
6 голосов
/ 27 января 2012

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

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

Ответы [ 4 ]

11 голосов
/ 14 сентября 2012

Этот ответ относится только к 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');
});

А в Упражнении я добавил немного, чтобы следить за этим - см. Выше в переопределении onConsoleMessage.

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

8 голосов
/ 07 февраля 2012

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

0 голосов
/ 12 сентября 2018

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

Step1- Убедитесь, что у вас есть minSdkVersion 17

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

0 голосов
/ 26 января 2016

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

открытый абстрактный void setMediaPlaybackRequiresUserGesture (логическое значение требуется)

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

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

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

...