android 中處理崩潰異常并重啟程序

分類:技術 時間:2016-10-24

有時候由于測試不充分或者程序潛在的問題而導致程序異常崩潰,這個是令人無法接受的,在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殺死異常進程就能夠實現重新啟動應用。

參考鏈接:

http://zheyiw.iteye.com/blog/1670990


Tags: 安卓開發

文章來源:http://blog.csdn.net/zkw12358/article/details/1109


ads
ads

相關文章
ads

相關文章

ad