Webview WebResourceResponse for streaming connections (like MJPEG) using okhttp

  android, mjpeg, okhttp, streaming, webview

I am using a webview to display multiple cameras (along with other data) via a single html page. The issue is that MJPEG streams with basic or digest authentication will not work when embedded using a standard IMG tag.

For Jpeg stills, this is easy enough to fix using shouldInterceptRequest and then making the actual request using okhttp followed by returning a WebResourceResponse object with the JPEG still in the body.

For MJPEG streams, I was hoping that I can do something similar since both okhttp response.body delivers and WebResourceResponse accepts and InputStream for the body.

The code snippet below does connect and get the OK response with content_length = -1 (unknown). However, when I return the WebResourceResponse object the IMG tag in the webview just shows the black "error" picture (also the "onerror" js function fires after a couple seconds).

I’m not sure how to debug this since I can’t find any way to get visibility on why the IMG tag doesn’t like the object passed.

Maybe something needs to be done / added to the okhttp code for streaming connections? Maybe WebResourceResponse is looking for a specific header?

Any ideas???

(auth is handled by okhttpdigester, works well)

OkHttpClient httpClient = digestermap.get(url.trim()).httpClient;

                Log.d("Proxy","Proxy for url " + url + qsf);
            
                Request request = new Request.Builder()
                        .url(url.trim() + qsf)
                        .build();

                Log.d("Proxy", request.toString());
                Long bftime = System.currentTimeMillis();
                Response response = httpClient.newCall(request).execute();
                Long ddelta = System.currentTimeMillis() - bftime;
                Log.d("Proxy", "Request complete " + ddelta + " ms size:" + response.body().contentLength() +" " + response.message());

                if (mjpeg){
                    if (response.isSuccessful()){
                        // just return the stream, maybe it will work .... NOPE
                        
                        Map<String, String> hmap = new HashMap<>();
                        for (Pair<? extends String, ? extends String> ss : response.headers()){
                            hmap.put(ss.getFirst(),ss.getSecond());
                            //Log.d(TAG, "Proxy header " + ss.getFirst() + " " + ss.getSecond());
                        }

                        return new WebResourceResponse(response.header("content-type"),
                                null,
                                response.code(),
                                response.message(),
                                hmap,
                                response.body().byteStream());
                    }else{
                        Log.d("Proxy", "MJPEG Failed");
                        response.close();
                        httpClient.connectionPool().evictAll();
                        return null;
                    }
                }

Source: Android Questions

LEAVE A COMMENT