Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android catch unhandled exception and show the dialog

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?

like image 646
Sergey Shustikov Avatar asked Mar 19 '23 09:03

Sergey Shustikov


2 Answers

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.

like image 132
Naruto Uzumaki Avatar answered Mar 31 '23 18:03

Naruto Uzumaki


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.

like image 30
14 revs, 12 users 16% Avatar answered Mar 31 '23 20:03

14 revs, 12 users 16%