package com.stardust.scriptdroid.tool; /** * Created by Stardust on 2017/2/2. */ import android.content.Intent; import android.util.Log; import android.view.WindowManager; import android.widget.Toast; import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.R; import com.stardust.util.IntentUtil; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.Thread.UncaughtExceptionHandler; public class CrashHandler implements UncaughtExceptionHandler { private static final String TAG = "CrashHandler"; private static int crashCount = 0; private static long firstCrashMillis = 0; private final Class<?> mErrorReportClass; public CrashHandler(Class<?> errorReportClass) { this.mErrorReportClass = errorReportClass; } public void uncaughtException(Thread thread, Throwable ex) { if (causedByBadWindowToken(ex)) { Toast.makeText(App.getApp(), R.string.text_no_floating_window_permission, Toast.LENGTH_SHORT).show(); IntentUtil.goToAppDetailSettings(App.getApp()); return; } try { Log.e(TAG, "Uncaught Exception", ex); if (crashTooManyTimes()) return; String msg = App.getApp().getString(R.string.sorry_for_crash) + ex.toString(); startErrorReportActivity(msg, throwableToString(ex)); System.exit(0); } catch (Throwable throwable) { throwable.printStackTrace(); } } private static boolean causedByBadWindowToken(Throwable e) { while (e != null) { if (e instanceof WindowManager.BadTokenException) { return true; } e = e.getCause(); } return false; } private void startErrorReportActivity(String msg, String detail) { Intent intent = new Intent(App.getApp(), this.mErrorReportClass); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.putExtra("message", msg); intent.putExtra("error", detail); App.getApp().startActivity(intent); } private boolean crashTooManyTimes() { if (crashIntervalTooLong()) { resetCrashCount(); return false; } crashCount++; return crashCount >= 5; } private void resetCrashCount() { firstCrashMillis = System.currentTimeMillis(); crashCount = 0; } private boolean crashIntervalTooLong() { return System.currentTimeMillis() - firstCrashMillis > 3000; } public static String throwableToString(Throwable throwable) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); throwable.printStackTrace(); throwable.printStackTrace(pw); return sw.toString(); } }