Well, I've been searching few days already, how to display HTML5 video in full-screen mode on android WebView.
I managed to play HTML5 videos on my webview. Problems are arising when displaying video in fullscreen mode.
As I figured out, android has two ways of handling the < video > tag:
-
On android versions <= 2.3.3, the onShowCustomView method is fired, and I can have the VideoView instance, and set listeners when the video completes, set controllers etc. So far so good.
-
On ICS (and probably 3.0 and above), it looks like the < video > is handled in different way. When the HTML5 video is played the onShowCustomView isn't being called on normal mode – it looks like there is an internal business inside the WebView that plays the video, and all the controls that are defined in the < video > tag are shown – I can't access it in any way. Actually, if the video is played in normal mode this is OK because the controls are there and are working.
That led me to the big problem: when displaying the video in full screen mode the onShowCustomView is being called – but on ICS the "view" parameter isn't an instance of VideoView.
I managed to find out that the instance is of VideoSurfaceView, a private inner class of HTML5VideoFullScreen class. The only way we can access this inner-class is via reflection.
After looking at GrepCode for this class, I learnt that unlike VideoView, the HTML5VideoFullScreen$VideoSurfaceView doesn't hold a MediaPlayer instance that I can listen to its events or access its controls. The only thing I can do is take this VideoSurfaceView as it is and put it inside a full-screen-layout without controlling it.
Bottom line – When displaying video in full-screen, I don't know when the video ends, its controls aren't shown – this is pretty sad. I can't get the trigger for closing the full-screen.
I tried few unsuccessful workarounds:
-
Reflection: I tried to reach the HTML5VideoFullScreen instance, which holds a MediaPlayer member, from the inner-class VideoSurfaceView. I didn't manage to get it, I'm not sure this is possible (ViewSurfaceView doesn't hold its owner's instance).
-
Register for the video events via Javascript (onended, for example), and handle what I need back in JAVA via JavascriptInterface: I found this solution isn't reliable because while doing this I encountered another problem: the < video > tag can be nested in an . The iframe source isn't mine and I can't get its content (getElementById or getElementsByTagName[i] are nulls) – which means, I can't reach the < video > element inside the iframe.
I'm still searching for a solution, very little is written about this issue. Did anyone manage to solve it? Help would be much appreciated!
VideoView class: Here (has MediaPlayer)
HTML5VideoFullScreen$VideoSurfaceView class: Here (doesn't have MediaPlayer)
Best Answer
Edit 2014/10: by popular demand I'm maintaining and moving this to GitHub. Please check cprcrack/VideoEnabledWebView for the last version. Will keep this answer only for reference.
Edit 2014/01: improved example usage to include the nonVideoLayout, videoLayout, and videoLoading views, for those users requesting more example code for better understading.
Edit 2013/12: some bug fixes related to Sony Xperia devices compatibility, but which in fact affected all devices.
Edit 2013/11: after the release of Android 4.4 KitKat (API level 19) with its new Chromium webview, I had to work hard again. Several improvements were made. You should update to this new version. I release this source under WTFPL.
Edit 2013/04: after 1 week of hard work, I finally have achieved everything I needed. I think this two generic classes that I have created can solve all you problems.
VideoEnabledWebChromeClient
can be used alone if you do not require the functionality thatVideoEnabledWebView
adds. ButVideoEnabledWebView
must always rely on aVideoEnabledWebChromeClient
. Please read all the comments of the both classes carefully.VideoEnabledWebChromeClient class
VideoEnabledWebView class
Example usage:
Main layout activity_main.xml in which we put a VideoEnabledWebView and other used views:
Activity's onCreate(), in which we initialize it:
And don't forget to call onBackPressed():