|
AdvancedUsage
IntroductionThis is ACRA's Advanced Usage Guide. You need to set up your project before using all the features described here. If you have any question or comment regarding ACRA, post a message on the Discussion Group. User InteractionThe default behavior of ACRA is to send crash reports silently. From the application user point of view, the application has crashed with the usual "Force Close" dialog, and that's all. Though, a report has been sent without the user being aware of it. Depending on the state of your application and your concern of your users data plan usage and private data handling, you might prefer notifying them that a crash report has been sent, or even ask him the authorization to send one... and why not ask him to describe what he was doing during the crash... ACRA offers all these options, and allows you to customize your application crash reporting notifications. 2 main notification modes are available:
Enabling user notification only requires you to add parameters to the @ReportsCrashes annotation and some string values to your resources. Toast notification@ReportsCrashes(formKey="dGVacG0ydVHnaNHjRjVTUTEtb3FPWGc6MQ",
mode = ReportingInteractionMode.TOAST,
forceCloseDialogAfterToast = false, // optional, default false
resToastText = R.string.crash_toast_text)
public class MyApplication extends Application {
...In your strings.xml : <string name="crash_toast_text">Ooooops ! I crashed, but a report has been sent to my developer to help fix the issue !</string> The forceCloseDialogAfterToast option allows you to choose to display the Android native Froce Close Dialog. Default is false to avoid warning users twice about a single issue, but your opinion about this may differ so the choice is yours. Status bar notification@ReportsCrashes(formKey="dGVacG0ydVHnaNHjRjVTUTEtb3FPWGc6MQ",
mode = ReportingInteractionMode.NOTIFICATION,
resToastText = R.string.crash_toast_text, // optional, displayed as soon as the crash occurs, before collecting data which can take a few seconds
resNotifTickerText = R.string.crash_notif_ticker_text,
resNotifTitle = R.string.crash_notif_title,
resNotifText = R.string.crash_notif_text,
resNotifIcon = android.R.drawable.stat_notify_error, // optional. default is a warning sign
resDialogText = R.string.crash_dialog_text,
resDialogIcon = android.R.drawable.ic_dialog_info, //optional. default is a warning sign
resDialogTitle = R.string.crash_dialog_title, // optional. default is your application name
resDialogCommentPrompt = R.string.crash_dialog_comment_prompt, // optional. when defined, adds a user text field input with this text resource as a label
resDialogOkToast = R.string.crash_dialog_ok_toast // optional. displays a Toast message when the user accepts to send a report.
)
public class MyApplication extends Application {
...In your strings.xml: <string name="crash_toast_text">Ooooops ! I crashed, but a report has been sent to my developer to help fix the issue !</string>
<string name="crash_notif_ticker_text">Unexpected error, please send a report...</string>
<string name="crash_notif_title">CrashTest has crashed...</string>
<string name="crash_notif_text">Please click here to help fix the issue.</string>
<string name="crash_dialog_title">CrashTest has crashed</string>
<string name="crash_dialog_text">An unexpected error occurred forcing the
application to stop. Please help us fix this by sending us error data,
all you have to do is click \'OK\'.</string>
<string name="crash_dialog_comment_prompt">You might add your comments about the problem below:</string>
<string name="crash_dialog_ok_toast">Thank you !</string>In your AndroidManifest.xml <application ...>
....
<activity android:name="org.acra.CrashReportDialog"
android:theme="@android:style/Theme.Dialog"
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:finishOnTaskLaunch="true" />
....
</application>Reports destinationThe default destination for reports is a Google Docs Form, storing data in a Google Docs Spreadsheet. This storage has some great advantages:
The only known limitation is that a Google Spreadsheet can't contain more than 400 000 cells. With ACRA 4.0 it lets you receive 11 428 crash reports in one spreadsheet... but you are allowed to delete old reports at any time! The following sections detail the other possible destinations for your crash reports: custom script, email, or any other destination you can imagine (if you implement the sender). And you can even send reports to multiple destinations. Sending reports to your own self-hosted scriptJust use the formUri parameter of the @ReportsCrashes annotation in your Application class : @ReportsCrashes(formKey = "", // will not be used
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). Your script will receive report fields as POST parameters named like the [http://code.google.com/p/acra/source/browse/trunk/CrashReport/src/org/acra/ReportField.java ReportField] enum values. Sending reports by emailFor some applications, sending reports to a Google Docs Form is not 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(formKey = "", // will not be used
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:
You can override the report fields list using the customReportContent option in the @ReportsCrashes annotation: @ReportsCrashes(formKey = "", // will not be used
mailTo = "reports@yourdomain.com",
customReportContent = { ReportField.APP_VERSION, 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:
Implementing your own senderSince ACRA v4.0, you can implement your own report sender: 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
}
}Three ReportSender implementations are already available:
Once your sender created, you have to declare it to ACRA. This is done 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);
ErrorReporter.getInstance().setReportSender(yourSender);
super.onCreate();
}For advanced usage, there is a full set of available methods to manage the list of active ReportSenders:
Reports ContentACRA provides lots of data about the device and the state of your application. There are some options to let you add even more data to help debugging. Adding your own variables content or traces in crash reportsTo help you track some specific issue, you can add custom data to reports. Simply use the following method in key places in your code : ErrorReporter.getInstance().putCustomData("myVariable", myVariable);All your custom data (only latest value for each one) will be added in the column "custom" just before the stack trace, one key = value pair per line. You can also use getCustomData("myVariable") and removeCustomData("myVariable") to get/remove data from the custom data map. Adding logcat, eventlog or radiolog extracts to reportsYou can enable adding a logcat extract to your reports by simply adding the READ_LOGS permission: <manifest ...>
...
<uses-permission android:name="android.permission.READ_LOGS"></uses-permission>
</manifest>The default behavior is to include the result of the following command: adb logcat -t 200 -v time This results to 200 lines of logcat with date, invocation time, priority/tag, and PID of the originating process. If this is not what you want, you can change this with your own command line using the logcatArguments in the @ReportsCrashes annotation. For example, if you prefer using: adb logcat -t 100 -v long ActivityManager:I MyApp:D *:S then add this to you {@ReportsCrashes} config: logcatArguments = { "-t", "100", "-v", "long", "ActivityManager:I", "MyApp:D", "*:S" }As you can see, you just have to split your command line arguments to a String array on each white space. Note for experts: even if the "-t XXX" argument is only available since android 2.2, you can use it safely as ACRA emulates it for older devices. In addition to the main default buffer, ACRA retrieves the 2 other alternative buffers event and radio. If these data are not of any use for you, you should consider deactivating their collection to enhance reporting time and memory management:
Note: System logs may contain private data logged by other applications like user email address, calendar events, contacts data... You should consider adding a user preference item to let your user choose to include system logs or not. Warning: collecting long system logs might take quite some time and induce a latency right after your application crash. Include them only if you know how to analyze them and avoid collecting more than 100 lines. Note: RADIOLOG and EVENTSLOG fields will be removed from the default reported fields in future ACRA versions. You'll have to activate them if you need them. Adding custom DropBoxManager events to your reportsDropBoxManager has been introduced in android API level 8 (2.2 - FroYo). This is a new logging system focused on persisting long chunks of text or data for debugging purposes. There is a Q&A on StackOverflow explaining the usage of this system. You need the READ_LOGS permission to collect these data, add it to your manifest with: <manifest ...>
...
<uses-permission android:name="android.permission.READ_LOGS"></uses-permission>
</manifest>A list of DropBox tags has been built by searching for DropBoxManager usage in android source code. All these system tagged events can be retrieved if you set @ReportsCrashes.includeDropBoxSystemTags to true on your application class:
@ReportsCrashes { formKey="xxxxxxxxxxxx",
...
inlcudeDropBoxSystemTags = true, // default is false
additionalDropBoxTags = {"your_own_tag", "another_additional_tag"},
dropboxCollectionMinutes = 10 // default is 5
...Warning: collecting DropBox events might take quite some time and induce a latency right after your application crash. If you don't know how to analyze them, you would better remove the DROPBOX field from the CrashReports-Template.csv before creating your spreadsheet, and copy the new content of your csv template in the {@ReportsCrashes. customReportContent} parameter. Increase the dropBoxCollectionMinutes only if you know what you are doing. Note: this field will be removed from the default reported fields in future ACRA versions. You'll have to activate it if you need it. Adding the Device Unique ID to your reportsIn some circumstances, tracking exactly which identified devices throw which report can be necessary. ACRA will include your users Device ID (IMEI for GSM and the MEID or ESN for CDMA phones) if you add the following permission to your application manifest: <manifest ...>
...
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
</manifest>Note: This unique device ID is considered as private data as it could let you track users behaviors... You should consider adding a user preference item to let your user choose to include this device id or not. Choosing which fields to be included in reportsYou can change the default set of fields included in your reports using @ReportsCrashes(customReportContent = { array of ReportField }). For example: import static ReportField.*;
@ReportsCrashes(formKey = "xxxxxxxxxxxxxxxx",
customReportContent = { APP_VERSION, ANDROID_VERSION, PHONE_MODEL, CUSTOM_DATA, STACK_TRACE, LOGCAT },
mode = ReportingInteractionMode.TOAST,
resToastText = R.string.crash_toast_text)
public class MyApplication extends Application {
...Your GoogleDoc spreadsheet has to be created with the same column. One easy way to recreate it is to copy/paste the list of fields (without the array braces) in a new text file with .csv extension and import it in GoogleDocs. Limiting your reports to what you really want and really use can help avoiding performance issues when collecting reports data. Only fields which are set in customReportContent are actually processed. Adding custom SharedPreferences namesYour applications default SharedPreferences are automatically collected in the SHARED_PREFERENCES field. You can provide additional SharedPreferences names using @ReportsCrashes(additionalSharedPreferences={"my.own.prefs","a.second.prefs"}). Letting your users control ACRASome ACRA behaviors can be configured by your application users through the use of SharedPreferences items:
If your SharedPreferences are not the application default SharedPreferences, you can provide ACRA with your own SharedPreferences name using the following @ReportsCrashes parameters:
Enable/disable ACRAAdd to your preferences xml file a CheckBoxPreference (checking it disables ACRA) : <CheckBoxPreference android:key="acra.disable"
android:title="@string/pref_disable_acra"
android:summaryOn="@string/pref_acra_disabled"
android:summaryOff="@string/pref_acra_enabled"
android:defaultValue="false"/>Or if you prefer the opposite (checking it to enable ACRA): <CheckBoxPreference android:key="acra.enable"
android:title="@string/pref_disable_acra"
android:summaryOn="@string/pref_acra_enabled"
android:summaryOff="@string/pref_acra_disabled"
android:defaultValue="true"/>Then add to your strings.xml files the 3 corresponding string resources. Enable/disable system logsIncluding logcat extracts in reports is a great tool for developers, but it can lead to privacy issues as some other applications might log private data like user account names, opened URLs, calendar events... Giving your users a way to control the inclusion of logcat data make them understand that you care about their privacy. This can be done with the inclusion of the following CheckBoxPreference: <CheckBoxPreference android:key="acra.syslog.enable"
android:summaryOn="@string/pref_acra_syslog_enabled"
android:summaryOff="@string/pref_acra_syslog_disabled"
android:title="@string/pref_acra_syslog"
android:defaultValue="true"/>Of course you have to define the matching strings in your strings.xml files. Enable/disable including DeviceIDIf you added the READ_PHONE_STATE permission to your application but want to let your user be able to disable the inclusion of their Device ID in crash reports, you can include the following CheckBoxPreference: <CheckBoxPreference android:key="acra.deviceid.enable"
android:title="@string/pref_acra_deviceid"
android:summaryOn="@string/pref_acra_deviceid_enabled"
android:summaryOff="@string/pref_acra_deviceid_disabled"
android:defaultValue="true"/>Don't forget to add the required strings in your strings.xml files. Set an email address to be added to reportsSome users might be willing to help debugging your app. You can ask them to input an email address that will be included in every report to allow you contact them: <EditTextPreference android:key="acra.user.email"
android:title="@string/pref_acra_user_email"
android:summary="@string/pref_acra_user_email_summary"/>Enable/disable auto accept reportsWhile in NOTIFICATION mode, you can allow your users to choose to auto-accept sending all reports. This is like letting them switch from NOTIFICATION mode to TOAST mode. <CheckBoxPreference android:key="acra.alwaysaccept"
android:title="@string/pref_acra_alwaysaccept"
android:summaryOn="@string/pref_acra_alwaysaccept_enabled"
android:summaryOff="@string/pref_acra_alwaysaccept_disabled"
android:defaultValue="false"/>Sending reports for caught exceptions or for unexpected application state without any exceptionAs a good programmer, your code is full of try/catch statements, and sometimes an interesting (unexpected) exception might be caught in one of these. You could also want your application to send a report without any Exception thrown, just because you know that your application is in an unexpected state. Both of these needs can be covered by this : ErrorReporter.getInstance().handleException(caughtException); You can provide any caught or custom Exception, or even null if you don't have any to provide. If you need to add silent trace reports whatever notification mode you configured for your application, you can also use: ErrorReporter.getInstance().handleSilentException(caughtException); | |
includeEventsLogcat and includeRadioLogcat don't exist in @ReportsCrashes?
It would be great if you provides on crash listener, that i can use for example to clear notifications of my app.
I store username and password to log onto a chat server in my preferences. the password is sent over as well in the clear. this will get into privacy issues. Is there a way to disable sending password fields in the preferences?
Thanks.
Link under the Sending reports to your own self-hosted script should be point to http://code.google.com/p/acra/source/browse/trunk/acra/src/main/java/org/acra/ReportField.java
If my application catches all exceptions would that still send those reports to the doc?
I believe what they are saying here is...
If you have an uncaught exception, it will generate a report (like normal). However, there are times that you caught the exception yourself and handle it gracefully i.e. your app does not crash. In those cases, you can use the handleException and handleSilentException methods to still send a report to you so you can better understand why these exceptions are happening in the first place.
In my app, To Do Mapr, I am implementing those handleSilentException methods in my catch block to send data about the user just so I can figure out why the exception happened in the first place.
I also worried about passwords saved in preferences sent with report...
Is it possible to disable it ?
erratum in this usefull guid: not inlcudeDropBoxSystemTags but includeDropBoxSystemTags.