How to catch crash without disturbing the normal crash flow - android

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);
}
}
});
}

Related

How to override handleUncaughtException without changing its functionallity

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

How do I handle uncaught exceptions and then delegate handling back to the system?

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"
... />

When activity crashes, the process stays alive and I cannot kill it

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);
}
}
}

android: how to quit the app properly on error

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.

Using Global Exception Handling on android

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.
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 !!!");
}
});
}
}
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
}
});
}
}
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.
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.
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()
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

Categories

Resources