Android NDK integration

Add Bugsnag to your Android NDK projects to automatically capture and report crashes in released applications.

New to Bugsnag? Create an account now.

Installation

Using Android Studio or Gradle

Add bugsnag-android-ndk to the dependencies section of your Module Gradle Settings, usually found at <project_dir>/app/build.gradle:

compile 'com.bugsnag:bugsnag-android-ndk:1.+'

Don’t forget to run Sync Project with Gradle Files after updating this file.

Using Maven

Add bugsnag-android-ndk as a dependencies in your pom.xml:

<dependency>
    <groupId>com.bugsnag</groupId>
    <artifactId>bugsnag-android-ndk</artifactId>
</dependency>

Manual AAR installation

Download the Android NDK latest release and the dependent release of bugsnag-android and place them in your app’s libs folder. Then add flatDirs as a repository and the archives to your module-level gradle settings:

repositories {
    flatDir {
        dirs 'libs'
    }
}
dependencies {
    compile(name:'bugsnag-android-ndk', ext:'aar')
    compile(name:'bugsnag-android', ext:'aar')
}

Basic configuration

Set your API key

Configure your integration API key in the <application> tag of your App Manifest file.

<application ...>
    <meta-data android:name="com.bugsnag.android.API_KEY" android:value="your-api-key-here "/>
</application>

You can find your integration API key immediately after creating a new project from your Bugsnag dashboard, or later on your project’s settings page.

Initialize the Bugsnag client

Create an Application subclass that initializes Bugsnag in onCreate:

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        Bugsnag.init(this);
    }
}

Update AndroidManifest.xml to use the custom Application class:

<application
  android:name=".MyApp">
</application>

If you don’t want to subclass Application, Bugsnag can be initialized in each Activity that is an entrypoint to your app instead:

public class ExampleActivity extends AppCompatActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bugsnag.init(this);
    }
}

Further configuration

If you’d like to configure Bugsnag further, check out the configuration options reference.

Showing full stacktraces

Configuring ProGuard

ProGuard is a commonly used tool to make your APK as small as possible, removing unused resources and minifying classes and methods with short names.

If you are using ProGuard (or DexGuard), see the Android mapping guide to configure uploading mapping files and displaying full debugging information in error reports including the original class and method names.

Showing native stacktraces

A native stacktrace consists of a list of addresses and numeric offsets. In order to replace the addresses with files and method names, Bugsnag can use a shared object mapping file. Check out our Android mapping guide for more details.

Using the Native API

By default Bugsnag will collect and report information if your application crashes. If you would like to use the native API to send other information to Bugsnag from you C or C++ code, add Bugsnag as a dependency of your target. The shared object files and headers are included in the release archive.

Using Android Gradle Plugin < 3.0:

add_library(lib_bugsnag SHARED IMPORTED)
set(BUGSNAG_VERSION 1.0.1)
set(BUGSNAG_DIR ${CMAKE_SOURCE_DIR}/build/intermediates/exploded-aar/com.bugsnag/bugsnag-android-ndk/${BUGSNAG_VERSION})
set_target_properties(lib_bugsnag PROPERTIES
    IMPORTED_LOCATION ${BUGSNAG_DIR}/jni/${ANDROID_ABI}/libbugsnag-ndk.so)
target_include_directories(your-native-lib PRIVATE ${BUGSNAG_DIR}/assets/include) # Insert your target name
target_link_libraries(your-native-lib lib_bugsnag) # Insert your target name

Using Android Gradle Plugin 3.2.1+:

The gradle plugin will automatically copy the shared object files from the bugsnag-android-ndk archive into a build folder.

Then update your CMakeLists.txt file to link the library:

add_library(lib_bugsnag SHARED IMPORTED)
set(BUGSNAG_LIB_DIR
    ${CMAKE_SOURCE_DIR}/build/intermediates/bugsnag-libs)
set(BUGSNAG_INCLUDE_DIR ${BUGSNAG_LIB_DIR}/assets/include)
set_target_properties(lib_bugsnag PROPERTIES IMPORTED_LOCATION
                      ${BUGSNAG_LIB_DIR}/jni/${ANDROID_ABI}/libbugsnag-ndk.so)
target_include_directories(your-native-lib PRIVATE ${BUGSNAG_INCLUDE_DIR})
target_link_libraries(your-native-lib lib_bugsnag)

Then you can set JNI environment which Bugsnag will use when sending error reports.

#include <bugsnag.h>

// ...
bugsnag_init(env);

Alternately, you can use the _env variants of the native API.

Reporting unhandled exceptions

