feat(feedback): Support runtime enable/disable of shake-to-report - #5827
Merged
Conversation
markushi
marked this pull request as ready for review
July 23, 2026 16:14
markushi
requested review from
0xadam-brown,
adinauer,
romtsn and
runningcode
as code owners
July 23, 2026 16:14
Contributor
|
📲 Install BuildsAndroid
|
Contributor
Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 343.31 ms | 417.23 ms | 73.91 ms |
| d15471f | 286.65 ms | 314.68 ms | 28.03 ms |
| d217708 | 409.83 ms | 474.72 ms | 64.89 ms |
| d500866 | 326.13 ms | 378.70 ms | 52.58 ms |
| fcec2f2 | 314.96 ms | 373.66 ms | 58.70 ms |
| d501a7e | 314.55 ms | 343.34 ms | 28.79 ms |
| 7414e9b | 322.49 ms | 378.88 ms | 56.39 ms |
| fcec2f2 | 357.47 ms | 447.32 ms | 89.85 ms |
| a416a65 | 316.52 ms | 359.67 ms | 43.15 ms |
| 983e0f0 | 350.64 ms | 386.44 ms | 35.79 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 6b019b7 | 0 B | 0 B | 0 B |
| d15471f | 1.58 MiB | 2.13 MiB | 559.54 KiB |
| d217708 | 1.58 MiB | 2.10 MiB | 532.97 KiB |
| d500866 | 0 B | 0 B | 0 B |
| fcec2f2 | 1.58 MiB | 2.12 MiB | 551.50 KiB |
| d501a7e | 0 B | 0 B | 0 B |
| 7414e9b | 0 B | 0 B | 0 B |
| fcec2f2 | 1.58 MiB | 2.12 MiB | 551.50 KiB |
| a416a65 | 1.58 MiB | 2.12 MiB | 555.26 KiB |
| 983e0f0 | 0 B | 0 B | 0 B |
Previous results on branch: feat/runtime-enable-disable-shake-to-report
Startup times
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ad80f17 | 315.06 ms | 364.31 ms | 49.24 ms |
| 7578b08 | 320.47 ms | 375.35 ms | 54.88 ms |
| 10e52bd | 358.70 ms | 433.06 ms | 74.36 ms |
| 0400a6b | 448.14 ms | 494.02 ms | 45.88 ms |
| be39d9f | 343.92 ms | 417.98 ms | 74.06 ms |
| 8594d29 | 355.30 ms | 449.74 ms | 94.44 ms |
| d65301f | 330.76 ms | 381.63 ms | 50.88 ms |
| 3a16473 | 370.90 ms | 449.96 ms | 79.06 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ad80f17 | 0 B | 0 B | 0 B |
| 7578b08 | 0 B | 0 B | 0 B |
| 10e52bd | 0 B | 0 B | 0 B |
| 0400a6b | 0 B | 0 B | 0 B |
| be39d9f | 0 B | 0 B | 0 B |
| 8594d29 | 0 B | 0 B | 0 B |
| d65301f | 0 B | 0 B | 0 B |
| 3a16473 | 0 B | 0 B | 0 B |
…r.setDialog to prevent overlapping feedback dialogs
…e-to-report' into feat/runtime-enable-disable-shake-to-report
…strong dialog reference cannot leak its activity
markushi
marked this pull request as draft
July 24, 2026 06:09
…nt stacked feedback dialogs
…g callback cannot crash the app
markushi
marked this pull request as ready for review
July 24, 2026 06:37
runningcode
reviewed
Jul 24, 2026
runningcode
reviewed
Jul 27, 2026
runningcode
left a comment
Contributor
There was a problem hiding this comment.
Looks good, just some small things!
romtsn
reviewed
Jul 30, 2026
9 tasks
- Scope shake suppression to the activity a feedback form is showing on, instead of a global paused flag. A dialog lives in its activity's window and is never notified when that activity is backgrounded, so tracking the owning activity removes the lifecycle heuristics entirely - Re-check enabled on shake dispatch so a concurrent disableOnShake() cannot still show a form - Narrow user-callback guards from Throwable to Exception so Errors propagate - Rename isFeedbackOnShakeEnabled() to isOnShakeEnabled() for consistency with enableOnShake()/disableOnShake(), and drop @ApiStatus.Internal Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
romtsn
approved these changes
Aug 11, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Shake suppression while a form is visible was keyed on a single activity ref resolved from CurrentActivityHolder, which is not necessarily the activity the form is showing on, and any form teardown cleared it. With two forms visible at once - e.g. showForm() called while a form is already up - the first one going away re-armed detection under the second, so a shake could stack another form on top. Forms now report themselves and their host activity to FeedbackShakeIntegration, which tracks them individually and only re-arms detection once no form remains on the current activity. Since the host activity is Android-only, pausing moves off the cross-platform IShakeController onto the integration itself. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
On Android these are dialogs, so name the internal members after what they are. The public API keeps "form" (SentryUserFeedbackForm, onFormOpen/onFormClose, showForm) since renaming it would be breaking and it is not Android-specific. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dialog.show() runs onStart() - which reports the dialog as visible and stops shake detection - before adding the window, so a failure in addView() left the dialog registered as visible with no callback ever reporting it gone. Shake detection then stayed off for the rest of the activity's lifetime while isOnShakeEnabled() still reported true. Also drop the global useShakeGesture check from the dialog's own shake opt-in: whether the integration is currently detecting is the only thing that matters there, and a dialog configured for shake detection should get it once the integration is off. Document on disableOnShake() that it only turns off the SDK-wide detection. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 92fc15f. Configure here.
… show Drives a real shake through the detector and injects a dialog that reports itself visible and then fails to show, the way Android runs onStart() before adding the window. Verified to fail without the re-arm in the catch block. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

