不论是个人还是团队开发,软件或多或少都会出现BUG,当出现BUG,开发人员就会想知道异常信息是什么,所以为了方便维护,Android开发都会通过继承Thread类内部的UncaughtExceptionHandler接口来记录保存异常信息,下面来具体分析该功能所用到的方法
首先要定义一个类来继承UncaughtExceptionHandler接口,并且重写uncaughtException方法,然后进行初始化,获取到系统的异常终止处理器。
UncaughtExceptionHandler接口代码
public interface UncaughtExceptionHandler {
void uncaughtException(Thread t, Throwable e);
}
此接口意义就是当线程出现异常终止时,默认是会把异常信息抛出给JAVA虚拟机进行处理。
getDefaultUncaughtExceptionHandler和setDefaultUncaughtExceptionHandler代码
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
return defaultUncaughtExceptionHandler;
}
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
defaultUncaughtExceptionHandler = eh;
}
getDefaultUncaughtExceptionHandler方法是返回当线程突然终止时调用的默认处理程序,但是未捕获异常就会返回值为空。
setDefaultUncaughtExceptionHandler方法是设置线程突然终止时调用的默认处理程序,也就是自己想代替默认处理机制时,所做的操作。
当定义了setDefaultUncaughtExceptionHandler,就会回调UncaughtExceptionHandler的uncaughtException方法,来执行信息记录或者上传
下面就举个保存异常信息到TXT文档中列子
完整代码:
CrashHandler类
public class CrashHandler implements UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler mhandler;
private static CrashHandler CRASHINSTANCE;
private Context mcontext;
//用于存储设备的相关信息
private Map<String, String> item = new HashMap<>();
/**
* 实例化实现单列模式
*/
private CrashHandler() {
}
//获取CrashHandler实例,单列模式
public static synchronized CrashHandler getInstance() {
if (CRASHINSTANCE == null) {
CRASHINSTANCE = new CrashHandler();
}
return CRASHINSTANCE;
}
/**
* 初始化
*
* @param context
*/
public void init(Context context) {
this.mcontext = context;
// 获取系统默认的UncaughtException处理器
mhandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 收集错误信息的处理
*/
public boolean handlerException(final Throwable ex) {
if (ex == null) {
return false;
}
//收集设备信息写入SD卡文件中
getInfo(ex);
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mcontext,"程序出现异常,将退出", Toast.LENGTH_LONG).show();
Looper.loop();
}
}).start();
return true;
}
/**
* 收集设备信息
*/
public void getInfo(Throwable exc) {
try {
//APK版本号
PackageManager pack = mcontext.getPackageManager();
PackageInfo info = pack.getPackageInfo(mcontext.getPackageName(), PackageManager.GET_ACTIVITIES);
if (info != null && info.versionName != null) {
item.put("versionName", info.versionName);
item.put("versionCode", info.versionCode + "");
}
//手机设备品牌和型号
TelephonyManager phone = (TelephonyManager) mcontext.getSystemService(Context.TELEPHONY_SERVICE);
if (phone != null) {
item.put("PhoneName", Build.BOARD);//手机品牌
item.put("PhoneType", Build.MODEL);//手机型号
}
StringBuffer sb = new StringBuffer();
//先把map里面的值存入sb中
for (Map.Entry<String, String> entry : item.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\n");
}
/*把错误信息存入sb中*/
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
exc.printStackTrace(printWriter);
Throwable cause = exc.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
sb.append(result);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File file = new File(Environment.getExternalStorageDirectory() + "/cqq/crash");
if (!file.exists()) {
file.mkdirs();
}
File filed = new File(file, "log.txt");
if (filed.exists()) {
filed.delete();
}
filed.createNewFile();
FileOutputStream output = new FileOutputStream(filed);
output.write(sb.toString().getBytes());
output.flush();
output.close();
}
} catch (Exception ex) {
}
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (!handlerException(e) && mhandler != null) {
mhandler.uncaughtException(t, e);
}else{
//等候两秒后退出
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
}
}
}
application类就需要对crash进行监控,需要在onCreate添加如下代码
//截取程序出现错误时的错误信息
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(getApplicationContext());
文档将会保存在SD卡下cqq/crash下的log.txt,带有设备信息和异常信息。
希望这篇文章可以帮到大家更好的学习!