可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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(); } });