有時候由于測試不充分或者程序潛在的問題而導致程序異常崩潰,這個是令人無法接受的,在android中怎樣捕獲程序的異常崩潰,然后進行一些必要的處理或重新啟動
應用這個問題困惱了我很久,今天終于解決了該問題,寫篇文章記錄一下。
首先捕獲程序崩潰的異常就必須了解一下java中UncaughtExceptionHandler這個接口,android沿用了此接口,在android API中:
通過實現此接口,能夠處理線程被一個無法捕捉的異常所終止的情況。如上所述的情況,handler將會報告線程終止和不明原因異常這個情況,如果沒有自定義handler,
線程管理組就被默認為報告異常的handler。
ThreadGroup 這個類就是實現了UncaughtExceptionHandler這個接口,如果想捕獲異常我們可以實現這個接口或者繼承ThreadGroup,并重載uncaughtException方法。
在java API中對該接口描述的更詳細:
我就不翻譯了,太吃力了....%gt;_lt;%。在實現UncaughtExceptionHandler時,必須重載uncaughtException(Thread thread, Throwable ex) ,如果我們沒有實現該接口
也就是沒有顯示捕捉異常,則ex為空,否則ex不為空,thread 則為出異常的線程。
接下來上代碼,實現UncaughtExceptionHandler接口,顯示處理線程異常終止的情況:
public class UnCeHandler implements UncaughtExceptionHandler { private Thread.UncaughtExceptionHandler mDefaultHandler; public static final String TAG = quot;CatchExcepquot;; CatchExcep application; public UnCeHandler(CatchExcep application){ //獲取系統默認的UncaughtException處理器 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); this.application = application; } @Override public void uncaughtException(Thread thread, Throwable ex) { if(!handleException(ex) amp;amp; mDefaultHandler != null){ //如果用戶沒有處理則讓系統默認的異常處理器來處理 mDefaultHandler.uncaughtException(thread, ex); }else{ try{ Thread.sleep(2000); }catch (InterruptedException e){ Log.e(TAG, quot;error : quot;, e); } Intent intent = new Intent(application.getApplicationContext(), MainActivity.class); PendingIntent restartIntent = PendingIntent.getActivity( application.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK); //退出程序 AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() 1000, restartIntent); // 1秒鐘后重啟應用 application.finishActivity(); } } /** * 自定義錯誤處理,收集錯誤信息 發送錯誤報告等操作均在此完成. * * @param ex * @return true:如果處理了該異常信息;否則返回false. */ private boolean handleException(Throwable ex) { if (ex == null) { return false; } //使用Toast來顯示異常信息 new Thread(){ @Override public void run() { Looper.prepare(); Toast.makeText(application.getApplicationContext(), quot;很抱歉,程序出現異常,即將退出.quot;, Toast.LENGTH_SHORT).show(); Looper.loop(); } }.start(); return true; } }通過在android Application 這個全局類中處理異常,如果不知道Application的作用請查看一下此鏈接: Application 詳解
public class CatchExcep extends Application{ ArrayListlt;Activitygt; list = new ArrayListlt;Activitygt;(); public void init(){ //設置該CrashHandler為程序的默認處理器 UnCeHandler catchExcep = new UnCeHandler(this); Thread.setDefaultUncaughtExceptionHandler(catchExcep); } /** * Activity關閉時,刪除Activity列表中的Activity對象*/ public void removeActivity(Activity a){ list.remove(a); } /** * 向Activity列表中添加Activity對象*/ public void addActivity(Activity a){ list.add(a); } /** * 關閉Activity列表中的所有Activity*/ public void finishActivity(){ for (Activity activity : list) { if (null != activity) { activity.finish(); } } //殺死該應用進程 android.os.Process.killProcess(android.os.Process.myPid()); } }
然后人為制造一個異常:
Button btn; TextView tv; private CatchExcep application; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn = (Button)findViewById(R.id.btn); tv = (TextView)findViewById(R.id.tv); application = (CatchExcep)getApplication(); application.init(); application.addActivity(this); btn.setOnClickListener(this); } /** * 人為制造的異常*/ public void press(){ new Thread(new Runnable() { @Override public void run() { tv.setText(quot;dfsdquot;); } }).start(); } @Override public void onClick(View v) { press(); } }
上訴代碼就能夠實現 應用出現無法捕捉的異常時,殺死當前進程,重新啟動一個應用。
我之前困擾的地方:搜了很多資料,殺死異常進程,重新啟動應用,網上應用都是通過Application對象調用startActivity(intent),然后殺死異常進程。但是我怎樣試都不成功,
進程是殺死了,但是應用卻沒啟動起來,如果不將異常進程殺死,那么關閉應用時就得關閉兩次,顯然不能夠接受。網上的一些方法都是錯誤的:如下幾篇博客:
http://blog.csdn.net/xianming01/article/details/7711160
http://blog.csdn.net/ryantang03/article/details/9336295?reload
他們的方法能夠捕獲異常,殺死異常進程,但是卻不能夠重新啟動應用。
如何殺死異常進程,重啟應用,就得使用PendingIntent,這個類是android中對Intent類的包裝,具體了解我會在寫一篇博客,自己也可以去查看android API。
通過AlarmManager 啟動它,并且關閉打開的Activity殺死異常進程就能夠實現重新啟動應用。
參考鏈接:
Tags: 安卓開發
文章來源:http://blog.csdn.net/zkw12358/article/details/1109