我是靠谱客的博主 犹豫火车,这篇文章主要介绍Android全局崩溃捕获,现在分享给大家,希望可以做个参考。

今天出了一个需求,由于APP有很多问题,尤其是崩溃,很让人头疼,所以需要可以把崩溃捕获的一个机制,然后将错误信息上传后台。这种情况我们会接入第三方,比如bugly,友盟等。但是让人头疼的是这是一个内网环境,也就是说没办法接外网,像bugly之类的第三方SDK都是要把错误日志上传到第三方的服务器的。下面是我在网上找的方案。

https://blog.csdn.net/wxx_csdn/article/details/79238842这是原文

首先创建一个类

复制代码
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package com.kinggrid.utils; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; import android.os.Looper; import android.os.Process; import android.support.v4.BuildConfig; import android.util.Log; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Field; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.Locale; import java.util.Map; public class CrashHandlerUtil implements Thread.UncaughtExceptionHandler { public static final String TAG = "CrashHandlerUtil"; //系统默认的UncaughtException处理类 private Thread.UncaughtExceptionHandler mDefaultHandler; //CrashHandler实例 private static CrashHandlerUtil INSTANCE = new CrashHandlerUtil(); //程序的Context对象 private Context mContext; //用来存储设备信息和异常信息 private Map<String, String> infos = new HashMap<>(); //用于格式化日期,作为日志文件名的一部分 private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINA); private String crashTip = "应用开小差了,稍后重启下,亲!"; public String getCrashTip() { return crashTip; } public void setCrashTip(String crashTip) { this.crashTip = crashTip; } private CrashHandlerUtil() { } public static CrashHandlerUtil getInstance() { return INSTANCE; } public void init(Context context) { mContext = context; //获取系统默认的UncaughtException处理器 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); //设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler(this); } /** * 当UncaughtException发生时会转入该函数来处理 * * @param thread 线程 * @param ex 异常 */ @Override public void uncaughtException(Thread thread, Throwable ex) { if (!handleException(ex) && mDefaultHandler != null) { //如果用户没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); } else { try { Thread.sleep(3000); } catch (InterruptedException e) { Log.e("error : ", e.toString()); e.printStackTrace(); } //退出程序 //退出JVM(java虚拟机),释放所占内存资源,0表示正常退出(非0的都为异常退出) System.exit(0); //从操作系统中结束掉当前程序的进程 Process.killProcess(Process.myPid()); } } /** * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. * * @param throwable 异常 * @return true:如果处理了该异常信息;否则返回false. */ private boolean handleException(final Throwable throwable) { if (throwable == null) { return false; } //使用Toast来显示异常信息 new Thread() { @Override public void run() { Looper.prepare(); throwable.printStackTrace(); CommonUtils.toastWord(mContext,getCrashTip()); Looper.loop(); } }.start(); //收集设备参数信息 collectDeviceInfo(mContext); //保存日志文件 saveCrashInfo2File(throwable); return true; } /** * 收集设备参数信息 * * @param ctx 上下文 */ public void collectDeviceInfo(Context ctx) { try { PackageManager pm = ctx.getPackageManager(); PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); if (pi != null) { String versionName = pi.versionName == null ? "null" : pi.versionName; String versionCode = pi.versionCode + ""; infos.put("versionName", versionName); infos.put("versionCode", versionCode); } } catch (PackageManager.NameNotFoundException e) { Log.e("ttt", "an error occured when collect package info:"+e.toString()); } Field[] fields = Build.class.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); infos.put(field.getName(), field.get(null).toString()); // Logger.e(field.getName() + " : " + field.get(null)); } catch (Exception e) { Log.e("ttt", "an error occured when collect crash info:"+e.toString()); } } } /** * 保存错误信息到文件中 * * @param ex 异常 * @return 返回文件名称, 便于将文件传送到服务器 */ private String saveCrashInfo2File(Throwable ex) { StringBuffer sb = new StringBuffer(); for (Map.Entry<String, String> entry : infos.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); sb.append(key + "=" + value + "n"); } Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); ex.printStackTrace(printWriter); Throwable cause = ex.getCause(); while (cause != null) { cause.printStackTrace(printWriter); cause = cause.getCause(); } printWriter.close(); String result = writer.toString(); sb.append(result); Log.e("ttt", sb.toString()); if(BuildConfig.DEBUG) { return null; } /* 这个 crashInfo 就是我们收集到的所有信息,可以做一个异常上报的接口用来提交用户的crash信息 */ String crashInfo = sb.toString(); Log.e("hhhhhhhhhhhhhhhh",crashInfo); return null; } }

然后在Application中初始化这个工具

复制代码
1
CrashHandlerUtil.getInstance().init(context);

这样,在CrashHandlerUtil类的saveCrashInfo2File方法中,crashInfo就是我们要的信息,信息示例如下

复制代码
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
SUPPORTED_64_BIT_ABIS=[Ljava.lang.String;@491cada versionCode=2 BOARD=rk30sdk BOOTLOADER=unknown TYPE=userdebug ID=LMY49F TIME=1541554307000 BRAND=rockchip TAG=Build SERIAL=XR4GSABRDB HARDWARE=rk30board SUPPORTED_ABIS=[Ljava.lang.String;@1c7dfb0b CPU_ABI=armeabi-v7a RADIO=unknown IS_DEBUGGABLE=true MANUFACTURER=rockchip SUPPORTED_32_BIT_ABIS=[Ljava.lang.String;@22bccc85 TAGS=test-keys CPU_ABI2=armeabi UNKNOWN=unknown USER=root FINGERPRINT=rockchip/rk312x/rk312x:5.1.1/LMY49F/root11070931:userdebug/test-keys HOST=android-compile PRODUCT=rk312x versionName=1.1 DISPLAY=rk312x-userdebug 5.1.1 LMY49F eng.root.20181107.093048 test-keys MODEL=rk312x DEVICE=rk312x java.lang.ArithmeticException: divide by zero at com.kinggrid.test.HomeActivityTwo$1.onRefresh(HomeActivityTwo.java:151) at com.scwang.smartrefresh.layout.SmartRefreshLayout$2.onAnimationEnd(SmartRefreshLayout.java:1304) at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1171) at android.animation.ValueAnimator$AnimationHandler.doAnimationFrame(ValueAnimator.java:722) at android.animation.ValueAnimator$AnimationHandler.run(ValueAnimator.java:738) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) at android.view.Choreographer.doCallbacks(Choreographer.java:580) at android.view.Choreographer.doFrame(Choreographer.java:549) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5280) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:963) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:758)

这样,相关的硬件信息和错误信息都会在这个字符串中显示。接下来只需要我们把这个字符串保存在本地,当我们再进来的时候,将文档上传到后台就可以了。

最后

以上就是犹豫火车最近收集整理的关于Android全局崩溃捕获的全部内容,更多相关Android全局崩溃捕获内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(80)

评论列表共有 0 条评论

立即
投稿
返回
顶部