diff --git a/docs/platforms/android/configuration/using-ndk.mdx b/docs/platforms/android/configuration/using-ndk.mdx index a3b851fc57013c..100fb8d7fd6588 100644 --- a/docs/platforms/android/configuration/using-ndk.mdx +++ b/docs/platforms/android/configuration/using-ndk.mdx @@ -136,6 +136,99 @@ 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. + + + +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 { + implementation "io.sentry:sentry-android-ndk-outproc:{{@inject packages.version('sentry.java.android', '8.64.0') }}" +} + +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.64.0') }}") +} + +configurations.configureEach { + exclude(group = "io.sentry", module = "sentry-native-ndk") +} +``` + +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`. + +Keep in mind: + +- The crash service runs in a separate process, `.sentry_ndk_crash`, while your app runs, and uses additional memory. +- 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`: