-
Notifications
You must be signed in to change notification settings - Fork 448
/
Cockroach.java
89 lines (75 loc) · 2.86 KB
/
Cockroach.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package com.wanjian.cockroach;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
/**
* Created by wanjian on 2017/2/14.
*/
public final class Cockroach {
public interface ExceptionHandler {
void handlerException(Thread thread, Throwable throwable);
}
private Cockroach() {
}
private static ExceptionHandler sExceptionHandler;
private static Thread.UncaughtExceptionHandler sUncaughtExceptionHandler;
private static boolean sInstalled = false;//标记位,避免重复安装卸载
/**
* 当主线程或子线程抛出异常时会调用exceptionHandler.handlerException(Thread thread, Throwable throwable)
* <p>
* exceptionHandler.handlerException可能运行在非UI线程中。
* <p>
* 若设置了Thread.setDefaultUncaughtExceptionHandler则可能无法捕获子线程异常。
*
* @param exceptionHandler
*/
public static synchronized void install(ExceptionHandler exceptionHandler) {
if (sInstalled) {
return;
}
sInstalled = true;
sExceptionHandler = exceptionHandler;
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
while (true) {
try {
Looper.loop();
} catch (Throwable e) {
// Binder.clearCallingIdentity();
if (e instanceof QuitCockroachException) {
return;
}
if (sExceptionHandler != null) {
sExceptionHandler.handlerException(Looper.getMainLooper().getThread(), e);
}
}
}
}
});
sUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
if (sExceptionHandler != null) {
sExceptionHandler.handlerException(t, e);
}
}
});
}
public static synchronized void uninstall() {
if (!sInstalled) {
return;
}
sInstalled = false;
sExceptionHandler = null;
//卸载后恢复默认的异常处理逻辑,否则主线程再次抛出异常后将导致ANR,并且无法捕获到异常位置
Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
throw new QuitCockroachException("Quit Cockroach.....");//主线程抛出异常,迫使 while (true) {}结束
}
});
}
}