diff --git a/docs/crashlytics/android-setup.md b/docs/crashlytics/android-setup.md index 2ea502c11b..b5a7dbcde0 100644 --- a/docs/crashlytics/android-setup.md +++ b/docs/crashlytics/android-setup.md @@ -57,12 +57,30 @@ apply plugin: 'com.google.firebase.crashlytics' // .. ``` -## 4. (Optional) Enable Crashlytics NDK reporting +## 4. (Optional) Configure Crashlytics NDK and GWP-ASan support + +### Enable NDK Crash Reporting Crashlytics NDK reporting allows you to capture Native Development Kit crashes, e.g. in React Native this will capture crashes originating from the Yoga layout engine. -Add the `firebaseCrashlytics` block line to the `android/app/build.gradle` file: +To enable NDK crash reporting, add the following to your `firebase.json` file: + +```json +{ + "react-native": { + "crashlytics_ndk_enabled": true + } +} +``` + +When `crashlytics_ndk_enabled` is set to `true`, React Native Firebase will automatically: +- Enable NDK crash reporting in the manifest +- Configure automatic native symbol upload for all release build variants + +> **Note**: The automatic symbol upload configuration works with standard release builds and custom build flavors (e.g., `playRelease`, `premiumRelease`). Any build variant with "release" in its name will have symbol upload enabled. + +If you need to manually configure symbol upload or override the automatic configuration, you can add the `firebaseCrashlytics` block to your `android/app/build.gradle` file: ```groovy android { @@ -70,10 +88,6 @@ android { buildTypes { release { - /* Add the firebaseCrashlytics extension (by default, - * it's disabled to improve build speeds) and set - * nativeSymbolUploadEnabled to true along with a pointer to native libs. */ - firebaseCrashlytics { nativeSymbolUploadEnabled true unstrippedNativeLibsDir 'build/intermediates/merged_native_libs/release/out/lib' @@ -84,6 +98,25 @@ android { } ``` +### Configure GWP-ASan Mode + +[GWP-ASan](https://developer.android.com/ndk/guides/gwp-asan) (GWP-AddressSanitizer) is a native memory allocator feature that helps detect heap memory errors. You can configure its behavior using `firebase.json`: + +```json +{ + "react-native": { + "crashlytics_gwp_asan_mode": "default" + } +} +``` + +Available values: +- `"default"` - The default behavior (system-determined, typically enabled for a small percentage of devices) +- `"never"` - Disable GWP-ASan completely +- `"always"` - Enable GWP-ASan on all devices (useful for testing, but not recommended for production due to performance impact) + +> **Recommended**: Use `"default"` for production builds to get memory error detection with minimal performance impact. + ## 5. Rebuild the project Once the above steps have been completed, rebuild your Android project: diff --git a/docs/crashlytics/usage/index.md b/docs/crashlytics/usage/index.md index c4f93149c7..6bdc446b4a 100644 --- a/docs/crashlytics/usage/index.md +++ b/docs/crashlytics/usage/index.md @@ -213,21 +213,47 @@ Because you have stack traces readily available while you're debugging your app, ## Crashlytics NDK React Native Firebase supports [Crashlytics NDK](https://firebase.google.com/docs/crashlytics/ndk-reports) reporting -which is enabled by default but will require a change as described in that link to enable symbol upload. +which allows Crashlytics to capture crashes originating from the Yoga layout engine used by React Native. -This allows Crashlytics to capture crashes originating from the Yoga layout engine used by React Native. +**Note:** NDK reporting is disabled by default due to memory usage concerns. -You can disable Crashlytics NDK in your `firebase.json` config. +### Enable NDK Reporting + +To enable NDK crash reporting, add the following to your `firebase.json`: + +```json +// /firebase.json +{ + "react-native": { + "crashlytics_ndk_enabled": true + } +} +``` + +When enabled, React Native Firebase will automatically: +- Enable NDK crash reporting in your Android app +- Configure automatic native symbol upload for all release build variants + +For more details on Android setup, see the [Android Setup](/crashlytics/android-setup) documentation. + +### Configure GWP-ASan + +[GWP-ASan](https://developer.android.com/ndk/guides/gwp-asan) (GWP-AddressSanitizer) is a native memory allocator feature that helps detect heap memory errors. You can configure its behavior: ```json // /firebase.json { "react-native": { - "crashlytics_ndk_enabled": false + "crashlytics_gwp_asan_mode": "default" } } ``` +Available values: +- `"default"` - System-determined (recommended for production) +- `"never"` - Disable GWP-ASan completely +- `"always"` - Enable on all devices (for testing only) + ## Crashlytics Javascript stacktrace issue generation React Native Crashlytics module by default installs a global javascript exception handler, and it records a crash with a javascript stack trace any time an unhandled javascript exception is thrown. Sometimes it is not desirable behavior since it might duplicate issues in combination with the default mode of javascript global exception handler chaining. We recommend leaving JS crashes enabled and turning off exception handler chaining. However, if you have special crash handling requirements, you may disable this behavior by setting the appropriate option to false: diff --git a/packages/crashlytics/android/build.gradle b/packages/crashlytics/android/build.gradle index dfb9b21e96..c0096fa865 100644 --- a/packages/crashlytics/android/build.gradle +++ b/packages/crashlytics/android/build.gradle @@ -57,6 +57,25 @@ project.ext { ]) } +apply from: file('./../../app/android/firebase-json.gradle') + +// Default to 'false' for the feature due to memory usage concerns +String crashlyticsNdkEnabled = 'false' +// Default to 'default' for GWP-ASan mode (other options: 'never', 'always') +String crashlyticsGwpAsanMode = 'default' + +if (rootProject.ext && rootProject.ext.firebaseJson) { + def rnfbConfig = rootProject.ext.firebaseJson + + // Allow users to opt-in to NDK crash reporting + if (rnfbConfig.isFlagEnabled('crashlytics_ndk_enabled', false) == true) { + crashlyticsNdkEnabled = 'true' + } + + // Allow users to configure GWP-ASan mode: 'default', 'never', or 'always' + crashlyticsGwpAsanMode = rnfbConfig.getStringValue('crashlytics_gwp_asan_mode', 'default') +} + android { def agpVersion = Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger() if (agpVersion >= 7) { @@ -65,6 +84,10 @@ android { defaultConfig { multiDexEnabled = true + manifestPlaceholders = [ + firebaseJsonCrashlyticsNdkEnabled: crashlyticsNdkEnabled, + firebaseJsonCrashlyticsGwpAsanMode: crashlyticsGwpAsanMode + ] } buildFeatures { @@ -100,3 +123,46 @@ ReactNative.shared.applyPackageVersion() ReactNative.shared.applyDefaultExcludes() ReactNative.module.applyAndroidVersions() ReactNative.module.applyReactNativeDependency("api") + +// Configure automatic NDK symbol upload for release variants if NDK is enabled +// This runs after all projects are evaluated to allow proper configuration +gradle.projectsEvaluated { + if (rootProject.ext && rootProject.ext.firebaseJson) { + def rnfbConfig = rootProject.ext.firebaseJson + + if (rnfbConfig.isFlagEnabled('crashlytics_ndk_enabled', false) == true) { + // Find the app project (the one with com.android.application plugin) + def targetAppProject = rootProject.subprojects.find { + it.plugins.hasPlugin('com.android.application') + } + + if (targetAppProject != null) { + try { + def android = targetAppProject.extensions.findByName('android') + + if (android != null && android.hasProperty('buildTypes')) { + // Configure all build types that contain 'release' (case insensitive) + android.buildTypes.all { buildType -> + if (buildType.name.toLowerCase().contains('release')) { + try { + buildType.ext.set('firebaseCrashlytics', [:]) + buildType.firebaseCrashlytics = [ + nativeSymbolUploadEnabled: true + ] + targetAppProject.logger.info("RNFirebase: Enabled Crashlytics NDK symbol upload for build type '${buildType.name}'") + } catch (Exception e) { + targetAppProject.logger.warn("RNFirebase: Could not automatically configure Crashlytics NDK symbol upload for build type '${buildType.name}'. " + + "You may need to add it manually to your app/build.gradle. See: https://rnfirebase.io/crashlytics/android-setup") + } + } + } + } + } catch (Exception e) { + targetAppProject.logger.warn("RNFirebase: Could not automatically enable Crashlytics NDK symbol upload: ${e.message}") + targetAppProject.logger.info("Please add the following to your android/app/build.gradle:") + targetAppProject.logger.info(" android { buildTypes { release { firebaseCrashlytics { nativeSymbolUploadEnabled true } } } }") + } + } + } + } +} diff --git a/packages/crashlytics/android/src/main/AndroidManifest.xml b/packages/crashlytics/android/src/main/AndroidManifest.xml index 3c29ac3d99..9bf5a280cf 100644 --- a/packages/crashlytics/android/src/main/AndroidManifest.xml +++ b/packages/crashlytics/android/src/main/AndroidManifest.xml @@ -6,6 +6,29 @@ + + + + + + + + +