【问题标题】:Auto playing vimeo videos in Android webview在 Android webview 中自动播放 vimeo 视频
【发布时间】:2012-02-20 06:41:20
【问题描述】:

我已经设法让 vimeo 视频加载和播放,使用以下。但是,vimeo oembed docs 中指示的 autoplay=1 不会在加载时自动播放。任何人都找到了自动播放的方法(还需要在视频播放结束时捕捉事件)

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

【问题讨论】:

  • 上面的代码在没有自动播放的情况下工作吗??
  • 是的,我还设置了一个显示/隐藏进度条的 WebViewClient,不确定设置自定义 WebViewClient 是否会影响它?
  • 但我尝试了很多使用你的代码。但它不起作用。所以我使用自定义 webview

标签: android video-streaming vimeo


【解决方案1】:

此答案仅针对 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 步。如果您希望视频在 WebView 上运行,则需要 WebChromeClient。这在此处记录: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);" +
  "});");
}

快速解释。 . .我在我的 JS 中使用 jQuery,下面是它。那只是为了方便,如果你想减轻负担,你可以直接做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 进入,包括带有 Vimeo 播放器的 iframe。加载文档后,我们等待播放器准备就绪。当播放器准备好时,我们添加一些监听器。 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 中,就在“播放”回调之后,我输入:

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

在 Activity 中,我需要注意这一点 - 请参阅上面的 onConsoleMessage 覆盖。

然而——在写这篇文章时,我还没有解决一个烦人的问题。 MediaPlayer 在 WebView 及其所有后代都消失后继续存在。我确信这会产生一些问题,但我还没有发现它们。

【讨论】:

  • 我注意到 ready 也不会被解雇。是坏了还是只是 Android 的 WEBVIEW UUUUUUHHHHHGGGGHHHH。
  • 我很确定它坏了——尽管 WebView 肯定有它的挑战。 Vimeo 只是悄悄地改造了他们的播放器(现在可能是四个星期前?)。我们花了一些时间来适应它,但上述解决方案仍然有效。
  • 我用比这少得多的代码让 Vimeo 工作(接受外部播放/暂停/搜索命令),我会在稍微清理一下代码后在这里发布另一个答案。跨度>
  • @JonWillis 你能分享你的代码吗?非常感谢!
  • 这是一个非常漫长的过程。你能发布一个简短的过程吗?
【解决方案2】:

我们遇到了同样的问题,似乎 Android WebView(以及 iOS 上的那些)没有编程为允许自动启动视频,因为它可能会占用某人的数据计划.除非您想以 Google 的 WebView 为起点并自己动手,否则您必须实际点击它。这并不像听起来那么容易,我们试过了!

【讨论】:

  • webviews 没有被编程来做这件事听起来似乎是合理的,你是否在 Android webview 类中找到了导致你得出这个结论的特定代码?
  • 不是没有代码可以阻止它,而是没有代码可以让它发生。
  • @CaseyB 这个答案是 2012 年的,还正确吗?
  • 我不知道,从那以后发生了很多变化。
【解决方案3】:

这是一个简单的解决方案

Step1-确保您拥有minSdkVersion 17

Step2- mWebView.getSettings().setMediaPlaybackRequiresUserGesture(false); 将此行粘贴到 Vimeo 类上。

【讨论】:

    【解决方案4】:

    我有同样的问题,我认为你可以使用这个来实现它:

    public abstract void setMediaPlaybackRequiresUserGesture (boolean 要求)

    在 API 级别 17 中添加 设置 WebView 是否需要用户手势 播放媒体。默认为真。

    参数需要WebView是否需要用户手势才能播放 媒体

    希望至少能帮到你一点!

    【讨论】:

      【解决方案5】:

      希望它可以帮助新手。 请尝试对您的 webview 进行以下设置。

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

      并在您的 Vimeo 视频网址中附加 autoplay=1

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

      这里的 resLink 看起来像“https://player.vimeo.com/video/your_video_id”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-03-16
        • 2016-12-28
        • 2016-12-22
        • 2013-12-11
        • 2013-05-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多