開發(fā)中有些地方未注意可能造成異常拋出未能caught到,然后彈出系統(tǒng)對話框強(qiáng)制退出。這種交互不好,而且開發(fā)者也不能及時獲取到底哪里出問題,當(dāng)然可以接入第三方Crash分析平臺比如Bugly、instabug,其實也可以自己很簡單的實現(xiàn)全局異常處理。
未捕獲異常大多發(fā)生在在多線程環(huán)境中,子線程拋出的異常是不能用主線程中try….catch捕獲。可以給線程設(shè)置UncaughtExceptionHandler,當(dāng)出現(xiàn)異常時會回調(diào)UncaughtExceptionHandler中的uncaughtException(Thread t, Throwable e) 方法。設(shè)置可以為某個線程單獨設(shè)
thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
當(dāng)想給所有線程設(shè)置時使用
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
實現(xiàn)自己的UncaughtExceptionHandler
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static final String TAG = "CrashHandler";
private Context mContext;
volatile private static CrashHandler sCrashHandler;
private CrashHandler(Context context) {
mContext = context;
}
public static CrashHandler getInstance(Context context){
if (sCrashHandler == null) {
synchronized (CrashHandler.class){
if (sCrashHandler == null) {
//使用Application Context
sCrashHandler=new CrashHandler(context.getApplicationContext());
}
}
}
return sCrashHandler;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (BuildConfig.DEBUG) Log.d(TAG, "uncaughtException: "+t.getName()+" "+e.getMessage());
//這里可以將異常信息保存或上傳
//...
//可根據(jù)情況選擇是否干掉當(dāng)前的進(jìn)程
android.os.Process.killProcess(android.os.Process.myPid());
}
}
這里自定義的CrashHandler 構(gòu)造時傳入并保存context,以便之后進(jìn)行異常處理操作,因為使用的單例模式,內(nèi)部有靜態(tài)實例,為了防止context引用Activity造成內(nèi)存泄露,因此使用application context。
在Application中注冊未捕獲異常處理器
public class CrashApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(CrashHandler.getInstance(this));
}
}
最后manifest中使用CrashApplication
<application
android:name=".CrashApplication"
android:allowBackup="true"
...