前言
小巫最近由于工作原因面临技术转型,从一个App开发者转变为SDK开发者,这两者的区别是非常明显的,从用户角度来讲,app开发主要面向普通的用户需求,然而SDK开发面向的却是开发人员;从技术角度来讲,app开发更多的只是UI层面、基于数据流的技术实现,而SDK开发可能就要涉及更多复杂的需求、更多底层相关的技术实现。前面我在公众号分享了一篇文章:一个好的SDK或好的开放平台应该为开发者提供什么?,大家有兴趣可以看看。本系列博文主要是想跟大家分享一下在Android平台中如何进行Crash分析并解决问题并告诉大家如何通过bugly进行崩溃捕获快速定位问题。
什么是Crash?
想必这个只要从事过编程工作的同学一定知道是什么?这里我们进行一些概念上的普及:
Crash就是由于代码异常而导致App非正常退出现象,也就是我们常说的『崩溃』
Android中有哪些类型Crash
通常情况下会有以下两种类型Crash:
- Java Crash
- Native Crash
本篇先探讨Java Crash,Native Crash我们会在下一篇重点讨论。
Java Crash在Android上的特点
1. 这类错误一般是由Java层代码触发的
2. 一般情况下程序出错时会弹出提示框,JVM虚拟机退出
3. 一般的Crash工具都能够捕获,系统也提供了API
举个栗子
我们可以看到,button是没有被实例化的,我们调用它的方法就会让程序崩溃,如下图所示:
通过Crash堆栈信息定位问题
上面就是一个很简单的Crash啦,相信很多同学在开发过程中一定遇到过这种情况,万恶的空指针啊,啊,啊。我们来看看logcat给我们输出的堆栈信息:
通过logcat查看Error级别日志,就可以完整看到打印出来的堆栈信息,我们找到『Caused by』信息:
- 1
- 1
这个日志很明确告诉我们,这个crash是由于空指针异常引起的,尝试通过一个空对象引用去调用虚方法setOnClickListener在com.devilwwj.androidcreashdemo.MainActivity.onCreate方法里,在MainActivity.java文件的18行的位置。
解决问题
上一节我们很轻松定位到问题,我们升华一下把它解决掉,我们找到18行,修改代码如下:
这个时候程序就正常运行了,是不是很简单啊,但这种情况是自己在开发中调试运行时可以通过logcat来定位问题,但如果产品上线之后你怎么办,用户都是小白哦,可不会给你提供错误日志,这个就是本篇文章要讲的重点,如果要让我们自己记录错误日志,怎么做?
通过UncaughtExceptionHandler来记录dump异常日志
- 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
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 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
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
上面是核心代码,可以直接拿去用,可以在Application类中进行初始化:
如果程序发生异常,就会将异常写入到指定文件中,日志的格式你可以自己指定,如果有上传服务器记录crash的需求就可以通过POST方式将文件上传,具体实现方式跟后台沟通即可。
最终的效果如下:
当然上面只适用于Java Crash捕获,如果想更专业捕获到异常并更高效分析程序问题,可以尝试使用专业的第三方SDK来实现,这里推荐『腾讯Bugly』,可以参考一下笔者前面发表的文章『快速集成Bugly Android SDK』。
总结
关于Java Crash的分析已经介绍完了,相对还是比较简单,通过简单的方式就能够捕获到异常,但别忘了,Android最头痛的不是这种异常,而是Native层的异常,有时候就算能让你拿到堆栈信息你也不一定会解决问题,比如你使用了第三方的so库,如果发生崩溃了,你也会崩溃的。想了解更多内容,敬请关注下一篇『Android Crash之Native Crash分享』。
Java Crash:http://blog.youkuaiyun.com/wwj_748/article/details/51520020
Native Crash:http://blog.youkuaiyun.com/wwj_748/article/details/51542359