Android WebView播放HTML5 / h.264 / mp4video,如何获取MediaPlayer

我有一个Activity ,这是一个WebView 。 里面有一个WebChromeClient 。 里面有几个callback函数可以返回MediaPlayer处理video的位数。 例如:

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

当我使用HTML <video>标记(通过注入)将一个MP4stream加载到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>标签加载video时,我不知道有什么办法强制WebChromeClient使用我为它创build的特定MediaPlayer 。 似乎决定使用一些隐藏的,这上面报告。 有没有办法find通过WebView上的<video>标签创build的MediaPlayer

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

“框架”代码是一个iframe来发布一些video(Vimeo和YouTube似乎至less采用这种方法)。 我已经修剪了这一点,以避免cruft:

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

而且这个class级:

  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 } 

作为一个侧面说明,我用reflection来挖掘,并以这种方式获得了MediaPlayer的位置,但是做这种事情之后,我总是觉得有些不自在。 即使我有MediaPlayer对象,我也不愿意发布它。 对MP源代码的一点研究表明,没有什么不好的事情会发生,但是。 。 。

我注意到,这不会发生在每个设备上。 HTC似乎比三星performance得更好(“相同的”操作系统/ API级别 – 我没有足够的雄心来比较这两个源代码树)。

下面的行为是令人讨厌的,但只对我来说(谁在看logcat输出,对于用户或应用程序来说似乎没有任何作用,只是我不喜欢这样的理念,即开始closuresMediaPlayer实例,设置它忙于caching,然后(如果/当用户终止我的应用程序)离开那里的dingleberry在这里,我有很多钱绑在治疗,似乎并没有帮助。

提前致谢。

Solutions Collecting From Web of "Android WebView播放HTML5 / h.264 / mp4video,如何获取MediaPlayer"

没有reflection就无法访问MediaPlayer – WebViewClient和WebChromeClient不会有意暴露它。 而且你说对于使用reflection会导致你破坏你的应用程序或者WebView是正确的,因为代码可以在Android版本甚至整个OEM之间变化。

如果你想这样做,你将不得不find对应于你的video元素的HTML5VideoView的实例。 这个对象创build并维护MediaPlayer的一个实例为“mPlayer”。 请参阅https://github.com/android/platform_frameworks_base/blob/jb-mr2-release/core/java/android/webkit/HTML5VideoView.java

在你的class级

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

join

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

在webviewclosures后摆脱我的错误信息。

现在,如果只有我可以得到的WebView播放/streamVimeovideo:(