Frequently asked questions

Contents

What are AnrLinkError and NdkLinkErrors?

On devices running older versions of Android, before API 23 (Marshmallow), the native library loading can be unreliable on certain OS versions. This can result in UnsatisfiedLinkErrors being thrown when BugSnag attempts to load the native libraries used for ANR and NDK detection. If this error occurs, ANR or NDK crash detection will be disabled and an AnrLinkError or NdkLinkError will be reported to BugSnag.

If you experience an UnsatisfiedLinkError we recommend linking BugSnag’s ANR plugin and/or NDK plugin using the Relinker library to reduce their incidence.

More recent Android versions (API 23+) do not have the same issue with native library loading so we recommend using this approach conditionally for older Android versions only.

Add the Relinker library using the installation instructions, then load the appropriate BugSnag plugin with:

ReLinker.loadLibrary(this, "bugsnag-ndk");
ReLinker.loadLibrary(this, "bugsnag-plugin-android-anr");

Does BugSnag support multi process apps?

Yes - if your app uses multiple processes then you should initialize BugSnag once in each process, with a unique persistenceDirectory value.

Configuration config = Configuration.load(this);
config.setPersistenceDirectory(new File("/my-custom-dir"));
Bugsnag.start(this, config);
Bugsnag.start(this, Configuration.load(this).apply {
  persistenceDirectory = File("/my-custom-dir")
})

Failing to make the persistenceDirectory unique will cause undefined behaviour in the storage of error and session reports.

If one of your processes uses an app component that is not an Activity then you should manually track sessions for that process. This is because automatic session tracking relies on activity lifecycle callbacks.

Because each process uses a separate JVM any custom configuration, such as attaching custom diagnostics, will need to be carried out on each BugSnag instance.

Why do I see StrictMode violations in my dashboard?

BugSnag can capture StrictMode violations depending on the policy you have set. See BugSnag’s StrictMode docs for more information.

How can I tell if BugSnag has finished initializing?

Calling BugSnag static client methods, such as Bugsnag.leaveBreadcrumb() and Bugsnag.addMetadata(), will throw an exception if you have not yet called Bugsnag.start().

We recommend calling Bugsnag.start() in the main thread as early as possible in your app’s lifecycle in order to catch all errors. Once this method has been invoked, it is safe to use other methods on the BugSnag client from any thread; a lock will cause the calling thread to wait for startup to complete fully.

In the unusual case where it’s not possible to determine whether or not Bugsnag.start() has been invoked, you can use Bugsnag.isStarted() to guard uses of BugSnag client methods.

How does BugSnag detect ANRs?

BugSnag detects ANRs using the SIGQUIT signal handler that runs at the same time as the ANR dialog is shown (giving the user the option to force quit the app or wait). SIGQUIT is used to dump the current runtime state and is called once the runtime determines the process should be killed due to an ANR. BugSnag’s ANR handler will only capture ANRs when the app’s UI is unresponsive, as SIGQUIT only occurs for unresponsive UI issues due to the main thread being blocked.

How does BugSnag report ANRs?

We schedule the delivery of ANR reports immediately, but these could be delayed until restart if the app is terminated before or during the send. In these cases we cannot guarantee delivery.

Does BugSnag capture background ANRs?

BugSnag does not capture background ANRs, since the SIGQUIT message we use to detect ANRs is not sent when the app is not in the foreground. This can sometimes also be the case when the user puts the app into the background, for example if a user input event is sent and the app is backgrounded before the ANR dialog can be shown we are unlikely to send an ANR report.

Why am I seeing a discrepancy between ANR counts in BugSnag and Google Play Console?

This is largely due to differences in detecting ANRs. BugSnag ANR detection makes use of the SIGQUIT handler that runs at the same time as the ANR dialog is shown (giving the user the option to force quit the app or wait). As the dialog is shown, a dump is written and added to the app’s historic exit reasons. Google uses these historic exit reasons to determine which exits were caused by ANRs and report them. All ANRs, including those we do not detect or report, can be detected programmatically on startup by using historic exit reasons. This leads to the following differences:

  • BugSnag only reports ANRs when the app was in the foreground, while Google includes ANRs that occurred while the app was in the background.

  • BugSnag does not report spurious silent kills of the app that show no ANR dialog, even when the app is in the foreground, though these may be reported by Google.

  • BugSnag’s ANR handler will only capture ANRs when the app’s UI is unresponsive.

There can also be a discrepancy caused by differences in reporting ANRs. BugSnag will often need an app restart for delivery. If the app is never restarted (e.g. if it’s deleted) the event will never reach BugSnag. By contrast Google uses Play Services to send their error reports, which does not require the app to be running.

If a user closes the application before the ANR dialog appears is that still reported to BugSnag as an ANR? What if the user force closes the application rather than selecting any option on the ANR dialog?

We report ANRs when the dialog is displayed but ignored, or ‘Wait’ is selected. We are unlikely to report ANRs when the user closes the application before the dialog appears, though this does depend on the version of Android.