package org.aisen.wen.support.utils; import android.content.Context; import android.view.InflateException; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.Calendar; /** * 捕捉Crash日志本地文件保存,且OOM导出Hprof文件 * * Created by wangdan on 16/4/26. */ public class CrashHandler implements Thread.UncaughtExceptionHandler { private Thread.UncaughtExceptionHandler mDefHandler; private static CrashHandler mCrashHandler; private Context context; private CrashHandler(Context context) { this.context = context; } public static void setupCrashHandler(Context context) { // 如果初始化在Application中,防止初始化两次创建两个 if (mCrashHandler != null) { return; } mCrashHandler = new CrashHandler(context); mCrashHandler.mDefHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(mCrashHandler); } @Override public void uncaughtException(Thread thread, Throwable ex) { if (isOOM(ex)) { HprofUtils.dumpHprof(context.getExternalFilesDir("logs").getAbsolutePath() + File.separator + "crash" + File.separator); } Logger.printExc(CrashHandler.class, ex); save2File(ex); if (mDefHandler != null) { mDefHandler.uncaughtException(thread, ex); } } private void save2File(Throwable ex) { try { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); ex.printStackTrace(pw); String crashLog = sw.toString(); String filePath = context.getExternalFilesDir("logs").getAbsolutePath() + File.separator + "crash" + File.separator; File file = new File(filePath + File.separator + new SimpleDateFormat("yyyyMMdd_HH-mm-ss-SSS").format(Calendar.getInstance().getTime()) + ".txt"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } if (!file.exists()) { file.createNewFile(); } FileWriter fileWriter = new FileWriter(file); fileWriter.write(crashLog); fileWriter.flush(); fileWriter.close(); } catch (Throwable e) { e.printStackTrace(); } } public static boolean isOOM(Throwable e) { int loopCount = 0; while (e != null && loopCount++ < 5) { if (isOOMInner(e)) { return true; } e = e.getCause(); } return false; } private static boolean isOOMInner(Throwable e) { if (e == null) { return false; } return (e instanceof OutOfMemoryError) || (e instanceof InflateException); } }