Crash Reporting an Android App with Crashlytics and Fabric

Theodhor Pandeli
Share

This article was updated on January 18, 2017. Specifically: Added coverage of Crashlytics Answers.

The Fabric Library from Twitter provides a suite of tools to complement and enhance your apps. In this tutorial I will focus on the crash reporting features that help pinpoint and track app crashes.

Adding the Fabric Plugin

Create a new project in Android Studio, choosing a minimum API level of 18 and adding a Blank Activity.

Open the Android Studio plugin manager, click Browse Repositories, search for Fabric and install the plugin. Restart Android Studio for the plugin to take effect and a new icon will appear in the upper toolbar.

Fabric Icon

Clicking the icon will open a panel on the right hand side of the Android Studio window. Click the power button to register or login to the Fabric service, then click Next, Crashlytics and Install.

Fabric will show you the changes it needs to make to your application, check them and click Apply in the bottom right of the screen.

Force A Simple Crash

As this is a sample application you have to force a crash by clicking a button in the app.

Open activity_main.xml and delete the unnecessary ‘Floating Action Bar Button’ code.

Inside the content_main.xml layout add two buttons to represent the report types that Crashlytics supports.

Replace the TextView with this code:

<LinearLayout
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="50dp">

  <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Simple Crash"
      android:onClick="forceCrash"
      android:layout_gravity="center" />

  <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Extra Info Crash"
      android:onClick="showUserDialog"
      android:layout_gravity="center"
      android:layout_marginTop="30dp" />
</LinearLayout>

Open the MainActivity.java class and delete the ‘Floating Action Button’ code. Before the onCreate() method, add the following:

private EditText userIdentifierEditText, userEmailEditText, userNameEditText;
private String userIdentifier, userEmail, userName;

These variables will be used in the second crash reporting type that includes custom user information.

The first simple crash throws a RuntimeException to cause an application crash.

Add the following after the onCreate() method:

public void forceCrash(View view) {
  throw new RuntimeException("This is a simple crash");
}

As the view is called on a button click, the function takes a View as a parameter and needs to be public. When clicked, the method forceCrash throws a RuntimeException and sends a report to the Fabric Dashboard. The information included in this report will contain the line of code that caused the crash and general device information.

Report Example

Force a crash that includes user information

The second button simulates a crash that allows a user to input information into a dialog. For example, the users e-mail or social network user names.

Add the function below after forceCrash(View view){} :

public void logUser(String userIdentifier, String userEmail, String userName) {
  // TODO: Use the current user's information
  // You can call any combination of these three methods
  Crashlytics.setUserIdentifier(userIdentifier);
  Crashlytics.setUserEmail(userEmail);
  Crashlytics.setUserName(userName);
}

The function requires three parameters of type String and adds them to the report sent. To get this data from a user you need a custom dialog with three input fields.

Create a custom layout called custom_dialog_layout.xml and add the following code:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/userIdentifier"
        android:inputType="number"
        android:hint="User Identifier:"/>
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/userEmail"
        android:hint="User Email:"/>
    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/userName"
        android:hint="User Name:"/>
    </android.support.design.widget.TextInputLayout>
</LinearLayout>

Add the following method to MainActivity.java that creates the dialog, gets the information, performs the crash and sends the report:

public void showUserDialog(View view) {
    LayoutInflater inflater = getLayoutInflater();
    View alertLayout = inflater.inflate(R.layout.custom_dialog_layout, null);
    userIdentifierEditText = (EditText) alertLayout.findViewById(R.id.userIdentifier);
    userEmailEditText = (EditText) alertLayout.findViewById(R.id.userEmail);
    userNameEditText = (EditText) alertLayout.findViewById(R.id.userName);

    AlertDialog.Builder alert = new AlertDialog.Builder(this);
    alert.setTitle("Information");
    alert.setView(alertLayout);
    alert.setCancelable(false);
    alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int which) {

        }
    });

    alert.setPositiveButton("Crash & Send", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // code for matching password
            userIdentifier = userIdentifierEditText.getText().toString();
            userEmail = userEmailEditText.getText().toString();
            userName = userNameEditText.getText().toString();
            if (!userIdentifier.equals("") && !userEmail.equals("") && !userName.equals("")) {
                logUser(userIdentifier, userEmail, userName);
                Toast.makeText(getBaseContext(), "Sending extra information...", Toast.LENGTH_SHORT).show();
                throw new RuntimeException("This is a crash with extra information");
            }
            Toast.makeText(getBaseContext(), "Information not send! Please complete all fields...", Toast.LENGTH_SHORT).show();
        }
    });
    AlertDialog dialog = alert.create();
    dialog.show();

}

When the second button is clicked, the application shows a dialog that asks for input. Clicking Crash & Send checks if the strings have values, performs the crash and sends the report containing the information.

Crash log with user information

Crashlytics Dashboard

To see the crash reports, access the Crashlytics dashboard of an individual app.

App Dashboard

Below the graph are the crashes corresponding to certain lines of code. To view more detailed information about a crash, click an item on the list.

Crash detail

To view more information about the user who sent the report, click *Viewing latest crash (More details…)_

User Details

Answers

Fabric also gives you the simplest tools to keep your application user metrics, events and behavior.

In order to keep the tracks of any Activity or View visited by the user, just add this code inside any method:

//New Answers data
        Answers.getInstance().logContentView(new ContentViewEvent()
                .putContentName("MainActivity")
                .putContentType("View")
                .putContentId("1234")
                .putCustomAttribute("Custom Number", 20)
                .putCustomAttribute("Screen Orientation", "Landscape"));

You can also create custom Answers Events by adding:

Answers.getInstance().logCustom(new CustomEvent("User registered")
                .putCustomAttribute("Custom Attribute", "Sample")
                .putCustomAttribute("Custom", 350));  

Answers Data

But Answers gives more options about the application metrics with many other events like below:

Answer Events

Conclusion

The Crashlytics component of Fabric provides a quick method of adding crash reporting to your apps, helping you identify common problems experienced by users and improve your app.

Please let me know in the comments below if you have any questions or problems.

CSS Master, 3rd Edition