Android WebView Воспроизведение видео HTML5 / h.264 / mp4, как попасть в MediaPlayer

У меня есть Activity который является WebView . У меня есть WebChromeClient внутри. Внутри этого есть несколько обратных вызовов, которые предназначены для возврата MediaPlayer обрабатывающего видеопотоки. Например:

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

Они не срабатывают при загрузке потока MP4 в WebView с использованием 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. 

Попытайтесь, как я могу, я не могу заставить его остановиться, хотя WebView очищается, а затем уничтожается. При загрузке видео с помощью тегов <video> я не знаю, как заставить WebChromeClient использовать определенный MediaPlayer который я создаю для него. Кажется, он решил использовать скрытый, который сообщает об этом выше. Есть ли способ найти MediaPlayer созданный с помощью <video> в WebView ?

–Обновить

Вот код для инициализации 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); 

Код «frame» является 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, похоже, ведет себя лучше, чем Samsung, например («тот же» уровень OS / API – я не настолько амбициозен, чтобы сравнивать два дерева источников).

Поведение, отмеченное ниже, вызывает раздражение, но только для меня (кто наблюдает за выходом logcat. Для пользователя или приложения он, кажется, не имеет никакого эффекта. Просто мне очень не нравится представление о том, что я запускаю экземпляр MediaPlayer, устанавливая (Если / когда пользователь прекращает мое приложение), оставляя там тупицу, которая висит там. На данный момент у меня много денег, связанных с терапией, и это, похоже, не помогает.

Заранее спасибо.

Solutions Collecting From Web of "Android WebView Воспроизведение видео HTML5 / h.264 / mp4, как попасть в MediaPlayer"

Невозможно получить доступ к 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 .

В вашем классе

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

добавление

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

Избавляется от сообщений об ошибках после закрытия веб-просмотра.

Теперь, если бы я мог получить веб-просмотр для воспроизведения / потокового видео vimeo 🙁