Android WebView 播放 HTML5/h.264/mp​​4 视频,如何进入 MediaPlayer

Posted

技术标签:

【中文标题】Android WebView 播放 HTML5/h.264/mp​​4 视频,如何进入 MediaPlayer【英文标题】:Android WebView Playing HTML5/h.264/mp4 Video, How to get at the MediaPlayer 【发布时间】:2012-09-07 05:37:59 【问题描述】:

我有一个Activity,它是一个WebView。我里面有一个WebChromeClient。在其中,有几个回调旨在返回处理视频位的MediaPlayer。例如:

@Override
public void onPrepared(MediaPlayer mp) 
    Log.i(TAG, " -------------> onPrepared");

当我使用 html <video> 标签(通过注入)将 MP4 流加载到 WebView 时,这些无法触发。

当我finish() 活动时,logcat 会报告:

09-13 23:55:24.590: E/MediaPlayer(7949): mOnBufferingUpdateListener is null. Failed to send MEDIA_BUFFERING_UPDATE message.
09-13 23:55:24.680: E/MediaPlayer(7949): mOnBufferingUpdateListener is null. Failed to send MEDIA_BUFFERING_UPDATE message.
09-13 23:55:24.680: E/MediaPlayer(7949): mOnVideoSizeChangedListener is null. Failed to send MEDIA_SET_VIDEO_SIZE message.
09-13 23:55:25.675: E/MediaPlayer(7949): mOnBufferingUpdateListener is null. Failed to send MEDIA_BUFFERING_UPDATE message.
09-13 23:55:26.735: E/MediaPlayer(7949): mOnBufferingUpdateListener is null. Failed to send MEDIA_BUFFERING_UPDATE message.
09-13 23:55:27.755: E/MediaPlayer(7949): mOnBufferingUpdateListener is null. Failed to send MEDIA_BUFFERING_UPDATE message.
09-13 23:55:28.705: E/MediaPlayer(7949): mOnBufferingUpdateListener is null. Failed to send MEDIA_BUFFERING_UPDATE message.

尽我所能,我无法让它停止,即使WebView 被清除,然后被销毁。使用<video> 标签加载视频时,我不知道有什么方法可以强制WebChromeClient 使用我为它创建的特定MediaPlayer。似乎决心使用一些隐藏的,它报告了上述内容。有没有办法找到通过WebView 上的<video> 标签创建的MediaPlayer

--更新

这里是初始化WebView的代码:

        mWebView = new WebView(mContext);

        mWebView.getSettings().setjavascriptEnabled(true);
        mWebView.getSettings().setPluginState(PluginState.OFF);
        mWebView.setVisibility(View.INVISIBLE);
        mWebView.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
        mWebView.getSettings().setBuiltInZoomControls(false);
        mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        mWebView.getSettings().setLoadWithOverviewMode(true);
        mWebView.getSettings().setUseWideViewPort(true);
        mWebView.clearHistory();
        mWebView.clearFormData();
        mWebView.clearCache(true);
        mWebView.getSettings().setAllowFileAccess(true);
        mWebView.getSettings().setUserAgentString("android Mozilla/5.0 AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");

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

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

        mDomain = "http://foo.bar.com";
        mWebView.requestFocus(View.FOCUS_DOWN);

        String meat = genMainHTML(R.raw.frame);

        mWebView.loadDataWithBaseURL(mDomain, meat, "text/html", "utf-8", null);

“帧”代码是一个 iframe,用于启动一些视频(至少 Vimeo 和 YouTube 似乎都采用这种方法)。我对它进行了一些修剪以避免杂乱无章:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div>
     <iframe src="-target.url.with.params-" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen>
     </iframe>
</div>
</body>
</html>

在那个 WebView 类中,存在这个类:

private class MyWebViewClient extends WebViewClient 

    @Override
    public void onPageFinished(WebView view, String url) 
            super.onPageFinished(view, url);
            String injection = injectPageMonitor();
            if(injection != null && !injectionComplete) 
                // Log.i(TAG, " ---------------> Page Loaded . . .");
                view.loadUrl(injection);
                injectionComplete = true;
        
    

    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) 
            Log.d(TAG, "*** Error ["+description+"] ["+failingUrl+"]");
        Toast.makeText(mContext, description, Toast.LENGTH_SHORT).show();
    


