UncaughtExceptionHandlerImpl.java 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package com.emato.ich.crash;
  2. import android.annotation.SuppressLint;
  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.Build;
  10. import android.os.Environment;
  11. import android.os.Looper;
  12. import android.util.Log;
  13. import android.widget.Toast;
  14. import com.emato.ich.MainActivity;
  15. import com.emato.ich.message.ICHPublishClient;
  16. import com.emato.ich.message.ICHTopic;
  17. import com.emato.ich.utils.BaseUtils;
  18. import org.eclipse.paho.client.mqttv3.MqttMessage;
  19. import java.io.ByteArrayOutputStream;
  20. import java.io.File;
  21. import java.io.FileOutputStream;
  22. import java.io.PrintWriter;
  23. import java.io.StringWriter;
  24. import java.io.Writer;
  25. import java.lang.reflect.Field;
  26. import java.text.DateFormat;
  27. import java.text.SimpleDateFormat;
  28. import java.util.Date;
  29. import java.util.HashMap;
  30. import java.util.Iterator;
  31. import java.util.Map;
  32. public class UncaughtExceptionHandlerImpl implements Thread.UncaughtExceptionHandler {
  33. private static final String TAG = UncaughtExceptionHandlerImpl.class.getName();
  34. private static UncaughtExceptionHandlerImpl INSTANCE;
  35. private Thread.UncaughtExceptionHandler mDefaultHandler;
  36. private Context mContext;
  37. private Map<String, String> infos = new HashMap();
  38. @SuppressLint({"SimpleDateFormat"})
  39. private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
  40. private boolean mIsDebug;
  41. private boolean mIsRestartApp;
  42. private long mRestartTime;
  43. private Class mRestartActivity;
  44. private String mTips;
  45. private UncaughtExceptionHandlerImpl() {
  46. }
  47. public static UncaughtExceptionHandlerImpl getInstance() {
  48. if (INSTANCE == null) {
  49. INSTANCE = new UncaughtExceptionHandlerImpl();
  50. }
  51. return INSTANCE;
  52. }
  53. public void init(Context context, boolean isDebug, boolean isRestartApp, long restartTime, Class restartActivity) {
  54. this.mIsRestartApp = isRestartApp;
  55. this.mRestartTime = restartTime;
  56. this.mRestartActivity = restartActivity;
  57. this.init(context, isDebug);
  58. }
  59. public void init(Context context, boolean isDebug) {
  60. this.mTips = "很抱歉,程序出现异常,即将退出...";
  61. this.mIsDebug = isDebug;
  62. this.mContext = context;
  63. this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
  64. Thread.setDefaultUncaughtExceptionHandler(this);
  65. }
  66. @SuppressLint("WrongConstant")
  67. public void uncaughtException(Thread thread, Throwable ex) {
  68. // TODO 发送异常信息
  69. MqttMessage mqttMessage = new MqttMessage();
  70. mqttMessage.setQos(1);
  71. mqttMessage.setPayload(getStackTrace(ex).toByteArray());
  72. ICHPublishClient.getInstance().publish(String.format(ICHTopic.ERROR_LOG_REPORT, BaseUtils.getClientId()), mqttMessage);
  73. if (!this.handleException(ex) && this.mDefaultHandler != null) {
  74. this.mDefaultHandler.uncaughtException(thread, ex);
  75. } else {
  76. try {
  77. Thread.sleep(1000L);
  78. } catch (InterruptedException var6) {
  79. Log.e(TAG, "error 出现未知异常: ", var6);
  80. mqttMessage.setPayload(getStackTrace(var6).toByteArray());
  81. ICHPublishClient.getInstance().publish(String.format(ICHTopic.ERROR_LOG_REPORT, BaseUtils.getClientId()), mqttMessage);
  82. }
  83. if (this.mIsRestartApp) {
  84. Intent intent = new Intent(this.mContext.getApplicationContext(), this.mRestartActivity);
  85. @SuppressLint("WrongConstant") AlarmManager mAlarmManager = (AlarmManager)this.mContext.getSystemService(Context.ALARM_SERVICE);
  86. @SuppressLint("WrongConstant") PendingIntent restartIntent = PendingIntent.getActivity(this.mContext.getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
  87. mAlarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + this.mRestartTime, restartIntent);
  88. }
  89. // android.os.Process.killProcess(android.os.Process.myPid());
  90. ((CrashApplication)this.mContext.getApplicationContext()).removeAllActivity();
  91. }
  92. }
  93. private static ByteArrayOutputStream getStackTrace(Throwable t) {
  94. ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream();
  95. t.printStackTrace(new java.io.PrintWriter(buf, true));
  96. return buf;
  97. }
  98. private boolean handleException(final Throwable ex) {
  99. if (ex == null) {
  100. return false;
  101. } else {
  102. (new Thread() {
  103. @SuppressLint("WrongConstant")
  104. public void run() {
  105. Looper.prepare();
  106. // Toast.makeText(UncaughtExceptionHandlerImpl.this.mContext, UncaughtExceptionHandlerImpl.this.getTips(ex), 1).show();
  107. Toast.makeText(UncaughtExceptionHandlerImpl.this.mContext, "很抱歉,程序出现异常,即将退出...", 1).show();
  108. Looper.loop();
  109. }
  110. }).start();
  111. return true;
  112. }
  113. }
  114. private String getTips(Throwable ex) {
  115. if (ex instanceof SecurityException) {
  116. if (ex.getMessage().contains("android.permission.CAMERA")) {
  117. this.mTips = "请授予应用相机权限,程序出现异常,即将退出.";
  118. } else if (ex.getMessage().contains("android.permission.RECORD_AUDIO")) {
  119. this.mTips = "请授予应用麦克风权限,程序出现异常,即将退出。";
  120. } else if (ex.getMessage().contains("android.permission.WRITE_EXTERNAL_STORAGE")) {
  121. this.mTips = "请授予应用存储权限,程序出现异常,即将退出。";
  122. } else if (ex.getMessage().contains("android.permission.READ_PHONE_STATE")) {
  123. this.mTips = "请授予应用电话权限,程序出现异常,即将退出。";
  124. } else if (!ex.getMessage().contains("android.permission.ACCESS_COARSE_LOCATION") && !ex.getMessage().contains("android.permission.ACCESS_FINE_LOCATION")) {
  125. this.mTips = "很抱歉,程序出现异常,即将退出,请检查应用权限设置。";
  126. } else {
  127. this.mTips = "请授予应用位置信息权,很抱歉,程序出现异常,即将退出。";
  128. }
  129. }
  130. return this.mTips;
  131. }
  132. public void collectDeviceInfo(Context ctx) {
  133. try {
  134. PackageManager pm = ctx.getPackageManager();
  135. @SuppressLint("WrongConstant") PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), 1);
  136. if (pi != null) {
  137. String versionName = pi.versionName == null ? "null" : pi.versionName;
  138. String versionCode = pi.versionCode + "";
  139. this.infos.put("versionName", versionName);
  140. this.infos.put("versionCode", versionCode);
  141. }
  142. } catch (PackageManager.NameNotFoundException var9) {
  143. Log.e(TAG, "an error occured when collect package info", var9);
  144. }
  145. Field[] fields = Build.class.getDeclaredFields();
  146. Field[] var11 = fields;
  147. int var12 = fields.length;
  148. for(int var13 = 0; var13 < var12; ++var13) {
  149. Field field = var11[var13];
  150. try {
  151. field.setAccessible(true);
  152. this.infos.put(field.getName(), field.get((Object)null).toString());
  153. Log.d(TAG, field.getName() + " : " + field.get((Object)null));
  154. } catch (Exception var8) {
  155. Log.e(TAG, "an error occured when collect crash info", var8);
  156. }
  157. }
  158. }
  159. private String saveCrashInfo2File(Throwable ex) {
  160. StringBuffer sb = new StringBuffer();
  161. Iterator var3 = this.infos.entrySet().iterator();
  162. String result;
  163. while(var3.hasNext()) {
  164. Map.Entry<String, String> entry = (Map.Entry)var3.next();
  165. String key = (String)entry.getKey();
  166. result = (String)entry.getValue();
  167. sb.append(key + "=" + result + "\n");
  168. }
  169. Writer writer = new StringWriter();
  170. PrintWriter printWriter = new PrintWriter(writer);
  171. ex.printStackTrace(printWriter);
  172. for(Throwable cause = ex.getCause(); cause != null; cause = cause.getCause()) {
  173. cause.printStackTrace(printWriter);
  174. }
  175. printWriter.close();
  176. result = writer.toString();
  177. sb.append(result);
  178. try {
  179. long timestamp = System.currentTimeMillis();
  180. String time = this.formatter.format(new Date());
  181. String fileName = "crash-" + time + "-" + timestamp + ".log";
  182. if (Environment.getExternalStorageState().equals("mounted")) {
  183. String path = "/sdcard/" + this.mContext.getPackageName() + "/crash/";
  184. File dir = new File(path);
  185. if (!dir.exists()) {
  186. dir.mkdirs();
  187. }
  188. FileOutputStream fos = new FileOutputStream(path + fileName);
  189. fos.write(sb.toString().getBytes());
  190. fos.close();
  191. }
  192. return fileName;
  193. } catch (Exception var14) {
  194. Log.e(TAG, "an error occured while writing file...", var14);
  195. return null;
  196. }
  197. }
  198. }