开发安卓的小伙伴都遇到过APP突然崩溃,无响应的情况.如果发生在自己手中,那么还可以通过IDE查看错误日志,但是实际都是发生在用户手中,那么这个时候产生崩溃,无响应ANR异常就很麻烦.无从下手.因此,需要全局异常捕获.也就是对未知异常,程序员没有处理的异常进行处理,记录等便于分析查找原因.
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
/**
* @ClassName MyUncaughtExceptionHandler
* @Description 全局捕捉异常
* @Author summerain0
* @Date 2020/9/11 15:31
*/
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
// 单例
private static MyUncaughtExceptionHandler myUncaughtExceptionHandler;
// 上下文
private Context context;
// 会输出到文件中
private StringBuilder stringBuilder;
// 系统异常处理器
private Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
public MyUncaughtExceptionHandler(Context context) {
this.context = context;
}
// 获取单例
public static synchronized MyUncaughtExceptionHandler getInstance(Context ctx) {
if (myUncaughtExceptionHandler == null) {
myUncaughtExceptionHandler = new MyUncaughtExceptionHandler(ctx);
}
return myUncaughtExceptionHandler;
}
// 初始化
public void init() {
defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
if (throwable == null) {
defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
}
// 创建集合对象
stringBuilder = new StringBuilder();
// 记录时间
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.SSS", Locale.getDefault());
String date = simpleDateFormat.format(new Date());
addMessage("崩溃时间", date);
// 记录应用版本信息
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
addMessage("版本名", pi.versionName);
addMessage("版本号", pi.versionCode);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
addMessage("error", "记录版本信息失败!" + e.getMessage());
}
// 记录设备信息
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
Object obj = field.get(null);
if (obj != null) {
addMessage(field.getName(), obj);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
addMessage("error", "记录设备信息失败!" + e.getMessage());
}
}
// 添加分隔符
addMessage(null, "==============================================================");
addMessage(null, "======================== 崩溃日志 =========================");
addMessage(null, "==============================================================");
// 记录崩溃信息
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
throwable.printStackTrace(printWriter);
Throwable cause = throwable.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
addMessage(null, writer.toString());
// 生成路径,保存至/Android/data/包名,无需读写权限
try {
File root = context.getExternalFilesDir("log");
String filename = date + ".log";
File file = new File(root, filename);
FileOutputStream fos = new FileOutputStream(file);
fos.write(stringBuilder.toString().getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
}
}
// 添加数据
private void addMessage(String key, Object obj) {
// 对数组做一下处理
if (obj instanceof String[]) {
String[] list = (String[]) obj;
ArrayList<String> array = new ArrayList<>(Arrays.asList(list));
stringBuilder.append(key).append("=").append(array.toString()).append("\n");
}
// 其他的都直接添加
if (key == null) {
stringBuilder.append(obj)
.append("\n");
} else {
stringBuilder.append(key)
.append("=")
.append(obj)
.append("\n");
}
}
}
import android.app.Application;
/**
* @ClassName MyApplication
* @Description TODO
* @Author summerain0
* @Date 2020/9/11 14:00
*/
public class MyApplication extends Application {
public static final String TAG = "MyApplication";
@Override
public void onCreate() {
super.onCreate();
// 初始化异常处理器
MyUncaughtExceptionHandler.getInstance(MyApplication.this).init();
}
}
android:name=".MyApplication"
....>