0%

Android-App崩溃处理

异常崩溃原因

在 Zygote 进程 fork 出 App 进程后,会调用 zygoteInit 方法,其中会执行 ActivityThread.main() 方法,在此之前会通过 Thread.setDefaultUncaughtExceptionHandler 方法设置 App 的默认异常处理器(打印异常,并终止进程)。

当 App 某个线程中发生异常后,会调用到 ThreadGroup 的 uncaughtException 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}
}

此时当某个线程发生异常时,会触发 ThreadGroup 的该方法,于是会执行默认的 UncaughtExceptionHandler 逻辑,即打印异常,并终止进程。

主线程异常处理

1
2
3
4
5
6
7
8
9
10
11
12
new Handler(Looper.getMainLooper()).post(this::loop);

// 处理主线程崩溃
private void loop() {
try {
Looper.loop();
} catch (Throwable e) {
// 相当于捕获了主线程所有消息的异常,然后重新loop起来
System.out.println("App exception");
loop();
}
}

该方法相当于捕获了主线程所有消息的异常,然后重新loop起来。

子线程异常

通过 Thread.setDefaultUncaughtExceptionHandler 来设置自定义处理拦截。

生命周期异常

替换 ActivityThread.mH.mCallback 来捕获生命周期异常,然后通过 token 来结束 Activity 或者直接杀死进程。