Thursday, 5 May 2016

How to fix 'Unfortunately App has stopped' errors

There is one problem that plagues Android Developer: the cursed Unfortunately, Android App has stopped error message. It appears when you're in the middle of using an app, and then forces that app to close.
Here's how to handle Unfortunately, app has stopped errors and show users an neat regret message within the app as shown below.


The Cause :
Your application quit because an uncaught RuntimeException was thrown.
The most common of these is the NullPointerException.

Here we are going to see how to catch the uncaught exception and schedule a task (Showing an Activity with regret message instead of App crash dialog).

Step 1 : Create a new project by going to File ⇒ New Android Application Project. Fill all the details and name your activity as MainActivity. (eclipse)

Step 2 : Create a new Activity by going to File ⇒ New ⇒ Other ⇒ Android Activity. Fill all the details and name your activity as RegretActivity.

Step 3 : Design the activity_regret.xml layout for RegretActivity under layout folder as shown below

activity_regret.xml

<RelativeLayout xmlns:android = "http://schemas.android.com/apk/res/android"
    xmlns:tools = "http://schemas.android.com/tools"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    tools:context = "${relativePackage}.${activityClass}" >
  
        <include
            android:id = "@+id/toolbar"
            layout = "@layout/toolbar" />
    <TextView
        android:id = "@+id/textView1"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_centerHorizontal = "true"
        android:layout_centerVertical = "true"
        android:text = "@string/msg_unexpected_error_occured"
        android:textAppearance = "?android:attr/textAppearanceLarge"
        android:textColor = "#505050"
        android:textStyle = "bold" />

    <TextView
        android:id = "@+id/textView2"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_below = "@+id/textView1"
        android:layout_centerHorizontal = "true"
        android:text = "@string/msg_sorry_for_the_inconvenience"
        android:textAppearance = "?android:attr/textAppearanceMedium" />

    <ImageView
        android:id = "@+id/imageView1"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_above = "@+id/textView1"
        android:layout_centerHorizontal = "true"
        android:contentDescription = "@string/tv_access_denied"
        android:src = "@drawable/ic_warning" />

    <Button
        android:id = "@+id/restart_button"
        android:layout_width = "wrap_content"
        android:layout_height = "wrap_content"
        android:layout_below = "@+id/textView2"
        android:layout_centerHorizontal = "true"
        android:layout_marginTop = "@dimen/pad_10dp"
        android:background = "@drawable/blue_button_background"
        android:paddingBottom = "@dimen/pad_5dp"
        android:paddingLeft = "@dimen/pad_10dp"
        android:paddingRight = "@dimen/pad_10dp"
        android:paddingTop = "@dimen/pad_5dp"
        android:text = "@string/restart_app"
        android:textColor = "@color/white"
        android:textSize = "@dimen/txt_15sp"
        android:textStyle = "bold"/>

</RelativeLayout>

Step 4 : Create a new class under src/package. Right Click on src/package (com.example.uncaughtexception) ⇒ New ⇒ Class and name it as UncaughtExceptionHandler.java and fill it with following code.

UncaughtExceptionHandler.java

public class UncaughtExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler
{

    /**
     * activity - Activity
     */

    private final ActionBarActivity activity;

    /**
     * UncaughtExceptionHandler - Constructor
     * @param context
     */

    public UncaughtExceptionHandler(ActionBarActivity context)
    {
        activity = context;
    }
   
    @Override
    public void uncaughtException(Thread thread, Throwable exception)
    {
        exception.printStackTrace();
       
        Intent intent = new Intent(activity, RegretActivity.class);
        activity.startActivity(intent);
        activity.finish();

        System.out.println("Error occurred Activity name : " + activity.getClass().getSimpleName());
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(10);
    }
}

Step 5 : Now open up the MainActivity  from src/package. Add the following statement next to the super.onCreate(); inside onCreate method.

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(this));


The above statement will catch the UncaughtExcption occurred in the activity.

Source code : Click here to download. 

Thanks a lot for reading...
Don't forget to share this post if you found it interesting!
If you find something to add to this post? or any other quick thoughts/hints that you think people will find useful? Share it in the comments & feedback's are most welcome.