Android WebView播放HTML5/h.264/mp4视频,如何获取MediaPlayer

Ted*_*ins 19 java android webview webchromeclient android-mediaplayer

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

@Override
public void onPrepared(MediaPlayer mp) {
    Log.i(TAG, " -------------> onPrepared");
}
Run Code Online (Sandbox Code Playgroud)

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

当我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.
Run Code Online (Sandbox Code Playgroud)

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

--update

以下是初始化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);
Run Code Online (Sandbox Code Playgroud)

"框架"代码是用于启动某些视频的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>
Run Code Online (Sandbox Code Playgroud)

在该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();
    }

}
Run Code Online (Sandbox Code Playgroud)

还有这堂课:

    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);
       }
   }
Run Code Online (Sandbox Code Playgroud)

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

        @Override
    public void onBufferingUpdate(MediaPlayer mp, int percent) {
        // Jump up and down because we got a mp!
                    // never happens, so no jumping
    }
Run Code Online (Sandbox Code Playgroud)

作为旁注,我确实在使用反射进行挖掘,并以这种方式得到了MediaPlayer,但在做完这种事情之后我总觉得有点蠢蠢欲动.即使我有MediaPlayer对象,我也不愿意发布它.对MP的源代码进行一点研究表明,没有什么不好的事情会发生,但是...

我注意到,这并没有发生在每台设备上.例如,HTC似乎比三星表现更好("相同的"操作系统/ API级别 - 我真的不够雄心勃勃,无法比较两个源代码树).

下面提到的行为很烦人,但仅限于我(正在观看logcat输出.对于用户或应用程序,它似乎没有任何影响.只是我真的不喜欢我正在开启MediaPlayer实例,设置的概念它忙着缓存,然后(如果/当用户终止我的应用程序时)将那个dingleberry挂在那里.此时我在治疗方面有很多钱,而且似乎没有帮助.

提前致谢.

Raj*_*ani 5

没有反射就无法访问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.

  • 这很好,但如何在 Android 5 中做到这一点?HTML5VideoView 不再存在。我尝试获取 mPlayer 和 mUri 但该类在 Android 5 中不再存在 (2认同)