From baafe855d68b9646b2b75324a2cb6b8ee8d2c5cd Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 7 Oct 2026 09:23:54 +0200 Subject: [PATCH 1/4] feat(android): Publish Nav3 support Commit adds the wiring needed to publish the sentry-android-navigation3 module, which implements our [phase 1](https://linear.app/getsentry/project/android-nav3-support-28432794ea7d/overview) support for Android's [Nav3 library](https://developer.android.com/guide/navigation/navigation-3). It also removes the `@ApiStatus.Internal` annotations from our public Nav3 APIs, including SentryNavEffect. See the SentryNavEffect KDoc and the sentry-android-navigation3 README for more details. --- .craft.yml | 1 + CHANGELOG.md | 2 ++ README.md | 1 + sentry-android-navigation3/README.md | 12 ++++++++++++ .../compose/navigation3/BackStackEntryMapper.kt | 2 -- .../io/sentry/compose/navigation3/SentryNavEffect.kt | 6 +++--- .../sentry/compose/navigation3/SentryNavOptions.kt | 2 -- 7 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 sentry-android-navigation3/README.md diff --git a/.craft.yml b/.craft.yml index bee668917c1..68eb5fac673 100644 --- a/.craft.yml +++ b/.craft.yml @@ -64,6 +64,7 @@ targets: maven:io.sentry:sentry-quartz: maven:io.sentry:sentry-okhttp: maven:io.sentry:sentry-android-navigation: + maven:io.sentry:sentry-android-navigation3: maven:io.sentry:sentry-compose: maven:io.sentry:sentry-compose-android: maven:io.sentry:sentry-compose-desktop: diff --git a/CHANGELOG.md b/CHANGELOG.md index f5d6ef0031b..67e2050c436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Features +- Add support for Android Navigation 3 through the new `sentry-android-navigation3` library ([#6233](https://github.com/getsentry/sentry-java/pull/6233)) + - Use `SentryNavEffect` to record navigation transactions, breadcrumbs, screen names, and additional context as your nav back stack changes. - Report the cellular network technology generation in `device.connection_effective_type`, for example `4g` or `5g` ([#6146](https://github.com/getsentry/sentry-java/pull/6146)) ### Dependencies diff --git a/README.md b/README.md index a827af6f987..97674f6cb5a 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Sentry SDK for Java and Android | sentry-android-timber | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-timber?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-timber) | 21 | | sentry-android-fragment | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-fragment?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-fragment) | 21 | | sentry-android-navigation | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-navigation?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-navigation) | 21 | +| sentry-android-navigation3 | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-navigation3?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-navigation3) | 21 | | sentry-android-sqlite | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-sqlite?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-sqlite) | 21 | | sentry-android-replay | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-replay?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-replay) | 26 | | sentry-compose-android | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-compose-android?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-compose-android) | 21 | diff --git a/sentry-android-navigation3/README.md b/sentry-android-navigation3/README.md new file mode 100644 index 00000000000..bdfec781fc4 --- /dev/null +++ b/sentry-android-navigation3/README.md @@ -0,0 +1,12 @@ +# sentry-android-navigation3 + +[Navigation 3](https://developer.android.com/guide/navigation/navigation-3) instrumentation for the Sentry Android SDK. + +Use `SentryNavEffect` alongside your `NavDisplay` to record navigation transactions, breadcrumbs, screen names, and back stack context as +users move around your app. Configure the data you want captured via `SentryNavOptions`. + +Because Nav3 back stacks can have arbitrary key types, host apps need to provide `SentryNavEffect` with a mapping between their back stack +keys and the data Sentry should display for each (see `BackStackEntryMapper`). + +See the [Navigation for Android docs](https://docs.sentry.io/platforms/android/integrations/navigation/) for additional details, including +installation, configuration, and limitations. diff --git a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt index 2412afffe8b..34281c85368 100644 --- a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt +++ b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt @@ -5,7 +5,6 @@ import org.jetbrains.annotations.ApiStatus /** Info about a given back stack entry, suitable for display in Sentry. */ @ApiStatus.Experimental -@ApiStatus.Internal public class SentryBackStackEntry( /** * A host-app defined name for a given back stack entry. @@ -146,7 +145,6 @@ public class SentryBackStackEntry( * ``` */ @ApiStatus.Experimental -@ApiStatus.Internal public fun interface BackStackEntryMapper { public fun map(backStackEntry: T): SentryBackStackEntry? } diff --git a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavEffect.kt b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavEffect.kt index d041a03b682..8b6269752b6 100644 --- a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavEffect.kt +++ b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavEffect.kt @@ -44,10 +44,11 @@ import org.jetbrains.annotations.ApiStatus * By default, the following data is produced every time the top of the provided [backStack] * changes: * - * - a new navigation transaction + * - a new navigation transaction (unless another transaction is already active on the current + * scope) * - a breadcrumb * - a screen name - * - a record of the current back stack (last 10 entries) + * - a record of the current back stack (last 5 entries) * * You can configure the above defaults via [SentryNavOptions]. (Screen names can be disabled via * [SentryOptions.setEnableScreenTracking].) @@ -75,7 +76,6 @@ import org.jetbrains.annotations.ApiStatus * @param options The kinds of navigation info this effect should record. */ @ApiStatus.Experimental -@ApiStatus.Internal @Composable public fun SentryNavEffect( backStack: List, diff --git a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavOptions.kt b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavOptions.kt index f463567f5e6..9a571d47dee 100644 --- a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavOptions.kt +++ b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/SentryNavOptions.kt @@ -19,7 +19,6 @@ private const val DEFAULT_MAX_CAPTURED_BACK_STACK_ENTRIES = 5 * ``` */ @ApiStatus.Experimental -@ApiStatus.Internal @Immutable public class SentryNavOptions private constructor( @@ -116,6 +115,5 @@ private constructor( * ``` */ @ApiStatus.Experimental -@ApiStatus.Internal public fun SentryNavOptions(configure: SentryNavOptions.Builder.() -> Unit = {}): SentryNavOptions = SentryNavOptions.Builder().apply(configure).build() From 9bbf262ded187c397a67c5a94ee81b246c76d8b5 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Wed, 7 Oct 2026 12:26:58 +0200 Subject: [PATCH 2/4] Minor doc updates --- .../compose/navigation3/BackStackEntryMapper.kt | 16 +++++++++------- .../compose/navigation3/BackStackObserver.kt | 2 +- .../compose/navigation3/SentryNavEffectTest.kt | 5 +++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt index 34281c85368..7455cfda5ff 100644 --- a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt +++ b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackEntryMapper.kt @@ -103,13 +103,15 @@ public class SentryBackStackEntry( * - [Map]s * - [Collection]s * - * Containers may be nested, but they must bottom out in supported scalar types. Cyclic or deeply - * nested containers will be skipped. + * Containers may be nested, but they must bottom out in supported scalar types. * * **Arguments fall back to `toString()` or nothing** * - * All non-supported argument types are stringified via `toString()`. If [map] throws or returns - * `null`, no arguments are recorded for that back stack entry. + * All non-supported argument types are stringified via `toString()`. + * + * No arguments will be recorded for a back stack entry if [map] throws or returns `null`, or if its + * arguments are cyclic, too deeply nested, or too large. If the SDK drops an entry's arguments, it + * adds a `dropped_by_sentry` field and corresponding reason in the Sentry UI. * * **Using kotlinx.serialization** * @@ -122,11 +124,11 @@ public class SentryBackStackEntry( * ```kotlin * @Serializable * @SerialName("Home") - * data class Home(userName: String) : NavKey + * data class Home(val userName: String) : NavKey * * @Serializable * @SerialName("ProductDetail") - * data class ProductDetail(userName: String, productId: String, tab: Tab) : NavKey + * data class ProductDetail(val userName: String, val productId: String) : NavKey * * ... * @@ -137,7 +139,7 @@ public class SentryBackStackEntry( * name = ProductDetail.serializer().descriptor.serialName, * // Select a subset of diagnostic arguments when serialization is unsafe * // or non-performant. - * arguments = mapOf("product_id" to entry.productId, "tab" to entry.tab) + * arguments = mapOf("product_id" to entry.productId) * ) * ... * } diff --git a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackObserver.kt b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackObserver.kt index 9b687d0b25f..37f694350fa 100644 --- a/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackObserver.kt +++ b/sentry-android-navigation3/src/main/kotlin/io/sentry/compose/navigation3/BackStackObserver.kt @@ -273,7 +273,7 @@ private data class BackStackData( val topEntryNormalized: NormalizedSentryBackStackEntry, /** * [NormalizedSentryBackStackEntry]s representing the newest - * [SentryNavOption.maxCapturedBackStackEntries] entries from the host app's back stack. + * [SentryNavOptions.maxCapturedBackStackEntries] entries from the host app's back stack. * * Possibly empty. */ diff --git a/sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/SentryNavEffectTest.kt b/sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/SentryNavEffectTest.kt index 93c1cde567f..7b8a4b99467 100644 --- a/sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/SentryNavEffectTest.kt +++ b/sentry-android-navigation3/src/test/kotlin/io/sentry/compose/navigation3/SentryNavEffectTest.kt @@ -3,7 +3,7 @@ package io.sentry.compose.navigation3 import android.app.Application import android.content.ComponentName import androidx.activity.ComponentActivity -import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf @@ -317,9 +317,10 @@ class SentryNavEffectTest { ) val currentTop = backStack.last() - LaunchedEffect(currentTop) { + DisposableEffect(currentTop) { val transaction = fixture.scopes.getSpan() as? SentryTracer observedTransactionNames += transaction?.name ?: "" + onDispose {} } } composeRule.waitForIdle() From c961c172e1618ed9eda39414a4c9ce6844ee8199 Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Wed, 7 Oct 2026 14:39:02 +0200 Subject: [PATCH 3/4] Update CHANGELOG Added details about Android Navigation 3 support and cellular network technology reporting. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e2050c436..0036c65807e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Add support for Android Navigation 3 through the new `sentry-android-navigation3` library ([#6233](https://github.com/getsentry/sentry-java/pull/6233)) - Use `SentryNavEffect` to record navigation transactions, breadcrumbs, screen names, and additional context as your nav back stack changes. + - See the [Navigation for Android docs](https://docs.sentry.io/platforms/android/integrations/navigation/) for additional details. - Report the cellular network technology generation in `device.connection_effective_type`, for example `4g` or `5g` ([#6146](https://github.com/getsentry/sentry-java/pull/6146)) ### Dependencies From e6b2b7ea2f030f4ef94027d9799080766bbed3ad Mon Sep 17 00:00:00 2001 From: Markus Hintersteiner Date: Wed, 7 Oct 2026 14:39:43 +0200 Subject: [PATCH 4/4] Update version number Updated the version number for sentry-android-navigation3 from 21 to 23. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 97674f6cb5a..f94eb9a9ae7 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Sentry SDK for Java and Android | sentry-android-timber | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-timber?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-timber) | 21 | | sentry-android-fragment | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-fragment?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-fragment) | 21 | | sentry-android-navigation | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-navigation?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-navigation) | 21 | -| sentry-android-navigation3 | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-navigation3?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-navigation3) | 21 | +| sentry-android-navigation3 | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-navigation3?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-navigation3) | 23 | | sentry-android-sqlite | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-sqlite?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-sqlite) | 21 | | sentry-android-replay | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-android-replay?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-android-replay) | 26 | | sentry-compose-android | [![Maven Central Version](https://img.shields.io/maven-central/v/io.sentry/sentry-compose-android?style=for-the-badge&logo=sentry&color=green)](https://central.sonatype.com/artifact/io.sentry/sentry-compose-android) | 21 |