3

Since last update of Android WebView a web page with a HTML5 canvas is not displayed correctly when hardware acceleration is disabled by setting the WebView's layer type to View.LAYER_TYPE_SOFTWARE. Is there a workaround for this problem?

When I leave out the following line of Java code: webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); Then the Content is displayed correctly.

Java code:

WebView webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
webView.loadUrl("file:///android_asset/Gradient.html");

Html file test.html:

<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// Create gradient
var grd = ctx.createLinearGradient(0,0,200,0);
grd.addColorStop(0,"red");
grd.addColorStop(1,"white");
// Fill with gradient
ctx.fillStyle = grd;
ctx.fillRect(10,10,150,80);
</script>
</body>
</html>

Expected result: Red linear gradient in black border https://heiri-web.ch/Gradient.png

Actual result: Empty black border https://heiri-web.ch/Empty.png

2 Answers 2

2

After submitting a bug report https://issuetracker.google.com/issues/139276381 to Google I received the reply that the bug will not be fixed as LAYER_TYPE_SOFTWARE is obsolete. Because I needed LAYER_TYPE_SOFTWARE to get a complete screenshot (including HTML5 canvas content) using WebView.getDrawingCache() I asked for an alternative method.

Following the advice of Bo Liu, member of the WebView developers team, I managed to get a complete screenshot of a WebView without using LAYER_TYPE_SOFTWARE: Create an ImageReader, use ImageReader.getSurface() to get a Surface, create a VirtualDisplay on the Surface, use VirtualDisplay.getDisplay() to get a Display, create a Presentation with the WebView in its layout on the Display, use Presentation.show(), use ImageReader.acquireLatestImage() to read the rendered Image of WebView content.

Sign up to request clarification or add additional context in comments.

Comments

-1

I found that the key to solving the HTML5 canvas issue in Android webview is within AndroidManifest.xml. What did I have to do? I kept the strategy of using a hybrid (custom) webview, because as I develop in Xamarin Forms for both iOS and Android, I needed the same solution on both platforms. On Android I did:

// Java (or similar [laughs])
// Enable hardware acceleration using code (>= level 19)
if (Build.VERSION.SDK_INT >= 19) {
    yourWebviewObj.setLayerType(View.LAYER_TYPE_HARDWARE, null);
} else {
    yourWebviewObj.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

yourSettingsObj.setRenderPriority(WebSettings.RenderPriority.HIGH);
yourSettingsObj.setCacheMode(WebSettings.LOAD_NO_CACHE);
// Xamarin for Android
// Enable hardware acceleration using code (>= level 19)
if (Build.VERSION.SdkInt >= 19)
{
    yourWebviewObj.SetLayerType (LayerType.Hardware, null);
}
else
{
    yourWebviewObj.SetLayerType (LayerType.Software, null);
}

yourWebviewObj.Settings.SetRenderPriority(WebSettings.RenderPriority.High);
yourWebviewObj.Settings.CacheMode = CacheModes.NoCache;

And finally, within AndroidManifest.xml find for android:handwareAccelerated="false" and you can change the value from false to true. This tip (additionally) works for both the Java universe and Xamarin.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.