From Android 11 (API 30), the Android OS provides information of an application process’s death in the ApplicationExitInfo
API. This can be particularly useful for diagnosing native (NDK) crashes and ANR events.
Use the bugsnag-plugin-android-exitinfo
plugin to augment your native crashes and ANRs with:
These are shown on the Threads tab of the BugSnag dashboard. Without the plugin, only the thread names and states can be captured in a native crash or ANR.
The “Open FileDescriptors” tab of the BugSnag dashboard shows the files that were open at the time of the crash.
The app’s Logcat messages leading up to the error are shown on the “Log Messages” tab on the BugSnag dashboard for apps running on Android 11 to 14 (the data is no longer available from Android 15).
Install bugsnag-plugin-android-exitinfo
on devices running Android 11+ (API 30) by adding the dependency to your app/build.gradle
or build.gradle.kts
file:
dependencies {
implementation("com.bugsnag:bugsnag-plugin-android-exitinfo:6.+")
}
dependencies {
implementation("com.bugsnag:bugsnag-plugin-android-exitinfo:6.+")
}
Then add the plugin to your configuration:
BugsnagExitInfoPlugin bugsnagExitInfoPlugin = new BugsnagExitInfoPlugin();
Configuration config = Configuration.load(this);
config.addPlugin(bugsnagExitInfoPlugin);
Bugsnag.start(this, config);
Bugsnag.start(this, Configuration.load(this).apply {
addPlugin(BugsnagExitInfoPlugin())
})
Please note that v6.0.0 or above of bugsnag-android
is required for this plugin. Enabling the plugin will add native stacktraces for all threads to your NDK events and the open file descriptors at the time of the crash will be displayed in a tab on the dashboard called “Open FileDescriptors”. You can also enable reporting of Logcat messages, by turning on the includeLogcat
configuration option – see below.
The plugin can be configured by passing it an ExitInfoPluginConfiguration
object with one or more of the following options:
To match a BugSnag event to a reported exit info record, we use ActivityManager
‘s ProcessStateSummary
to store a unique session ID. This may interfere with other tools using this API, in which case the behavior can be disabled as follows:
ExitInfoPluginConfiguration exitInfoPluginConfiguration = new ExitInfoPluginConfiguration();
exitInfoPluginConfiguration.setDisableProcessStateSummaryOverride(false);
BugsnagExitInfoPlugin bugsnagExitInfoPlugin = new BugsnagExitInfoPlugin(exitInfoPluginConfiguration);
Configuration config = Configuration.load(this);
config.addPlugin(bugsnagExitInfoPlugin);
Bugsnag.start(this, config);
Bugsnag.start(Configuration.load(this).apply {
val exitInfoPluginConfiguration = ExitInfoPluginConfiguration().apply {
disableProcessStateSummaryOverride = true
}
addPlugin(BugsnagExitInfoPlugin(exitInfoPluginConfiguration))
})
If disabled – or if session tracking is disabled – BugSnag falls back to using the process ID (PID) stored in a file.
When enabled, sends Logcat messages with your event to a “Log Messages” tab on the dashboard:
ExitInfoPluginConfiguration exitInfoPluginConfiguration = new ExitInfoPluginConfiguration();
exitInfoPluginConfiguration.setIncludeLogcat(true);
BugsnagExitInfoPlugin bugsnagExitInfoPlugin = new BugsnagExitInfoPlugin(exitInfoPluginConfiguration);
Configuration config = Configuration.load(this);
config.addPlugin(bugsnagExitInfoPlugin);
Bugsnag.start(this, config);
Bugsnag.start(Configuration.load(this).apply {
val exitInfoPluginConfiguration = ExitInfoPluginConfiguration().apply {
includeLogcat = true
}
addPlugin(BugsnagExitInfoPlugin(exitInfoPluginConfiguration))
})
The messages are ordered with the newest first with the oldest being truncated if the maxStringValueLength
value is reached (10,000 characters by default).
This option is off by default to avoid duplicate reporting if Logcat messages are already being recorded as breadcrumbs.
Sends a list of open file descriptors at the time of the crash with your event to an “Open FileDescriptors” tab on the dashboard:
ExitInfoPluginConfiguration exitInfoPluginConfiguration = new ExitInfoPluginConfiguration();
exitInfoPluginConfiguration.setListOpenFds(false);
BugsnagExitInfoPlugin bugsnagExitInfoPlugin = new BugsnagExitInfoPlugin(exitInfoPluginConfiguration);
Configuration config = Configuration.load(this);
config.addPlugin(bugsnagExitInfoPlugin);
Bugsnag.start(this, config);
Bugsnag.start(Configuration.load(this).apply {
val exitInfoPluginConfiguration = ExitInfoPluginConfiguration().apply {
listOpenFds = false
}
addPlugin(BugsnagExitInfoPlugin(exitInfoPluginConfiguration))
})
This option is enabled by default.