studio chrome java android webview android-mediaplayer webchromeclient

java - chrome - webview android studio



Android WebView Reproducción de video HTML5/h.264/mp4, Cómo llegar al MediaPlayer (2)

Tengo una Activity que es una vista WebView . Tengo un WebChromeClient dentro de él. Dentro de eso, hay varias devoluciones de llamada que están destinadas a devolver el MediaPlayer maneja los bits de video. Por ejemplo:

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

Estos no se activan cuando cargo un flujo de MP4 en la WebView utilizando etiquetas <video> HTML (a través de inyección).

Cuando finish() la actividad, el logcat informa de esto:

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.

Por más que lo intente, no puedo hacer que se detenga, a pesar de que la vista WebView se borra y luego se destruye. Al cargar video usando etiquetas <video> , no conozco ninguna forma de forzar a WebChromeClient a usar un MediaPlayer particular que creo para él. Parece determinado a usar algún oculto, que reporta lo anterior. ¿Hay alguna manera de ubicar el MediaPlayer creado a través de una etiqueta <video> en un WebView ?

--Actualizar

Aquí está el código para inicializar el 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);

El código de "marco" es un iframe para lanzar un video (al menos, tanto Vimeo como YouTube parecen adoptar este enfoque). He recortado esto un poco para evitar el crucero:

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

Dentro de esa clase de WebView, existe esta clase:

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

Y también esta clase:

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

Y he anulado todos los sospechosos habituales, en caso de que tenga suerte y obtenga alguna respuesta del MediaPlayer:

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

Como nota al margen, me dediqué a hacer reflexiones y conseguí el MediaPlayer de esa manera, pero siempre me siento un poco mal después de hacer ese tipo de cosas. Y a pesar de que tengo el objeto MediaPlayer, me resisto a lanzarlo. Un poco de estudio del código fuente de MP sugiere que no pasaría nada malo, pero. . .

Esto no sucede en todos los dispositivos, me he dado cuenta. HTC parece comportarse mejor que Samsung, por ejemplo ("mismo" nivel de OS / API: no soy lo suficientemente ambicioso como para comparar los dos árboles de origen).

El comportamiento que se observa a continuación es molesto, pero solo para mí (quién está viendo la salida logcat. Para el usuario o la aplicación parece no tener ningún efecto. Es solo que realmente me disgusta la idea de que estoy iniciando una instancia de MediaPlayer, configuración se almacena en la memoria caché, y luego (si / cuando el usuario termina mi aplicación) dejando esa dingleberry colgando por ahí. Tengo mucho dinero atado a la terapia en este momento, y no parece estar ayudando.

Gracias por adelantado.


No hay manera de acceder a MediaPlayer sin reflexión: WebViewClient y WebChromeClient no lo exponen intencionalmente. Y tiene razón al decir que el uso de la reflexión podría hacer que rompa su aplicación o la WebView, ya que el código puede variar entre las versiones de Android e incluso entre los OEM.

Si desea hacer esto, deberá ubicar la instancia de HTML5VideoView que corresponde a su elemento de video. Este objeto crea y mantiene una instancia de MediaPlayer como "mPlayer". Consulte https://github.com/android/platform_frameworks_base/blob/jb-mr2-release/core/java/android/webkit/HTML5VideoView.java .


en tu clase

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

añadiendo

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

se deshace de los mensajes de error para mí después del cierre de la vista web.

Ahora solo si pudiera obtener la vista web para reproducir / transmitir videos de vimeo :(