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
@taliesin-ai taliesin-ai added v3 and removed v3-alpha labels Aug 9, 2026
@leaanthony leaanthony added android Android platform mobile Mobile platform work labels Aug 9, 2026 — with ChatGPT Codex Connector
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

android Android platform cli mobile Mobile platform work v3

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants