123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- package com.edufound.reader.util;
- import android.content.Context;
- import android.os.Build;
- import android.os.Handler;
- import android.os.Looper;
- import android.os.Message;
- import com.edufound.reader.listener.ActivityKillerV15_V20;
- import com.edufound.reader.listener.ActivityKillerV21_V23;
- import com.edufound.reader.listener.ActivityKillerV24_V25;
- import com.edufound.reader.listener.ActivityKillerV26;
- import com.edufound.reader.listener.ActivityKillerV28;
- import com.edufound.reader.listener.IActivityKiller;
- import java.lang.reflect.Field;
- import me.weishu.reflection.Reflection;
- /**
- * Created by wanjian on 2017/2/14.
- */
- public final class Cockroach {
- private static IActivityKiller sActivityKiller;
- private static ExceptionHandler sExceptionHandler;
- private static boolean sInstalled = false;//标记位,避免重复安装卸载
- private static boolean sIsSafeMode;
- private Cockroach() {
- }
- public static void install(Context ctx, ExceptionHandler exceptionHandler) {
- if (sInstalled) {
- return;
- }
- try {
- //解除 android P 反射限制
- Reflection.unseal(ctx);
- } catch (Throwable throwable) {
- throwable.printStackTrace();
- }
- sInstalled = true;
- sExceptionHandler = exceptionHandler;
- initActivityKiller();
- Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- if (sExceptionHandler != null) {
- sExceptionHandler.uncaughtExceptionHappened(t, e);
- }
- if (t == Looper.getMainLooper().getThread()) {
- isChoreographerException(e);
- safeMode();
- }
- }
- });
- }
- /**
- * 替换ActivityThread.mH.mCallback,实现拦截Activity生命周期,直接忽略生命周期的异常的话会导致黑屏,目前
- * 会调用ActivityManager的finishActivity结束掉生命周期抛出异常的Activity
- */
- private static void initActivityKiller() {
- //各版本android的ActivityManager获取方式,finishActivity的参数,token(binder对象)的获取不一样
- if (Build.VERSION.SDK_INT >= 28) {
- sActivityKiller = new ActivityKillerV28();
- } else if (Build.VERSION.SDK_INT >= 26) {
- sActivityKiller = new ActivityKillerV26();
- } else if (Build.VERSION.SDK_INT == 25 || Build.VERSION.SDK_INT == 24) {
- sActivityKiller = new ActivityKillerV24_V25();
- } else if (Build.VERSION.SDK_INT >= 21 && Build.VERSION.SDK_INT <= 23) {
- sActivityKiller = new ActivityKillerV21_V23();
- } else if (Build.VERSION.SDK_INT >= 15 && Build.VERSION.SDK_INT <= 20) {
- sActivityKiller = new ActivityKillerV15_V20();
- } else if (Build.VERSION.SDK_INT < 15) {
- sActivityKiller = new ActivityKillerV15_V20();
- }
- try {
- hookmH();
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- private static void hookmH() throws Exception {
- final int LAUNCH_ACTIVITY = 100;
- final int PAUSE_ACTIVITY = 101;
- final int PAUSE_ACTIVITY_FINISHING = 102;
- final int STOP_ACTIVITY_HIDE = 104;
- final int RESUME_ACTIVITY = 107;
- final int DESTROY_ACTIVITY = 109;
- final int NEW_INTENT = 112;
- final int RELAUNCH_ACTIVITY = 126;
- Class activityThreadClass = Class.forName("android.app.ActivityThread");
- Object activityThread = activityThreadClass.getDeclaredMethod("currentActivityThread").invoke(null);
- Field mhField = activityThreadClass.getDeclaredField("mH");
- mhField.setAccessible(true);
- final Handler mhHandler = (Handler) mhField.get(activityThread);
- Field callbackField = Handler.class.getDeclaredField("mCallback");
- callbackField.setAccessible(true);
- callbackField.set(mhHandler, new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- if (Build.VERSION.SDK_INT >= 28) {//android P 生命周期全部走这
- final int EXECUTE_TRANSACTION = 159;
- if (msg.what == EXECUTE_TRANSACTION) {
- try {
- mhHandler.handleMessage(msg);
- } catch (Throwable throwable) {
- sActivityKiller.finishLaunchActivity(msg);
- notifyException(throwable);
- }
- return true;
- }
- return false;
- }
- switch (msg.what) {
- case LAUNCH_ACTIVITY:// startActivity--> activity.attach activity.onCreate r.activity!=null activity.onStart activity.onResume
- try {
- mhHandler.handleMessage(msg);
- } catch (Throwable throwable) {
- sActivityKiller.finishLaunchActivity(msg);
- notifyException(throwable);
- }
- return true;
- case RESUME_ACTIVITY://回到activity onRestart onStart onResume
- try {
- mhHandler.handleMessage(msg);
- } catch (Throwable throwable) {
- sActivityKiller.finishResumeActivity(msg);
- notifyException(throwable);
- }
- return true;
- case PAUSE_ACTIVITY_FINISHING://按返回键 onPause
- try {
- mhHandler.handleMessage(msg);
- } catch (Throwable throwable) {
- sActivityKiller.finishPauseActivity(msg);
- notifyException(throwable);
- }
- return true;
- case PAUSE_ACTIVITY://开启新页面时,旧页面执行 activity.onPause
- try {
- mhHandler.handleMessage(msg);
- } catch (Throwable throwable) {
- sActivityKiller.finishPauseActivity(msg);
- notifyException(throwable);
- }
- return true;
- case STOP_ACTIVITY_HIDE://开启新页面时,旧页面执行 activity.onStop
- try {
- mhHandler.handleMessage(msg);
- } catch (Throwable throwable) {
- sActivityKiller.finishStopActivity(msg);
- notifyException(throwable);
- }
- return true;
- case DESTROY_ACTIVITY:// 关闭activity onStop onDestroy
- try {
- mhHandler.handleMessage(msg);
- } catch (Throwable throwable) {
- notifyException(throwable);
- }
- return true;
- }
- return false;
- }
- });
- }
- private static void notifyException(Throwable throwable) {
- if (sExceptionHandler == null) {
- return;
- }
- if (isSafeMode()) {
- sExceptionHandler.bandageExceptionHappened(throwable);
- } else {
- sExceptionHandler.uncaughtExceptionHappened(Looper.getMainLooper().getThread(), throwable);
- safeMode();
- }
- }
- public static boolean isSafeMode() {
- return sIsSafeMode;
- }
- private static void safeMode() {
- sIsSafeMode = true;
- if (sExceptionHandler != null) {
- sExceptionHandler.enterSafeMode();
- }
- while (true) {
- try {
- Looper.loop();
- } catch (Throwable e) {
- isChoreographerException(e);
- if (sExceptionHandler != null) {
- sExceptionHandler.bandageExceptionHappened(e);
- }
- }
- }
- }
- /**
- * view measure layout draw时抛出异常会导致Choreographer挂掉
- * <p>
- * 建议直接杀死app。以后的版本会只关闭黑屏的Activity
- *
- * @param e
- */
- private static void isChoreographerException(Throwable e) {
- if (e == null || sExceptionHandler == null) {
- return;
- }
- StackTraceElement[] elements = e.getStackTrace();
- if (elements == null) {
- return;
- }
- for (int i = elements.length - 1; i > -1; i--) {
- if (elements.length - i > 20) {
- return;
- }
- StackTraceElement element = elements[i];
- if ("android.view.Choreographer".equals(element.getClassName())
- && "Choreographer.java".equals(element.getFileName())
- && "doFrame".equals(element.getMethodName())) {
- sExceptionHandler.mayBeBlackScreen(e);
- return;
- }
- }
- }
- }
|