一、崩溃检测原理

通过thread.setDefaultUncaughtExceptionHandler(),设置默认异常处理Handler,对未被捕获异常进行处理。

虚拟机会将没有处理的异常交给默认的UncaughtExceptionHandler处理,我们需要做的是将异常上报至服务端处理,APP端按照原本的逻辑走下去。
代码很简单:

/*** 系统默认的handler*/Thread.UncaughtExceptionHandler mDefaultHandler;mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {     @Override     public void uncaughtException(Thread t, Throwable e) {         handleException(thread, ex);         //收集数据上报之后交给默认的handler处理         if (mDefaultHandler != null) {         mDefaultHandler.uncaughtException(thread, ex);         }     }});

我们在handleException中手机设备的硬件和软件信息将其上报给服务端。

二、ANR检测

方法一:通过向UI线程发送消息判断

Android UI线程是一个通过Looper进行消息循环的过程,UI线程不断的从消息队列中获取消息进行处理,而UI线程不会处理耗时任务,所以向UI线程发送的消息会得到及时处理,如果超过一段时间没有被处理,那说明发生了ANR。

所以实现方案是:
开一个子线程,定时想UI线程发送消息。若没有及时处理,说明主线程没有响应,认为是ANR异常。

@Override    public void run() {        while (true) {            watchDogHandler.sendEmptyMessage(MESSAGE_WATCHDOG_TIME_TICK);            try {                Thread.sleep(ACTIVITY_ANR_TIMEOUT);            } catch (InterruptedException e) {                e.printStackTrace();            }            //如果相等,说明过了ACTIVITY_ANR_TIMEOUT的时间后watchDogHandler仍没有处理消息,已经ANR了            if (timeTick == lastTimeTick) {               //todo 上报ANR异常            } else {                lastTimeTick = timeTick;            }        }    }    private class WatchDogHandler extends Handler {        @Override        public void handleMessage(Message msg) {            timeTick++;            timeTick = timeTick % Integer.MAX_VALUE;            LogUtil.i("timeTick = " + timeTick);            LogUtil.i("lastTimeTick = " + lastTimeTick);        }    }

方法二:通过监控主线程处理消息的时长判断

通过查看Looper源码知道,里面有一段很关键的代码如下:

public static void loop() {         ...        for (;;) {            ...            if (logging != null) {                logging.println(">>>>> Dispatching to " + msg.target + " " +                        msg.callback + ": " + msg.what);            }            ...            msg.target.dispatchMessage(msg);            ...            if (logging != null) {                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);            }            ...            }            ...        }    }

从上面这段代码可以看出,loop方法在处理每一个消息前后都会打印相关的日志,那么我们可以设置自定义的logging来判断每次处理消息的耗时。

Looper.getMainLooper().setMessageLogging(new Printer() {     @Override     public void println(String x) {         //通过计算两次打印日志的时间来判断处理消息的时间是否过长,从而认为是ANR。     }});

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. Android(安卓)中handler 的应用
  3. Android应用程序键盘(Keyboard)消息处理机制分析(三)
  4. Android:Android基础知识
  5. android有了eventbus,一切与关界面通信问题迎刃而解。
  6. Android中Handler消息处理
  7. Android(安卓)四种异步操作UI界面的方法
  8. Android在非UI线程中更新UI的方法
  9. 【移动开发】Android游戏开发SurfaceView应用----手指发动小球(小

随机推荐

  1. Android系统自带主题样式(android:theme),An
  2. Android界面——LinearLayout和RelativeL
  3. RelativeLayout 常用XML 属性
  4. android Wifi自动连接
  5. Android使用ViewFlipper做页面切换,与手势
  6. Android发展史
  7. 写一个没有Activity的 HelloWorld for an
  8. 通过xml加载菜单Menus
  9. Android图形系统分析与移植--五、Android
  10. android设置在ListView中让TextView滚动