抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

前言

开发安卓的小伙伴都遇到过APP突然崩溃,无响应的情况.如果发生在自己手中,那么还可以通过IDE查看错误日志,但是实际都是发生在用户手中,那么这个时候产生崩溃,无响应ANR异常就很麻烦.无从下手.因此,需要全局异常捕获.也就是对未知异常,程序员没有处理的异常进行处理,记录等便于分析查找原因.

源码

MyUncaughtExceptionHandler.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;

/**
* @ClassName MyUncaughtExceptionHandler
* @Description 全局捕捉异常
* @Author summerain0
* @Date 2020/9/11 15:31
*/
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
// 单例
private static MyUncaughtExceptionHandler myUncaughtExceptionHandler;
// 上下文
private Context context;
// 会输出到文件中
private StringBuilder stringBuilder;
// 系统异常处理器
private Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;

public MyUncaughtExceptionHandler(Context context) {
this.context = context;
}

// 获取单例
public static synchronized MyUncaughtExceptionHandler getInstance(Context ctx) {
if (myUncaughtExceptionHandler == null) {
myUncaughtExceptionHandler = new MyUncaughtExceptionHandler(ctx);
}
return myUncaughtExceptionHandler;
}

// 初始化
public void init() {
defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}

@Override
public void uncaughtException(Thread thread, Throwable throwable) {
if (throwable == null) {
defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
}

// 创建集合对象
stringBuilder = new StringBuilder();

// 记录时间
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSS", Locale.getDefault());
String date = simpleDateFormat.format(new Date());
addMessage("崩溃时间", date);

// 记录应用版本信息
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
addMessage("版本名", pi.versionName);
addMessage("版本号", pi.versionCode);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
addMessage("error", "记录版本信息失败!" + e.getMessage());
}

// 记录设备信息
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
Object obj = field.get(null);
if (obj != null) {
addMessage(field.getName(), obj);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
addMessage("error", "记录设备信息失败!" + e.getMessage());
}
}

// 添加分隔符
addMessage(null, "==============================================================");
addMessage(null, "======================== 崩溃日志 =========================");
addMessage(null, "==============================================================");

// 记录崩溃信息
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
throwable.printStackTrace(printWriter);
Throwable cause = throwable.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
addMessage(null, writer.toString());

// 生成路径,保存至/Android/data/包名,无需读写权限
try {
File root = context.getExternalFilesDir("log");
String filename = date + ".log";
File file = new File(root, filename);
FileOutputStream fos = new FileOutputStream(file);
fos.write(stringBuilder.toString().getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
}
}

// 添加数据
private void addMessage(String key, Object obj) {
// 对数组做一下处理
if (obj instanceof String[]) {
String[] list = (String[]) obj;
ArrayList<String> array = new ArrayList<>(Arrays.asList(list));
stringBuilder.append(key).append("=").append(array.toString()).append("\n");
}
// 其他的都直接添加
if (key == null) {
stringBuilder.append(obj)
.append("\n");
} else {
stringBuilder.append(key)
.append("=")
.append(obj)
.append("\n");
}
}

}

MyApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import android.app.Application;

/**
* @ClassName MyApplication
* @Description TODO
* @Author summerain0
* @Date 2020/9/11 14:00
*/
public class MyApplication extends Application {
public static final String TAG = "MyApplication";

@Override
public void onCreate() {
super.onCreate();
// 初始化异常处理器
MyUncaughtExceptionHandler.getInstance(MyApplication.this).init();
}
}

AndroidManifest.xml

1
2
3
4
<application
android:name=".MyApplication"
....>
</application>

评论