2010-05-04 50 views
81

我想爲我的Android應用程序中的所有線程設置全局未捕獲的異常處理程序。因此,在我的Application子類中,我將Thread.UncaughtExceptionHandler的實現設置爲未捕獲異常的默認處理程序。在Android中設置全局未捕獲的異常處理程序的理想方式

Thread.setDefaultUncaughtExceptionHandler(
       new DefaultExceptionHandler(this)); 

在我的實現中,我試圖顯示一個AlertDialog顯示適當的異常消息。

但是,這似乎並不奏效。每當任何未處理的線程拋出異常時,我都會獲得庫存,操作系統默認對話框(「對不起! - 應用程序已停止 - 意外對話」)。

什麼是正確和理想的方式來設置未捕獲的異常的默認處理程序?

+1

能否請你分享代碼相同.. – 2012-04-20 11:11:43

+2

如果您想記錄您的例外情況,請查看http://acra.ch/。 ACRA允許您將錯誤報告發送至Google-Doc或通過電子郵件發送給您。 – 2013-01-21 12:53:13

+1

@Alexander或者您可以使用Google Analytics for Android,並記錄您想要的所有例外... – 2013-06-27 16:48:29

回答

23

設置這應該是所有你需要做的。 (請確保你之後導致進程停止 - 事情可能處於不確定狀態。)

首先要檢查的是Android處理程序是否仍在調用。有可能你的版本被調用但失敗致命,並且system_server在看到進程崩潰時顯示一個通用對話框。

在處理程序頂部添加一些日誌消息,以查看它是否到達那裏。從getDefaultUncaughtExceptionHandler打印結果,然後拋出未捕獲的異常以導致崩潰。密切關注logcat輸出,看看發生了什麼。

+10

「處理錯誤後拋出未捕獲的異常以導致崩潰」仍然很重要。我剛剛經歷過它。我處理異常後,我的應用程序被鎖定,並未拋出未捕獲的異常。 – OneWorld 2010-10-20 10:06:52

+0

@OneWorld Jepp在這裏同樣如此 - 至少對於鎖定部分來說 - 似乎沒有任何辦法可以「拯救」應用程序從崩潰畢竟。 – AgentKnopf 2012-04-04 07:47:15

+0

@Zainodis我對這個問題發表了一個溫和的離題答案,給出了一個Crittercism的鏈接 - 我認爲他們有一個功能,可以讓你「保存」應用程序從崩潰畢竟。不知道 - 我只使用免費版atm。 – 2012-08-28 06:48:25

3

我想禁用,在您的uncaughtException()方法不調用previousHandler.uncaughtException(),其中previousHandler由

previousHandler = Thread.getDefaultUncaughtExceptionHandler(); 
3

FWIW我知道這是有點偏離主題,但我們一直在使用Crittercism's free plan成功。它們還提供一些高級功能,例如處理異常,以便應用程序不會崩潰。

在免費版本中,用戶仍然看到崩潰,但至少我得到了電子郵件和堆棧跟蹤。

我們也使用iOS版本(但我從我的同事那裏聽說它不太好)。


這裏有類似的問題:

1

它不工作,直到你打電話

android.os.Process.killProcess(android.os.Process.myPid()); 

在很EN d你的UncaughtExceptionHandler。

8

我發佈了簡單的solution很久以前的自定義處理Android崩潰。這是一個小黑客,但它適用於所有Android版本(包括棒棒糖)。

首先有點理論。在Android中使用未捕獲的異常處理程序時遇到的主要問題與主要(又名UI)線程中引發的異常有關。這是爲什麼。當應用程序啓動系統調用ActivityThread.main方法,準備好,開始您的應用程序的Main looper

public static void main(String[] args) { 
    … 
    … 
    Looper.prepareMainLooper(); 
    … 
    Looper.loop(); 
    throw new RuntimeException("Main thread loop unexpectedly exited"); 
} 

主要尺蠖是負責處理張貼在UI線程(包括與UI渲染和互動的所有消息)消息。如果在UI線程中拋出異常,它將被異常處理程序捕獲,但由於您不在loop()方法中,因此無法向用戶顯示任何對話框或活動,因爲沒有人可以處理UI給你的消息。

建議的解決方案非常簡單。我們用我們自己的方法運行Looper.loop方法,並用try-catch塊將其包圍。當發現異常時,我們會按照我們的要求處理它(例如,開始我們的自定義報告活動),並再次調用Looper.loop方法。

下面的方法演示了這種方法(它應該從Application.onCreate監聽器調用):

private void startCatcher() { 
    UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler(); 

    // the following handler is used to catch exceptions thrown in background threads 
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler(new Handler())); 

    while (true) { 
     try { 
      Looper.loop(); 
      Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler); 
      throw new RuntimeException("Main thread loop unexpectedly exited"); 
     } catch (Throwable e) { 
      showCrashDisplayActivity(e); 
     } 
    } 
} 

正如你可以看到未捕獲的異常處理程序僅用於在後臺線程拋出的異常。以下處理程序捕獲的異常,並將它們傳播到UI線程:

static class UncaughtHandler implements UncaughtExceptionHandler { 

    private final Handler mHandler; 

    UncaughtHandler(Handler handler) { 
     mHandler = handler; 
    } 

    public void uncaughtException(Thread thread, final Throwable e) { 
     mHandler.post(new Runnable() { 
      public void run() { 
       throw new BackgroundException(e); 
      } 
     }); 
    } 
} 

使用這種技術可以用我的GitHub庫示例項目:https://github.com/idolon-github/android-crash-catcher

+0

正如人們可能會猜到的那樣,這樣不僅可以顯示自定義錯誤對話框,而且還允許用戶忽略異常並繼續使用應用程序(儘管對於已發佈的應用程序來說這看起來不是個好主意,但它可以在調試或測試期間非常方便)。 – Idolon 2015-01-24 14:31:37

+0

嗨,雖然這工作捕捉未捕獲的異常,但由於某些原因,此代碼總是拋出異常。最初我雖然是因爲你在startCatcher方法中有RuntimeException行,但我在刪除它後仍然收到異常。我不確定這是否是必需的。無論如何,我得到的異常是'java.lang.RuntimeException:執行暫停的不恢復的活動'。我相信當我嘗試啓動自己的活套時,系統會暫停即將開始的活動?我不確定,但任何幫助,將不勝感激。謝謝 – sttaq 2015-09-28 09:09:03

+0

如果我刪除startCatcher,即運行沒有你的代碼的應用程序,那麼一切正常,沒有任何例外。 – sttaq 2015-09-28 09:45:06