Skip to content

feat(android): [Part 4] Prefer Activity ui.load transactions over Nav3 transactions - #6484

Open
0xadam-brown wants to merge 3 commits into
fix/nav3-lifecycle-3-lease-withdrawalfrom
feat/nav3-lifecycle-4-ui-load-preference
Open

0xadam-brown wants to merge 3 commits into
fix/nav3-lifecycle-3-lease-withdrawalfrom
feat/nav3-lifecycle-4-ui-load-preference

Conversation

@0xadam-brown

@0xadam-brown 0xadam-brown commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

PR Stack (Nav3 Lifecycle)


📜 Description

When the user opens an Activity from a Nav3 root, that Activity's ui.load transaction is now bound to the scope instead of being blocked by the Nav3 root's nav transaction (API 29+), matching Nav2. A Nav3 transaction blocked by a closing Activity's ui.load is retried once.

Prior (and wrong) assumption Problematic scenario Before After
Nav transactions only compete with each other for the transaction slot The user opens another Activity from a nav root The nav transaction keeps the slot and blocks the new Activity's ui.load transaction† On API 29+, ui.load binds in preference to the nav transaction, as it does with Nav2

† TTID and TTFD were never affected. Both spans are children of ui.load itself, so they're sent whether or not ui.load is bound to the shared IScope. Binding only decides which transaction ambient spans (HTTP, db, etc.) attach to.

How this PR fixes things

This PR withdraws the lease when a covering Activity is created. On API 29+ this happens in onActivityPreCreated, which runs before ActivityLifecycleIntegration tries to bind ui.load, thereby allowing the ui.load transaction to beat out the nav transaction.

Below API 29 there's no onActivityPreCreated, so creation is reported from onActivityCreated, meaning the nav transaction beats out the ui.load transaction.

Known gaps

Documented in the package README.

  • A ui.action transaction from the gesture that caused the return can still block the nav transaction.
  • Spans produced between the return and the closed Activity's destruction attach to its ui.load.
  • An Activity that's left without being destroyed triggers no retry.

Addressing the last two would require updating ActivityLifecycleIntegration to unbind a finishing Activity's ui.load when it pauses. That'd change behavior for every app and not just users of Nav3, so I haven't included it here. We could follow-up at some point if we care to. Nicely, tackling things in ActivityLifecycleIntegration would have the happy side effect of simplifying the heuristics we have to use here.

💡 Motivation and Context

Nav2 lets an Activity's ui.load transaction take precedence, but Nav3 blocked it whenever the Activity was opened from a Nav3 root, so the Activity's auto-instrumented spans went elsewhere. Withdrawing the lease only on resume (#6483) also left the covering Activity's onCreate/onStart work attributed to the previous root.

addresses: JAVA-785

💚 How did you test it?

  • Unit tests
  • Integration tests
  • Had my clanker thoroughly test the pre- and post-stack behavior via the Nav3 sample app i) to verify the stack really does what it claims to and ii) to ensure it doesn't introduce any regressions. (Did so on both pre-API 29 and post-API 29 devices.)

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

Last PR in the stack. Once the stack is merged into the collection branch, squash-merge #6480 into main.

⚠️ Merge this PR using a merge commit (not squash). Only the collection branch is squash-merged into main.

…nsactions

The Nav3 lease is now also withdrawn when an Activity is created over the leaseholder, not only when it resumes. On API 29+, creation is reported from onActivityPreCreated, before ActivityLifecycleIntegration binds the new Activity's ui.load transaction, so the leaseholder's nav transaction no longer holds the scope's transaction slot and ui.load binds, as with Nav2. Errors and spans from the new Activity's onCreate and onStart are no longer attributed to the leaseholder on any API level.

Because ui.load now binds, returning quickly to a nav root while the closed Activity's ui.load is still running would leave the nav root's transaction blocked. The coordinator therefore retries binding the leaseholder's nav transaction once when another Activity is destroyed, within 10s of the blocked attempt. Below API 29, there's no onActivityPreCreated, so the new Activity's ui.load stays unbound as before; this is documented in the package README.
@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 7b3da29

@sentry

sentry Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.63.0 (1) release

⚙️ sentry-android Build Distribution Settings

@0xadam-brown 0xadam-brown changed the title feat(android): [Nav3 Lifecycle 4] Prefer an Activity's ui.load over Nav3 transactions feat(android): [Part 4] Prefer Activity ui.load transactions over Nav3 transactions Nov 6, 2026
@0xadam-brown
0xadam-brown marked this pull request as ready for review November 6, 2026 12:32
@0xadam-brown
0xadam-brown requested review from a team and adinauer as code owners November 6, 2026 12:32
@0xadam-brown
0xadam-brown requested review from markushi and runningcode and removed request for a team November 6, 2026 12:32
@0xadam-brown 0xadam-brown added the sanity-check PR needs a lightweight review for obvious issues label Nov 6, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sanity-check PR needs a lightweight review for obvious issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant