package com.shayu.phonelive; import android.app.Application; import android.content.Context; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.widget.Toast; import com.google.firebase.crashlytics.FirebaseCrashlytics; import com.yunbao.common.BuildConfig; import com.yunbao.common.bean.CrashSaveBean; import com.yunbao.common.utils.AppManager; import com.yunbao.common.utils.FileUtil; import com.yunbao.common.utils.SpUtil; import com.yunbao.common.utils.ToastUtil; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; /** * @ClassName NeverCrashUtils * @Description 全局捕获异常 */ public class NeverCrashUtils { private final static String TAG = NeverCrashUtils.class.getSimpleName(); private final static NeverCrashUtils INSTANCE = new NeverCrashUtils(); private boolean debugMode; private MainCrashHandler mainCrashHandler; private UncaughtCrashHandler uncaughtCrashHandler; private NeverCrashUtils() { } public static NeverCrashUtils getInstance() { return INSTANCE; } private synchronized MainCrashHandler getMainCrashHandler() { if (null == mainCrashHandler) { mainCrashHandler = (t, e) -> { }; } return mainCrashHandler; } /** * 主线程发生异常时的回调,可用于打印日志文件 *

* 注意跨线程操作的可能 */ public NeverCrashUtils setMainCrashHandler(MainCrashHandler mainCrashHandler) { this.mainCrashHandler = mainCrashHandler; return this; } private synchronized UncaughtCrashHandler getUncaughtCrashHandler() { if (null == uncaughtCrashHandler) { uncaughtCrashHandler = (t, e) -> { }; } return uncaughtCrashHandler; } /** * 子线程发生异常时的回调,可用于打印日志文件 *

* 注意跨线程操作的可能 */ public NeverCrashUtils setUncaughtCrashHandler(UncaughtCrashHandler uncaughtCrashHandler) { this.uncaughtCrashHandler = uncaughtCrashHandler; return this; } private boolean isDebugMode() { return debugMode; } /** * debug模式,会打印log日志,且toast提醒发生异常,反之则都没有 */ public NeverCrashUtils setDebugMode(boolean debugMode) { this.debugMode = debugMode; return this; } /** * 完成监听异常的注册 * * @param application application */ private boolean errorWhile = true; public void register(Application application) { //主线程异常拦截 new Handler(Looper.getMainLooper()).post(() -> { while (errorWhile) { try { Looper.loop(); } catch (Throwable e) { if (isDebugMode()) { Log.e(TAG, "未捕获的主线程异常行为", e); } e.printStackTrace(); AppContext.setFirebaseCrashData(); FirebaseCrashlytics.getInstance().recordException(e); AppManager.runDebugCode(() -> Toast.makeText(application, "发生闪退:" + e.getMessage(), Toast.LENGTH_SHORT).show()); FileUtil.saveStringToFile(new File(application.getDir("files", Context.MODE_PRIVATE).getAbsolutePath()), throwableToString(e), "error.log"); getMainCrashHandler().mainException(Looper.getMainLooper().getThread(), e); AppManager.runDebugCode(() -> errorWhile = false); // return; } } }); /* //子线程异常拦截 Thread.setDefaultUncaughtExceptionHandler((t, e) -> { if (isDebugMode()) { Log.e(TAG, "未捕获的子线程异常行为", e); } e.printStackTrace(); Toast.makeText(application, "发生闪退", Toast.LENGTH_SHORT).show(); FileUtil.saveStringToFile(new File(application.getDir("files", Context.MODE_PRIVATE).getAbsolutePath()),throwableToString(e),"error.log"); getMainCrashHandler().mainException(Looper.getMainLooper().getThread(), e); getUncaughtCrashHandler().uncaughtException(t, e); });*/ } public interface MainCrashHandler { void mainException(Thread t, Throwable e); } public interface UncaughtCrashHandler { void uncaughtException(Thread t, Throwable e); } private static String throwableToString(Throwable e) { StringWriter writer = new StringWriter(); writer.write("time=" + System.currentTimeMillis() + "\n"); writer.write("AndroidVersion=" + Build.VERSION.SDK_INT + "\n"); writer.write("AndroidName=" + Build.VERSION.RELEASE + "\n"); writer.write("PhoneName=" + Build.BRAND + "\n"); writer.write("Phone=" + Build.MODEL + "\n"); writer.write("CPU=" + Arrays.toString(Build.SUPPORTED_ABIS) + "\n"); writer.write("runTime=" + (System.currentTimeMillis() - CrashSaveBean.getInstance().getStartTime()) + "\n"); writer.write("enterRoom=" + CrashSaveBean.getInstance().getEnterRoom() + "\n"); writer.write("slidingRoom=" + CrashSaveBean.getInstance().getSlidingRoom() + "\n"); writer.write("playSvga=" + CrashSaveBean.getInstance().getPlaySvga() + "\n"); writer.write("ActivitySize=" + CrashSaveBean.getInstance().getActivitySize() + "\n"); writer.write("UserData=" + SpUtil.getInstance().getStringValue(SpUtil.USER_INFO) + "\n"); writer.write("[ERROR]"); PrintWriter printWriter = new PrintWriter(writer); e.printStackTrace(printWriter); return writer.toString(); } }