📜 Description
Adds a runtime API to toggle shake-to-report after
Sentry.init():Sentry.feedback().enableOnShake()Sentry.feedback().disableOnShake()Sentry.feedback().isOnShakeEnabled()SentryFeedbackOptions.isUseShakeGesture()now only determines the initial state; the runtime API overrides it afterwards. Propagation works similar toIFormHandler/ReplayControllerby introducing a newSentryFeedbackOptions.IShakeController, implemented byFeedbackShakeIntegrationon Android and by a logging no-op elsewhere.This also required re-wiring on-demand dialogs vs. the automatic ones, so that no duplicate dialogs are shown and no duplicate detectors run at the same time:
FeedbackShakeIntegrationis always installed and registers itself as theIShakeController, even when the option starts out disabled — otherwise there would be nothing to enable later. It arms/disarms the detector inenableOnShake()/disableOnShake().onFormVisibleinonStart,onFormGoneinonStop, withonDetachedFromWindowas a safety net for teardown without a dismiss). Detection is suppressed for the activity hosting a form and only re-armed once no form remains there, so neither a form on a backgrounded activity nor one of two simultaneously visible forms can re-enable detection under a visible one. This replaces the previousonFormCloseswap-and-restore dance, which was fragile and could leak the host activity.SentryUserFeedbackFormonly starts a detector of its own for the per-form opt-in case (useShakeGestureenabled via a configurator while it is globally off); otherwise it defers to the integration, including if shake-to-report gets enabled globally between form creation and the shake.onFormOpen/onFormClose/onSubmitSuccess/onSubmitErrorcallbacks are now guarded, so a crashing callback can't take down the app or skip SDK-side cleanup.💡 Motivation and Context
Having a runtime option to enable / disable the feedback.
Closes #5486 (#5486)
💚 How did you test it?
Unit tests (
FeedbackShakeIntegrationTest,SentryUserFeedbackFormTest,FeedbackApiTest,SentryOptionsTest) + manual testing with the Android sample app.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps