Rethrow UncaughtExceptionHandler Exception after Logging It

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

In my Application class I am trying to catch a force close before it happens, so I can log it and then rethrow it so the android can handle it. I do this since some users do not report force closes.

I am developing in eclipse, and eclipse is not allowing me to rethrow the exception. It shows an error saying "Unhandled exception type Throwable: Surround with try/catch". How can I rethrow the exception?

public class MainApplication extends Application {     @Override     public void onCreate()     {     super.onCreate();      try     {         //Log exception before app force closes         Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {             @Override             public void uncaughtException(Thread thread, Throwable ex) {                 AnalyticsUtils.getInstance(MainApplication.this).trackEvent(                         "Errors",                       // Category                         "MainActivity",                 // Action                         "Force Close: "+ex.toString(),  // Label                         0);                             // Value                 AnalyticsUtils.getInstance(MainApplication.this).dispatch();                  Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG);                  //rethrow the Exception so user can report it                 //throw ex; //<-- **eclipse is showing an error to surround with try/catch**             }         });      } catch (Exception e)     {         e.printStackTrace();     } }

}

回答1:

Apologies, not an Android expert - but looks like you can't throw ex because your method signature "void uncaughtException(Thread, Throwable)" doesn't declare that it "throws" anything.

Assuming you're overriding an API interface and (a) can't modify this signature and (b) don't want to because you'd be throwing it out of context, could you instead use a decorator pattern and basically subclass the default UncaughtExceptionHandler implementation to log your message and then let it carry on processing as usual?

Edit: untested, but this might look a bit like:

    final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();     Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {         @Override         public void uncaughtException(Thread thread, Throwable ex) {             // your code              AnalyticsUtils.getInstance(MainApplication.this).trackEvent(                     "Errors",                       // Category                     "MainActivity",                 // Action                     "Force Close: "+ex.toString(),  // Label                     0);                             // Value             AnalyticsUtils.getInstance(MainApplication.this).dispatch();             Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG).show();              // carry on with prior flow             subclass.uncaughtException(thread, ex);         }     });


回答2:

I'm not exactly sure if this is what you want, however you can add a finally clause that will run after either a successful try or a handled catch:

try {     //your code } catch (Exception e) {     //print stack trace } finally {     //Log }


回答3:

I think following code should work. Executing handler code using a new Thread allows application to show alert/toast and perform other operations.

Also, you may try invoking System.exit(0) just before exiting run(). This relaunches the last activity.

I checked this on both Ginger Bread as well as Jelly Bean.

final UncaughtExceptionHandler subclass = Thread.currentThread().getUncaughtExceptionHandler();     Thread.currentThread().setUncaughtExceptionHandler(new UncaughtExceptionHandler() {         @Override         public void uncaughtException(Thread thread, Throwable ex) {             new Thread() {                 @Override                 public void run() {                     Looper.prepare();                       // your code                      AnalyticsUtils.getInstance(MainApplication.this).trackEvent(                             "Errors",                       // Category                             "MainActivity",                 // Action                             "Force Close: "+ex.toString(),  // Label                             0);                             // Value                     AnalyticsUtils.getInstance(MainApplication.this).dispatch();                     Toast.makeText(MainApplication.this, "Snap! Something broke. Please report the Force Close so I can fix it.", Toast.LENGTH_LONG);                      Looper.loop();                 }             }.start();         }     });


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!