Is there a code example, or a tutorial on how to use the Thread.setDefaultUncaughtExceptionHandler
method? Basically I'm trying to display a custom alert dialog, whenever an exception is thrown, in my application. Is it possible to do this? I know it's a little bit tricky to display something on the screen, if the exception is thrown in the UI thread but I don't know any work around for this.

- 9,113
- 13
- 65
- 78

- 4,633
- 12
- 42
- 58
-
May I ask what the point is? The standard Android dialog allows users to report the crash, which will send a stack trace to your account. If you really want to do it - well, just start a new intent with Theme.Dialog, pass the exception information in the extras, and you're set. – EboMike Dec 13 '10 at 09:47
-
1In my application I'm using a data base file. If the application fails to connect to the data base, an exception will be thrown. I want to catch this exception and display a custom message. This is just an example. There are more situations like this. So it would be better for me to catch all of these exceptions in on place. – Gratzi Dec 13 '10 at 09:49
-
That doesn't sound like a good idea. Failure to connect to a database is a specific problem with a specific exception. You're handling any possible exception, including a NullPointerException because of sloppy code. I would *strongly* recommend putting try/catch blocks around your database code that *only* catches database-specific exceptions. – EboMike Dec 13 '10 at 09:56
-
In my code, there are many operations which include the data base. I was trying to find a way, not to use try catch blocks every time a data base operation is executed. Are you saying that the best practice would be to stick with the try catch blocks? isn't a way to handle these cases in on place? – Gratzi Dec 13 '10 at 10:02
-
7"Are you saying that the best practice would be to stick with the try catch blocks?" -- IMHO, yes. – CommonsWare Dec 13 '10 at 11:48
-
Do we need to set the handler explicitly for each activity, or can we set it globally via the Application class? - what about services? will that work for them as well? – Haggai Sep 20 '22 at 10:28
7 Answers
Basic Example for someone who comes to this page with a solution :)
public class ChildActivity extends BaseActivity {
@SuppressWarnings("unused")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int a=1/0;
}
}
Class for handling error:
public class BaseActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
Log.e("Alert","Lets See if it Works !!!");
}
});
}
}
-
2Don't you need to throw the exception again to stop the execution and not to leave the thread in an undetermined state? – Vaiden Feb 26 '12 at 18:35
-
1I couldn't your :D . In uncaughtException u can give what ever handling u want . – Code_Life Feb 27 '12 at 06:04
-
@Vaiden: No need to re-throw the exception. The OS has already terminated the thread, thus will not return to it after your handler has completed. – HammerNL Sep 04 '13 at 08:08
-
1Some of my other activities tell me `Cannot reduce the visibility of the inherited method from BaseActivity` after I do this. Just realized the problem. BaseActivity's `onCreate` was set to `public` but all of my descended activities' `onCreate` are set to `protected`. Just changed BaseActivity's to be `protected` as well. – theblang Jan 14 '14 at 21:34
-
20
-
Here's a variant of the answer by Mohit Sharma with the following improvements:
- Doesn't cause the app/service to freeze after error handling
- Lets Android do its normal error handling after your own
Code:
public class BaseActivity extends Activity {
@Override
public void onCreate() {
super.onCreate();
final Thread.UncaughtExceptionHandler oldHandler =
Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(
Thread paramThread,
Throwable paramThrowable
) {
//Do your own error handling here
if (oldHandler != null)
oldHandler.uncaughtException(
paramThread,
paramThrowable
); //Delegates to Android's error handling
else
System.exit(2); //Prevents the service/app from freezing
}
});
}
}
-
2Sorry for the late question, but is there a reason you use exit code 2 in your `System.exit()` call? Does Android care about the exit code? I can't seem to find any info on this... – Markus A. May 13 '15 at 19:09
-
@MarkusA., I can't remember why I used that code. Maybe `0` and `1` caused the app to freeze or something. – Sam May 13 '15 at 21:38
-
1Hmmm... I guess this might be worth a separate question: http://stackoverflow.com/questions/30226842/does-android-care-about-exit-status-code-passed-to-system-exit Let's see what comes of it... – Markus A. May 13 '15 at 23:29
-
1Great answer but i ran into two issues when using your answer. First thing is that if you let all your activities inherit from BaseActivity or you reinstantiate your activity inheriting from BaseActivity, you chain all your default Handlers together: first intent: custom Exception Handler (cEH) calls default Exception Handler (dEH) second intent: cEH -> cEH of first intent -> dEH third intent: cEH -> cEH of second intent -> cEH of first intent -> dEH ..... which leads to calling your defined action mulitiple times and an out of memory exception in the end. – GC268DM Jan 10 '19 at 14:14
-
@Sam How can i add custom message to it. Like "app has been busy" instead of the default "App has stopped working" ? – Prajwal Waingankar Aug 20 '19 at 09:14
-
@PrajwalW, I recommend using [ACRA](https://www.acra.ch/) for global exception handling instead of a custom solution. However, I wouldn't recommend telling users that the app is busy when it in fact crashed since that looks unprofessional and might put off users. – Sam Aug 21 '19 at 00:01
For those who just want to see exception details when your app crashes on device (in debug config). This is application class:
private Thread.UncaughtExceptionHandler oldHandler;
@Override
public void onCreate() {
super.onCreate();
if (!BuildConfig.DEBUG)
return;
oldHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
try {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
Intent intent = new Intent(Intent.ACTION_SEND);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_TEXT, sw.toString());
intent.setType("text/plain");
startActivity(intent);
} catch(Exception ex) {
ex.printStackTrace();
} finally {
if (oldHandler != null)
oldHandler.uncaughtException(t, e);
else
System.exit(1);
}
});
}
It uses external app as your UI thread might not working anymore.

