Android全局捕获异常
Android全局捕获异常
This commit is contained in:
parent
7cccc48b80
commit
199bd7ee3c
144
Android/Demo1/NeverCrashUtils.java
Normal file
144
Android/Demo1/NeverCrashUtils.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主线程发生异常时的回调,可用于打印日志文件
|
||||
* <p>
|
||||
* 注意跨线程操作的可能
|
||||
*/
|
||||
public NeverCrashUtils setMainCrashHandler(MainCrashHandler mainCrashHandler) {
|
||||
this.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);
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user