无论我们开发的APP经过多么详细的测试也不能完全保证不会出现崩溃的问题。所以为了我们APP的健壮性和用户体验我们需要在应用Crash的时候给用户一个提示并且重新启动,同时也需要将Crash的信息同步到服务端,用来分析Crash原因,好做出相应的修改或处理。
怎样捕获Crash信息
为了捕获应用的Crash信息我们需要一个很重要的类:UncaughtExceptionHandler,来捕获程序中没有处理的异常信息。
未捕获的异常指的是:程序中没有被try...catch...语句捕获向上抛出的异常。
我们需要在APP级别捕获这类异常。如果没有处理这类异常Android系统就会弹出一个提示框并且关闭程序,这种体验很不好。
首先我们可以设计一个CrashHandler类,它继承UncaughtExceptionHandler。
代码如下:
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static CrashHandler INSTANCE = new CrashHandler();
//上下文
private Context mContext;
//系统默认的异常处理
private Thread.UncaughtExceptionHandler mDefaultHandler;
private CrashHandler() { }
public static CrashHandler getInstance() {
return INSTANCE;
}
public CrashHandler init(Context ctx) {
mContext = ctx;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
return INSTANCE;
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
if (!handleException(throwable) && mDefaultHandler != null) {
//如果没有处理就使用系统默认的异常处理
mDefaultHandler.uncaughtException(thread, throwable);
} else {
//APP重新启动
}
}
private boolean handleException(final Throwable ex) {
if (ex == null) {
return true;
}
new Thread(new Runnable() {
@Override
public void run() {
//这块可以进行异常信息的记录和上传
//一般可以将异常信息保存到SD卡的固定目录,在程序重新启动后上传服务端
//因为Toast显示需要一个Looper
Looper.prepare();
Toast.makeText(mContext, "信息:" + ex.getLocalizedMessage(), Toast.LENGTH_LONG).show();
//开始循环
Looper.loop();
}
}).start();
//等待3秒用来显示Toast
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
注册:在写完CrashHandler后我们还需要注册一下,我们可以在我们APP自定义的Application中注册,也可以在BaseActivity中注册,代码类似。
public class BaseActivity extends Activity {
//系统默认的异常处理
private Thread.UncaughtExceptionHandler mDefaultHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
CrashHandler crashHandler = CrashHandler.getInstance().init(this);
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
}
}