After completing installation and basic configuration, unhandled exceptions will be automatically reported to your Bugsnag dashboard.

Reporting handled errors

If you would like to send handled exceptions to Bugsnag, you can pass any Throwable object to the Bugsnag.notify method:

try {
    // Some potentially crashy code
} catch (Throwable exception) {
    Bugsnag.notify(exception);
}

It can often be helpful to adjust the severity or attach custom diagnostics to handled exceptions. For more information, see reporting handled errors.

Alternately, from C or C++, you can invoke bugsnag_notify with a title, description and severity:

bugsnag_notify("Invalidation Error", "No name specified", BSG_SEVERITY_WARN);

Sending diagnostic data

Automatically captured diagnostics

Bugsnag will automatically capture and attach the following diagnostic data to every exception report:

  • A full stacktrace
  • Application information (package name, app name, version)
  • Device information (manufacturer, brand, model, total memory)
  • Screen information (density, dpi, resolution, orientation)
  • System information (android version, locale, rooted state)

Attaching custom diagnostics

It can often be helpful to attach application-specific diagnostic data to exception reports. This can be accomplished by setting a callback which will be invoked before any reports are sent to Bugsnag:

Bugsnag.beforeNotify(new BeforeNotify() {
    @Override
    public boolean run(Error error) {
        // Attach customer information to every error report
        error.addToTab("account", "name", "Acme Co.");
        error.addToTab("account", "paying_customer", true);

        return true;
    }
});

For more information, see customizing error reports.

Identifying users

In order to correlate errors with customer reports, or to see a list of users who experienced each error, it is helpful to capture and display user information.

This can be accomplished by calling setUser:

Bugsnag.setUser("123456", "james@acme.co", "James Smith");

Or bugsnag_set_user from C or C++:

bugsnag_set_user("123456", "james@acme.co", "James Smith");

For more information, see configuration options.

Session tracking

Bugsnag tracks the number of “sessions” that happen within your application. This allows you to compare crash rates between releases and helps you to understand the quality of your releases.

Sessions are captured and reported by default. This behaviour can be disabled using the setAutoCaptureSessions configuration option.

Bugsnag will automatically report a session each time an Activity is in the Started state, 30 seconds after all Activities have remained in the Stopped state.

If you want control over what is deemed a session, you can switch off automatic session tracking with the setAutoCaptureSessions option, and call startSession() when appropriate for your application.

Logging breadcrumbs

In order to understand what happened in your application before each crash, it can be helpful to leave short log statements that we call breadcrumbs. The last several breadcrumbs are attached to a crash to help diagnose what events lead to the error.

Automatically captured breadcrumbs

By default, Bugsnag captures common events including:

  • Activity Lifecycle callbacks
  • Network connectivity changes
  • Bluetooth connectivity changes
  • Battery state changes
  • Device rotation
  • Media Scanner events
  • Telephony events
  • Other device metrics and more

Attaching custom breadcrumbs

Leaving breadcrumbs can be accomplished by calling leaveBreadcrumb:

Bugsnag.leaveBreadcrumb("App loaded");
Bugsnag.leaveBreadcrumb("User clicked a button");

Additional data can be attached to breadcrumbs by using the longer form of leaveBreadcrumb:

Map<String, String> metadata = new HashMap<>();
metadata.put("from", "moka");
metadata.put("to", "french press");
Bugsnag.leaveBreadcrumb("Preference updated", BreadcrumbType.STATE, metadata);

From C or C++, leave breadcrumbs using bugsnag_leave_breadcrumb, including a message and the type:

bugsnag_leave_breadcrumb("App loaded", BSG_CRUMB_STATE);

When logging breadcrumbs, we’ll keep track of the timestamp, and show both the message and timestamp on your dashboard. Individual breadcrumb size is limited to 4kb after serialization. Any larger breadcrumbs will be dropped from the payload while logging a warning.

Filtering breadcrumbs

You can register a callback which is executed each time a breadcrumb is captured using beforeRecordBreadcrumb. This can be helpful if you wish to filter out certain automatic breadcrumbs from your application, for example:

Bugsnag.beforeRecordBreadcrumb(new BeforeRecordBreadcrumb() {
    @Override
    public boolean shouldReport(@NonNull Breadcrumb breadcrumb) {
        if (breadcrumb.getName().equals("Noisy breadcrumb")) {
            return false; // ignore the breadcrumb
        } else {
            return true; // capture the breadcrumb
        }
    }
});

Next steps

  • View bugsnag-android-ndk, the library powering Bugsnag for Android NDK, on GitHub
  • Get support for your questions and feature requests