1+ package com .gaolei .mvpmodel .base .utils ;
2+
3+ import android .app .AlarmManager ;
4+ import android .app .PendingIntent ;
5+ import android .content .Context ;
6+ import android .content .Intent ;
7+ import android .content .pm .PackageInfo ;
8+ import android .content .pm .PackageManager ;
9+ import android .os .Environment ;
10+ import android .os .Looper ;
11+ import android .view .Gravity ;
12+ import android .widget .Toast ;
13+
14+
15+ import com .gaolei .mvpmodel .application .CustomApplication ;
16+
17+ import java .io .File ;
18+ import java .io .FileOutputStream ;
19+ import java .io .PrintWriter ;
20+ import java .io .StringWriter ;
21+ import java .io .Writer ;
22+ import java .text .SimpleDateFormat ;
23+ import java .util .Date ;
24+ import java .util .LinkedHashMap ;
25+ import java .util .Map ;
26+
27+ public class CrashHandler implements Thread .UncaughtExceptionHandler {
28+ /**
29+ * 系统默认的异常处理类
30+ */
31+ private Thread .UncaughtExceptionHandler mDefaultHandler ;
32+ Context mcontext ;
33+ private static CrashHandler INSTANCE = new CrashHandler ();
34+ String errorSavePath ;
35+ //用来存储设备信息和异常信息
36+ private Map <String , String > infos = new LinkedHashMap ();
37+
38+ public static CrashHandler getInstance () {
39+ return INSTANCE ;
40+ }
41+
42+ public void init (Context context ) {
43+ mcontext = context ;
44+ mDefaultHandler = Thread .getDefaultUncaughtExceptionHandler ();// 获取默认的异常处理类
45+ Thread .setDefaultUncaughtExceptionHandler (this );// 设置当前处理类为默认的异常处理类
46+ }
47+
48+ @ Override
49+ public void uncaughtException (Thread thread , Throwable ex ) {
50+ if (!handleException (ex ) && mDefaultHandler != null ) {
51+ mDefaultHandler .uncaughtException (thread , ex );// 如果未处理异常,那么系统默认的异常处理类处理
52+ } else {
53+ try {
54+ Thread .sleep (1500 );
55+ } catch (Exception e ) {
56+ // TODO: handle exception
57+ }
58+
59+
60+
61+ //崩溃后,重启应用
62+ Intent intent = new Intent ();
63+ intent .setAction (Intent .ACTION_MAIN );
64+ intent .putExtra ("error_reboot" , true );
65+
66+ PendingIntent pendingIntent = PendingIntent .getActivity (
67+ mcontext .getApplicationContext (), 0 , intent ,
68+ PendingIntent .FLAG_ONE_SHOT );
69+ AlarmManager mgr = (AlarmManager ) mcontext
70+ .getSystemService (Context .ALARM_SERVICE );
71+ mgr .set (AlarmManager .RTC , System .currentTimeMillis () + 1500 ,
72+ pendingIntent ); // 1秒钟后重启应用
73+ android .os .Process .killProcess (android .os .Process .myPid ());
74+ System .exit (10 );
75+ }
76+ }
77+
78+ private boolean handleException (Throwable ex ) {
79+ if (ex == null ) {
80+ return false ;
81+ }
82+ new Thread () {
83+ @ Override
84+ public void run () {
85+ Looper .prepare ();
86+ Toast toast = Toast .makeText (mcontext , "程序出错了,我们会尽快修复,稍后将重启应用!" ,
87+ Toast .LENGTH_LONG );
88+ toast .setGravity (Gravity .CENTER , 0 , 0 );
89+ toast .show ();
90+ Looper .loop ();
91+ }
92+ }.start ();
93+
94+ collectDeviceInfo ();
95+ saveCrashInfoIntoSd (ex );
96+ return true ;// 测试阶段全部抛出
97+ // return false;
98+ }
99+
100+ // 收集设备、软件参数信息
101+ private void collectDeviceInfo () {
102+ try {
103+ PackageManager pm = CustomApplication .context .getPackageManager ();
104+ PackageInfo pi = pm .getPackageInfo (CustomApplication .context .getPackageName (), PackageManager .GET_ACTIVITIES );
105+ if (pi != null ) {
106+ String versionName = pi .versionName == null ? "null" : pi .versionName ;
107+ String versionCode = pi .versionCode + "" ;
108+ infos .put ("systemVersion" , SystemUtil .getSystemVersion ());
109+ infos .put ("deviceModel" , SystemUtil .getSystemModel ());
110+ infos .put ("deviceBrand" , SystemUtil .getDeviceBrand ());
111+ infos .put ("versionName" , versionName );
112+ infos .put ("versionCode" , versionCode );
113+ }
114+ } catch (PackageManager .NameNotFoundException e ) {
115+ }
116+
117+ }
118+
119+ // 保存错误信息到SD卡文件中
120+ private void saveCrashInfoIntoSd (Throwable ex ) {
121+ //创建文件夹
122+ errorSavePath = Environment .getExternalStorageDirectory ().getPath () + "/" + mcontext .getPackageName () + "/crash" ;
123+ File dir = new File (errorSavePath );
124+ if (!dir .exists ()) dir .mkdirs ();
125+
126+ SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss" );
127+ String time = formatter .format (new Date ());
128+ StringBuffer sb = new StringBuffer ();
129+ sb .append ("\n " + time + "\n " );
130+ for (Map .Entry <String , String > entry : infos .entrySet ()) {
131+ String key = entry .getKey ();
132+ String value = entry .getValue ();
133+ sb .append (key + "=" + value + "\n " );
134+ }
135+
136+ sb .append (getCrashInfo (ex ));
137+
138+ try {
139+ //创建文件
140+ String fileName = "crash-" + time + ".txt" ;
141+ File file = new File (errorSavePath + "//" + fileName );
142+ if (!file .exists ()) file .createNewFile ();
143+
144+ FileOutputStream fos = new FileOutputStream (file );
145+ fos .write (sb .toString ().getBytes ());
146+ fos .close ();
147+ } catch (Exception e ) {
148+ e .printStackTrace ();
149+ }
150+ }
151+
152+ /**
153+ * 得到程序崩溃的详细信息
154+ */
155+ public String getCrashInfo (Throwable ex ) {
156+ Writer result = new StringWriter ();
157+ PrintWriter printWriter = new PrintWriter (result );
158+ ex .setStackTrace (ex .getStackTrace ());
159+ ex .printStackTrace (printWriter );
160+ printWriter .close ();
161+ return result .toString ();
162+ }
163+ }
0 commit comments