Skip to content

Report Destinations

William Ferguson edited this page Jan 31, 2016 · 16 revisions

Introduction

The following sections details the possible destinations for your crash reports: custom script, email, third-party backend, or any other destination you can imagine (if you implement the sender). And you can even send reports to multiple destinations.

Contents

Sending reports to your own self-hosted script

Just use the formUri parameter of the @ReportsCrashes annotation in your Application class :

@ReportsCrashes(formUri = "http://yourserver.com/yourscript",
                formUriBasicAuthLogin = "yourlogin", // optional
                formUriBasicAuthPassword = "y0uRpa$$w0rd", // optional
                mode = ReportingInteractionMode.TOAST,
                resToastText = R.string.crash_toast_text)
public class MyApplication extends Application {
...

The formUri can be over HTTPS (even with self signed certificates) and can require a BASIC HTTP authentication (pass your login and password with formUriBasicAuthLogin and formUriBasicAuthPassword).

With the default configuration, your script will receive a POST request with report fields as POST parameters named like the ReportField enum values.

Since ACRA v4.4.0, if you are sending reports over SSL using a self-signed certificate, you need to set the option ReportsCrashes.disableSSLCertValidation to true.

POST/PUT request

Since ACRA v4.5.0, you can choose to send reports via an HTTP PUT request rather than an HTTP POST request.

Switching to PUT is done by setting the httpMethod option to org.acra.sender.HttpSender.Method.PUT.

When using a PUT request, ACRA adds automatically the Report ID at the end of the formUri. For example, with the following ACRA configuration:

@ReportsCrashes(formUri = "http://yourserver.com/yourscript",
                formUriBasicAuthLogin = "yourlogin", // optional
                formUriBasicAuthPassword = "y0uRpa$$w0rd", // optional
                httpMethod = org.acra.sender.HttpSender.Method.PUT,
                mode = ReportingInteractionMode.TOAST,
                resToastText = R.string.crash_toast_text)
public class MyApplication extends Application {
...

a new report is sent to http://yourserver.com/yourscript/fe24835f-8117-4639-bfea-f57c77205771. fe24835f-8117-4639-bfea-f57c77205771 is a unique report identifier generated by ACRA (REPORT_ID field).

Data encoding (FORM/JSON)

The defaults settings encode reports data key/value pairs as a form-urlencoded string.

Since ACRA v4.5.0, you have the option to send reports data encoded as a detailed JSON tree structure. You can see here 2 examples of the data generated with the default set of ReportFields.

Switching to JSON is done by setting the configuration option reportType to org.acra.sender.HttpSender.Type.JSON.

Adjusting the socket timeout

The default socket timeout for ACRA is 8 seconds and if your server does not respond quickly enough then ACRA will timeout the socket connection and you can experience this as empty reports on the server.

If you are experiencing timeouts when sending reports, you can adjust the socket timeout with the socketTimeout option (time in milliseconds).

Sending reports by email

For some applications, sending reports to a Google Docs Form or other Http based solutions is not an option. The problem is that they require the INTERNET permission.

For pure offline applications, users might even be frightened to grant this permission and can be suspicious about the real goal of the app or the developer.

To get crash reports without granting INTERNET permission, you can use the mailTo setting from @ReportsCrashes:

@ReportsCrashes(formUri = "http://yourserver.com/yourscript",
                mailTo = "reports@yourdomain.com",
                mode = ReportingInteractionMode.TOAST,
                resToastText = R.string.crash_toast_text)
public class MyApplication extends Application {
...

Including a full report could be quite difficult due to the data size. Default fields included in email reports are:

  • ReportField.USER_COMMENT
  • ReportField.ANDROID_VERSION
  • ReportField.APP_VERSION_NAME
  • ReportField.BRAND
  • ReportField.PHONE_MODEL
  • ReportField.CUSTOM_DATA
  • ReportField.STACK_TRACE

You can override the report fields list using the customReportContent option in the @ReportsCrashes annotation:

@ReportsCrashes(mailTo = "reports@yourdomain.com",
                customReportContent = { ReportField.APP_VERSION_CODE, ReportField.APP_VERSION_NAME, ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL, ReportField.CUSTOM_DATA, ReportField.STACK_TRACE, ReportField.LOGCAT },                
                mode = ReportingInteractionMode.TOAST,
                resToastText = R.string.crash_toast_text)
public class MyApplication extends Application {
...

Emails are sent with an ACTION_SEND intent. This means that the following steps are required for the application user before any report is sent:

  • pick preferred email client (if no default app set)
  • review & actually send the email

Implementing your own sender

Several ReportSender implementations are already available:

  • HttpSender: (default when formUri is set) send reports to a server-side component located at a configurable URI via formUri. Reports can be sent via PUT or POST request and as FORM or JSON encoded data.
  • EmailIntentSender: keeps only a selected set of fields and puts them in an Intent to be send by another application.

But since ACRA v4.0, you can implement your own ReportSender and configure ACRA to use that instead of or in addition to other ReportSenders.

Syntax for ACRA 4.8+:

public class YourOwnSender implements ReportSender {

    // NB requires a no arg constructor.

    @Override
    public void send(Context context, CrashReportData report) throws ReportSenderException {
        // Iterate over the CrashReportData instance and do whatever
        // you need with each pair of ReportField key / String value
    }
}

Syntax for ACRA 4.0 to 4.7:

public class YourOwnSender implements ReportSender {

    public YourOwnSender(... your params ...){
        // initialize your sender with needed parameters
    }

    @Override
    public void send(CrashReportData report) throws ReportSenderException {
        // Iterate over the CrashReportData instance and do whatever
        // you need with each pair of ReportField key / String value
    }
}

Once your sender has been created, you have to declare it to ACRA.

ACRA 4.8+ instructions:

You can either declare your ReportSender(s) via the reportSenderFactoryClasses attribute of the ReportCrashes annotation. THis is the recommended approach.

@ReportCrashes{
   ...
   reportSenderFactoryClasses = {your.funky.ReportSender.class, other.funky.ReportSender.class} 
}
public class YourApplication extends Application {
    @Override
    public void onCreate() {
        ACRA.init(this);
        super.onCreate();
    }
}

Or configure them programmatically BEFORE calling ACRA.init().

@ReportCrashes{
   ...
}
public class YourApplication extends Application {
    @Override
    public void onCreate() {
        final ACRAConfiguration config = new ACRAConfigurationFactory().create(this);

        final Class[] myReportSenderClasses = ...
        config.setReportSenderFactoryClasses(myReportSenderClasses)

        ACRA.init(this, config);
        super.onCreate();
    }
}

NB pre ACRA 4.8 instructions:

Declare your ReportSenders in your Application class, in the onCreate() method, right after the ACRA.init() call:

    @Override
    public void onCreate() {
        ACRA.init(this);
        YourOwnSender yourSender = new YourOwnSender(whatever, parameters, needed);
        ACRA.getErrorReporter().setReportSender(yourSender);
        super.onCreate();
    }

NB pre ACRA 4.8 instructions:

For advanced usage, there is a full set of available methods to manage the list of active ReportSenders:

  • setReportSender(ReportSender): sets a new sender as the single active sender
  • addReportSender(ReportSender): adds a new sender to the list of active senders, without removing all previous active senders
  • removeReportSender(ReportSender): removes a specific instance of a sender
  • removeReportSenders(Class): removes all active instances of a specific ReportSender implementation
  • removeAllReportSenders(): clears the list of active ReportSenders
Clone this wiki locally