pdlivexp/app/src/main/java/com/shayu/phonelive/NeverCrashUtils.java

130 lines
4.1 KiB
Java
Raw Normal View History

package com.shayu.phonelive;
import android.app.Application;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import com.yunbao.common.utils.FileUtil;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @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;
}
/**
* 主线程发生异常时的回调可用于打印日志文件
* <p>
* 注意跨线程操作的可能
*/
public NeverCrashUtils setMainCrashHandler(MainCrashHandler mainCrashHandler) {
mainCrashHandler = mainCrashHandler;
return this;
}
private synchronized UncaughtCrashHandler getUncaughtCrashHandler() {
if (null == uncaughtCrashHandler) {
uncaughtCrashHandler = (t, e) -> {
};
}
return uncaughtCrashHandler;
}
/**
* 子线程发生异常时的回调可用于打印日志文件
* <p>
* 注意跨线程操作的可能
*/
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);
}
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);
}
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();
PrintWriter printWriter=new PrintWriter(writer);
e.printStackTrace(printWriter);
return "[ERROR]"+writer.toString();
}
}