开发安卓的小伙伴都遇到过APP突然崩溃,无响应的情况.如果发生在自己手中,那么还可以通过IDE查看错误日志,但是实际都是发生在用户手中,那么这个时候产生崩溃,无响应ANR异常就很麻烦.无从下手.因此,需要全局异常捕获.也就是对未知异常,程序员没有处理的异常进行处理,记录等便于分析查找原因.
MyUncaughtExceptionHandler.java
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 |
import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.Build; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Locale; /** * @ClassName MyUncaughtExceptionHandler * @Description 全局捕捉异常 * @Author summerain0 * @Date 2020/9/11 15:31 */ public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { // 单例 private static MyUncaughtExceptionHandler myUncaughtExceptionHandler; // 上下文 private Context context; // 会输出到文件中 private StringBuilder stringBuilder; // 系统异常处理器 private Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler; public MyUncaughtExceptionHandler(Context context) { this.context = context; } // 获取单例 public static synchronized MyUncaughtExceptionHandler getInstance(Context ctx) { if (myUncaughtExceptionHandler == null) { myUncaughtExceptionHandler = new MyUncaughtExceptionHandler(ctx); } return myUncaughtExceptionHandler; } // 初始化 public void init() { defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(Thread thread, Throwable throwable) { if (throwable == null) { defaultUncaughtExceptionHandler.uncaughtException(thread, throwable); } // 创建集合对象 stringBuilder = new StringBuilder(); // 记录时间 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSS", Locale.getDefault()); String date = simpleDateFormat.format(new Date()); addMessage("崩溃时间", date); // 记录应用版本信息 try { PackageManager pm = context.getPackageManager(); PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES); addMessage("版本名", pi.versionName); addMessage("版本号", pi.versionCode); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); addMessage("error", "记录版本信息失败!" + e.getMessage()); } // 记录设备信息 Field[] fields = Build.class.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); Object obj = field.get(null); if (obj != null) { addMessage(field.getName(), obj); } } catch (IllegalAccessException e) { e.printStackTrace(); addMessage("error", "记录设备信息失败!" + e.getMessage()); } } // 添加分隔符 addMessage(null, "=============================================================="); addMessage(null, "======================== 崩溃日志 ========================="); addMessage(null, "=============================================================="); // 记录崩溃信息 Writer writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); throwable.printStackTrace(printWriter); Throwable cause = throwable.getCause(); while (cause != null) { cause.printStackTrace(printWriter); cause = cause.getCause(); } printWriter.close(); addMessage(null, writer.toString()); // 生成路径,保存至/Android/data/包名,无需读写权限 try { File root = context.getExternalFilesDir("log"); String filename = date + ".log"; File file = new File(root, filename); FileOutputStream fos = new FileOutputStream(file); fos.write(stringBuilder.toString().getBytes()); fos.close(); } catch (IOException e) { e.printStackTrace(); defaultUncaughtExceptionHandler.uncaughtException(thread, throwable); } } // 添加数据 private void addMessage(String key, Object obj) { // 对数组做一下处理 if (obj instanceof String[]) { String[] list = (String[]) obj; ArrayList<String> array = new ArrayList<>(Arrays.asList(list)); stringBuilder.append(key).append("=").append(array.toString()).append("\n"); } // 其他的都直接添加 if (key == null) { stringBuilder.append(obj) .append("\n"); } else { stringBuilder.append(key) .append("=") .append(obj) .append("\n"); } } } |
MyApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import android.app.Application; /** * @ClassName MyApplication * @Description TODO * @Author summerain0 * @Date 2020/9/11 14:00 */ public class MyApplication extends Application { public static final String TAG = "MyApplication"; @Override public void onCreate() { super.onCreate(); // 初始化异常处理器 MyUncaughtExceptionHandler.getInstance(MyApplication.this).init(); } } |
AndroidManifest.xml
1 2 3 4 |
<application android:name=".MyApplication" ....> </application> |
文章评论