diff --git a/Android/Demo1/NeverCrashUtils.java b/Android/Demo1/NeverCrashUtils.java new file mode 100644 index 0000000..a290fc7 --- /dev/null +++ b/Android/Demo1/NeverCrashUtils.java @@ -0,0 +1,144 @@ + +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.yunbao.common.utils.FileUtil; +import com.yunbao.common.utils.SpUtil; + +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 + */ + public void register(Application application) { + //主线程异常拦截 + new Handler(Looper.getMainLooper()).post(() -> { + while (true) { + try { + Looper.loop(); + } catch (Throwable 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); + + } + } + }); + + //子线程异常拦截 + 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("UserData="+SpUtil.getInstance().getStringValue(SpUtil.USER_INFO)+"\n"); + writer.write("[ERROR]"); + PrintWriter printWriter=new PrintWriter(writer); + e.printStackTrace(printWriter); + return writer.toString(); + } +} \ No newline at end of file