15

It's a general question, which raised from specific scenario, but I'd like to get a general answer how to deal with the following situation:

Background:

I have an app, which is using some 3rd party library (ad network provider SDK - specifically - AdMob SDK, based on Google Play Services). Functionality of this library is not critical for the application. The library creates one or more background worker threads. Sometimes (very rare case) there is an unhandled exception in one of these background threads, causing to crashing the application. I'd like to ignore all exceptions, caused by this library, regardless of their cause: in worst case the app user will not see an ad - it's much better than app crash.

Since the library itself creates the background threads - I cannot just wrap them by try/catch.

Question

Is there any way to catch all non-handled background (non-main) thread exceptions and just to kill the thread in such case, and to prevent app crash?

Related questions

I saw a lot of several questions, but some of them are too specific (and not covering my case), others refer to situation when the developer has a control on thread creation and is able to wrap the whole thread with try/catch. If I still missed the relevant question, covering this case, I will appreciate the link

Denis Itskovich
  • 4,383
  • 3
  • 32
  • 53
  • 2
    Have you tried installing a handler for the worker thread and try to not kill the process? I don't know if that's possible because you may not have access to the worker thread that is crashing. I know flurry manages to install a handler for the entire process and transmit a bug report before app crashes. Perhaps it's doable through this route. – over_optimistic Apr 10 '14 at 04:28
  • @over_optimistic Thanks! I tried using Thread.setDefaultUncaughtExceptionHandler and it works like a charm :) ! Please write this as answer so I can accept it – Denis Itskovich Apr 10 '14 at 18:27
  • 1
    http://stackoverflow.com/questions/2764394/ideal-way-to-set-global-uncaught-exception-handler-in-android/ – fadden Jun 01 '15 at 19:45

2 Answers2

19

All you need to do is Extend all the activities with BaseActivity. The app never crashes at any point

Code sniplet for BaseActivity :

public class BaseActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
                Log.e("Error"+Thread.currentThread().getStackTrace()[2],paramThrowable.getLocalizedMessage());
            }
        });
    }
}
Roope Hakulinen
  • 7,326
  • 4
  • 43
  • 66
Rohit
  • 647
  • 14
  • 30
  • 4
    I think it's better to put this code into custom Application class, since it is intended to run only once in an app's lifetime – Denis Itskovich Apr 11 '15 at 06:25
  • 3
    after adding this to my app, Whenever my app crashes it stucks on black screen. Please help me on this – Shashwat Gupta Dec 05 '17 at 11:29
  • 1
    You absolutely should not set an uncaught exception handler in _all_ activities, as only one global handler can be assigned and only one will be called (from the docs: `This handler is invoked in case any Thread dies due to an unhandled exception.`). Assigning handlers through activities can in fact result in code referencing properties of dead activities. As already mentioned, assign only one handler at Application-scope. – d4vidi Feb 25 '20 at 12:19
4

As mentioned above, Thread.setDefaultUncaughtExceptionHandler is the proper way to handle this. Create the class:

 private class MyThreadUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        Log.e(TAG, "Received exception '" + ex.getMessage() + "' from thread " + thread.getName(), ex);
    }
}

Then call setDefaultUncaughtExceptionHandler from your main thread:

 Thread t = Thread.currentThread();
 t.setDefaultUncaughtExceptionHandler(new MyThreadUncaughtExceptionHandler());
Janin
  • 41
  • 3
  • 2
    `Thread.setDefaultUncaughtExceptionHandler(new MyThreadUncaughtExceptionHandler());` why need a new instance? – iamVishal16 Nov 27 '19 at 05:26