Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intercepting HTML5 video source request in Android WebView

I have an app which shows a HTML5 page with a video element in a WebView. It took me a while to figure out how to get the video working, but finally I succeeded to play the video embedded in a WebView on an Samsung Galaxy Tab (Android 3.1). I used the following code for the video tag:

<video controls poster="img/poster.jpg" height="240" width="360">
        <source src="video/BigBuck.m4v">
        <source src="video/BigBuck.theora.ogv" type="video/ogg">
        <source src="video/BigBuck.webm" type="video/webm">
        HTML5 video not supported.
</video>

The video element has multiple sources and now I'm trying to capture the selected video source (and format) before the video starts to play. When I click the play button, I see a HTTP request for the video file arriving at the web server where the video files are stored, but I don't succeed in intercepting this request at the app-side.

I looked at several methods to see whether the request for the video file passes there, but I didn't saw it pass in any of them.

  • In shouldOverrideUrlLoading(WebView view, String url) in my WebViewClient only the initial HTML5 page request passes.
  • In shouldInterceptRequest (WebView view, String url) in my WebViewClient I see only passing the initial HTML5 page request and a request for the video poster image, but not for the video file.
  • onShowCustomView(View view, CustomViewCallback callback) in my WebChromeClient is only called when I click the fullscreen control button on the HTML5 page when the video is already playing, but not when I click the play button. (What is actually the purpose of this method?)

Does anyone have a suggestion for another method where I can capture the request for the video file or can anyone explain me what actually happens when I click the play button on the video element?

like image 200
Erika Avatar asked Jan 25 '12 08:01

Erika


1 Answers

I solved the problem using a javascript approach. When the HTML page is loaded, a loadedmetadata event is fired when the video metadata has been loaded. From that moment on you can get the selected video source from the currentSrc attribute of the video element and pass it via a JavascriptInterface to the Android native code.

Below is the code of the HTML5 video element. "Android" is the name by which the JavascriptInterface can be accessed in javascript.

<video poster="image/poster.jpg" height="240" width="360" onloadedmetadata="Android.interceptPlay(this.currentSrc);">
    <source src="video/BigBuck.m4v">
    <source src="video/BigBuck.webm" type="video/webm">
    <source src="video/BigBuck.theora.ogv" type="video/ogg">
    HTML5 video not supported.
</video>

The code of the JavascriptInterface

private class JavaScriptInterface {
    Context mContext;

    /* Instantiate the interface and set the context */
    JavaScriptInterface(Context c) {
        mContext = c;
    }

    public void interceptPlay(String source) {
        // do something
    }
}

And finally add the JavascriptInterface to the WebView at Activity creation time

mWebView.addJavascriptInterface(new JavaScriptInterface(this), "Android");

It’s important to catch the loadedmetadata event by adding the onloadedmetadata attribute to the HTML5 video element and not by registering an event listener at page load via addEventListener("loadedmetadata",...) because on a fast network the loadedmetadata event may be fired before the listener is registered (see http://dev.opera.com/articles/view/consistent-event-firing-with-html5-video)

like image 75
Erika Avatar answered Sep 29 '22 18:09

Erika