转载自:http://faywong.github.io/posts/2015-01-15-03.html
最近发现客户端中android4.3上GS4手机上的WebApp应用特别容易crash。分析了源代码之后发现,在ActivityThread中回收内存时会调用EGLImpl里边去,回收RenderThread,进而调用到计算CPU FPS的逻辑,进而crash:
java.lang.Error: signal 11 (Address not mapped to object) at address 0xbe59dff0 [at libPowerStretch.so:0x2d4c (_ZN11LucidConfig13calcTargetFPSEi+0x1b)] at system.lib.libPowerStretch_so.0x2d4c(LucidConfig::calcTargetFPS(int):0x1b:0) at system.lib.libPowerStretch_so.0x2f23(LucidConfig::isLucidActive(bool):0x86:0)
因为在问题出在系统层而android应用回收内存这个message是ActivityManager发出,为正常且必要的行为,无法规避。最终选择如下方式将其绕过:
public class H5WebViewRenderPolicy { public static boolean shouldDisableHardwareRenderInLayer() { // case 1: samsung GS4 on android 4.3 is know to cause crashes at libPowerStretch.so:0x2d4c // use GT-I95xx to match more GS4 series devices though GT-I9500 is the typical device final boolean isSamsungGs4 = android.os.Build.MODEL != null && android.os.Build.MODEL.contains("GT-I95") && android.os.Build.MANUFACTURER != null && android.os.Build.MANUFACTURER.equals("samsung"); final boolean isJbMr2 = Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2; if (isSamsungGs4 && isJbMr2) { return true; } return false; } }
以上定义一个渲染策略类(方便以后维护),针对GS4 + android 4.3这种组合在WebView layer层面关闭硬件加速(这样就不会存在RenderThread,自然也就没法触发上文的crash)。
之后在自定义WebView中利用上以上渲染策略类:
final boolean meetApiLevel11 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; if (H5WebViewRenderPolicy.shouldDisableHardwareRenderInLayer() && meetApiLevel11) { final View underlyingWebView = webView.getUnderlyingWebView(); if (underlyingWebView != null && webView.getType().equals(WebViewType.SYSTEM_BUILD_IN)) { try { underlyingWebView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } catch (Exception globalException) { globalException.printStackTrace(); } } }
更新 2015/2/1
该现象表现在多款三星制造的搭载android 4.3系统的手机上,不仅限于GS4