还有这个类:

    private class MyWebChromeClient extends WebChromeClient implements MediaPlayer.OnInfoListener, MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnErrorListener, MediaPlayer.OnVideoSizeChangedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnBufferingUpdateListener 

       @Override
       public void onProgressChanged(WebView view, int progress) 
           //Log.e(TAG, " -------------> Progress Changed . . . . ["+progress+"] mWebView ["+mWebView+"] ["+view+"]");
           if(progress == 100) 
                               // Do something really interesting
             else  
               updateBuffering(UPDATE_PERCENT_LAUNCH_EXTRACTOR + (progress / 2));
           
       

       @Override
       public boolean onConsoleMessage(ConsoleMessage cm) 
                       // Spit out lots of console messages here
           return(true);
       
   

我已经覆盖了所有常见的嫌疑人,以防万一我幸运并从 MediaPlayer 中得到一些响应:

        @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) 
        // Jump up and down because we got a mp!
                    // never happens, so no jumping
    

作为旁注,我确实使用反射进行了挖掘并通过这种方式获得了 MediaPlayer,但在做那种事情之后我总是觉得有点古怪。即使我有 MediaPlayer 对象,我也不愿意发布它。对 MP 源代码的一点研究表明不会发生任何不好的事情,但是 . . .

这并不是在每台设备上都会发生的,我注意到了。例如,HTC 的表现似乎比三星好(“相同的”操作系统/API 级别——我并没有足够的野心来比较两个源代码树)。

下面提到的行为很烦人,但仅限于我(正在观看 logcat 输出的人。对于用户或应用程序来说,它似乎没有任何效果。只是我真的不喜欢我正在启动 MediaPlayer 的想法例如,将其设置为繁忙的缓存,然后(如果/当用户终止我的应用程序时)将那个丁香莓挂在那里。此时我有很多钱用于治疗,这似乎没有帮助.

提前致谢。

【问题讨论】:

看看这篇文章:***.com/questions/12156162/… 似乎是一个类似的问题。请看这个帖子:***.com/questions/12156162/… 马克 - 非常感谢。正如您所建议的,我已将我的 cmets 移至您提出的问题。在那个帖子中,'Tony' 准确地提出了我喜欢 采用的方法。但是我似乎无法在没有反射的情况下找到MediaPlayer,这总是让我想去拜访绅士们洗漱。 你说“尽我所能,我无法让它停止,即使 WebView 被清除,然后被销毁” - 你怎么知道它被销毁了?取消对 WebView 的引用可能还不够,我认为您可能需要取消设置 WebViewClient 和任何其他引用,然后才能将其销毁/垃圾收集? 好点。我会试试的。 【参考方案1】:

没有反射就无法访问 MediaPlayer - WebViewClient 和 WebChromeClient 不会故意公开它。你说得对,使用反射可能会导致你的应用程序或 WebView 崩溃,因为代码可能因 Android 版本而异,甚至因 OEM 而异。

如果您想这样做,您必须找到与您的视频元素相对应的 HTML5VideoView 实例。该对象创建并维护 MediaPlayer 的一个实例作为“mPlayer”。请参阅https://github.com/android/platform_frameworks_base/blob/jb-mr2-release/core/java/android/webkit/HTML5VideoView.java。

【讨论】:

抱歉延迟回复。这很有帮助,但是,每次我偷看时,HTML5VideoViewProxy 似乎都是空的。所以,我继续筛选胆量。不过谢谢! 网址不存在了 这很好,但如何在 Android 5 中做到这一点? HTML5VideoView 不再存在。我尝试获取 mPlayer 和 mUri,但 Android 5 中不再有该类 对此有更新的答案吗?由于 API 21+,这似乎不再是一个选项;他们是否已经公开了获得上述 MediaPlayer 的方法?【参考方案2】:

在你的班级

private class MyWebChromeClient extends WebChromeClient 
                                implements ..... MediaPlayer.onCompletion 

添加

@Override
public void onCompletion(MediaPlayer mp) 
    // TODO Auto-generated method stub
    mp.release();           

在 webview 关闭后为我消除错误消息。

现在要是我能让 webview 播放/流式传输 vimeo 视频就好了:(

【讨论】:

谢谢。我早该想到的。 有一个非常大的解决方案,使用这种方法,这里:***.com/a/16179544/550471 拯救我的一天

以上是关于Android WebView 播放 HTML5/h.264/mp​​4 视频,如何进入 MediaPlayer的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 视频未在 android webview 中播放

音频和视频未在 Android WebView HTML5 中播放

Android WebView播放html5视频,退出全屏后为啥就是黑屏了

Android WebView 播放 HTML5/h.264/mp​​4 视频,如何进入 MediaPlayer

Android webview html5 视频自动播放在 android 4.0.3 上不起作用

html5视频无法与android webview一起使用