Automated Android Crash Reports with ACRA and Cloudant

Making a basic Android app is easy. Making a reliable, scalable, and robust Android app, on the other hand, can be quite challenging. With thousands of available devices pumped out from tons of different manufacturers, assuming that a single piece of code will work reliably across phones is naive at best. Segmentation is the greatest trade off for having an open platform, and we pay the price in the currency of code maintenance, which continues long after an app has passed the production stage.

Why Android error reporting matters

So, what happens when an Android app crashes or becomes non-responsive? Well, the "Force Close" dialog pops up, letting the user know that something is gone wrong. If the app was downloaded through Google Play, the user will be prompted to report the crash by sending a detailed Android crash report (including time, phone model, Android version, stack trace, etc.) that you (the developer) can view in the the Developer's Console, allowing you to address the culprit bug.

This all sound very nice-but there's a major problem with Android's default error reporting: users tend not to use it, leaving developers clueless as to the state of their apps. This all sound very nice-but there's a major problem with using Android's default error reporting: users tend not to take action when their apps crash; in fact, the majority choose not to send in Android error reports. How then, can you, as a conscientious developer, gain reliable insights into your app's crashes and failings?

A reliable Android crash log is especially important when users don't send crash reports.

Introducing ACRA

ACRA stands for "Automated Crash Reporting for Android". It's a free library that lets you solve the 'manual error reporting' problem with a few lines of code. Once you've implemented the library and everything has been properly initialized, you'll be able to extract the same Android error logs as the Google default (plus a bunch of added customization options) automatically and without requiring the user to take action.
Beyond that, ACRA lets you choose how you'd like to inform the user of an Android crash, with the default being silent background reporting, and alternatives including customized dialogs.
Until recently, ACRA was backed by Google Spreadsheet, which meant that you were able to receive all your reports in a single file, hosted for free on your Google Drive account. Unfortunately, Google requested that we not use this option in the future, so we're left with a couple of alternatives for sending in crash report data, some of which we will cover in this tutorial:
  • Standard email (still requires user interaction).
  • Custom email/HTTP client (requires extensive setup).
  • Custom back-end (with options ranging from free to commercial solutions).
In this article, we'll analyze one of these solutions: hosting your ACRA reports on a Cloudantback-end and visualizing the data with acralyzer.

Setting up a Cloudant back-end

The first thing we need to do is register a Cloudant account. Of course, there's a catch: Cloudant's services are not entirely free, but according to their pricing page it's very unlikely that you'll exceed the monthly $5 limit (unless you have huge user base and a ton of bugs in your code).
Once we've registered, we need to understand how things work. At a high level, our back-end will consist of two components:
  1. A storage database or, to be more precise, an Apache CouchDB. CouchDB stores its data in JSON format, which means that all reports sent from the Android device must match the format in order to be inserted as an entry. A database insert is a simple HTTP POST or PUT request.
  2. A web app (for analysis) or, to be more precise, a CouchApp. This is a simple JavaScript application that lets you run queries and display the data stored in the CouchDB instance.
In order for our back-end to work properly, we'll need to setup these two components. In theory, we could build the database and the app from source, and then use a tool to deploy them to our back-end-but the good folk at ACRA have already done that for us. So the easiest approach is to replicate a remote database and a remote app.
Let's go ahead and replicate an empty ACRA CouchDB:
  • Select the 'Replication' section in your Cloudant dashboard.
  • As the source database, select 'Remote database' with as the URL.
  • As the target database, select 'New database' and name it "acra-{myapp}" (without the quotation marks). Note that the {myapp} parameter should be unique to your app, and that the database name must start with "acra-".
  • Click 'Replicate'.
This illustrates how to set up a Cloudant back-end to manage Android crash reporting.
Thus, we have successfully replicated the database for report storing. Next, we need to replicate the acralyzer CouchApp so that we can visualize the data:
  • Select the 'Replication' section in your Cloudant dashboard.
  • As the source database, select 'Remote database' with as the URL.
  • As the target database, select 'New database' and name it "acralyzer".
  • Click 'Replicate'.
