4

I want to handle unhandled exception in my app without any third-party libraries.

So i write a code.

Activity :

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Thread.setDefaultUncaughtExceptionHandler(new ReportHelper(this));
    throw new NullPointerException();
}

My crash handler :

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.MessageQueue;
import android.widget.Toast;

/**
 * Created by S-Shustikov on 08.06.14.
 */
public class ReportHelper implements Thread.UncaughtExceptionHandler {
    private final AlertDialog dialog;
    private       Context     context;

    public ReportHelper(Context context) {
        this.context = context;
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage("Application was stopped...")
                .setPositiveButton("Report to developer about this problem.", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                    }
                })
                .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        // Not worked!
                        dialog.dismiss();
                        System.exit(0);
                        android.os.Process.killProcess(android.os.Process.myPid());

                    }
                });

        dialog = builder.create();
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        showToastInThread("OOPS!");
    }

    public void showToastInThread(final String str){
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(context, "OOPS! Application crashed", Toast.LENGTH_SHORT).show();
                if(!dialog.isShowing())
                    dialog.show();
                Looper.loop();

            }
        }.start();
    }
}

When i start app as you see i throwed NullPointerException. Toast in my handling logic was showed, and dialog was showed too. BUT! Dialog clicks was not handling correct. I mean logic in onClick method was not worked. What the problem and how i can fix that?

Sergey Shustikov
  • 15,377
  • 12
  • 67
  • 119

3 Answers3

5

In my case, I moved AlertDialog.Builder in thread run function like this:

public void showToastInThread(final String str){
    new Thread() {
        @Override
        public void run() {
            Looper.prepare();

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage("Application was stopped...")
            .setPositiveButton("Report to developer about this problem.", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {

                }
            })
            .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    // Not worked!
                    dialog.dismiss();
                    System.exit(0);
                    android.os.Process.killProcess(android.os.Process.myPid());

                }
            });

            dialog = builder.create();


            Toast.makeText(context, "OOPS! Application crashed", Toast.LENGTH_SHORT).show();
            if(!dialog.isShowing())
                dialog.show();
            Looper.loop();

        }
    }.start();
}

and all thing work perfectly.

Hope this help you.

Naruto Uzumaki
  • 2,019
  • 18
  • 37
2

According this post, the state of the application is unknown, when setDefaultUncaughtExceptionHandler is called. This means that your onClick listeners may not be active anymore.

Why not use this method:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    try {
        setContentView(R.layout.main);
        Thread.setDefaultUncaughtExceptionHandler(new ReportHelper(this));
        throw new NullPointerException();
    } catch (NullPointerException e) {
        new ReportHelper(this);
    }
}

and remove ReportHelper implementing the Thread.UncaughtExceptionHandler interface.

Your method of not explicitly catching exceptions can be seen as an anti-pattern.

Community
  • 1
  • 1
Martin Konecny
  • 57,827
  • 19
  • 139
  • 159
  • But click was not handled. I checked that in debug. – Sergey Shustikov Jun 08 '14 at 20:59
  • 1
    If i remove my ReportHelper i will got a compile error because `Thread.setDefaultUncaughtExceptionHandler` pass the parameter which implements `Thread.UncaughtExceptionHandler`. I hope you missed this. – Sergey Shustikov Jun 09 '14 at 09:50
  • I put the Log into `uncaughtException(Thread thread, Throwable ex)` and i see magic behavior. this method calls 3 times from different threads. – Sergey Shustikov Jun 09 '14 at 11:26
0

Since an exception occurs on the UI-Thread: the state of this thread is probably unexpected

So try simply this in your click handler :

.setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    android.os.Process.killProcess(android.os.Process.myPid());

                }
            });
ben75
  • 29,217
  • 10
  • 88
  • 134