在程序运行的过程中,有时候出现异常信息,比如运行时异常时,我们可以通过UncaughtExceptionHandler这个类捕捉到异常信息,并写入sd卡中,方便后期修改bug与调试。
首先自定义CatchErrorHandler实现UncaughtExceptionHandler接口,重写uncaughtException方法,当程序出现异常时会调用此方法。具体CatchErrorHandler类如下代码
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 异常处理,异常信息写入文件
*/
public class CatchErrorHandler implements UncaughtExceptionHandler {
public static final String TAG = "CrashErrorHandler";
private static CatchErrorHandler catchErrorHandler = null;
private Context mContext;
private UncaughtExceptionHandler mDefaultHandler;
private Map<String, String> infos = new HashMap<String, String>();
private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH_mm_ss");
private static String logPath ;
/**
* 单例模式,保证只实例化一次
* @return
*/
public static CatchErrorHandler getInstance(Context context){
if (catchErrorHandler ==null){
synchronized (CatchErrorHandler.class){
if (catchErrorHandler ==null)
catchErrorHandler = new CatchErrorHandler(context);
}
}
return catchErrorHandler;
}
private CatchErrorHandler(Context context){
mContext = context;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
logPath = Environment.getExternalStorageDirectory().getAbsolutePath()+File.separator+mContext.getPackageName()+File.separator+"errorlog";
File file = new File(logPath);
if (!file.exists()){
file.mkdirs();
}
}
/**
* 当 UncaughtException 发生时会转入该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
if (!handleException(throwable) && mDefaultHandler != null) {
mDefaultHandler.uncaughtException(thread, throwable);
} else {
//系统退出,kill进程
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 处理异常信息
* @param throwable
*/
private boolean handleException(Throwable throwable) {
if (throwable == null) {
return false;
}
// 保存日志文件
saveErrorInfoToFile(throwable);
return true;
}
/**
* 保存错误信息到sd中
* @param throwable
*/
private void saveErrorInfoToFile(Throwable throwable) {
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : infos.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\n");
}
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();
String result = writer.toString();
sb.append(result);
try {
String time = formatter.format(new Date());
String fileName =logPath +File.separator + "error-"+ time + ".txt";
File f = new File(fileName);
if(!f.getParentFile().exists() || !f.getParentFile().isDirectory()){
f.getParentFile().mkdirs();
}
if (f.exists()) {
f.delete();
}
f.createNewFile();
FileOutputStream fos = new FileOutputStream(f);
fos.write(sb.toString().getBytes());
fos.close();
fos.flush();
} catch (Exception e) {
}
}
}
在CatchApplication的oncreate方法中实例化CatchErrorHandler,
CatchErrorHandler.getInstance(this);
接下来,我们在MainActivity中进行测试,测试代码如下,点击Test按钮后,在sd卡的项目目录的errlog目录可看到相应错误txt文件。
public class MainActivity extends AppCompatActivity {
private TextView textView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.test).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.setText("catch erroe");
}
}
);
}
}
原码下载地址,原码下载