This step consists of replicating the acra app to visualize the Android crash log data.
Note: replicating the acralyzer app is optional. You won't need it if you're only interested in storing your Android crash report, rather than visualizing the data (we'll take a closer look at acralyzer in the next section of this Android tutorial). If you feel confident enough with your JavaScript skills, you could even write your own analytics app! But that's outside the scope of this blog post.
The last step of the initial setup process is to add security permissions. Cloudant provides its own security layer over CouchDB with finer control on individual rights, so in order to write a report to our database we need to create a user account with write permissions:
  • Select the 'Database' section in your Cloudant dashboard.
  • Click the permissions section (lock icon) for the acra-{myapp} database.
  • Click 'Generate API keys'.
  • Write down the generated username and password (we'll use them later).
  • Add write permissions for the generated username.
Add security permissions so your Android crash logs and reports are accessible later.

Visualizing Android crash reports with acralyzer

Once replicated, the acralyzer dashboard can be easily accessed by following https://{myapp} I'll admit: it's not the prettiest analytics tool out there, but it serves its purpose.
From the top menu, you can select which database you want to visualize (it is possible to host multiple databases for different apps in a single project; this will affect your usage quota) and preview the data in the main dashboard. For example, you can:
  • Plot the number of reports by unit of time (hour, day, month, etc.).
  • View the distribution of reports by Android-specific metrics (Android version, SDK version, app version, device, etc.).
  • List all crash reports (with a detailed stack trace) or view all bugs (here, a "bug" is a group of identical reports sourced from different users).
  • Preview details for a single bug and set its status as resolved (if fixed).
  • Purge old or obsolete entries.
Visualizing Android crash log data can be very helpful to improving your app more strategically.
Note that the Android crash metrics available for visualization will depend on the reports we choose to send from our app. ACRA offers a variety of report fields, some of which can be quite large in size or not completely relevant to bug fixing. For most projects, the required report fields will be sufficient. These include:

Implementing ACRA in your Android project

As previously mentioned in this tutorial, implementing ACRA is very easy and just requires a few quick steps.

Add dependency

First, we need to include the library as a dependency in one of the following ways:
  • As a .jar file in your /libs folder.
  • As a maven dependency:
  • As a gradle dependency:
    compile 'ch.acra:acra:X.Y.Z'

Add Application class

Next, we need to add an Android Application class to our project (or update an existing class, as there can only be one instance) and declare it in the AndroidManifest.xml:
And setup ACRA there:
formUri = "https://{myusername}{myapp}/_design/acra-storage/_update/report",
reportType = HttpSender.Type.JSON,
httpMethod = HttpSender.Method.POST,
formUriBasicAuthPassword = "GENERATED_PASSWORD",
formKey = "", // This is required for backward compatibility but not used
customReportContent = {
mode = ReportingInteractionMode.TOAST,
resToastText = R.string.toast_crash

publicclassMainAppextendsApplication {

publicvoidonCreate() {
// The following line triggers the initialization of ACRA
That's it! Of course, you'll need to replace all the {myapp} placeholders with actual values, as well as values for formUriBasicAuthLogin and formUriBasicAuthPassword.
As you can see from the above code snippet, we're only using the required report fields. Feel free to add any other fields that may be relevant to your application.
You can also choose to use PUT instead of POST. In that case, the REPORT_ID will be appended to the end of the former as a parameter.
Finally, you can also choose how the user is informed of the Android app's crash, the default being a silent background report. In our case, we choose to display a Toast message letting the user know that the crash has been reported and a bug fix should be available soon.

Need help? Here's a sample project

To see ACRA in action, I've setup the acra_examplerepo on GitHub. It features a simple app that initializes ACRA on start up and let's you crash it by pressing a button (which then triggers a null pointer exception). The crash data is sent to an example Cloudant database that can be visualized here.
To view the data, log in with the following credentials:
  • Username: medo
  • Password: acraexample

Alternatives to ACRA

ACRA isn't the only option for automated Android error reporting. Since crashes are bound to happen, there's a big business-to-developer (B2D) market out there attempting to monetize their resolution.
Crittercism, for example, is a very mature platform for crash reporting. It looks great, offers a bunch of options for data analysis, and is very easy to integrate. The only downside: price, and the free trial is fairly limited in terms of number of active users, days of data retention, and support). BugSense is a similar service.
In my opinion, however, Crashlytics is a superior solution. Until recently, Crashlytics had a freemium model (with a paid premium tier); but now (after their acquisition by Twitter), all the formerly-premium features are available for free. There are no usage costs, fees, or limits. This is the preferred means of error reporting for a lot of high profile and high ranking companies and developers, as it's very easy to use and offers powerful analytics and visualization tools. It even integrates with most popular IDEs as a plugin (e.g., Eclipse, Android Studio), so adding Crashlytics to your app is as simple as selecting a project and pressing a button. These plugins also enables you to track crash reports from your IDE without having to open up a browser.
So, why use ACRA then when there are other alternatives out there that look way better and offer more features for the same implementation effort? I'll give you two reasons.
  1. All these other options are closed source, proprietary software. Even with a basket full of EULAs, you can't be sure exactly how your data is gathered and handled. On the other hand, ACRA and acralyzer are open source projects hosted on GitHub that you can easily fork and tailor to your needs.
  2. Data mobility. Let's say you're unsatisfied with Cloudant. It's a breeze to replicate and migrate your data to another back-end. You're guaranteed that the data stays yours.
As with many choices, this one boils down to personal preference and familiarity. Check out this Google+ thread for more discussion on the various alternatives available for making your app more reliable.

In conclusion

ACRA is a highly robust and highly customizable library that can be utilized alongside Cloudant and acralyzer to achieve free, automated crash reporting and basic analytics for your app, all for minimal implementation effort.
Writing reliable Android code requires a lot of experience and foresight, but none of us are truly omniscient. Be prepared for the unexpected crashes and errors, and be ready to fix the unexpected as soon as possible. That's the kind of work that goes into great products and great user experiences.
About The Author:

Demir Selmanovic
Demir is a developer and project manager with over 15 years of professional experience in a wide range of software development roles. He excels as a solo developer, team member, team leader, or manager of multiple distributed teams. He works closely with clients to define ideas and deliver products.

JavaScriptC#Web App DevelopmentWindowsMicrosoft SQL ServerjQueryASP.NET MVCNode.jsT-SQLJavaGoogle Maps APIGoogle MapsAngularJSAndroidPostgreSQL
Hire Demir »

Find us on Facebook