From 2b64495a8ba25ef58e4ea8b95311d6b5958df0fc Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 3 Nov 2026 20:03:10 +0100 Subject: [PATCH 1/6] docs(android): Add experimental out-of-process crash handling Document the opt-in out-of-process backend of the NDK integration, which captures native crashes in a separate crash service process and sends them right away. Cover enabling it with and without the Sentry Android Gradle Plugin, the API 30+ requirement, and what the separate process means for the app. Ref: getsentry/sentry-native#1725 Ref: getsentry/sentry-java#6347 Ref: getsentry/sentry-android-gradle-plugin#1474 --- .../android/configuration/using-ndk.mdx | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docs/platforms/android/configuration/using-ndk.mdx b/docs/platforms/android/configuration/using-ndk.mdx index a3b851fc57013c..d8a428eb81bf8a 100644 --- a/docs/platforms/android/configuration/using-ndk.mdx +++ b/docs/platforms/android/configuration/using-ndk.mdx @@ -136,6 +136,65 @@ You can also configure these options in `AndroidManifest.xml`, which is useful w For details about the native watchdog and heartbeat behavior, see the [Native SDK app hang documentation](/platforms/native/app-hangs/). +## Out-of-Process Crash Handling + +By default, the NDK integration handles a native crash inside the crashing process, and the SDK sends it the next time the app starts. With out-of-process crash handling, a crash service in a separate process captures the crash and sends it right away. This way, you see native crashes even from users who don't open the app again. + + + +Out-of-process crash handling is experimental. It requires Android 11 (API level 30) or later. On older Android versions, the SDK doesn't report native crashes in this mode. + + + +Enable it with the [Sentry Android Gradle Plugin](/platforms/android/configuration/gradle/): + +```groovy {filename:app/build.gradle} +sentry { + ndkBackend = "native" +} +``` + +```kotlin {filename:app/build.gradle.kts} +sentry { + ndkBackend.set("native") +} +``` + +The plugin adds `sentry-android-ndk-outproc` and replaces `sentry-native-ndk` with `sentry-native-ndk-outproc`. + +Without the plugin, add `sentry-android-ndk-outproc` and exclude `sentry-native-ndk`, which the `sentry-android` bundle includes: + +```groovy {filename:app/build.gradle} +dependencies { + implementation "io.sentry:sentry-android-ndk-outproc:{{@inject packages.version('sentry.java.android', '8.21.1') }}" +} + +configurations.configureEach { + exclude group: "io.sentry", module: "sentry-native-ndk" +} +``` + +```kotlin {filename:app/build.gradle.kts} +dependencies { + implementation("io.sentry:sentry-android-ndk-outproc:{{@inject packages.version('sentry.java.android', '8.21.1') }}") +} + +configurations.configureEach { + exclude(group = "io.sentry", module = "sentry-native-ndk") +} +``` + +If the build contains both native packages, Gradle fails with a conflict on the capability `io.sentry:sentry-ndk-backend`. + +If you [link against the NDK libraries](#allowing-the-compiler-to-link-libraries), keep your `CMakeLists.txt`. Without the plugin, depend on `io.sentry:sentry-native-ndk-outproc` instead of `io.sentry:sentry-native-ndk`. + +Keep in mind: + +- The crash service runs in a separate process, `.sentry_ndk_crash`, while your app runs, and uses additional memory. +- Android creates your `Application` in that process too. The SDK skips its own initialization there. If your `Application.onCreate` does other startup work, check `Application.getProcessName()` and skip that work in the crash service process. +- With the [Tombstone Integration](/platforms/android/configuration/tombstones/) enabled on Android 12 (API level 31) or later, the crash service merges the tombstone into the native crash event before it sends it. +- If the crash service can't send the crash, for example without a network connection, the SDK sends it the next time the app starts. + ## Disable NDK Integration You can disable the NDK integration by adding the following to your `AndroidManifest.xml`: From 29a7880ccb5fa5e828bde2298ff0c29f981e056f Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 4 Nov 2026 09:43:18 +0100 Subject: [PATCH 2/6] docs(android): Note the crash service freeze after the app exits Android can freeze the crash service shortly after the app exits, so a slow upload may not finish. The SDK then sends the crash on a later app start. Document this as a known limitation of out-of-process crash handling. --- docs/platforms/android/configuration/using-ndk.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/platforms/android/configuration/using-ndk.mdx b/docs/platforms/android/configuration/using-ndk.mdx index d8a428eb81bf8a..b170a395076bb7 100644 --- a/docs/platforms/android/configuration/using-ndk.mdx +++ b/docs/platforms/android/configuration/using-ndk.mdx @@ -193,7 +193,7 @@ Keep in mind: - The crash service runs in a separate process, `.sentry_ndk_crash`, while your app runs, and uses additional memory. - Android creates your `Application` in that process too. The SDK skips its own initialization there. If your `Application.onCreate` does other startup work, check `Application.getProcessName()` and skip that work in the crash service process. - With the [Tombstone Integration](/platforms/android/configuration/tombstones/) enabled on Android 12 (API level 31) or later, the crash service merges the tombstone into the native crash event before it sends it. -- If the crash service can't send the crash, for example without a network connection, the SDK sends it the next time the app starts. +- If the crash service can't finish sending the crash, the SDK sends it on a later app start. This can happen without a network connection, or on Android 14 (API level 34) and later, where Android freezes the service 10 seconds after the app exits. ## Disable NDK Integration From f0c2c2758505da5283f6087aee2c56ba93742ad4 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 4 Nov 2026 19:02:04 +0100 Subject: [PATCH 3/6] docs(android): Drop the Gradle plugin from out-of-process crash handling The `ndkBackend` option of the Gradle plugin is parked for now, so add the package and the exclude directly. --- .../android/configuration/using-ndk.mdx | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/docs/platforms/android/configuration/using-ndk.mdx b/docs/platforms/android/configuration/using-ndk.mdx index b170a395076bb7..168cd11655bcbd 100644 --- a/docs/platforms/android/configuration/using-ndk.mdx +++ b/docs/platforms/android/configuration/using-ndk.mdx @@ -146,23 +146,7 @@ Out-of-process crash handling is experimental. It requires Android 11 (API level -Enable it with the [Sentry Android Gradle Plugin](/platforms/android/configuration/gradle/): - -```groovy {filename:app/build.gradle} -sentry { - ndkBackend = "native" -} -``` - -```kotlin {filename:app/build.gradle.kts} -sentry { - ndkBackend.set("native") -} -``` - -The plugin adds `sentry-android-ndk-outproc` and replaces `sentry-native-ndk` with `sentry-native-ndk-outproc`. - -Without the plugin, add `sentry-android-ndk-outproc` and exclude `sentry-native-ndk`, which the `sentry-android` bundle includes: +To enable it, add `sentry-android-ndk-outproc` and exclude `sentry-native-ndk`, which the `sentry-android` bundle includes: ```groovy {filename:app/build.gradle} dependencies { @@ -186,7 +170,7 @@ configurations.configureEach { If the build contains both native packages, Gradle fails with a conflict on the capability `io.sentry:sentry-ndk-backend`. -If you [link against the NDK libraries](#allowing-the-compiler-to-link-libraries), keep your `CMakeLists.txt`. Without the plugin, depend on `io.sentry:sentry-native-ndk-outproc` instead of `io.sentry:sentry-native-ndk`. +If you [link against the NDK libraries](#allowing-the-compiler-to-link-libraries), keep your `CMakeLists.txt`, but depend on `io.sentry:sentry-native-ndk-outproc` instead of `io.sentry:sentry-native-ndk`. Keep in mind: From a4fe2a0313756f924f43531639e565920e3bdbbf Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 Nov 2026 15:26:39 +0100 Subject: [PATCH 4/6] docs(android): Expand on the second Application instance Android runs `Application.onCreate` in the crash service process too. Spell out the side effects for app startup code and how to skip it. --- .../android/configuration/using-ndk.mdx | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/docs/platforms/android/configuration/using-ndk.mdx b/docs/platforms/android/configuration/using-ndk.mdx index 168cd11655bcbd..efd33c234ed1b1 100644 --- a/docs/platforms/android/configuration/using-ndk.mdx +++ b/docs/platforms/android/configuration/using-ndk.mdx @@ -175,10 +175,60 @@ If you [link against the NDK libraries](#allowing-the-compiler-to-link-libraries Keep in mind: - The crash service runs in a separate process, `.sentry_ndk_crash`, while your app runs, and uses additional memory. -- Android creates your `Application` in that process too. The SDK skips its own initialization there. If your `Application.onCreate` does other startup work, check `Application.getProcessName()` and skip that work in the crash service process. +- Android creates a second instance of your `Application` in that process. See [Second Application Instance](#second-application-instance). - With the [Tombstone Integration](/platforms/android/configuration/tombstones/) enabled on Android 12 (API level 31) or later, the crash service merges the tombstone into the native crash event before it sends it. - If the crash service can't finish sending the crash, the SDK sends it on a later app start. This can happen without a network connection, or on Android 14 (API level 34) and later, where Android freezes the service 10 seconds after the app exits. +### Second Application Instance + +Android creates a second instance of your `Application` class in the crash service process. The SDK skips its own initialization there, so only one SDK runs and sessions aren't tracked twice. + + + +Code in `Application.onCreate` also runs in the crash service process, which can initialize libraries twice, repeat background work, or cause conflicts over shared files. + + + +To run startup code only in the main process, return early from `Application.onCreate` in other processes: + +```kotlin {filename:MyApplication.kt} +class MyApplication : Application() { + override fun onCreate() { + super.onCreate() + if (!isMainProcess()) return + + // your startup work + } + + private fun isMainProcess() = + Build.VERSION.SDK_INT < Build.VERSION_CODES.P || + Application.getProcessName() == applicationInfo.processName + // or, to skip only the crash service process: + // !Application.getProcessName().endsWith(".sentry_ndk_crash") +} +``` + +```java {filename:MyApplication.java} +public class MyApplication extends Application { + @Override + public void onCreate() { + super.onCreate(); + if (!isMainProcess()) { + return; + } + + // your startup work + } + + private boolean isMainProcess() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.P + || Application.getProcessName().equals(getApplicationInfo().processName); + // or, to skip only the crash service process: + // || !Application.getProcessName().endsWith(".sentry_ndk_crash"); + } +} +``` + ## Disable NDK Integration You can disable the NDK integration by adding the following to your `AndroidManifest.xml`: From 24b0b0f2a3828606a2951beeacbb7e079821d8bf Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 Nov 2026 17:21:12 +0100 Subject: [PATCH 5/6] docs(android): Clarify when to exclude sentry-native-ndk Only the `sentry-android` bundle pulls in `sentry-native-ndk`, so builds that use `sentry-android-core` don't need the exclude. --- docs/platforms/android/configuration/using-ndk.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/platforms/android/configuration/using-ndk.mdx b/docs/platforms/android/configuration/using-ndk.mdx index efd33c234ed1b1..81f687844e851b 100644 --- a/docs/platforms/android/configuration/using-ndk.mdx +++ b/docs/platforms/android/configuration/using-ndk.mdx @@ -168,7 +168,7 @@ configurations.configureEach { } ``` -If the build contains both native packages, Gradle fails with a conflict on the capability `io.sentry:sentry-ndk-backend`. +You don't need to exclude `sentry-native-ndk` if you use `sentry-android-core` instead of the `sentry-android` bundle. If the build contains both native packages, Gradle fails with a conflict on the capability `io.sentry:sentry-ndk-backend`. If you [link against the NDK libraries](#allowing-the-compiler-to-link-libraries), keep your `CMakeLists.txt`, but depend on `io.sentry:sentry-native-ndk-outproc` instead of `io.sentry:sentry-native-ndk`. From 493dd68cf951dc47c737af26f3f050404ec558e1 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 5 Nov 2026 17:22:03 +0100 Subject: [PATCH 6/6] docs(android): Set the outproc fallback version to 8.64.0 The snippets copied `8.21.1` from the older NDK snippet, which predates `sentry-android-ndk-outproc`. Use the first release expected to ship it. --- docs/platforms/android/configuration/using-ndk.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/platforms/android/configuration/using-ndk.mdx b/docs/platforms/android/configuration/using-ndk.mdx index 81f687844e851b..100fb8d7fd6588 100644 --- a/docs/platforms/android/configuration/using-ndk.mdx +++ b/docs/platforms/android/configuration/using-ndk.mdx @@ -150,7 +150,7 @@ To enable it, add `sentry-android-ndk-outproc` and exclude `sentry-native-ndk`, ```groovy {filename:app/build.gradle} dependencies { - implementation "io.sentry:sentry-android-ndk-outproc:{{@inject packages.version('sentry.java.android', '8.21.1') }}" + implementation "io.sentry:sentry-android-ndk-outproc:{{@inject packages.version('sentry.java.android', '8.64.0') }}" } configurations.configureEach { @@ -160,7 +160,7 @@ configurations.configureEach { ```kotlin {filename:app/build.gradle.kts} dependencies { - implementation("io.sentry:sentry-android-ndk-outproc:{{@inject packages.version('sentry.java.android', '8.21.1') }}") + implementation("io.sentry:sentry-android-ndk-outproc:{{@inject packages.version('sentry.java.android', '8.64.0') }}") } configurations.configureEach {