开发踩坑

三星 Android 4.3 机型上 webview crash

2017-03-22  本文已影响1545人  Enowr

这个问题多出现在三星制造的搭载 Android 4.3 系统的手机上。

问题的原因是在 ActivityThread 回收内存时会调用 com.google.android.gles_jni.EGLImpl 类相关方法,并回收 RenderThread,进而调用到计算 CPU FPS 的逻辑,导致 crash:

native stacktrace
#00 pc 0x00002d4c /system/lib/libPowerStretch.so (LucidConfig::calcTargetFPS(int))
#01 pc 0x00002f23 /system/lib/libPowerStretch.so (LucidConfig::isLucidActive(bool))
...
at dalvik.system.NativeStart.run(Native Method)
main
at com.google.android.gles_jni.EGLImpl.eglReleaseThread(Native Method)
at android.view.HardwareRenderer$Gl20Renderer$Gl20RendererEglContext.onTerminate(HardwareRenderer.java:1743)
at android.opengl.ManagedEGLContext.execTerminate(ManagedEGLContext.java:84)
at android.opengl.ManagedEGLContext.doTerminate(ManagedEGLContext.java:132)
at android.view.WindowManagerGlobal.endTrimMemory(WindowManagerGlobal.java:460)
at android.app.ActivityThread.handleTrimMemory(ActivityThread.java:4374)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1531)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
...

问题出在系统层面,Android 应用回收内存的 Message 是 ActivityManager 发出,属于系统正常行为,无法规避。

解决方法:

  1. 定义一个渲染策略类,针对 samsung + android 4.3这种组合在 WebView layer 层面关闭硬件加速。(这样就不会存在RenderThread,自然也就没法触发上文的 crash
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;
    return isSamsungGs4 && isJbMr2;
}
  1. 在自定义 WebView 中使用以上渲染策略类。
    final boolean meetApiLevel11 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
    if (shouldDisableHardwareRenderInLayer() && meetApiLevel11) {
        try {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        } catch (Exception globalException) {
            globalException.printStackTrace();
        }
    }
上一篇下一篇

猜你喜欢

热点阅读