Skip to content

feat(android): emit cancelable BackButtonPressed event before default navigation - #5891

Open
mortenolsrud wants to merge 1 commit into
wailsapp:masterfrom
mortenolsrud:feat/android-back-button-event
Open

feat(android): emit cancelable BackButtonPressed event before default navigation#5891
mortenolsrud wants to merge 1 commit into
wailsapp:masterfrom
mortenolsrud:feat/android-back-button-event

Conversation

@mortenolsrud

@mortenolsrud mortenolsrud commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Description

The Android back button is hardcoded to webView.goBack() else exit. This breaks SPA routing, unsaved-changes guards, in-app navigation stacks, modal dismissal, and any app that needs to intercept the back action.

This emits a cancelable common:BackButtonPressed event before performing the default navigation. If a Go listener calls event.Cancel(), the default action is suppressed and the app handles navigation itself. If no listener cancels (or no listener is registered), the legacy behavior remains unchanged.

app.Event.OnApplicationEvent(events.Common.BackButtonPressed, func(e *application.ApplicationEvent) {
    if myModal.IsOpen() {
        myModal.Close()
        e.Cancel() // don't navigate back
    }
    // If we don't cancel, webView.goBack() / exit happens normally
})

Implementation: a new synchronous JNI call nativeOnBackPressed() → Go invokes handleApplicationEvent (which processes hooks and listeners) → returns boolean (cancelled or not) → Java honors the result.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • Android cross-compile (android/arm64 via NDK) — compiles.
  • Desktop build (GTK3) — compiles (Common event addition).
  • Host-side tests pass.
  • Java LSP: no errors.

The back-button behavior is fully backwards-compatible: apps with no BackButtonPressed listener see exactly the same goBack/exit behavior as before.

  • Windows
  • macOS
  • Linux

Test Configuration

  • Wails CLI: v3.0.0-beta.3
  • Go: go1.26.5
  • Ubuntu 24.04.4, Android NDK 26.3.11579264

Checklist:

  • My code follows the general coding style of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Notes:

Summary by CodeRabbit

  • New Features
    • Added Android back-button event support.
    • Applications can intercept back-button actions before navigating WebView history or exiting.
    • Added the common:BackButtonPressed event for handling back-button actions.
    • When the event is not handled by the application, Android continues with the standard back-navigation behavior, including WebView history navigation or exiting the screen.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7116bd70-896c-45b2-957d-9411e25d397b

📥 Commits

Reviewing files that changed from the base of the PR and between 69ca688 and 7f3576f.

📒 Files selected for processing (6)
  • v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java
  • v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsBridge.java
  • v3/pkg/application/application_android.go
  • v3/pkg/events/events.go
  • v3/pkg/events/events.txt
  • v3/pkg/events/known_events.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • v3/pkg/events/known_events.go
  • v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsBridge.java
  • v3/pkg/events/events.go
  • v3/pkg/application/application_android.go
  • v3/pkg/events/events.txt
  • v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java

Walkthrough

Android back-button actions now pass through Go event handling. A consumed event stops further processing. An unconsumed event follows the existing WebView history or activity-exit behavior.

Changes

Android back-button handling

Layer / File(s) Summary
Back-button event contract
v3/pkg/events/events.go, v3/pkg/events/events.txt, v3/pkg/events/known_events.go
Defines common:BackButtonPressed, assigns event identifier 1296, maps it to JavaScript, and registers it as a known event.
Java-to-Go event dispatch
v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsBridge.java, v3/pkg/application/application_android.go
Adds Java native forwarding and a JNI callback that synchronously dispatches the event and returns its cancellation state.
Activity fallback behavior
v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java
Stops processing when Go consumes the back action. Otherwise, it preserves WebView navigation or activity exit behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MainActivity
  participant WailsBridge
  participant nativeOnBackPressed
  participant GoApplication
  participant WebView
  MainActivity->>WailsBridge: onBackPressed()
  WailsBridge->>nativeOnBackPressed: forward back-button action
  nativeOnBackPressed->>GoApplication: dispatch BackButtonPressed
  GoApplication-->>nativeOnBackPressed: return cancellation state
  nativeOnBackPressed-->>WailsBridge: return JNI boolean
  WailsBridge-->>MainActivity: return consumed state
  alt Event consumed
    MainActivity->>MainActivity: stop back-button processing
  else Event not consumed
    MainActivity->>WebView: navigate back or exit activity
  end
Loading

Poem

A rabbit sends back through the bridge,
Go checks the event at the ridge.
If consumed, the hops are done;
If not, WebView takes its run. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the Android feature: a cancelable BackButtonPressed event before default navigation.
Description check ✅ Passed The description covers motivation, implementation, type, testing, configuration, and checklist; it omits an issue or WEP link but remains mostly complete.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@v3/pkg/application/application_android.go`:
- Around line 746-752: Update the back-button handling around
handleApplicationEvent so registered Go listeners complete before
event.IsCancelled() is read. Use the existing cancellation-safe synchronous
event path or wait for listener completion specifically for
common:BackButtonPressed, while preserving the current JNI_TRUE/JNI_FALSE return
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 561baa6d-0b11-4ae1-9746-569a2343891e

📥 Commits

Reviewing files that changed from the base of the PR and between 2014eb6 and e59606c.

📒 Files selected for processing (6)
  • v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java
  • v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsBridge.java
  • v3/pkg/application/application_android.go
  • v3/pkg/events/events.go
  • v3/pkg/events/events.txt
  • v3/pkg/events/known_events.go

Comment thread v3/pkg/application/application_android.go
@mortenolsrud
mortenolsrud force-pushed the feat/android-back-button-event branch from e59606c to 69ca688 Compare August 4, 2026 08:51
@mortenolsrud

Copy link
Copy Markdown
Contributor Author

Valid observation — addressed in the force-push with an expanded comment explaining the design:

Hooks run synchronously (before handleApplicationEvent returns) and can cancel reliably. Listeners run asynchronously (goroutines) and cannot cancel in time for the JNI return. This is by design — same pattern as WindowClosing hooks on desktop.

The code comment and doc now explicitly state: use RegisterApplicationEventHook (not OnApplicationEvent) for cancellation:

app.Event.RegisterApplicationEventHook(events.Common.BackButtonPressed, func(e *application.ApplicationEvent) {
    e.Cancel() // runs synchronously, reliably suppresses default behavior
})

OnApplicationEvent still fires for non-cancelation use cases (logging, analytics, etc.) — it just can't stop the back action because it runs async.

… navigation

The back button was hardcoded to webView.goBack() else exit, breaking
SPA routing (unsaved-changes guards, in-app navigation, search overlays).
Apps had no way to intercept or override the back action.

Add a common:BackButtonPressed event that fires synchronously from
onBackPressed via a new nativeOnBackPressed JNI call. If a Go listener
calls event.Cancel(), the back action is suppressed — the app handles
navigation itself. If no listener cancels, the legacy behavior
(goBack / exit) remains as the default.

Usage:
  app.Event.OnApplicationEvent(events.Common.BackButtonPressed, func(e *application.ApplicationEvent) {
      // handle back press (e.g. close a modal, navigate in-app)
      e.Cancel() // suppress the default goBack/exit
  })
@mortenolsrud
mortenolsrud force-pushed the feat/android-back-button-event branch from 69ca688 to 7f3576f Compare August 4, 2026 10:33
@taliesin-ai taliesin-ai added this to the v3.1.0 milestone Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants