ANDROID NDK
Make C/C++ stack trace more understandable on Firebase Crashlytics and PlayStore
How to upload native debug symbols to make fix of C/C++ bug easier and get 100% crash free user
The same way Firebase Crashlytics and Play Store need a mapping file to decode Java / Kotlin crash stack traces, they also need a specific mapping file to decode native crash stack traces.
To generate this file, an application needs to access unstripped
versions of native libraries .so
and the stripped
ones.
An unstripped
.so
file contains native debug symbols. It means it keeps for each instruction the information of the line in the source code, the variable and function names.
By default, a published library, in a aar
file (by using the maven
or maven-publish
plugin) embeds the stripped .so
. There are no debug symbols so we can’t get understandable native stack traces in case of a crash.
Publish a library with unstripped .so files
For Android Gradle plugin 7.0 and above
In the library’s build.gradle
, use keepDebugSymbols
to select which .so
embed in its unstripped
version.
Here, all .so
are unstripped
:
For Android Gradle plugin 4.2 and under
In the library build.gradle
, use doNotStrip
to select which .so
embed in its unstripped version.
Here, all .so
are unstripped
:
⚠️ Because an unstripped .so
contains all debug symbols, it's far bigger than the stripped one.
You could be afraid that your .aab
size will increase drastically.
Don’t worry, users won’t see the difference because, during the release of your application, the release task will do the transformation unstripped -> stripped
.
Upload debug symbol to the Play store
To upload native debug symbols on the Play Store, you must ship them in the released .aab
.
This information will be in the .aab
at the following path: BUNDLE_METADATA/com.android.tools.build.debugsymbols/{ABI}/{your_native_lib.so.dbg}
In the application’s build.gradle
, add the following configuration:
debugSymbolLevel
can take two values:
FULL
: you will get function names, files, and line numbers in the Play Console's symbolicated stack traces.SYMBOL_TABLE
: you will get function names in the Play Console's symbolicated stack traces.
Use this second value if your debug symbol file is more than 300Mo because the Play Store fixes a file size limitation. Otherwise, we should use FULL
to get the most information.
Upload debug symbol on Firebase Crashlytics
In the application’s build.gradle
, if Firebase Crashlytics is already setup, you just have to add this dependency:
dependencies {
implementation 'com.google.firebase:firebase-crashlytics-ndk:{VERSION}'
}
You also have some configuration to do:
- Enable native symbol upload feature for your
release
buildType. - Define the path of your
stripped
andunstripped
native libraries.
These files are localized in specific directories:
- stripped:
$buildDir/intermediates/stripped_native_libs/{BUILD_VARIANT}/out/lib
- unstripped:
$buildDir/intermediates/merged_native_libs/{BUILD_VARIANT}/out/lib
⚠️ Check that the files don’t have the same size to be sure the stripped versions are generated. Unstripped versions should be bigger than the stripped ones.
If your application doesn’t have product flavors, the configuration you add inbuild.gradle
will look like this:
Now you can build a release .aab
of your application.
After the build, call uploadCrashlyticsSymbolFile{BUILD_VARIANT}
to upload native debug symbols on the platform.
If your app doesn’t have product flavors, the task is uploadCrashlyticsSymbolFileRelease
.
Conclusion
If you followed all the intructions, now you know:
- How to publish a library with unstripped .so files.
- How to publish native debug symbols on the Play Store.
- How to publish native debug symbols on Firebase crashlytics.
Future native crash reports will be more explicit and it will be easier to fix them and get 100% crash free user !