本篇文章包含以下内容:
Crash异常捕获的简单使用 Crash异常捕获并发送到服务器
在项目中,我们常常会遇到Crash的现象,也就是程序崩溃的时候,这个时候最常看到的就是这个界面
如果你的项目已经发布到市场上了,这样的崩溃对于开发人员是看不到的,所以我们得想方法将崩溃信息发送到服务器,交给我们的程序员查看,Google考虑到这一点,也提供了Thread.UncaughtExceptionHandler接口来实现这一问题
一、Crash异常捕获的简单使用
创建Crash异常捕获很简单,主要的步骤有:
创建BaseApplication继承Application并实现Thread.UncaughtExceptionHandler 通过Thread.setDefaultUncaughtExceptionHandler(this)设置默认的异常捕获 最后在manifests中注册创建的BaseApplication
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
class
BaseApplication
extends
Application
implements
Thread.UncaughtExceptionHandler {
@Override
public
void
onCreate() {
super
.onCreate();
//设置异常捕获
Thread.setDefaultUncaughtExceptionHandler(
this
);
}
@Override
public
void
uncaughtException(
final
Thread thread,
final
Throwable ex) {
//当有异常产生时执行该方法
}
}
|
我们可以在uncaughtException()方法中输出异常信息,并让它隔两秒杀死自己进程,这样就不会弹出崩溃的弹窗,让它直接退出程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/**
* 当有异常产生时执行该方法
* @param thread 当前线程
* @param ex 异常信息
*/
@Override
public
void
uncaughtException(
final
Thread thread,
final
Throwable ex) {
new
Thread(
new
Runnable() {
@Override
public
void
run() {
Log.e(
"TAG"
,
"currentThread:"
+Thread.currentThread()+
"---thread:"
+thread.getId()+
"---ex:"
+ex.toString());
}
}).start();
SystemClock.sleep(
2000
);
android.os.Process.killProcess(android.os.Process.myPid());
}
|
最后一步,别忘了在manifests中注册BaseApplication
1
|
</application>
|
我们通过运行这个方法,来测试我们的程序
1
2
3
|
private
void
testError() {
int
a =
10
/
0
;
}
|
查看Log信息,验证我们的错误信息
1
2
3
|
12
-
18
11
:
40
:
02.074
7510
-
7555
/com.handsome.ap E/TAG: currentThread:Thread[Thread-
325
,
5
,main]---thread:
1
---ex:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.handsome.ap/com.handsome.ap.Activity.MainActivity}:
java.lang.ArithmeticException: pide by zero
|
完整代码
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
|
public
class
BaseApplication
extends
Application
implements
Thread.UncaughtExceptionHandler {
@Override
public
void
onCreate() {
super
.onCreate();
//设置异常捕获
Thread.setDefaultUncaughtExceptionHandler(
this
);
}
/**
* 当有异常产生时执行该方法
* @param thread 当前线程
* @param ex 异常信息
*/
@Override
public
void
uncaughtException(
final
Thread thread,
final
Throwable ex) {
new
Thread(
new
Runnable() {
@Override
public
void
run() {
Log.e(
"TAG"
,
"currentThread:"
+Thread.currentThread()+
"---thread:"
+thread.getId()+
"---ex:"
+ex.toString());
}
}).start();
SystemClock.sleep(
2000
);
android.os.Process.killProcess(android.os.Process.myPid());
}
}
|
二、Crash异常捕获并发送到服务器
其实这里就是将上面的简单使用进行封装,在一个类中处理相关的逻辑,主要步骤和上面是一样的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public
class
CrashHandler
implements
Thread.UncaughtExceptionHandler {
/**
* 捕获异常回掉
*
* @param thread 当前线程
* @param ex 异常信息
*/
@Override
public
void
uncaughtException(Thread thread, Throwable ex) {
//导出异常信息到SD卡
dumpExceptionToSDCard(ex);
//上传异常信息到服务器
uploadExceptionToServer(ex);
//延时1秒杀死进程
SystemClock.sleep(
2000
);
Process.killProcess(Process.myPid());
}
}
|
我们为下面的信息保存先提供一些成员变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//文件夹目录
private
static
final
String PATH = Environment.getExternalStorageDirectory().getPath() +
"/crash_log/"
;
//文件名
private
static
final
String FILE_NAME =
"crash"
;
//文件名后缀
private
static
final
String FILE_NAME_SUFFIX =
".trace"
;
//上下文
private
Context mContext;
//单例模式
private
static
CrashHandler sInstance =
new
CrashHandler();
private
CrashHandler() {}
public
static
CrashHandler getInstance() {
return
sInstance;
}
|
提供一个初始化的方法,记得调用Thread.setDefaultUncaughtExceptionHandler(this)这个方法
1
2
3
4
5
6
7
8
9
10
11
|
/**
* 初始化方法
*
* @param context
*/
public
void
init(Context context) {
//将当前实例设为系统默认的异常处理器
Thread.setDefaultUncaughtExceptionHandler(
this
);
//获取Context,方便内部使用
mContext = context.getApplicationContext();
}
|
剩下的就是保存异常信息了,这里发送到服务端采用的是Bmob第三方后端云
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
|
/**
* 导出异常信息到SD卡
*
* @param ex
*/
private
void
dumpExceptionToSDCard(Throwable ex) {
if
(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return
;
}
//创建文件夹
File dir =
new
File(PATH);
if
(!dir.exists()) {
dir.mkdirs();
}
//获取当前时间
long
current = System.currentTimeMillis();
String time =
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).format(
new
Date(current));
//以当前时间创建log文件
File file =
new
File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
try
{
//输出流操作
PrintWriter pw =
new
PrintWriter(
new
BufferedWriter(
new
FileWriter(file)));
//导出手机信息和异常信息
PackageManager pm = mContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
pw.println(
"发生异常时间:"
+ time);
pw.println(
"应用版本:"
+ pi.versionName);
pw.println(
"应用版本号:"
+ pi.versionCode);
pw.println(
"android版本号:"
+ Build.VERSION.RELEASE);
pw.println(
"android版本号API:"
+ Build.VERSION.SDK_INT);
pw.println(
"手机制造商:"
+ Build.MANUFACTURER);
pw.println(
"手机型号:"
+ Build.MODEL);
ex.printStackTrace(pw);
//关闭输出流
pw.close();
}
catch
(Exception e) {
}
}
/**
* 上传异常信息到服务器
*
* @param ex
*/
private
void
uploadExceptionToServer(Throwable ex) {
Error error =
new
Error(ex.getMessage());
error.save(
new
SaveListener<string>() {
@Override
public
void
done(String objectId, BmobException e) {
}
});
}</string>
|
在我们的Application中创建该异常捕获
1
2
|
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(
this
);
|
我们同样按照上面的方法来测试这个异常捕获,运行程序,在文件夹中找到我们创建的目录
找到对应文件
查看对应信息
后台数据库的信息
完整代码
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
|
public
class
CrashHandler
implements
Thread.UncaughtExceptionHandler {
//文件夹目录
private
static
final
String PATH = Environment.getExternalStorageDirectory().getPath() +
"/crash_log/"
;
//文件名
private
static
final
String FILE_NAME =
"crash"
;
//文件名后缀
private
static
final
String FILE_NAME_SUFFIX =
".trace"
;
//上下文
private
Context mContext;
//单例模式
private
static
CrashHandler sInstance =
new
CrashHandler();
private
CrashHandler() {}
public
static
CrashHandler getInstance() {
return
sInstance;
}
/**
* 初始化方法
*
* @param context
*/
public
void
init(Context context) {
//将当前实例设为系统默认的异常处理器
Thread.setDefaultUncaughtExceptionHandler(
this
);
//获取Context,方便内部使用
mContext = context.getApplicationContext();
}
/**
* 捕获异常回掉
*
* @param thread 当前线程
* @param ex 异常信息
*/
@Override
public
void
uncaughtException(Thread thread, Throwable ex) {
//导出异常信息到SD卡
dumpExceptionToSDCard(ex);
//上传异常信息到服务器
uploadExceptionToServer(ex);
//延时1秒杀死进程
SystemClock.sleep(
2000
);
Process.killProcess(Process.myPid());
}
/**
* 导出异常信息到SD卡
*
* @param ex
*/
private
void
dumpExceptionToSDCard(Throwable ex) {
if
(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return
;
}
//创建文件夹
File dir =
new
File(PATH);
if
(!dir.exists()) {
dir.mkdirs();
}
//获取当前时间
long
current = System.currentTimeMillis();
String time =
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
).format(
new
Date(current));
//以当前时间创建log文件
File file =
new
File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
try
{
//输出流操作
PrintWriter pw =
new
PrintWriter(
new
BufferedWriter(
new
FileWriter(file)));
//导出手机信息和异常信息
PackageManager pm = mContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
pw.println(
"发生异常时间:"
+ time);
pw.println(
"应用版本:"
+ pi.versionName);
pw.println(
"应用版本号:"
+ pi.versionCode);
pw.println(
"android版本号:"
+ Build.VERSION.RELEASE);
pw.println(
"android版本号API:"
+ Build.VERSION.SDK_INT);
pw.println(
"手机制造商:"
+ Build.MANUFACTURER);
pw.println(
"手机型号:"
+ Build.MODEL);
ex.printStackTrace(pw);
//关闭输出流
pw.close();
}
catch
(Exception e) {
}
}
/**
* 上传异常信息到服务器
*
* @param ex
*/
private
void
uploadExceptionToServer(Throwable ex) {
Error error =
new
Error(ex.getMessage());
error.save(
new
SaveListener<string>() {
@Override
public
void
done(String objectId, BmobException e) {
}
});
}
}
</string>
|
到这里我们的Crash异常捕获就结束了,很简单的一段代码就可以解决你缺少的项目经验
转自:https://www.2cto.com/kf/201612/578595.html