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();
}
}
}
If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.
In C# 5.0, a mechanism was added that enables the throwing of a previously thrown exception without losing the stack trace information in the original exception. This lets you rethrow exceptions, for example, even from outside a catch block and, therefore, without using an empty throw.
An exception caught by one catch can be rethrown so that it can be caught by an outer catch. To rethrow an exception, you simply specify throw, without specifying an expression.
Throwing an exception is as simple as using the "throw" statement. You then specify the Exception object you wish to throw. Every Exception includes a message which is a human-readable error description. It can often be related to problems with user input, server, backend, etc.
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);
}
});
For anyone finding this question only now, I'm not sure if any of the above answers were correct when posted, but they're not now. What you want nowadays is to create a new class that implements Thread.UncaughtExceptionHandler
and in the constructor, save Thread.getCurrentUncaughtExceptionHandler()
to a field, and you call its uncaughtException(Thread, Throwable)
at the end of your uncaughtException(Thread, Throwable)
method. Then you call Thread.setUncaughtExceptionHandler()
from whatever code instantiates your class, often MainApplication.onCreate
.
So the full code would look something like:
//MainApplication.java
public class MainApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
CustomUncaughtExceptionHandler cueh = new CustomUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(cueh);
}
}
//CustomUncaughtExceptionHandler.java
class CustomUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler oldHandler;
CustomUncaughtExceptionHandler() {
oldHandler = Thread.getDefaultUncaughtExceptionHandler();
}
@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();
if (oldHandler != null) {
oldHandler.uncaughtException(thread, ex);
else {
System.exit(1);
}
}
}
You can also store the original default uncaught exception handler somewhere else for restoration later (or add a getOldHandler()
method) if for whatever reason you decide you don't want your code to run anymore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With