2022-08-25 15:52:20 +08:00
|
|
|
|
package com.shayu.phonelive;
|
2022-10-21 18:28:50 +08:00
|
|
|
|
|
2022-08-25 15:52:20 +08:00
|
|
|
|
import android.app.Application;
|
2022-09-07 13:09:40 +08:00
|
|
|
|
import android.content.Context;
|
2022-10-22 15:59:00 +08:00
|
|
|
|
import android.os.Build;
|
2022-08-25 15:52:20 +08:00
|
|
|
|
import android.os.Handler;
|
|
|
|
|
import android.os.Looper;
|
|
|
|
|
import android.util.Log;
|
2022-09-07 13:09:40 +08:00
|
|
|
|
import android.widget.Toast;
|
2022-10-21 18:28:50 +08:00
|
|
|
|
|
2023-08-15 10:37:06 +08:00
|
|
|
|
import com.google.firebase.crashlytics.FirebaseCrashlytics;
|
2023-03-24 10:52:44 +08:00
|
|
|
|
import com.yunbao.common.BuildConfig;
|
2022-10-27 15:28:43 +08:00
|
|
|
|
import com.yunbao.common.bean.CrashSaveBean;
|
2023-04-08 15:45:47 +08:00
|
|
|
|
import com.yunbao.common.utils.AppManager;
|
2022-09-07 13:09:40 +08:00
|
|
|
|
import com.yunbao.common.utils.FileUtil;
|
2022-10-22 13:23:57 +08:00
|
|
|
|
import com.yunbao.common.utils.SpUtil;
|
2023-08-15 10:37:06 +08:00
|
|
|
|
import com.yunbao.common.utils.ToastUtil;
|
2022-10-22 13:23:57 +08:00
|
|
|
|
|
2022-09-07 13:09:40 +08:00
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.PrintWriter;
|
|
|
|
|
import java.io.StringWriter;
|
2022-10-22 15:59:00 +08:00
|
|
|
|
import java.util.Arrays;
|
2022-08-25 15:52:20 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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) {
|
2022-10-06 11:43:06 +08:00
|
|
|
|
this.mainCrashHandler = mainCrashHandler;
|
2022-08-25 15:52:20 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 完成监听异常的注册
|
2022-10-27 15:28:43 +08:00
|
|
|
|
*
|
2022-08-25 15:52:20 +08:00
|
|
|
|
* @param application application
|
|
|
|
|
*/
|
2023-04-08 15:45:47 +08:00
|
|
|
|
private boolean errorWhile = true;
|
|
|
|
|
|
2022-08-25 15:52:20 +08:00
|
|
|
|
public void register(Application application) {
|
|
|
|
|
//主线程异常拦截
|
|
|
|
|
new Handler(Looper.getMainLooper()).post(() -> {
|
2023-04-08 15:45:47 +08:00
|
|
|
|
while (errorWhile) {
|
2022-08-25 15:52:20 +08:00
|
|
|
|
try {
|
|
|
|
|
Looper.loop();
|
|
|
|
|
} catch (Throwable e) {
|
|
|
|
|
if (isDebugMode()) {
|
|
|
|
|
Log.e(TAG, "未捕获的主线程异常行为", e);
|
|
|
|
|
}
|
2022-09-09 13:36:01 +08:00
|
|
|
|
e.printStackTrace();
|
2023-08-15 10:37:06 +08:00
|
|
|
|
AppContext.setFirebaseCrashData();
|
|
|
|
|
FirebaseCrashlytics.getInstance().recordException(e);
|
2023-04-08 15:45:47 +08:00
|
|
|
|
AppManager.runDebugCode(() -> Toast.makeText(application, "发生闪退:" + e.getMessage(), Toast.LENGTH_SHORT).show());
|
2022-10-27 15:28:43 +08:00
|
|
|
|
FileUtil.saveStringToFile(new File(application.getDir("files", Context.MODE_PRIVATE).getAbsolutePath()), throwableToString(e), "error.log");
|
2022-08-25 15:52:20 +08:00
|
|
|
|
getMainCrashHandler().mainException(Looper.getMainLooper().getThread(), e);
|
2023-04-08 15:45:47 +08:00
|
|
|
|
AppManager.runDebugCode(() -> errorWhile = false);
|
|
|
|
|
// return;
|
2022-08-25 15:52:20 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-10-24 17:55:43 +08:00
|
|
|
|
/*
|
2022-08-25 15:52:20 +08:00
|
|
|
|
//子线程异常拦截
|
|
|
|
|
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
|
|
|
|
|
if (isDebugMode()) {
|
|
|
|
|
Log.e(TAG, "未捕获的子线程异常行为", e);
|
|
|
|
|
}
|
2022-09-09 13:36:01 +08:00
|
|
|
|
e.printStackTrace();
|
2022-09-07 13:09:40 +08:00
|
|
|
|
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);
|
2022-08-25 15:52:20 +08:00
|
|
|
|
getUncaughtCrashHandler().uncaughtException(t, e);
|
2022-09-07 13:09:40 +08:00
|
|
|
|
|
2022-10-24 17:55:43 +08:00
|
|
|
|
});*/
|
2022-08-25 15:52:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public interface MainCrashHandler {
|
|
|
|
|
void mainException(Thread t, Throwable e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public interface UncaughtCrashHandler {
|
|
|
|
|
void uncaughtException(Thread t, Throwable e);
|
|
|
|
|
}
|
2022-10-27 15:28:43 +08:00
|
|
|
|
|
2022-09-07 13:09:40 +08:00
|
|
|
|
private static String throwableToString(Throwable e) {
|
2022-10-27 15:28:43 +08:00
|
|
|
|
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");
|
2023-04-08 15:45:47 +08:00
|
|
|
|
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");
|
2022-10-27 15:28:43 +08:00
|
|
|
|
writer.write("UserData=" + SpUtil.getInstance().getStringValue(SpUtil.USER_INFO) + "\n");
|
2022-10-22 13:23:57 +08:00
|
|
|
|
writer.write("[ERROR]");
|
2022-10-27 15:28:43 +08:00
|
|
|
|
PrintWriter printWriter = new PrintWriter(writer);
|
2022-09-07 13:09:40 +08:00
|
|
|
|
e.printStackTrace(printWriter);
|
2022-10-22 13:23:57 +08:00
|
|
|
|
return writer.toString();
|
2022-09-07 13:09:40 +08:00
|
|
|
|
}
|
2022-08-25 15:52:20 +08:00
|
|
|
|
}
|