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

Мне удалось получить видео vimeo для загрузки и воспроизведения, используя следующее. Однако autoplay = 1, как указано в vimeo oembed doc 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"); 

Этот ответ специфичен только для 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. // NB 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('');" + "});"); } . 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, и все его потомки исчезли. Я уверен, что это создает некоторые проблемы, но я еще не определил их.

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

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

Public abstract void setMediaPlaybackRequiresUserGesture (boolean require)

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

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

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