Get Android NDK crash reports

If your Android app contains native libraries, you can enable full stack traces and detailed crash reports for your native code from Firebase Crashlytics with a few small updates to your app's build configuration. This guide describes how to configure crash reporting with the new Firebase Crashlytics SDK.

Before you begin

To get started, set up Crashlytics.

  1. As a part of Step 2 (Add the Firebase Crashlytics plugin to your app), make sure your app is using the Crashlytics Gradle plugin v2.4.0+, which allows you to upload symbols using only your unstripped binaries to generate symbolicated crashes.

Step 1: Update your Gradle configuration

In your app-level build.gradle, declare the Crashlytics NDK runtime dependency:

Java

apply plugin: 'com.android.application'
apply plugin: 'com.google.firebase.crashlytics'

dependencies {
  // ...

  // Import the BoM for the Firebase platform
  implementation platform('com.google.firebase:firebase-bom:28.4.1')

  // Declare the dependency for the Firebase Crashlytics NDK library.
  // If you previously declared the Firebase Crashlytics dependency, replace it.
  // When using the BoM, you don't specify versions in Firebase library dependencies
  implementation 'com.google.firebase:firebase-crashlytics'
  implementation 'com.google.firebase:firebase-crashlytics-ndk'
  implementation 'com.google.firebase:firebase-analytics'
}

// …
android {
  // ...
  buildTypes {
      release {
          // Add this extension
          firebaseCrashlytics {
              // Enable processing and uploading of native symbols to Crashlytics servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled true
          }
      }
  }
}

By using the Firebase Android BoM, your app will always use compatible versions of the Firebase Android libraries.

(Alternative) Declare Firebase library dependencies without using the BoM

If you choose not to use the Firebase BoM, you must specify each Firebase library version in its dependency line.

Note that if you use multiple Firebase libraries in your app, we highly recommend using the BoM to manage library versions, which ensures that all versions are compatible.

  dependencies {
      // Declare the dependency for the Firebase Crashlytics NDK library.
      // If you previously declared the Firebase Crashlytics dependency, replace it.
      // When NOT using the BoM, you must specify versions in Firebase library dependencies
      implementation 'com.google.firebase:firebase-crashlytics:18.2.1'
      implementation 'com.google.firebase:firebase-crashlytics-ndk:18.2.1'
      implementation 'com.google.firebase:firebase-analytics:19.0.1'
  }
  

Kotlin+KTX

apply plugin: 'com.android.application'
apply plugin: 'com.google.firebase.crashlytics'

dependencies {
  // ...

  // Import the BoM for the Firebase platform
  implementation platform('com.google.firebase:firebase-bom:28.4.1')

  // Declare the dependency for the Firebase Crashlytics NDK library.
  // If you previously declared the Firebase Crashlytics dependency, replace it.
  // When using the BoM, you don't specify versions in Firebase library dependencies
  implementation 'com.google.firebase:firebase-crashlytics-ktx'
  implementation 'com.google.firebase:firebase-crashlytics-ndk'
  implementation 'com.google.firebase:firebase-analytics-ktx'
}

// …
android {
  // ...
  buildTypes {
      release {
          // Add this extension
          firebaseCrashlytics {
              // Enable processing and uploading of native symbols to Crashlytics servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled true
          }
      }
  }
}

By using the Firebase Android BoM, your app will always use compatible versions of the Firebase Android libraries.

(Alternative) Declare Firebase library dependencies without using the BoM

If you choose not to use the Firebase BoM, you must specify each Firebase library version in its dependency line.

Note that if you use multiple Firebase libraries in your app, we highly recommend using the BoM to manage library versions, which ensures that all versions are compatible.

  dependencies {
      // Declare the dependency for the Firebase Crashlytics NDK library.
      // If you previously declared the Firebase Crashlytics dependency, replace it.
      // When NOT using the BoM, you must specify versions in Firebase library dependencies
      implementation 'com.google.firebase:firebase-crashlytics-ktx:18.2.1'
      implementation 'com.google.firebase:firebase-crashlytics-ndk:18.2.1'
      implementation 'com.google.firebase:firebase-analytics-ktx:19.0.1'
  }
  

Required for Crashlytics NDK version 17.3.0: If your app uses targetSdkLevel 30 or above, you must also disable the Pointer Tagging feature in your app by adding the following to your AndroidManifest.xml:

<application android:allowNativeHeapPointerTagging="false">
...
</application>

For more information, read Developer support for Tagged Pointers.

Step 2: Enable native symbol uploading

