2013-07-07 33 views
7

我正在開發一個應用程序,並且每過一段時間,我的一個後臺工作線程就會有一種或另一種類型的未捕獲異常。這些異常會導致該線程崩潰,但由於它不在UI線程上,因此應用程序會繼續運行。 如何在後臺線程中強制這些未捕獲的異常崩潰整個應用程序?如果有相同的上下文崩潰信息(如堆棧跟蹤)可用,那將會很好。Android:線程中出現未捕獲的異常並導致崩潰

我想這樣做,以便當我將應用程序發佈給我的測試人員時,它不會變得沒有響應。相反,當後臺線程有一個未捕獲的異常時,應用程序將轉到它的崩潰處理程序並向我發送一份報告(我正在使用ACRA,但這應該不重要)。這比靜靜地失敗的應用程序更好。

回答

0

你可以在實現java.lang.Thread.UncaughtExceptionHandler的課程中捕獲未捕獲的異常。

  • 創建實現UncaughtExceptionHandler的一類,並把你uncaughtException overidden功能需要的行爲。
    你可以在這個功能中做任何你想要的行爲,比如發送日誌到服務器,向用戶顯示自定義崩潰對話框等。
  • 你的活動/線程添加Thread.setDefaultUncaughtExceptionHandler();並給出你的異常處理程序類的實例。


+0

這不適用於所有Executor實現。其中一些人不打電話給處理程序。你必須重寫'afterExecute'並重新拋出RuntimeException或Error從那裏強制它崩潰。 – Monstieur

2

晚的答案,但我問自己同樣的問題。

我們在生產中使用了Crashlytics,但是如果爲開發構建應用程序,則會啓用某些斷言,並記錄錯誤實際上會拋出錯誤,以便我們的開發人員可以檢測到任何不正確的行爲。

但正如您所說,在後臺線程中拋出一個錯誤不會導致應用程序崩潰。

爲了確保應用程序在構建開發時立即崩潰,我們只需在主循環中使用Handler來在主線程上拋出異常。

它看起來有點像這樣:


public static void assertTrue(boolean condition, String msg) { 
    if (condition) { 
     return; 
    } 

    final IllegalStateException e = new IllegalStateException(message); 
    if (BuildConfig.RELEASE) { 
     Crashlytics.logException(e); 
     return; 
    } 

    Log.e("ASSERT", message, e); 
    if (Looper.getMainLooper() != Looper.myLooper()) { 
     mMainThreadHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       throw e; 
      } 
     }); 
    } 

    throw e; 
} 
+0

雖然這看起來像一個有前途的解決方案,但我還是不清楚幾件事: 1.您如何避免run()中的「未捕獲的異常」的Intellij錯誤() 2.您在哪裏獲得mainThreadHandler在此靜態上下文中? –

0

原始版本低於

事實上,經過進一步的測試中,我發現,您可以通過只交給異常到你的主線程簡化代碼直。

public static <T extends Exception> void throwOnMainThread(T exception) { 
    Thread mainThread = Looper.getMainLooper().getThread(); 
    mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, exception); 
} 

這會從任何地方崩潰的主線程是安全的,甚至稱不設置自定義的UncaughtExceptionHandler。

原來的答覆:

考慮從後臺線程崩潰主線程下列靜態方法:

public static <T extends Exception> void throwOnMainThread(final T exception) { 
    Handler mainThreadHandler = new Handler(Looper.getMainLooper()); 
    mainThreadHandler.post(new Runnable() { 
     @Override 
     public void run() { 
      Thread currentThread = Thread.currentThread(); 
      currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, exception); 
     } 
    }); 
} 

首先,我們獲得通過主尺蠖主線程處理程序。然後我們發佈一個Runnable,它將調用該線程的UncaughtExceptionHandler,並將其傳遞給我們的異常。

把它放到一個utils類中,你將能夠從基本上任何地方在主線程上拋出異常。

崩潰主線程然後可通過使用

ThreadUtils.throwOnMainThread(new RuntimeException()); 

例如來實現。

相關問題