当应用发生崩溃,需要讲崩溃信息保存起来,上传服务器或者保存到数据库
网上这块资料很多,简单记录当作学习笔记吧
接口UncaughtExceptionHandler的定义
public static interface UncaughtExceptionHandler {
/**
* The thread is being terminated by an uncaught exception. Further
* exceptions thrown in this method are prevent the remainder of the
* method from executing, but are otherwise ignored.
*
* @param thread the thread that has an uncaught exception
* @param ex the exception that was thrown
*/
void uncaughtException(Thread thread, Throwable ex);
}
需要实现的方法为uncaughtException,其中的ex就是被抛出的异常
对应的CrashHandler设置为单例。
/**
* 单例模式
*/
private CrashHandler() {
}
private static CrashHandler instance = null;
public static CrashHandler getInstance() {
if (null == instance) {
instance = new CrashHandler();
}
return instance;
}
CrashHandler中的init方法,设置系统的异常处理器为CrashHandler
// 系统默认的处理器,需要在自己处理完之后交还给系统处理
private Thread.UncaughtExceptionHandler mDefaultHandler;
public void init(Context context) {
this.context = context;
// 系统默认的处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
CrashHandler中的getCrashInfo 方法
private StringBuffer getCrashInfo(Throwable ex) {
StringBuffer sb = new StringBuffer();
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
// 当前时间
sb.append("TIME=" + time + "\n");
// 当前手机信息
sb.append("DEVICE=" + Build.DEVICE + "\n");
sb.append("VERSION=" + Build.VERSION.RELEASE + "\n");
// 获取app的信息
PackageManager pm = context.getPackageManager();
PackageInfo pi;
try {
pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = pi.versionName == null ? "null" : pi.versionName;
String versionCode = pi.versionCode + "";
// app的版本号和版本名
sb.append("versionName=" + versionName + "\n");
sb.append("versionCode=" + versionCode + "\n");
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
// 崩溃错误日志
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
sb.append(result + "\n");
return sb;
}
具体实现的uncaughtException 方法,这里一定要交还给系统的处理器
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// 获取错误信息 ,写入数据库
StringBuffer crashInfo = getCrashInfo(ex);
Log.e(TAG, crashInfo.toString());
//处理完之后调用默认系统处理器(不调用会一直黑屏)
mDefaultHandler.uncaughtException(thread, ex);
//打印错误信息
ex.printStackTrace();
}
对应的自定的Application类
public class AppApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
CrashHandler.getInstance().init(getApplicationContext());
}
}
别忘了在清单文件中修改一下Applicationd配置,为自定义的AppApplication
MainActivity中
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//崩溃测试
System.out.println(1/0);
}
}
打印日志(部分)如下
01-29 01:19:40.371: E/leafact-CrashHandler(2029): TIME=2016-01-29 01:19:40
01-29 01:19:40.371: E/leafact-CrashHandler(2029): DEVICE=vbox86p
01-29 01:19:40.371: E/leafact-CrashHandler(2029): VERSION=4.4.4
01-29 01:19:40.371: E/leafact-CrashHandler(2029): versionName=1.0
01-29 01:19:40.371: E/leafact-CrashHandler(2029): versionCode=1
01-29 01:19:40.371: E/leafact-CrashHandler(2029): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.crashapp/com.example.crashapp.MainActivity}: java.lang.ArithmeticException: divide by zero
对于获取的crashInfo,我们可以上传数据到服务器,可以在本地新建Crash_table表进行存储。
有了CrashHandler,对于不断的更新稳定版本很重要