fix(v3): restore Android build and runtime message handling#5022
fix(v3): restore Android build and runtime message handling#5022leaanthony wants to merge 5 commits intov3-alphafrom
Conversation
Fixes five regressions in Android support: 1. Restore events.Android struct (IDs 1259-1270) and JS event mappings that were removed from events.go, breaking events_common_android.go 2. Pass flags to runtime.Core() in nativeOnPageFinished to match the updated API signature used by all other platforms 3. Call setupCommonEvents() in the CGO build's run() method (the non-CGO build already did this) 4. Replace the stub handleMessageForAndroid() with real MessageProcessor routing so JS-to-Go runtime calls (bound methods, clipboard, etc.) actually work 5. Handle non-JSON string messages (e.g. "wails:runtime:ready") that the JS bridge sends before attempting JSON parse Fixes #5020 Co-authored-by: Varun Chawla <varun_6april@hotmail.com>
|
WalkthroughRestores Android event definitions and implements Android message routing: initializes a guarded global MessageProcessor at platform startup, routes JNI callbacks (plain-string and JSON RuntimeRequest) through it with window-ID inference and context-based handling, updates runtime JS/asset serving, and centralizes mobile method-name resolution. Changes
Sequence Diagram(s)sequenceDiagram
participant JNI as Android JNI Callback
participant Handler as handleMessageForAndroid
participant MsgProc as MessageProcessor
participant Runtime as Runtime/Core
participant Asset as Asset Server
participant Response as JSON Response
JNI->>Handler: send message (string or JSON)
alt plain-string (non-JSON)
Handler->>Response: return {"success":true}
else JSON RuntimeRequest
Handler->>Handler: unmarshal into RuntimeRequest
Handler->>MsgProc: HandleRuntimeCallWithIDs(ctx, req)
MsgProc->>Runtime: execute method (with flags/window id)
Runtime->>MsgProc: result / error
MsgProc->>Handler: result / error
Handler->>Asset: (for runtime assets) set `x-wails-window-id`, use httptest recorder
Asset->>Handler: asset body / runtime error body
Handler->>Response: marshal JSON response
end
Response->>JNI: response string
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR fixes critical Android build and runtime issues that were preventing the Android platform from functioning. The changes restore missing Android event definitions, update the runtime initialization to match the current API, and implement proper message routing for JavaScript-to-Go calls.
Changes:
- Restores the
events.Androidstruct and JavaScript event mappings (IDs 1259-1270) that were previously removed - Updates
runtime.Core()call innativeOnPageFinishedto pass flags parameter, matching all other platforms - Adds
setupCommonEvents()call in CGO build path to map Android platform events to common events - Replaces stub
handleMessageForAndroid()with fullMessageProcessorimplementation for routing runtime calls - Handles non-JSON string messages (like
"wails:runtime:ready") before attempting JSON parse
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
v3/pkg/events/events.go |
Adds Android event struct with 12 lifecycle/WebView events and their JavaScript mappings |
v3/pkg/application/application_android.go |
Updates runtime.Core() to pass flags, adds setupCommonEvents() call, implements MessageProcessor routing with global state |
v3/pkg/application/application_android_nocgo.go |
Implements MessageProcessor routing with global state, mirrors CGO implementation for non-CGO builds |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
v3/pkg/application/application_android.go (1)
526-532:⚠️ Potential issue | 🟠 MajorMemory leak:
C.CStringallocations in error response and success response paths are never freed.
C.CStringallocates memory that must be freed withC.free. The strings created at lines 527 and 532 are passed toC.createJStringand never freed, causing memory leaks on every message handled.🐛 Proposed fix to free C strings
if app == nil { errorResponse := `{"error":"App not initialized"}` - return C.createJString(env, C.CString(errorResponse)) + cErr := C.CString(errorResponse) + defer C.free(unsafe.Pointer(cErr)) + return C.createJString(env, cErr) } // Parse and handle the message response := handleMessageForAndroid(app, goMessage) - return C.createJString(env, C.CString(response)) + cResp := C.CString(response) + defer C.free(unsafe.Pointer(cResp)) + return C.createJString(env, cResp) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@v3/pkg/application/application_android.go` around lines 526 - 532, The C.CString allocations for errorResponse and the success response are never freed causing a leak; update the code around the error path and the call to handleMessageForAndroid so that each C.CString passed into C.createJString is freed afterwards (use C.free with the unsafe.Pointer of the C string, e.g., free the result of C.CString(errorResponse) and the C.CString(response) after calling C.createJString), and ensure any early returns still free their C strings; refer to createJString, C.CString, C.free, handleMessageForAndroid, errorResponse and response to locate where to add the frees.
🧹 Nitpick comments (2)
v3/pkg/application/application_android_nocgo.go (1)
188-192: Non-JSON detection heuristic is reasonable but limited.The check
message[0] != '{'works for the documented use case ("wails:runtime:ready"), but note that it will also silently succeed for any malformed message not starting with{. This is acceptable given the current use case, but consider adding a comment documenting the known non-JSON messages for future maintainers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@v3/pkg/application/application_android_nocgo.go` around lines 188 - 192, The non-JSON detection in handleMessageForAndroid currently checks only message[0] != '{' and returns early; update the code by adding a clarifying comment above that if-block documenting the known non-JSON messages (e.g. "wails:runtime:ready") and noting the heuristic’s limitation (it will treat any non-{ start as non-JSON), so future maintainers understand the intent; reference handleMessageForAndroid and the androidLogf call so the comment sits next to that logic.v3/pkg/application/application_android.go (1)
640-688: Significant code duplication with the non-CGO build.The
handleMessageForAndroidfunction is nearly identical betweenapplication_android.goandapplication_android_nocgo.go. Consider extracting the shared logic into a common file (e.g.,application_android_common.gowithout build tags, or with//go:build android) to reduce maintenance burden and ensure consistent behavior.The same JSON escaping issue noted in the non-CGO review (error messages not properly escaped) applies here as well.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@v3/pkg/application/application_android.go` around lines 640 - 688, The function handleMessageForAndroid duplicates logic across builds and also returns unescaped error strings; extract the shared logic into a single helper (e.g., processAndroidRuntimeMessage(ctx, app, message) or handleMessageForAndroidCommon) placed in a common Android file (without differing build tags) and have both application_android.go and application_android_nocgo.go call it; while refactoring, replace all direct fmt.Sprintf(`{"error":"%s"}`, err.Error())/raw string returns with proper JSON construction (e.g., build a struct like type runtimeResp struct{ Error string `json:"error"`; Success *bool `json:"success,omitempty"` } and json.Marshal it or json.Marshal(map[string]string{"error": err.Error()})) so errors are correctly escaped, and keep existing behaviors such as filling WebviewWindowID and logging via androidLogf and using messageProc.HandleRuntimeCallWithIDs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@v3/pkg/application/application_android_nocgo.go`:
- Around line 196-198: The JSON error strings are built by interpolating
err.Error() directly, which can produce invalid JSON; update the error returns
in handleMessageForAndroid (and the other similar return sites around the
current diff) to json.Marshal the error string and embed the marshaled bytes
into the response (e.g. produce {"error":<marshaledError>}) so quotes and
control characters are escaped; if json.Marshal fails, fall back to a safe
literal (or an empty string) and still log the marshal error via androidLogf —
replace the current fmt.Sprintf(`{"error":"%s"}`, err.Error()) returns with
building the response using the json.Marshal result and keep the existing
androidLogf call.
---
Outside diff comments:
In `@v3/pkg/application/application_android.go`:
- Around line 526-532: The C.CString allocations for errorResponse and the
success response are never freed causing a leak; update the code around the
error path and the call to handleMessageForAndroid so that each C.CString passed
into C.createJString is freed afterwards (use C.free with the unsafe.Pointer of
the C string, e.g., free the result of C.CString(errorResponse) and the
C.CString(response) after calling C.createJString), and ensure any early returns
still free their C strings; refer to createJString, C.CString, C.free,
handleMessageForAndroid, errorResponse and response to locate where to add the
frees.
---
Nitpick comments:
In `@v3/pkg/application/application_android_nocgo.go`:
- Around line 188-192: The non-JSON detection in handleMessageForAndroid
currently checks only message[0] != '{' and returns early; update the code by
adding a clarifying comment above that if-block documenting the known non-JSON
messages (e.g. "wails:runtime:ready") and noting the heuristic’s limitation (it
will treat any non-{ start as non-JSON), so future maintainers understand the
intent; reference handleMessageForAndroid and the androidLogf call so the
comment sits next to that logic.
In `@v3/pkg/application/application_android.go`:
- Around line 640-688: The function handleMessageForAndroid duplicates logic
across builds and also returns unescaped error strings; extract the shared logic
into a single helper (e.g., processAndroidRuntimeMessage(ctx, app, message) or
handleMessageForAndroidCommon) placed in a common Android file (without
differing build tags) and have both application_android.go and
application_android_nocgo.go call it; while refactoring, replace all direct
fmt.Sprintf(`{"error":"%s"}`, err.Error())/raw string returns with proper JSON
construction (e.g., build a struct like type runtimeResp struct{ Error string
`json:"error"`; Success *bool `json:"success,omitempty"` } and json.Marshal it
or json.Marshal(map[string]string{"error": err.Error()})) so errors are
correctly escaped, and keep existing behaviors such as filling WebviewWindowID
and logging via androidLogf and using messageProc.HandleRuntimeCallWithIDs.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
v3/pkg/application/application_android.gov3/pkg/application/application_android_nocgo.gov3/pkg/events/events.go
| androidLogf("error", "🤖 [handleMessageForAndroid] Failed to parse: %v", err) | ||
| return fmt.Sprintf(`{"error":"%s"}`, err.Error()) | ||
| } |
There was a problem hiding this comment.
Error messages aren't JSON-escaped, risking malformed responses.
If err.Error() contains quotes or control characters, the resulting JSON will be invalid. Consider using json.Marshal for the error string to ensure proper escaping.
🔧 Proposed fix using json.Marshal for error strings
if err := json.Unmarshal([]byte(message), &req); err != nil {
androidLogf("error", "🤖 [handleMessageForAndroid] Failed to parse: %v", err)
- return fmt.Sprintf(`{"error":"%s"}`, err.Error())
+ errStr, _ := json.Marshal(err.Error())
+ return fmt.Sprintf(`{"error":%s}`, errStr)
}Apply similar changes to the other error returns at lines 219-221 and 229-231.
Also applies to: 219-221, 229-231
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@v3/pkg/application/application_android_nocgo.go` around lines 196 - 198, The
JSON error strings are built by interpolating err.Error() directly, which can
produce invalid JSON; update the error returns in handleMessageForAndroid (and
the other similar return sites around the current diff) to json.Marshal the
error string and embed the marshaled bytes into the response (e.g. produce
{"error":<marshaledError>}) so quotes and control characters are escaped; if
json.Marshal fails, fall back to a safe literal (or an empty string) and still
log the marshal error via androidLogf — replace the current
fmt.Sprintf(`{"error":"%s"}`, err.Error()) returns with building the response
using the json.Marshal result and keep the existing androidLogf call.
Deploying wails with
|
| Latest commit: |
d9bca83
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://26522eea.wails.pages.dev |
| Branch Preview URL: | https://fix-android-build-and-runtim.wails.pages.dev |
|
@leaanthony would you like this testing? I can pull this branch and try it? |
|
When i pull/clean this branch and then run `` |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
v3/pkg/application/messageprocessor_android.go (1)
58-77: Placeholder implementations noted.The Android-specific runtime functions (
androidHapticsVibrate,androidDeviceInfo,androidShowToast) are currently stubs with TODO comments indicating JNI implementation is pending. This is acceptable for restoring build functionality, but these should be tracked for future implementation.Would you like me to open an issue to track the JNI implementation for these Android runtime functions?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@v3/pkg/application/messageprocessor_android.go` around lines 58 - 77, Create a tracked issue documenting the pending JNI implementations for androidHapticsVibrate, androidDeviceInfo, and androidShowToast (include expected behavior, required JNI surface, and acceptance criteria), then update each TODO comment in those functions to reference the new issue ID/URL so future work is discoverable; ensure the stub behavior remains unchanged so builds stay green.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@v3/pkg/application/messageprocessor_android.go`:
- Around line 58-77: Create a tracked issue documenting the pending JNI
implementations for androidHapticsVibrate, androidDeviceInfo, and
androidShowToast (include expected behavior, required JNI surface, and
acceptance criteria), then update each TODO comment in those functions to
reference the new issue ID/URL so future work is discoverable; ensure the stub
behavior remains unchanged so builds stay green.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 875fbf0a-87bd-407c-90c9-fd41f556dbe0
📒 Files selected for processing (4)
v3/pkg/application/messageprocessor.gov3/pkg/application/messageprocessor_android.gov3/pkg/application/messageprocessor_ios.gov3/pkg/application/messageprocessor_mobile_stub.go
|
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
v3/UNRELEASED_CHANGELOG.md (1)
26-26: Consider expanding the changelog entry to capture the full scope of restored functionality.The current entry accurately describes the build fix (decoupling iOS symbols) but doesn't convey what Android features were actually broken or restored. Based on the PR objectives, this fix also:
- Restores Android event definitions and JavaScript event mappings
- Implements full message routing from JavaScript to Go (enabling functions like Greet to work)
- Adds handling for runtime-ready messages
A more comprehensive entry might help users understand the user-facing impact (e.g., "Android example now builds and runs with working JS↔Go communication") rather than just the technical build fix.
📝 Suggested expansion
-- Fix Android shared-library builds by decoupling mobile runtime logging from iOS-only symbols, allowing Android runtime message handling changes to compile correctly (`#5022`) +- Fix Android shared-library builds and restore runtime functionality: decouples mobile method logging from iOS-only symbols (fixing compilation errors), restores Android event definitions, and implements full MessageProcessor routing for JS↔Go communication (`#5022`)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@v3/UNRELEASED_CHANGELOG.md` at line 26, Update the changelog entry for PR `#5022` in v3/UNRELEASED_CHANGELOG.md to not only mention the decoupling of iOS-only symbols, but also list the restored user-facing Android functionality: restored Android event definitions and JavaScript event mappings, full JS→Go message routing (enabling functions like Greet), and handling of runtime-ready messages so the Android example now builds and runs with working JS↔Go communication; keep the sentence concise and user-focused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@v3/UNRELEASED_CHANGELOG.md`:
- Line 26: Update the changelog entry for PR `#5022` in v3/UNRELEASED_CHANGELOG.md
to not only mention the decoupling of iOS-only symbols, but also list the
restored user-facing Android functionality: restored Android event definitions
and JavaScript event mappings, full JS→Go message routing (enabling functions
like Greet), and handling of runtime-ready messages so the Android example now
builds and runs with working JS↔Go communication; keep the sentence concise and
user-focused.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 510f7ba5-1773-43ad-bcbd-22efd882ffc6
📒 Files selected for processing (1)
v3/UNRELEASED_CHANGELOG.md
Summary
events.Androidstruct and JS event mappings removed fromevents.go(IDs 1259–1270)runtime.Core()innativeOnPageFinishedto match the updated API used by all other platformssetupCommonEvents()in the CGO build path (non-CGO already did this)handleMessageForAndroid()with realMessageProcessorrouting so JS→Go calls workwails:runtime:ready) before attempting JSON parseTest plan
go build ./pkg/events/passesgo vet ./pkg/events/passeswails3 task android:packagewails:runtime:readystring message doesn't cause JSON parse errors in logsFixes #5020
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores