Android 全局异常捕获实例详解
Android全局异常捕获
今天就来说说作为程序猿的我们每天都会遇到的东西bug,出bug不可怕可怕的是没有出bug时的堆栈信息,那么对于bug的信息收集就显得尤为重要了,一般用第三方bugly或者友盟等等都能轻易收集,但是由于公司不让使用第三方,而安卓正好有原生的异常收集类UncaughtExceptionHandler,那么今天博客就从这个类开始.
UncaughtExceptionHandler见名知意,即他是处理我们未捕获的异常,具体使用分两步
1.实现我们自己的异常处理类
publicclassCrashHandlerimplementsThread.UncaughtExceptionHandler{
@Override
publicvoiduncaughtException(Threadthread,Throwableex){
}
}
需要我们实现Thread.UncaughtExceptionHandler接口当有未捕获的异常的时候会回调uncaughtException(Threadthread,Throwableex)方法
2.设置该CrashHandler为系统默认的
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
以上只是使用步骤的介绍,具体项目中的使用我直接贴代码
在application中初始化
packagecom.zly.www.basedemo.base;
importandroid.app.Application;
importandroid.content.Context;
importcom.zly.www.basedemo.exception.CrashHandler;
/**
*Createdbyzlyon2016/6/11.
*/
publicclassAppApplicationextendsApplication{
privatestaticContextmContext;
@Override
publicvoidonCreate(){
super.onCreate();
this.mContext=this;
CrashHandler.getInstance().init(this);//初始化全局异常管理
}
publicstaticContextgetContext(){
returnmContext;
}
}
CrashHandler实现类如下
packagecom.zly.www.basedemo.exception;
importandroid.content.Context;
importandroid.content.pm.PackageInfo;
importandroid.content.pm.PackageManager;
importandroid.os.Build;
importandroid.os.Environment;
importandroid.os.Looper;
importandroid.util.Log;
importandroid.widget.Toast;
importcom.zly.www.basedemo.utils.AppManager;
importjava.io.File;
importjava.io.FileOutputStream;
importjava.io.PrintWriter;
importjava.io.StringWriter;
importjava.io.Writer;
importjava.lang.reflect.Field;
importjava.text.SimpleDateFormat;
importjava.util.Date;
importjava.util.HashMap;
importjava.util.Map;
/**
*全局异常捕获
*Createdbyzlyon2016/7/3.
*/
publicclassCrashHandlerimplementsThread.UncaughtExceptionHandler{
/**
*系统默认UncaughtExceptionHandler
*/
privateThread.UncaughtExceptionHandlermDefaultHandler;
/**
*context
*/
privateContextmContext;
/**
*存储异常和参数信息
*/
privateMapparamsMap=newHashMap<>();
/**
*格式化时间
*/
privateSimpleDateFormatformat=newSimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
privateStringTAG=this.getClass().getSimpleName();
privatestaticCrashHandlermInstance;
privateCrashHandler(){
}
/**
*获取CrashHandler实例
*/
publicstaticsynchronizedCrashHandlergetInstance(){
if(null==mInstance){
mInstance=newCrashHandler();
}
returnmInstance;
}
publicvoidinit(Contextcontext){
mContext=context;
mDefaultHandler=Thread.getDefaultUncaughtExceptionHandler();
//设置该CrashHandler为系统默认的
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
*uncaughtException回调函数
*/
@Override
publicvoiduncaughtException(Threadthread,Throwableex){
if(!handleException(ex)&&mDefaultHandler!=null){//如果自己没处理交给系统处理
mDefaultHandler.uncaughtException(thread,ex);
}else{//自己处理
try{//延迟3秒杀进程
Thread.sleep(3000);
}catch(InterruptedExceptione){
Log.e(TAG,"error:",e);
}
//退出程序
AppManager.getAppManager().AppExit(mContext);
}
}
/**
*收集错误信息.发送到服务器
*@return处理了该异常返回true,否则false
*/
privatebooleanhandleException(Throwableex){
if(ex==null){
returnfalse;
}
//收集设备参数信息
collectDeviceInfo(mContext);
//添加自定义信息
addCustomInfo();
//使用Toast来显示异常信息
newThread(){
@Override
publicvoidrun(){
Looper.prepare();
Toast.makeText(mContext,"程序开小差了呢..",Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
//保存日志文件
saveCrashInfo2File(ex);
returntrue;
}
/**
*收集设备参数信息
*@paramctx
*/
publicvoidcollectDeviceInfo(Contextctx){
//获取versionName,versionCode
try{
PackageManagerpm=ctx.getPackageManager();
PackageInfopi=pm.getPackageInfo(ctx.getPackageName(),PackageManager.GET_ACTIVITIES);
if(pi!=null){
StringversionName=pi.versionName==null?"null":pi.versionName;
StringversionCode=pi.versionCode+"";
paramsMap.put("versionName",versionName);
paramsMap.put("versionCode",versionCode);
}
}catch(PackageManager.NameNotFoundExceptione){
Log.e(TAG,"anerroroccuredwhencollectpackageinfo",e);
}
//获取所有系统信息
Field[]fields=Build.class.getDeclaredFields();
for(Fieldfield:fields){
try{
field.setAccessible(true);
paramsMap.put(field.getName(),field.get(null).toString());
}catch(Exceptione){
Log.e(TAG,"anerroroccuredwhencollectcrashinfo",e);
}
}
}
/**
*添加自定义参数
*/
privatevoidaddCustomInfo(){
}
/**
*保存错误信息到文件中
*
*@paramex
*@return返回文件名称,便于将文件传送到服务器
*/
privateStringsaveCrashInfo2File(Throwableex){
StringBuffersb=newStringBuffer();
for(Map.Entryentry:paramsMap.entrySet()){
Stringkey=entry.getKey();
Stringvalue=entry.getValue();
sb.append(key+"="+value+"\n");
}
Writerwriter=newStringWriter();
PrintWriterprintWriter=newPrintWriter(writer);
ex.printStackTrace(printWriter);
Throwablecause=ex.getCause();
while(cause!=null){
cause.printStackTrace(printWriter);
cause=cause.getCause();
}
printWriter.close();
Stringresult=writer.toString();
sb.append(result);
try{
longtimestamp=System.currentTimeMillis();
Stringtime=format.format(newDate());
StringfileName="crash-"+time+"-"+timestamp+".log";
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
Stringpath=Environment.getExternalStorageDirectory().getAbsolutePath()+"/crash/";
Filedir=newFile(path);
if(!dir.exists()){
dir.mkdirs();
}
FileOutputStreamfos=newFileOutputStream(path+fileName);
fos.write(sb.toString().getBytes());
fos.close();
}
returnfileName;
}catch(Exceptione){
Log.e(TAG,"anerroroccuredwhilewritingfile...",e);
}
returnnull;
}
}
activity管理类
packagecom.zly.www.basedemo.utils;
importjava.util.Stack;
importandroid.app.Activity;
importandroid.app.ActivityManager;
importandroid.content.Context;
/**
*Activity管理类:用于管理Activity和退出程序
*Createdbyzlyon2016/6/11.
*/
publicclassAppManager{
//Activity栈
privatestaticStackactivityStack;
//单例模式
privatestaticAppManagerinstance;
privateAppManager(){
}
/**
*单一实例
*/
publicstaticAppManagergetAppManager(){
if(instance==null){
instance=newAppManager();
}
returninstance;
}
/**
*添加Activity到堆栈
*/
publicvoidaddActivity(Activityactivity){
if(activityStack==null){
activityStack=newStack();
}
activityStack.add(activity);
}
/**
*获取当前Activity(堆栈中最后一个压入的)
*/
publicActivitycurrentActivity(){
Activityactivity=activityStack.lastElement();
returnactivity;
}
/**
*结束当前Activity(堆栈中最后一个压入的)
*/
publicvoidfinishActivity(){
Activityactivity=activityStack.lastElement();
finishActivity(activity);
}
/**
*结束指定的Activity
*/
publicvoidfinishActivity(Activityactivity){
if(activity!=null){
activityStack.remove(activity);
activity.finish();
activity=null;
}
}
/**
*结束指定类名的Activity
*/
publicvoidfinishActivity(Class>cls){
for(Activityactivity:activityStack){
if(activity.getClass().equals(cls)){
finishActivity(activity);
break;
}
}
}
/**
*结束所有Activity
*/
publicvoidfinishAllActivity(){
for(inti=0;i
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!