user1745504
user1745504

Reputation:

WebView.draw(android.graphics.Canvas) won't draw HTML5 canvas to android.graphics.Canvas

Hey I'm trying to draw a webview to a bitmap the following way:

CustomWebView webView = (CustomWebView) findViewById(R.id.chart_webview_renderer);

String capturePathString = Environment.getExternalStorageDirectory().getPath() + "/temp/ms_" + System.currentTimeMillis() + ".png";

Bitmap bm = Bitmap.createBitmap(webView.getMeasuredWidth(), webView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);

Canvas bigcanvas = new Canvas(bm);
Paint paint = new Paint();
int iHeight = bm.getHeight();
bigcanvas.drawBitmap(bm, 0, iHeight, paint);
webView.draw(bigcanvas);

if (bm != null) {
    try {
        OutputStream fOut = null;
        File file = new File(capturePathString);
        fOut = new FileOutputStream(file);

        bm.compress(Bitmap.CompressFormat.PNG, 50, fOut);
        fOut.close();
        fOut.flush();
        bm.recycle();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

This works fine on the tablets we have available for testing here (Galaxy Tab 2 and 3). But results in a white bitmap of the correct size on a Sony Xperia Z and Samsung Galaxy S2.

The webpage it is trying to draw to the bitmap contains ONLY an HTML5 canvas and when I also add normal HTML to it, it will draw just that HTML to the bitmap just fine.

The webview is set as invisible behind all views, although I have tried making it visible and on top of all views which produced no different results.

Upvotes: 1

Views: 1487

Answers (1)

user1745504
user1745504

Reputation:

I wasn't able to solve this issue with the original method I used. So I added the following javascript fix to the html: https://code.google.com/p/todataurl-png-js/ to allow the use of

canvas.toDataUrl() 

which returns a Base64 encoded PNG image. I then used

WebView.addJavascriptInterface

to allow the javascript to send the base64 encoded image to java, which then saved it on the device.

A rough example of what I did is this:

// After initializing the webview:
JavaScriptInterface jsInterface = new JavaScriptInterface();
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(jsInterface, "android");

// The class used as javascript interface for saving the image to a file
public class JavaScriptInterface {
    @JavascriptInterface
    public void canvasToImage(String base64ImageData){
        String capturePathString = Environment.getExternalStorageDirectory().getPath() + "/temp/ms_" + System.currentTimeMillis() + ".png";

        try{
            File file = new File(capturePathString);
            file.getParentFile().mkdirs();
            FileOutputStream fos = new FileOutputStream(file);
            byte[] decodedString = android.util.Base64.decode(base64ImageData, android.util.Base64.DEFAULT);
            fos.write(decodedString);

            fos.flush();
            fos.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

// In the javascript it looks something like this
function canvasToImage(){
    var dataUrl = canvas.toDataURL();

    window.android.canvasToImage(dataUrl.replace("data:image/png;base64,", ""));
}

It isn't as clean as I'd hope it would be, but it works on all devices here now!

Upvotes: 2

Related Questions