- 121
- 1
- 7
I just wanted to point out my experience so far. I am using the solution suggested by https://stackoverflow.com/a/26560727/2737240 to flush the exception into my log file before giving control to the default exception handler.
However, my structure looks like this:
BaseActivity
|
_______________________
| | |
Activity A Activity B Activity C
final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e, defaultEH);
}
});
where handleUncaughtException(thread, e, defaultEH);
writes to the log and hands the call over to the original UncaughtExceptionHandler.
So what happened by using this code was the following:
- Activity A is instantiated
- New Default Exception Handler (DEH) is now my log handler + the old DEH
- Activity B is instantiated
- New DEH is now my log handler + the old DEH (log handler + original DEH)
- Activity C is instantiated
- New DEH is now my log handler + the old DEH (log handler + log handler + original DEH)
So it's a chain growing infinitely causing two problems:
- The specified custom code (in my case writing to the log file) will be called multiple times, which is not the desired action.
- The reference of defaultEh is kept in the heap even after the activity has been finished, because it is used by the reference chain so the worst thing that could happen is an out of memory exception.
Therefore I added one more thing to finally make this work without issues:
private static boolean customExceptionHandlerAttached = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!customExceptionHandlerAttached) {
final Thread.UncaughtExceptionHandler defaultEH = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e, defaultEH);
}
});
customExceptionHandlerAttached = true;
}
}
With this solution we can make sure to:
- add a custom exception handler for our desired action
- ensure that this action is only triggered once
- allowing garbage collector to dispose our activity completely by calling finish()

- 403
- 7
- 15
-
Wouldn't this be put in the Application class? With your approach, customExceptionHandlerAttached will be reset to false on rotation. – AndroidLearner Feb 01 '21 at 17:36
Keep in mind that the The RuntimePermission("setDefaultUncaughtExceptionHandler")
is checked prior to setting the handler and make sure you cause the process to halt afterwards, by throwing an uncaught exception, as things could be in an uncertain state.
Do not display anything, indeed the UI thread might have been the one that crashed, do write a log and/or send the details to a server, instead. You might want to check out this question and its answers.
if you want use this library
https://github.com/selimtoksal/Android-Caught-Global-Exception-Library
create your TransferObject not all in your activities just use in Base activity

- 222
- 1
- 8
You need to add the following code in the application class
override fun onCreate() {
super.onCreate()
Thread.setDefaultUncaughtExceptionHandler { _, e -> handleUncaughtException(e) }
}
private fun handleUncaughtException(e: Throwable) {
if (isUIThread()) invokeLogActivity(e)
else Handler(Looper.getMainLooper()).post { invokeLogActivity(e) }
}
private fun isUIThread(): Boolean {
return Looper.getMainLooper().thread === Thread.currentThread()
}
private fun invokeLogActivity(e: Throwable) {
val intent = Intent(currentActivity(), ErrorActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.putExtra("stackTrace", getStackTraceAsString(e))
startActivity(intent)
exitProcess(1)
}
private fun getStackTraceAsString(throwable: Throwable): String {
val sw = StringWriter()
val pw = PrintWriter(sw)
throwable.printStackTrace(pw)
return sw.toString()
}

- 59
- 5