這個問題多出現(xiàn)在三星制造的搭載 Android 4.3 系統(tǒng)的手機上瞭稼。
問題的原因是在 ActivityThread 回收內(nèi)存時會調(diào)用 com.google.android.gles_jni.EGLImpl
類相關(guān)方法,并回收 RenderThread
蹭秋,進而調(diào)用到計算 CPU FPS
的邏輯衷恭,導(dǎo)致 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)
...
問題出在系統(tǒng)層面此叠,Android 應(yīng)用回收內(nèi)存的 Message 是 ActivityManager 發(fā)出,屬于系統(tǒng)正常行為匾荆,無法規(guī)避拌蜘。
解決方法:
- 定義一個渲染策略類杆烁,針對 samsung + android 4.3這種組合在
WebView layer
層面關(guān)閉硬件加速牙丽。(這樣就不會存在RenderThread
简卧,自然也就沒法觸發(fā)上文的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;
}
- 在自定義
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();
}
}