绝对完美的App是不存在的,我们的应用有时可能会出现莫名(我们第一时间没有发现)的Exception时,就可能在没有任何提示的情况下退出,如果不做任何处理的话,给用户的体验可想而知了:最可能的结果就是直接卸载掉我们的应用APK。此时我们就要用到UncaughtExceptionHandler来控制异常发生。
UncaughtExceptionHandler:线程未捕获异常控制器是用来处理未捕获异常的。 如果程序出现了未捕获异常默认情况下则会出现强行关闭对话框实现该接口并注册为程序中的默认未捕获异常处理 这样当未捕获异常发生时,就可以做些异常处理操作 例如:收集异常信息,发送错误报告 等。UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告。
---------------丑陋分隔线:UncaughtExceptionHandler 捕获异常并保存到log文件,方便查看-------------------------------------
public class CrashHandler implements UncaughtExceptionHandler {private Context mContext;
private static final String DEFAULT_LOG_FILE = "log";
/**保存log文件的后缀名*/
private static final String FILE_NAME_SUFFIX = ".log";
/**单例*/
private static CrashHandler sInstance = null;
/**系统默认的异常处理(默认情况下,系统会终止当前的异常程序)*/
private UncaughtExceptionHandler mDefaultCrashHandler;
private CrashHandler(Context cxt) {
/**获取系统默认的异常处理器*/
mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
/**将当前实例设为系统默认的异常处理器*/
Thread.setDefaultUncaughtExceptionHandler(this);
/**获取Context,方便内部使用*/
this.mContext = cxt.getApplicationContext();
}
public synchronized static CrashHandler create(Context cxt) {
if (sInstance == null) {
sInstance = new CrashHandler(cxt);
}
return sInstance;
}
/**
* 这个是最关键的函数,当程序中有未被捕获的异常,系统将会自动调用#uncaughtException方法
* thread为出现未捕获异常的线程,ex为未捕获的异常,有了这个ex,我们就可以得到异常信息。
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
try {
/**保存异常信息到SD卡中*/
saveToSDCard(ex);
}
catch (Exception e) {
}
finally {
/**如果系统提供了默认的异常处理器,则交给系统去结束我们的程序,否则就由我们自己结束自己*/
if (mDefaultCrashHandler != null) {
mDefaultCrashHandler.uncaughtException(thread, ex);
}
}
}
private void saveToSDCard(Throwable ex) throws Exception {
File file = FileUtils.getSaveFile(mContext.getPackageName() + File.separator + DEFAULT_LOG_FILE, SystemTool.getDataTime("yyyy-MM-dd-HH-mm-ss") + FILE_NAME_SUFFIX);
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
/**导出发生异常的时间*/
pw.println(SystemTool.getDataTime("yyyy-MM-dd-HH-mm-ss"));
/**导出手机信息*/
dumpPhoneInfo(pw);
pw.println();
/**导出异常的调用栈信息*/
ex.printStackTrace(pw);
pw.close();
}
private void dumpPhoneInfo(PrintWriter pw) throws NameNotFoundException {
/**应用的版本名称和版本号*/
PackageManager pm = mContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
pw.print("App Version: ");
pw.print(pi.versionName);
pw.print('_');
pw.println(pi.versionCode);
pw.println();
/** android版本号*/
pw.print("OS Version: ");
pw.print(Build.VERSION.RELEASE);
pw.print("_");
pw.println(Build.VERSION.SDK_INT);
pw.println();
/**手机制造商*/
pw.print("Vendor: ");
pw.println(Build.MANUFACTURER);
pw.println();
/**手机型号*/
pw.print("Model: ");
pw.println(Build.MODEL);
pw.println();
/**cpu架构*/
pw.print("CPU ABI: ");
pw.println(Build.CPU_ABI);
pw.println();
}
}
------------------然后在Application的onCreate*()方法中进行初始化就可以了----------------------------------------------------------------
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(this);
}