This documentation is for version 4 of the BugSnag Android notifier. We recommend upgrading to the latest release using our Upgrade guide. Documentation for the current release can be found here.
The Bugsnag
client object has several properties which can be set to customize the content of error reports and how the reports are sent.
Most configuration options should be specified by creating a Configuration
object and passing it into Bugsnag.init
:
Configuration config = new Configuration("your-api-key-here");
config.setAppVersion("1.0.0-alpha");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setAppVersion("1.0.0-alpha")
Bugsnag.init(this, config)
To set different configuration values based on build variants or product flavors, see Customizing by build setting.
automaticallyCollectBreadcrumbs
By default we will automatically add breadcrumbs for common application events such as activity lifecycle events and system intents. To disable this behavior, set this property to false:
Configuration config = new Configuration("your-api-key-here");
config.setAutomaticallyCollectBreadcrumbs(false);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setAutomaticallyCollectBreadcrumbs(false)
Bugsnag.init(this, config)
beforeNotify
Add a callback to be executed code before every notification to BugSnag.
You can use this to add or modify information attached to an error
before it is sent to your dashboard. You can also return false
from
any callback to halt execution.
Bugsnag.beforeNotify(new BeforeNotify() {
@Override
public boolean run(Error error) {
error.setSeverity(Severity.INFO);
return true;
}
});
Bugsnag.beforeNotify {
it.severity = Severity.INFO
true
}
See the customizing error reports reference for more information.
disableExceptionHandler
By default, BugSnag reports unhandled exceptions in your application automatically.
To disable this behavior, call disableExceptionHandler
:
Bugsnag.disableExceptionHandler();
Bugsnag.disableExceptionHandler()
resumeSession
Resumes a session which has previously been stopped, or starts a new session if none exists. If a session has already been resumed or started and has not been stopped, calling this method will have no effect. You should disable automatic session tracking via setAutoCaptureSessions
if you call this method.
It’s important to note that sessions are stored in memory for the lifetime of the application process and are not persisted on disk. Therefore calling this method on app startup would start a new session, rather than continuing any previous session.
You should call this at the appropriate time in your application when you wish to resume a previously started session. Any subsequent errors which occur in your application will be reported to BugSnag and will count towards your application’s stability score.
client.resumeSession();
client.resumeSession()
Also see startSession
and stopSession
.
setAppVersion
We’ll automatically pull your app version from the versionName
field
in your AndroidManifest.xml
file. If you’d like to override this you
can call setAppVersion
:
Configuration config = new Configuration("your-api-key-here");
config.setAppVersion("1.0.0-alpha");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setAppVersion("1.0.0-alpha")
Bugsnag.init(this, config)
setAutoCaptureSessions
By default, BugSnag will automatically capture and report session information from your application. Use this flag to disable all automatic reporting.
Configuration config = new Configuration("your-api-key-here");
config.setAutoCaptureSessions(false);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.autoCaptureSessions = false
Bugsnag.init(this, config)
If you want control over what is deemed a session, you can switch off automatic session tracking with the setAutoCaptureSessions
option, and manage the session lifecycle using startSession()
, stopSession()
and resumeSession()
.
setContext
BugSnag uses the concept of “contexts” to help display and group your
errors. Contexts represent what was happening in your application at
the time an error occurs. In an android app the “context” is automatically set as the foreground Activity
.
If you would like to set this value manually, you can call setContext
:
Bugsnag.setContext("SecondTutorialStep");
Bugsnag.setContext("SecondTutorialStep")
If your bugsnag-android version is older than 4.3.2, it is necessary to add the GET_TASKS
permission to your manifest to enable automatic context tracking.
setDelivery
Sets the Delivery
implementation used to make network calls to the BugSnag Error Reporting and Sessions API.
This may be useful if you have requirements such as certificate pinning and rotation, which are not supported by the default implementation.
Configuration config = new Configuration("your-api-key-here");
config.setDelivery(new CertPinnedDelivery());
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setDelivery(CertPinnedDelivery())
Bugsnag.init(this, config)
To provide custom delivery functionality, create a class which implements
the Delivery
interface. Please note
that request bodies must match the structure specified in the Error
Reporting and Sessions API documentation.
If delivery fails but you wish to retry the request at a later date,
then throw a DeliveryFailureException
. The
notifier will catch this exception, automatically cache the payload and trigger delivery later
on.
For example, if the device has no network connectivity, it may make sense to store the report and send it later:
if (!hasNetworkConnection) {
throw new DeliveryFailureException("No network connection - try again later!");
}
if (!hasNetworkConnection) {
throw DeliveryFailureException("No network connection - try again later!")
}
A full example of a custom Delivery
which uses certificate pinning is provided below.
/**
* A custom API client which uses Square's OkHttp3 Library to pin certificates.
*/
class CertPinnedApiClient implements Delivery {
OkHttpClient okHttpClient;
// The public key hash(es) for your cert
// can be found by following OkHttp3 instructions:
// https://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
CertPinnedApiClient() {
String hash1 = "sha256/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
String hash2 = "sha256/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("mywebsite.com", hash1) // expires in 2019
.add("mywebsite.com", hash2) // expires in 2020
.build();
okHttpClient = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
}
String getReportJson(Report report) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
JsonStream jsonStream = new JsonStream(new PrintWriter(baos));
report.toStream(jsonStream);
jsonStream.flush();
return baos.toString("UTF-8");
} catch (IOException e) {
throw new RuntimeException("Failed to generate request", e);
}
}
@Override
public void deliver(Report report, Configuration config) throws DeliveryFailureException {
try {
MediaType mediaType = MediaType.parse("application/json");
Request request = new Request.Builder()
.headers(Headers.of(config.getErrorApiHeaders()))
.url(config.getEndpoint())
.post(RequestBody.create(mediaType, getReportJson(report)))
.build();
Response response = okHttpClient.newCall(request).execute();
} catch (IOException e) {
throw new DeliveryFailureException("No network connection", e);
}
}
@Override
public void deliver(SessionTrackingPayload payload,
Configuration config) throws DeliveryFailureException {
// implement as per Error Report, but use config.getSessionEndpoint() and config.getSessionApiHeaders()
}
}
/**
* A custom API client which uses Square's OkHttp3 Library to pin certificates.
*/
class CertPinnedApiClient : Delivery {
var okHttpClient: OkHttpClient
// The public key hash(es) for your cert
// can be found by following OkHttp3 instructions:
// https://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html
init {
val hash1 = "sha256/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
val hash2 = "sha256/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
val certificatePinner = CertificatePinner.Builder()
.add("mywebsite.com", hash1) // expires in 2019
.add("mywebsite.com", hash2) // expires in 2020
.build()
okHttpClient = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
}
fun getReportJson(report: Report): String {
try {
val baos = ByteArrayOutputStream()
val jsonStream = JsonStream(PrintWriter(baos))
report.toStream(jsonStream)
jsonStream.flush()
return baos.toString("UTF-8")
} catch (e: IOException) {
throw RuntimeException("Failed to generate request", e)
}
}
override fun deliver(report: Report?, config: Configuration?) {
try {
val mediaType = MediaType.parse("application/json")
val request = Request.Builder()
.headers(Headers.of(config?.errorApiHeaders)) // add error API headers
.url(config?.endpoint) // use error API endpoint
.post(RequestBody.create(mediaType, getReportJson(report!!)))
.build()
val response = okHttpClient.newCall(request).execute()
} catch (e: IOException) {
throw DeliveryFailureException("No network connection", e)
}
}
override fun deliver(payload: SessionTrackingPayload?, config: Configuration?) {
// implement as per Error Report, but use config.sessionEndpoint and config.sessionApiHeaders
}
}
setDetectAnrs
When the main thread of an Android app is blocked for too long, it appears unresponsive and the Android OS creates an Application Not Responding (ANR) error, presenting the user with a dialog option to force quit the app.
By default ANR detection is disabled.
Configuration config = new Configuration("your-api-key-here");
config.setDetectAnrs(true);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.detectAnrs = true
Bugsnag.init(this, config)
setEndpoints
By default we will send error reports to notify.bugsnag.com and sessions to sessions.bugsnag.com.
If you are using BugSnag On-premise you’ll need to set these to your Event Server
and Session Server endpoints. If the notify
endpoint is set but the sessions
endpoint is not, session tracking
will be disabled automatically to avoid leaking session information outside of your server configuration, and a warning will be logged.
Configuration config = new Configuration("your-api-key-here");
config.setEndpoints("https://notify.example.com", "https://sessions.example.com");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setEndpoints("https://notify.example.com", "https://sessions.example.com")
Bugsnag.init(this, config)
setFilters
Sets which values should be removed from any MetaData
objects before
sending them to BugSnag. Use this if you want to ensure you don’t send
sensitive data such as passwords, and credit card numbers to our
servers. Any keys which contain these strings will be filtered. By default, the password
key will be filtered.
Configuration config = new Configuration("your-api-key-here");
config.setFilters(new String[]{"password", "credit_card_number"});
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setFilters("password", "credit_card_number")
Bugsnag.init(this, config)
By default, filters
is set to "password"
setIgnoreClasses
Sets for which exception classes we should not send exceptions to BugSnag.
Configuration config = new Configuration("your-api-key-here");
config.setIgnoreClasses("java.net.UnknownHostException", "com.example.Custom");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setIgnoreClasses("java.net.UnknownHostException", "com.example.Custom")
Bugsnag.init(this, config)
setLaunchCrashThresholdMs
Sets the threshold in milliseconds for an uncaught error to be considered as a crash on launch. If a crash is detected on launch, BugSnag will attempt to send the report synchronously. By default, this value is set at 5,000ms. Setting the value to 0 will disable this behaviour.
Configuration config = new Configuration("your-api-key-here");
config.setLaunchCrashThresholdMs(10000);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.launchCrashThresholdMs = 10000
Bugsnag.init(this, config)
setMaxBreadcrumbs
Sets the maximum number of breadcrumbs which will be stored. Once the threshold is reached, the oldest breadcrumbs will be deleted.
Configuration config = new Configuration("your-api-key-here");
config.setMaxBreadcrumbs(50);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.maxBreadcrumbs = 50
Bugsnag.init(this, config)
metaData
Add information to attach to every report. To attach information dynamically at
the time of capture, use beforeNotify
.
Configuration config = new Configuration("your-api-key-here");
config.getMetaData().addToTab("account", "name", "Acme Co.");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.metaData.addToTab("account", "name", "Acme Co.")
Bugsnag.init(this, config)
setNotifyReleaseStages
By default, BugSnag will be notified of exceptions that happen in any
releaseStage
. If you would like to change which release stages
notify BugSnag of exceptions you can call setNotifyReleaseStages
:
Configuration config = new Configuration("your-api-key-here");
config.setNotifyReleaseStages("production", "development", "testing");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setNotifyReleaseStages("production", "development", "testing")
Bugsnag.init(this, config)
setPersistUserBetweenSessions
Set whether or not BugSnag should persist user information between application sessions.
If set then any user information set will be re-used until
Bugsnag.clearUser()
is called.
Configuration config = new Configuration("your-api-key-here");
config.setPersistUserBetweenSessions(true);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.persistUserBetweenSessions = true
Bugsnag.init(this, config)
setProjectPackages
Sets which package names BugSnag should consider as a part of the running application. We mark stacktrace lines as in-project if they originate from any of these packages.
Configuration config = new Configuration("your-api-key-here");
config.setProjectPackages("com.company.package1", "com.company.package2");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setProjectPackages("com.company.package1", "com.company.package2")
Bugsnag.init(this, config)
By default, projectPackages
is set to be the package you called
Bugsnag.init
from.
setReleaseStage
If you would like to distinguish between errors that happen in
different stages of the application release process (development,
production, etc) you can set the releaseStage
that is reported to
BugSnag.
Configuration config = new Configuration("your-api-key-here");
config.setReleaseStage("testing");
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setReleaseStage("testing")
Bugsnag.init(this, config)
If you are running a debug build, we’ll automatically set this to “development”, otherwise it is set to “production”.
setSendThreads
Sets if we should collect and send thread state along with errors.
By default sendThreads
is set to true
.
Configuration config = new Configuration("your-api-key-here");
config.setSendThreads(false);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setSendThreads(false)
Bugsnag.init(this, config)
setUser
BugSnag helps you understand how many of your users are affected by each error. In order to do this, we need to send along user information with every exception.
If you would like to enable this, set the user
. You can set the user
id, which is usually the unique id to represent that user across all
your apps, the user’s email address and the user’s name:
Bugsnag.setUser("userId", "user@email.com", "User Name");
Bugsnag.setUser("userId", "user@email.com", "User Name")
bugsnag_set_user_env(env, "userId", "user@example.com", "User Name");
setVersionCode
We’ll automatically pull your versionCode from the versionCode
field
in your AndroidManifest.xml
file. If you’d like to override this you
can call setVersionCode
:
Configuration config = new Configuration("your-api-key-here");
config.setVersionCode(55);
Bugsnag.init(this, config);
val config = Configuration("your-api-key-here")
config.setVersionCode(55)
Bugsnag.init(this, config)
startSession
Starts tracking a new session. You should disable automatic session tracking via setAutoCaptureSessions
if you call this method.
You should call this at the appropriate time in your application when you wish to start a session. Any subsequent errors which occur in your application will be reported to BugSnag and will count towards your application’s stability score. This will start a new session even if there is already an existing session; you should call resumeSession
if you only want to start a session when one doesn’t already exist.
client.startSession();
client.startSession()
Also see resumeSession
and stopSession
.
stopSession
Stops tracking a session. You should disable automatic session tracking via setAutoCaptureSessions
if you call this method.
You should call this at the appropriate time in your application when you wish to stop a session. Any subsequent errors which occur in your application will still be reported to BugSnag but will not count towards your application’s stability score. This can be advantageous if, for example, you do not wish the stability score to include crashes in a background service.
client.stopSession();
client.stopSession()
Also see resumeSession
and startSession
.
BugSnag can be set up to use different configuration values for different build variants, by using the following manifest placeholders in your app’s build.gradle script.
android {
defaultConfig {
manifestPlaceholders = [
// omit any of the following placeholders to use the default values
bugsnagApiKey: "<api-key>",
bugsnagBuildUUID: "<build-uuid>",
bugsnagAppVersion: "1.0.0",
bugsnagVersionCode: 55,
bugsnagEndpoint: "https://notify.bugsnag.com",
bugsnagReleaseStage: "<release-stage>",
bugsnagSendThreads: true,
bugsnagEnableExceptionHandler: true,
bugsnagPersistUserBetweenSessions: false,
bugsnagAutoCaptureSessions: true,
bugsnagDetectNdkCrashes: true,
bugsnagDetectAnrs: true
]
}
productFlavors {
free {
manifestPlaceholders = [
// override defaultConfig values here
]
}
}
}
For all the values you wish to configure, provide a meta-data element at the bottom of your manifest file.
<application>
<meta-data android:name="com.bugsnag.android.API_KEY" android:value="${bugsnagApiKey}"/>
<meta-data android:name="com.bugsnag.android.BUILD_UUID" android:value="${bugsnagBuildUUID}"/>
<meta-data android:name="com.bugsnag.android.APP_VERSION" android:value="${bugsnagAppVersion}"/>
<meta-data android:name="com.bugsnag.android.VERSION_CODE" android:value="${bugsnagVersionCode}"/>
<meta-data android:name="com.bugsnag.android.ENDPOINT" android:value="${bugsnagEndpoint}"/>
<meta-data android:name="com.bugsnag.android.RELEASE_STAGE" android:value="${bugsnagReleaseStage}"/>
<meta-data android:name="com.bugsnag.android.SEND_THREADS" android:value="${bugsnagSendThreads}"/>
<meta-data android:name="com.bugsnag.android.ENABLE_EXCEPTION_HANDLER" android:value="${bugsnagEnableExceptionHandler}"/>
<meta-data android:name="com.bugsnag.android.PERSIST_USER_BETWEEN_SESSIONS" android:value="${bugsnagPersistUserBetweenSessions}"/>
<meta-data android:name="com.bugsnag.android.AUTO_CAPTURE_SESSIONS" android:value="${bugsnagAutoCaptureSessions}"/>
<meta-data android:name="com.bugsnag.android.DETECT_NDK_CRASHES" android:value="${bugsnagDetectNdkCrashes}"/>
<meta-data android:name="com.bugsnag.android.DETECT_ANRS" android:value="${bugsnagDetectAnrs}"/>
</application>
Finally, initialize BugSnag in your Application class.
Bugsnag.init(this);
Bugsnag.init(this)
When using the BugSnag Android Gradle plugin the API key must be set directly in the manifest or by using manifest placeholders.
Gradle resource values allow you to share custom fields and values between build files and app code. For example, to set a release stage in your build configuration, set a resource value in your Gradle file:
def bugsnag_release_stage = project.hasProperty("bugsnag-release-stage")
? project.property("bugsnag-release-stage") : "staging"
buildTypes {
release {
resValue("string", "bugsnag_release_stage", "${bugsnag_release_stage}")
}
}
To load the value automatically when BugSnag starts, set a placeholder in your app manifest for the value:
<application ...>
<meta-data android:name="com.bugsnag.android.RELEASE_STAGE"
android:value="@string/bugsnag_release_stage"/>
</application>
Properties can also be loaded at runtime if needed (though not required if placeholders are set in app manifest):
Configuration config = new Configuration(getString(R.string.bugsnag_release_stage));
Bugsnag.start(this, config);
val config = Configuration(getString(R.string.bugsnag_release_stage))
Bugsnag.start(this, config)