Monday, 4 April 2016

How to avoid Force Close Error in Android

All android developer must have faced force close issue while developing an application.
Here is a method to catch that error and treat it elegantly.
This will create an error page kind of mechanism in your android application.So whenever your application is crashed user will not able to see that irritating pop up dialog. Instead of that app will display a predefined view to the user.
To make such kind of mechanism we need to make one error handler and an Activity class which will gain the view whenever the app gets forced closed.
package com.example.forceclose;

import java.io.PrintWriter;
import java.io.StringWriter;

import android.app.Activity;
import android.content.Intent;
import android.os.Build;

public class ExceptionHandler implements
        java.lang.Thread.UncaughtExceptionHandler {
    private final Activity myContext;
    private final String LINE_SEPARATOR = "\n";

    public ExceptionHandler(Activity context) {
        myContext = context;
    }

    public void uncaughtException(Thread thread, Throwable exception) {
        StringWriter stackTrace = new StringWriter();
        exception.printStackTrace(new PrintWriter(stackTrace));
        StringBuilder errorReport = new StringBuilder();
        errorReport.append("************ CAUSE OF ERROR ************\n\n");
        errorReport.append(stackTrace.toString());

        errorReport.append("\n************ DEVICE INFORMATION ***********\n");
        errorReport.append("Brand: ");
        errorReport.append(Build.BRAND);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Device: ");
        errorReport.append(Build.DEVICE);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Model: ");
        errorReport.append(Build.MODEL);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Id: ");
        errorReport.append(Build.ID);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Product: ");
        errorReport.append(Build.PRODUCT);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("\n************ FIRMWARE ************\n");
        errorReport.append("SDK: ");
        errorReport.append(Build.VERSION.SDK);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Release: ");
        errorReport.append(Build.VERSION.RELEASE);
        errorReport.append(LINE_SEPARATOR);
        errorReport.append("Incremental: ");
        errorReport.append(Build.VERSION.INCREMENTAL);
        errorReport.append(LINE_SEPARATOR);

        Intent intent = new Intent(myContext, AnotherActivity.class);
        intent.putExtra("error", errorReport.toString());
        myContext.startActivity(intent);

        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(10);
    }

}
Above class will work as a listener for forced close error. We will have a full error log plus device information too. Sometimes it also happens that particular error is coming from some specific manufacturer’s device. You can see that Intent and startActivity is used to start the new Activity whenever app crashes. So it will start the activity named CrashActivity whenever app get crashed.For now I have passed the stack trace as an intent’s extras.
Now because CrashActivity is a regualr Android Actitvity you can handle it in whatever way you want.
Now comes the important part i.e. How to catch that exception.
Though it is very simple. Copy following line of code in your each Activity just after the call of super method in your overriden onCreate method.
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
Your Activity may look something like this…
public class ForceClose extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

       Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));

        setContentView(R.layout.main);

        // Your mechanism is ready now.. In this activity from anywhere 
        // if you get force close error it will be redirected to the CrashActivity.
    }
}
Your output will look like this


Android