I added an exceptionhandler for unhandled exceptions, to know that the app has crashed on the next app start:
#Override
public void uncaughtException(Thread thread, Throwable ex) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putString("crashed", "yes");
editor.commit();
}
I added the handler via:
Thread.setDefaultUncaughtExceptionHandler(this);
Now the thing is: since I added the handler, the app behaves differently on error:
Before I added the handler I got a popup telling me that the app has crashed.
Now, after adding the handler the app just freezes, and after a while android shows me a popup telling me that the app does not respond anymore and whether I want to wait any longer. This is not good IMO. Any hints, how to properly exit after an application crash?
you can save the original exception handler , so that you can call it after you are done with doing your own custom operations on the unhandled exception . something like this:
//Inside UncaughtExceptionHandler.java:
…
private UncaughtExceptionHandler defaultUEH;
public DefaultExceptionHandler()
{
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
#Override
public void uncaughtException(Thread t, Throwable e)
{
//do anything you wish about the Throwable e :getStackTrace(),getCause(),getClass()...
//call the original uncaught exception handler:
defaultUEH.uncaughtException(t, e);
}
I suggest that you integrate your logic with ACRA, so that it can handle the issues of crash reporting and cleanup.
Related
I asked this question some time back on Stackoverflow, the answer worked for me, It overrides thehandleUncaughtException, I save the exception and throws the default Unfortunately app has stopped working, but when i integrated this in my app, I am facing an issue.
This is the answer i got.
private Thread.UncaughtExceptionHandler defaultExceptionHandler;
public void registerCrash(){
defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException (Thread thread, Throwable e){
handleUncaughtException (thread, e);
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
}
});
}
What it does, first it goes to handleUncaughtException (thread, e); i save the crash log in this method, then it reads this line
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
here we throw uncaught exception again, so it goes to the first line again, and again saves the exception, and this goes in loop, and application becomes not responding.
What i want is to save crash log, and then show the default Unfortunate message to user.
EDIT
On Application launch it reads this;
defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
When application crashes, it reads these lines
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException (Thread thread, Throwable e){
handleUncaughtException (thread, e); //Custom Method
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
}
So it first goes to handleUncaughtException() there i have provided custom implementation, then it goes to this;
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
The defaultExceptionHandler is never null; So it goes in a loop in case of multiple crashes.
I have tried adding count there, but it was 0 each time.
The most likely explanation is that your registerCrash() method is being called twice.
The first time, you register Handler 1; there is no default handler at this point, so it sets defaultExceptionHandler to null. The second time, you register Handler 2, and then update defaultExceptionHandler to point to Handler 1.
On an uncaught exception, Handler 2 gets invoked first. It calls your custom handler method, then invokes defaultExceptionHandler, which now points to Handler 1.
Handler 1 gets invoked. It calls your custom handler method a second time, then it invokes defaultExceptionHandler, which now points to itself. This step repeats until your stack overflows.
I suggest two changes. First, add a guard to ensure you only register your crash handler once. Second, don't store the fallback handler in a field; capture it in a closure so the value seen by your handler never changes.
private static final AtomicBoolean CRASH_HANDLER_REGISTERED = new AtomicBoolean();
public void registerCrash() {
if (CRASH_HANDLER_REGISTERED.compareAndSet(false, true)) {
final Thread.UncaughtExceptionHandler defaultHandler =
Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e); // Custom Method
if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, e);
}
}
}
);
}
}
I suggest you to try another approach, avoid overriding exceptions, catch it and retrive the error code, and do this:
when x code with x conditions verify, do that
I want to send a firebase crash report for every uncaught exception in my app but I also want to Android system to show the "App has stopped responding" dialog. How do I go about this?? I already have an UncaughtException handler that sends the firebase crash report. My issue now is letting Android handle the rest of the process.
The uncaught exception can be delegated back to system by storing the old exception handler and passing uncaught exceptions to it.
First create an Application class as below:
public class Controller extends Application {
private static Thread.UncaughtExceptionHandler defaultHandler;
#Override
public void onCreate() {
super.onCreate();
if (defaultHandler == null) {
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
}
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
FirebaseCrash.report(e); //or whatever
defaultHandler.uncaughtException(t, e); //this will show crash dialog.
}
});
}
}
Then use this class as application in the manifest as:
<application
android:name=".Controller"
... />
I know there are already good tools available like crashlytics, but i have a requirment and i can't use these tools.
All i need to is to save the crash log before application exists, and that without disturbing the normal flow, and using any 3rd party library
I have implemented this, but it has disturb the normal flow of android crashing. I want to save the log, but don't want to disturb the normal crashing flow.
This is what i am doing to save the crash log.
public void registerCrash(){
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler()
{
#Override
public void uncaughtException (Thread thread, Throwable e)
{
handleUncaughtException (thread, e);
}
});
}
public void handleUncaughtException (Thread thread, Throwable e)
{
thread.getStackTrace();
savePreferenceData(e.toString());
System.exit(0);
}
public void savePreferenceData(String data) {
SharedPreferences sharedPreferences= context.getSharedPreferences(LOG_DATA, Context.MODE_PRIVATE);
SharedPreferences.Editor prefsEditor = sharedPreferences.edit();
prefsEditor.putString(STACK_TRACE, data);
prefsEditor.apply();
}
The problem is that, It restarts the application, without giving the default Alert dialog to user. Unfortunately App has stopped.
Kindly guide me how to save crash log witout disturbing the normal crash mechanisim
Before setting the UncaughtExceptionHandler, keep track of the one that was set before and simply call it from your own handler after you are done:
private Thread.UncaughtExceptionHandler defaultExceptionHandler;
public void registerCrash(){
defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler (new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException (Thread thread, Throwable e){
handleUncaughtException (thread, e);
if(defaultExceptionHandler != null){
defaultExceptionHandler.uncaughtException(thread, e);
}
}
});
}
I am handling the Uncaught Exception in android as follow
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable e) {
handleUncaughtException(thread, e);
}
})
public void handleUncaughtException(Thread thread, Throwable e) {
Helper.logUncaughtExceptionToFile(e); // Just to log the exception
}
It works fine for me, it handle the exceptions, but when exception happened my function got called then the application crashes. Is this how it should work? I don't want the application to crash
Only the thread related exceptions are being handled.if the particular thread has the job of fetching data to UI then the application crashes without the required values for generating UI.
I am developing an app with quite a few threads, it often crashes so far, whenever I load the new version from eclipse, it seems to create a new process.
I cannot seem to find a way to kill the old processes, they do not apear in the running apps.
I can see that I have multiple processes related to my app in the process list ("ps" command).
Is there a way to make sure the app process actually dies on crash?
have you tried this android.os.Process.killProcess(android.os.Process.myPid()); it can kill your process
You can kill your app's process by:
System.exit(1);
It order to know when your app crashes (exception that's not being caught) you'll need to define:
Thread.setDefaultUncaughtExceptionHandler(new CustomUncaughtExceptionHandler());
In your main Thread.
CustomUncaughtExceptionHandler is:
public class CustomUncaughtExceptionHandler implements UncaughtExceptionHandler
{
private UncaughtExceptionHandler defaultUEH;
public CustomUncaughtExceptionHandler()
{
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e)
{
// Put system.exit here
if (defaultUEH != null)
{
defaultUEH.uncaughtException(t, e);
}
else
{
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
defaultUEH.uncaughtException(t, e);
}
}
}