本文章源码下载地址UnCaughtExcetionTest
app做不到毫无bug,而测试如果又不到位的时候经常会出现用户使用正式版本的app后崩溃,但是开发者却不知道原因是什么,你也不能求着用户来给你重现让你找原因。
那么该怎么办呢?其实可以记录app未捕获的异常信息,从而根据信息查找原因。
android 中有一个叫UncaughtExceptionHandler的接口,实现该接口后,会重写public void uncaughtException(Thread thread, Throwable ex)
,然后app会将未处理的异常传送到这里,从而可以在这里实现未处理异常的捕获。
使用的方法一般是建立一个MyApplication类继承自程序的Application父类,再在该类实现接口,这样可以捕获程序生命周期中的未处理异常。
这里不推荐自己实现,而是推荐使用第三方库osama-radadr的FireCrasher,github地址为:FireCrasher.
使用方法为在build.gradle(Module:app)中加入以下声明:
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
// 以下在 dependencies中添加
compile 'com.github.osama-raddad:FireCrasher:v1.1'
然后创建一个MyApplication类继承自Application:
public class MyApplication extends Application {
private static final String ERROR_DIR_PATH = Environment
.getExternalStorageDirectory() + File.separator + "AppErrorNotes";
private void showToast(String text){
Toast.makeText(this,text,Toast.LENGTH_SHORT).show();
}
@Override
public void onCreate() {
super.onCreate();
// 创建存放日志的文件夹
createAppErrorDirectory();
// FireCrasher使用
FireCrasher.install(this, new CrashListener() {
@Override
public void onCrash(Throwable throwable, Activity activity) {
// 这里可以选择是否恢复发生异常的Activity
// recover(activity);
Toast.makeText(getBaseContext(),"发生错误啦",Toast.LENGTH_SHORT).show();
// 保存异常信息的路径
String path = ERROR_DIR_PATH + File.separator + "11.txt";
File file = new File(path);
if (!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
Writer writer = new FileWriter(file,true);
PrintWriter printWriter = new PrintWriter(writer);
printWriter.write("app error :");
throwable.printStackTrace(printWriter);
printWriter.flush();
printWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
throwable.printStackTrace();
}
});
}
private void createAppErrorDirectory(){
File file = new File(ERROR_DIR_PATH);
if (!file.exists()){
file.mkdir();
}
}
}
务必要记得在AndroidManifest.xml中添加MyApplication的声明以及读写SD卡的权限。
以下是一个未处理的空指针异常的代码:
public class MainActivity extends AppCompatActivity {
Button btnStart;
TextView tvText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = (Button) findViewById(R.id.btn_start);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 由于tvText组件没有初始化,因此会报空指针异常,而这里并没有做处理
tvText.setText("点击了按钮");
}
});
}
}
效果图: