heiri
heiri

Reputation: 53

Android WebView with layer_type_software not showing HTML5 canvas content

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

Upvotes: 3

Views: 3465

Answers (2)

heiri
heiri

Reputation: 53

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.

Upvotes: 2

vinicius.stutz
vinicius.stutz

Reputation: 31

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.

Upvotes: -1

Related Questions