To produce readable stack traces from NDK crashes, Crashlytics needs to know about the symbols in your native binaries. Our Gradle plugin includes the uploadCrashlyticsSymbolFileBUILD_VARIANT task to automate this process (to access this task, make sure nativeSymbolUploadEnabled is set to true).

For method names to appear in your stack traces, you must explicitly invoke the uploadCrashlyticsSymbolFileBUILD_VARIANT task after each build of your NDK library. For example:

>./gradlew app:assembleBUILD_VARIANT\
           app:uploadCrashlyticsSymbolFileBUILD_VARIANT

The Crashlytics NDK v17.3.0+ and Gradle plugin v2.4.1+ depend on the presence of the GNU build id within the native shared objects. You can verify the presence of this id by running readelf -n on each binary. If the build id is absent, add -Wl,--build-id to your build system's flags to fix the problem.

Step 3 (optional): Upload symbols for library modules and external dependencies

Our symbol upload task assumes you are building your native libraries as part of your app module's Gradle build, using standard NDK build tools such as CMake. If you are using a customized NDK build process within Gradle, or your native libraries are built in a library/feature module or provided by a 3rd party, you may need to explicitly specify the path to your unstripped libraries. The firebaseCrashlytics extension provides the property unstrippedNativeLibsDir to do this.

Add the following to your app-level build.gradle file:

// …
android {
    // ...
    buildTypes {
        release {
            firebaseCrashlytics {
                nativeSymbolUploadEnabled true
                unstrippedNativeLibsDir file("path/to/unstripped/dir")
            }
        }
    }
}

The Crashlytics plugin will search the specified directory and all its subdirectories for native libraries with a .so extension. Crashlytics will then extract debugging symbols from all such libraries and upload them to the Firebase servers.

The unstrippedNativeLibsDir property accepts any arguments allowable for org.gradle.api.Project#files(Object...), including java.lang.String, java.io.File, and org.gradle.api.file.FileCollection. You can specify multiple directories for a single build flavor by providing a list or FileCollection instance.

Step 4 (optional): Customize NDK crash reports

You can optionally include the crashlytics.h header in your C++ code to add metadata to NDK crash reports, such as logs, custom keys, and user IDs. crashlytics.h is available as a header-only C++ library in the Firebase Android SDK GitHub Repository. Read the comments in the header file for instructions on using the NDK C++ APIs.

Step 5 (optional): Enable Breakpad symbol file for symbolication

The Crashlytics Gradle plugin provides the following functionality:

  • Processes your unstripped native binaries to generate symbol files.
  • Uploads the generated symbol files to our servers to be used later when symbolicating native crashes.

The Crashlytics Gradle plugin supports two types of symbol file formats:
the Crashlytics symbol file (cSYM) and the Breakpad symbol file.

A Breakpad-generated symbol file contains more information than a Crashlytics-generated symbol file, including the Call Frame Info (CFI) which is used in the unwinding process to help calculate stack frames. Using CFI will result in higher-fidelity stack traces, especially for highly-optimized applications such as games and media apps.

You can enable use of the Breakpad-based symbol file generator in one of two ways:

  • Option 1: Enable via the firebaseCrashlytics extension in your build.gradle file

    Add the following to your app-level build.gradle file:

    android {
      // ...
      buildTypes {
        // ...
        release {
          // ...
          firebaseCrashlytics {
            // existing; required for either symbol file generator
            nativeSymbolUploadEnabled true
            // Add this optional new block to specify breakpad() or csym()
            symbolGenerator {
               breakpad()
            }
          }
        }
      }
    }
    

    To switch back to the default Crashlytics symbol file generator, you can do either of the following:

    • Omit the symbolGeneratorblock entirely, as the plugin uses the Crashlytics symbol file generator by default.

    • Keep the block, but change breakpad() to csym().

  • Option 2: Enable via a property line in your Gradle properties file

    You can use the com.google.firebase.crashlytics.symbolGenerator property to control which symbol file generator to use. Valid values for the property are breakpad or csym. If unspecified, the current default is equivalent to csym, though that may change in future versions.

    You can manually update your Gradle properties file or update the file via the command line. For example, to enable the Breakpad symbol file generator, specify the value of breakpad as shown in the following command:

    ./gradlew -Pcom.google.firebase.crashlytics.symbolGenerator=breakpad \
    app:assembleRelease app:uploadCrashlyticsSymbolFileRelease
    

Step 6: See your crash reports

Verify that Crashlytics is properly reporting NDK crashes by building your app, uploading symbols, and forcing a native crash. You’ll need to restart the app after it crashes for Crashlytics to send the report. You should see the crash in your Firebase console within a few minutes.

Troubleshooting

If you're seeing different stack traces in the Firebase console and in the logcat, refer to the Troubleshooting guide.