Android layer_type_software 未显示 HTML5 canvas 内容的 WebView
Android WebView with layer_type_software not showing HTML5 canvas content
自从上次更新 Android WebView 后,当通过将 WebView 的图层类型设置为 [=30= 来禁用硬件加速时,带有 HTML5 canvas 的网页无法正确显示].这个问题有解决方法吗?
当我遗漏下面这行 Java 代码时:
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, 空);
然后内容就可以正确显示了。
Java代码:
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 文件 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>
预期结果:
黑边红色线性渐变
https://heiri-web.ch/Gradient.png
实际结果:
空的黑色边框
https://heiri-web.ch/Empty.png
我发现解决 HTML5 canvas webview 中 Android 问题的关键就在 AndroidManifest.xml 中。我必须做什么?我保留了使用混合(自定义)webview 的策略,因为当我在 Xamarin Forms 中为 iOS 和 Android 开发时,我需要在两个平台上使用相同的解决方案。在 Android 我做了:
// 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;
最后,在 AndroidManifest.xml 中找到 android:handwareAccelerated="false"
,您可以将值从 false
更改为 true
。此技巧(另外)适用于 Java 宇宙和 Xamarin。
在 https://issuetracker.google.com/issues/139276381 向 Google 提交错误报告后,我收到回复说该错误将不会修复,因为 LAYER_TYPE_SOFTWARE
已过时。因为我需要 LAYER_TYPE_SOFTWAR
E 才能使用 WebView.getDrawingCache()
获得完整的屏幕截图(包括 HTML5 canvas 内容),所以我要求另一种方法。
在 WebView 开发团队成员 Bo Liu 的建议下,我设法在不使用 LAYER_TYPE_SOFTWARE
的情况下获得了 WebView 的完整屏幕截图:
创建一个 ImageReader,使用 ImageReader.getSurface()
获取一个 Surface,在 Surface 上创建一个 VirtualDisplay,使用 VirtualDisplay.getDisplay()
获取一个 Display,在 Display 上的布局中使用 WebView 创建一个 Presentation,使用 Presentation.show()
,使用ImageReader.acquireLatestImage()
读取WebView内容渲染后的Image。
自从上次更新 Android WebView 后,当通过将 WebView 的图层类型设置为 [=30= 来禁用硬件加速时,带有 HTML5 canvas 的网页无法正确显示].这个问题有解决方法吗?
当我遗漏下面这行 Java 代码时: webView.setLayerType(View.LAYER_TYPE_SOFTWARE, 空); 然后内容就可以正确显示了。
Java代码:
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 文件 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>
预期结果: 黑边红色线性渐变 https://heiri-web.ch/Gradient.png
实际结果: 空的黑色边框 https://heiri-web.ch/Empty.png
我发现解决 HTML5 canvas webview 中 Android 问题的关键就在 AndroidManifest.xml 中。我必须做什么?我保留了使用混合(自定义)webview 的策略,因为当我在 Xamarin Forms 中为 iOS 和 Android 开发时,我需要在两个平台上使用相同的解决方案。在 Android 我做了:
// 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;
最后,在 AndroidManifest.xml 中找到 android:handwareAccelerated="false"
,您可以将值从 false
更改为 true
。此技巧(另外)适用于 Java 宇宙和 Xamarin。
在 https://issuetracker.google.com/issues/139276381 向 Google 提交错误报告后,我收到回复说该错误将不会修复,因为 LAYER_TYPE_SOFTWARE
已过时。因为我需要 LAYER_TYPE_SOFTWAR
E 才能使用 WebView.getDrawingCache()
获得完整的屏幕截图(包括 HTML5 canvas 内容),所以我要求另一种方法。
在 WebView 开发团队成员 Bo Liu 的建议下,我设法在不使用 LAYER_TYPE_SOFTWARE
的情况下获得了 WebView 的完整屏幕截图:
创建一个 ImageReader,使用 ImageReader.getSurface()
获取一个 Surface,在 Surface 上创建一个 VirtualDisplay,使用 VirtualDisplay.getDisplay()
获取一个 Display,在 Display 上的布局中使用 WebView 创建一个 Presentation,使用 Presentation.show()
,使用ImageReader.acquireLatestImage()
读取WebView内容渲染后的Image。