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.
As a part of Step 2 (Add Firebase Crashlytics 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:26.6.0') // 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 dependenciesimplementation '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 dependenciesimplementation 'com.google.firebase:firebase-crashlytics:17.3.1'implementation 'com.google.firebase:firebase-crashlytics-ndk:17.3.1' implementation 'com.google.firebase:firebase-analytics:18.0.2' }
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:26.6.0') // 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 dependenciesimplementation '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 dependenciesimplementation 'com.google.firebase:firebase-crashlytics-ktx:17.3.1'implementation 'com.google.firebase:firebase-crashlytics-ndk:17.3.1' implementation 'com.google.firebase:firebase-analytics-ktx:18.0.2' }
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 external dependencies
Our symbol upload task assumes you are building your native libraries as part
of your Gradle build, using standard NDK build tools such as CMake. If you have
externally-built native libraries, or are using a customized NDK build process
within Gradle, you may need to explicitly specify the path to your unstripped
libraries. The firebaseCrashlytics
extension provides the property
unstrippedNativeLibsDir
to do this.
// … android { // ... buildTypes { release { firebaseCrashlytics { nativeSymbolUploadEnabled true unstrippedNativeLibsDir ‘path/to/unstripped/parent/dir’ } } } }
Our plugin assumes libraries are located in architecture-specific
subdirectories under the specified directory. In the following example, both
subdirectories x86
and arm64
contain the libraries libfoo.so
and
libbar.so
.
unstrippedNativeLibsDir/
+- x86/
|
+- libfoo.so
+- libbar.so
+- arm64/
|
+- libfoo.so
+- libbar.so
If your build system does not adhere to the above structure/naming scheme,
manually create this structure on your local disk prior to
invoking the uploadCrashlyticsSymbolFileBUILD_VARIANT
task.
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: 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.