天天看點

android程式崩潰後重新開機

有時候由于測試不充分或者程式潛在的問題而導緻程式異常崩潰,這個是令人無法接受的,在android中怎樣捕獲程式的異常崩潰,然後進行一些必要的處理或重新啟動

應用這個問題困惱了我很久,今天終于解決了該問題,寫篇文章記錄一下。

首先捕獲程式崩潰的異常就必須了解一下java中uncaughtexceptionhandler這個接口,android沿用了此接口,在android api中:

android程式崩潰後重新開機

通過實作此接口,能夠處理線程被一個無法捕捉的異常所終止的情況。如上所述的情況,handler将會報告線程終止和不明原因異常這個情況,如果沒有自定義handler,

線程管理組就被預設為報告異常的handler。

threadgroup 這個類就是實作了uncaughtexceptionhandler這個接口,如果想捕獲異常我們可以實作這個接口或者繼承threadgroup,并重載uncaughtexception方法。

在java api中對該接口描述的更詳細:

android程式崩潰後重新開機

我就不翻譯了,太吃力了....%>_<%。在實作uncaughtexceptionhandler時,必須重載uncaughtexception(thread thread, throwable ex) ,如果我們沒有實作該接口

也就是沒有顯示捕捉異常,則ex為空,否則ex不為空,thread 則為出異常的線程。

接下來上代碼,實作uncaughtexceptionhandler接口,顯示處理線程異常終止的情況:

public class uncehandler implements uncaughtexceptionhandler {  

    private thread.uncaughtexceptionhandler mdefaulthandler;    

    public static final string tag = "catchexcep";  

    catchexcep application;  

    public uncehandler(catchexcep application){  

         //擷取系統預設的uncaughtexception處理器    

         mdefaulthandler = thread.getdefaultuncaughtexceptionhandler();  

         this.application = application;  

    }  

    @override  

    public void uncaughtexception(thread thread, throwable ex) {      

        if(!handleexception(ex) && mdefaulthandler != null){   

            //如果使用者沒有處理則讓系統預設的異常處理器來處理    

            mdefaulthandler.uncaughtexception(thread, ex);                

        }else{         

            try{    

                thread.sleep(2000);    

            }catch (interruptedexception e){    

                log.e(tag, "error : ", 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(), "很抱歉,程式出現異常,即将退出.",   

                        toast.length_short).show();    

                looper.loop();    

            }   

        }.start();    

        return true;    

    }    

}  

public class catchexcep extends application{  

    arraylist<activity> list = new arraylist<activity>();  

    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;  

    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("dfsd");  

            }  

        }).start();  

    public void onclick(view v) {  

        press();  

上訴代碼就能夠實作 應用出現無法捕捉的異常時,殺死目前程序,重新啟動一個應用。

我之前困擾的地方:搜了很多資料,殺死異常程序,重新啟動應用,網上應用都是通過application對象調用startactivity(intent),然後殺死異常程序。但是我怎樣試都不成功,

程序是殺死了,但是應用卻沒啟動起來,如果不将異常程序殺死,那麼關閉應用時就得關閉兩次,顯然不能夠接受。網上的一些方法都是錯誤的:如下幾篇部落格:

<a target="_blank" href="http://blog.csdn.net/xianming01/article/details/7711160">http://blog.csdn.net/xianming01/article/details/7711160</a>

<a target="_blank" href="http://blog.csdn.net/ryantang03/article/details/9336295?reload">http://blog.csdn.net/ryantang03/article/details/9336295?reload</a>

他們的方法能夠捕獲異常,殺死異常程序,但是卻不能夠重新啟動應用。

如何殺死異常程序,重新開機應用,就得使用pendingintent,這個類是android中對intent類的包裝,具體了解我會在寫一篇部落格,自己也可以去檢視android api。

通過alarmmanager 啟動它,并且關閉打開的activity殺死異常程序就能夠實作重新啟動應用。

參考連結:

<a target="_blank" href="http://zheyiw.iteye.com/blog/1670990">http://zheyiw.iteye.com/blog/1670990</a>

繼續閱讀