[WEP] Wails v3 Mobile Support (Android)#5500
Conversation
WalkthroughThis PR introduces a formal proposal document for Wails v3 Android support. The proposal outlines a Tri-Bridge architecture combining a Go runtime layer via ChangesWails v3 Android Mobile Architecture Proposal
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes 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)
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.
Actionable comments posted: 7
🧹 Nitpick comments (2)
v3/wep/proposals/wails-mobile/proposal.md (2)
12-31: ⚡ Quick winConsider adding security considerations section.
The proposal's Detailed Design section covers asset serving, WebView hosting, and plugin architecture, but doesn't address security implications such as:
- WebView sandboxing and JavaScript bridge security
- Asset serving origin validation to prevent unauthorized access
- Plugin permission model and privilege escalation risks
- Input validation for JS → Go → Java call chain
Consider adding a "Security Considerations" section to the proposal addressing these concerns, especially since this introduces a new attack surface for mobile applications.
🤖 Prompt for 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. In `@v3/wep/proposals/wails-mobile/proposal.md` around lines 12 - 31, Add a "Security Considerations" section to the proposal that addresses WebView and bridge hardening (e.g., restrict JavaScript bridges and origin checks for Wails.CallGo in wails.js), asset-serving validation when using embed.FS and intercepting URLs (ensure origin/host whitelist for WailsWebViewActivity), EventBus and NativeCallHandler authorization/validation to prevent unauthorized event injection, and a plugin permission model with least-privilege rules and input validation for the JS→Go→Java call chain (validate and sanitize arguments before invoking native plugins).
65-66: 💤 Low valueConsider project sustainability with single maintainer.
The maintenance plan identifies a single maintainer (
@its-ernest) for the Android implementation. For a critical feature like mobile support, consider:
- Identifying a co-maintainer or backup maintainer
- Documenting a knowledge transfer plan
- Establishing a succession plan if the primary maintainer becomes unavailable
This helps ensure long-term sustainability of the Android mobile support.
🤖 Prompt for 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. In `@v3/wep/proposals/wails-mobile/proposal.md` around lines 65 - 66, Update the "Maintenance Plan" section to address single-maintainer risk: add a co-maintainer or designated backup (name or role), outline a concise knowledge transfer plan (documentation, walkthroughs, and handoff checklist) and include a succession plan describing how responsibility will be transferred if the primary maintainer (`@its-ernest`) becomes unavailable; make these additions under the existing "Maintenance Plan" heading and reference following Wails v3 coding standards and documentation responsibilities.
🤖 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/wep/proposals/wails-mobile/proposal.md`:
- Around line 30-31: The proposal currently names the frontend bridge API as
Wails.CallGo(method, ...args) but the runtime actually exposes
window.wails.invoke(msg); update the proposal to reconcile these: either (A)
explicitly state that Wails.CallGo is a higher-level wrapper implemented on top
of window.wails.invoke (describe mapping: Wails.CallGo serializes method+args
into the invoke message and forwards to window.wails.invoke), or (B) replace all
references to Wails.CallGo with the concrete runtime API window.wails.invoke and
document the required message shape and helper patterns; reference the symbols
Wails.CallGo and window.wails.invoke so readers can find the implementation
and/or wrapper code.
- Around line 40-41: Clarify the toolchain paragraph to accurately state that
using -buildmode=c-shared requires CGO and gomobile for cross-compiling Go into
Android artifacts but does not necessarily require the full Android NDK/Android
Studio for all workflows (explain when the NDK is only needed, e.g., for native
C/C++ code or custom toolchains), and add a one-line introduction of the wailsm
CLI (e.g., "wailsm: a CLI helper that automates gomobile setup and AAR
generation") so readers understand it automates gomobile and Android packaging;
update the sentence that currently reads "Requires Android SDK/NDK" to mention
CGO/-buildmode=c-shared and conditional NDK need, and insert the wailsm
description next to the gomobile mention.
- Line 6: The markdown heading "Summary" is using an h3 ("### Summary") which
skips h2 after the document title; change the heading marker for the "Summary"
heading to h2 by replacing "### Summary" with "## Summary" in the proposal.md so
the heading hierarchy is correct.
- Line 4: Update the proposal creation date line that currently reads
"**Created:** 2026-05-26" to a date that matches or predates the PR creation
date (e.g., "2026-05-23"); locate the literal string "**Created:** 2026-05-26"
in proposal.md and replace it with the corrected date.
- Around line 15-18: The proposal's mention that EventBus "supports polling from
the native side to push events to JavaScript" is ambiguous against the "Battery
Efficiency First" principle; update the proposal to explicitly state whether
EventBus uses continuous polling or an event-driven low-wakeup model and, if
polling is used, add a mitigation strategy: implement batching/coalescing,
adaptive intervals with exponential backoff, idle-disablement and explicit wake
triggers, and a max-poll frequency cap; edit the EventBus section (EventBus) to
document the exact behavior, the algorithms/parameters for backoff and batching,
and a short justification cross-referencing the Android battery-efficiency
guideline so reviewers can verify it meets the principle.
- Around line 25-28: The Plugin Architecture section is inaccurate: update the
text to reflect that v3 uses a thin Java-to-Go JNI bridge rather than Java-side
feature plugins by default—mention the exact JS→Java→Go call chain
(WailsJSBridge.invoke → WailsBridge.handleMessage → nativeHandleMessage) and
asset handling via nativeServeAsset, and reference the JNI exports implemented
in v3/pkg/application/application_android.go and the JS/Java wiring in
v3/examples/android/.../WailsJSBridge, WailsBridge, MainActivity; alternatively,
if you intend a Java plugin layer, add concrete references showing where Java
plugins are defined/registered and how Go dispatches to them (file/class names
and dispatch functions) so the proposal matches the v3 reference implementation.
- Around line 20-23: Update the proposal to use the exact domain used by the
Android implementation: change any occurrences of "https://wails.local" to
"https://wails.localhost/" and note that
WebViewAssetLoader.Builder#setDomain("wails.localhost") and the base URL
construction must match; explicitly state that assets are served in-process via
WebViewAssetLoader/PathHandler for requests to https://wails.localhost/*
(same-origin, no external network) and that WailsWebViewActivity should
intercept only those requests while any request that falls through must be
treated as potential DNS/TLS/network exposure; keep the NativeCallHandler
description but add this security clarification.
---
Nitpick comments:
In `@v3/wep/proposals/wails-mobile/proposal.md`:
- Around line 12-31: Add a "Security Considerations" section to the proposal
that addresses WebView and bridge hardening (e.g., restrict JavaScript bridges
and origin checks for Wails.CallGo in wails.js), asset-serving validation when
using embed.FS and intercepting URLs (ensure origin/host whitelist for
WailsWebViewActivity), EventBus and NativeCallHandler authorization/validation
to prevent unauthorized event injection, and a plugin permission model with
least-privilege rules and input validation for the JS→Go→Java call chain
(validate and sanitize arguments before invoking native plugins).
- Around line 65-66: Update the "Maintenance Plan" section to address
single-maintainer risk: add a co-maintainer or designated backup (name or role),
outline a concise knowledge transfer plan (documentation, walkthroughs, and
handoff checklist) and include a succession plan describing how responsibility
will be transferred if the primary maintainer (`@its-ernest`) becomes unavailable;
make these additions under the existing "Maintenance Plan" heading and reference
following Wails v3 coding standards and documentation responsibilities.
🪄 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
Run ID: 737f2ac7-9a04-4c90-b88d-1419bc05cdfd
📒 Files selected for processing (1)
v3/wep/proposals/wails-mobile/proposal.md
| # WEP: Wails v3 Mobile Support (Android) | ||
|
|
||
| **Author:** Ernest ([@its-ernest](https://github.com/its-ernest)) | ||
| **Created:** 2026-05-26 |
There was a problem hiding this comment.
Correct the proposal creation date.
The document shows a creation date of "2026-05-26", but the PR was created on "2026-05-23". The proposal date should match or predate the PR creation date.
📅 Proposed fix
-**Created:** 2026-05-26
+**Created:** 2026-05-23📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| **Created:** 2026-05-26 | |
| **Created:** 2026-05-23 |
🤖 Prompt for 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.
In `@v3/wep/proposals/wails-mobile/proposal.md` at line 4, Update the proposal
creation date line that currently reads "**Created:** 2026-05-26" to a date that
matches or predates the PR creation date (e.g., "2026-05-23"); locate the
literal string "**Created:** 2026-05-26" in proposal.md and replace it with the
corrected date.
| **Author:** Ernest ([@its-ernest](https://github.com/its-ernest)) | ||
| **Created:** 2026-05-26 | ||
|
|
||
| ### Summary |
There was a problem hiding this comment.
Fix markdown heading level.
The heading level jumps from h1 (line 1) to h3 (line 6), skipping h2. Use ## Summary instead of ### Summary to maintain proper heading hierarchy.
📝 Proposed fix
-### Summary
+## Summary📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ### Summary | |
| ## Summary |
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)
[warning] 6-6: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3
(MD001, heading-increment)
🤖 Prompt for 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.
In `@v3/wep/proposals/wails-mobile/proposal.md` at line 6, The markdown heading
"Summary" is using an h3 ("### Summary") which skips h2 after the document
title; change the heading marker for the "Summary" heading to h2 by replacing
"### Summary" with "## Summary" in the proposal.md so the heading hierarchy is
correct.
| 1. **Core Go Runtime (Mobile Core):** | ||
| * A mobile-compatible subset of the Wails v3 runtime. | ||
| * Uses `gomobile bind` to generate an AAR for Android. | ||
| * Implements an `EventBus` that supports polling from the native side to push events to JavaScript. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for EventBus implementation patterns in the codebase to verify the polling design
rg -n --type=go -C3 'EventBus|polling' --glob '!vendor/**'Repository: wailsapp/wails
Length of output: 1655
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Show the proposal lines in question
echo "---- proposal.md (around lines 10-25) ----"
nl -ba v3/wep/proposals/wails-mobile/proposal.md | sed -n '10,30p'
# 2) Show the battery efficiency principle line
echo "---- ANDROID_ARCHITECTURE.md (around lines 20-45) ----"
nl -ba v3/ANDROID_ARCHITECTURE.md | sed -n '20,45p'
# 3) Search for EventBus / polling usage beyond Go-only
echo "---- repo search for EventBus ----"
rg -n --glob '!vendor/**' --glob '!**/node_modules/**' 'EventBus' .
echo "---- repo search for polling (md/go) ----"
rg -n --glob '!vendor/**' --glob '!**/node_modules/**' 'polling' .Repository: wailsapp/wails
Length of output: 162
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- proposal.md (lines 12-22) ----"
awk 'NR>=12 && NR<=22 {printf "%d:%s\n", NR, $0}' v3/wep/proposals/wails-mobile/proposal.md || true
echo "---- ANDROID_ARCHITECTURE.md (lines 25-40) ----"
awk 'NR>=25 && NR<=40 {printf "%d:%s\n", NR, $0}' v3/ANDROID_ARCHITECTURE.md || true
echo "---- repo search for EventBus (any filetype) ----"
rg -n --glob '!vendor/**' --glob '!**/node_modules/**' 'EventBus' .
echo "---- repo search for polling word (any filetype) ----"
rg -n --glob '!vendor/**' --glob '!**/node_modules/**' 'polling' .Repository: wailsapp/wails
Length of output: 11971
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- proposal.md (lines 14-25, more context) ----"
awk 'NR>=14 && NR<=28 {printf "%d:%s\n", NR, $0}' v3/wep/proposals/wails-mobile/proposal.md
echo "---- docs architecture EventBus section (guides/architecture.mdx) ----"
awk 'NR>=60 && NR<=130 {printf "%d:%s\n", NR, $0}' docs/src/content/docs/guides/architecture.mdx
echo "---- docs architecture concept diagram context (concepts/architecture.mdx, EN not searched) ----"
# show a small window around the first EventBus diagram occurrence in zh-cn file as representative
awk 'NR>=190 && NR<=270 {printf "%d:%s\n", NR, $0}' docs/src/content/docs/zh-cn/concepts/architecture.mdx | head -n 120Repository: wailsapp/wails
Length of output: 4403
Clarify/justify native-side “polling” EventBus vs the battery-efficiency principle
The proposal says it “implements an EventBus that supports polling from the native side to push events to JavaScript” (v3/wep/proposals/wails-mobile/proposal.md:15-18), but the Android design principle is “Battery Efficiency First” (v3/ANDROID_ARCHITECTURE.md:31). Clarify whether this is continuous polling or an event-driven/low-wakeup approach (e.g., batching, adaptive intervals/backoff, coalescing, and disabling when idle); if true polling is required, document the mitigation strategy to avoid battery drain.
🤖 Prompt for 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.
In `@v3/wep/proposals/wails-mobile/proposal.md` around lines 15 - 18, The
proposal's mention that EventBus "supports polling from the native side to push
events to JavaScript" is ambiguous against the "Battery Efficiency First"
principle; update the proposal to explicitly state whether EventBus uses
continuous polling or an event-driven low-wakeup model and, if polling is used,
add a mitigation strategy: implement batching/coalescing, adaptive intervals
with exponential backoff, idle-disablement and explicit wake triggers, and a
max-poll frequency cap; edit the EventBus section (EventBus) to document the
exact behavior, the algorithms/parameters for backoff and batching, and a short
justification cross-referencing the Android battery-efficiency guideline so
reviewers can verify it meets the principle.
| 2. **Native Container (Android/Java):** | ||
| * A custom `Activity` (e.g., `WailsWebViewActivity`) that hosts the `WebView`. | ||
| * Intercepts URL requests (e.g., `https://wails.local`) to serve assets directly from Go's `embed.FS`. | ||
| * Implements a `NativeCallHandler` interface to receive and route calls from Go. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for WebViewAssetLoader and URL scheme patterns in existing Android implementation
rg -n --type=java -C5 'WebViewAssetLoader|wails\.local|setWebViewClient' --glob '**/android/**'
rg -n --type=kotlin -C5 'WebViewAssetLoader|wails\.local|setWebViewClient' --glob '**/android/**'Repository: wailsapp/wails
Length of output: 41272
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the exact proposal section in question
sed -n '1,60p' v3/wep/proposals/wails-mobile/proposal.md | sed -n '15,35p' || true
sed -n '15,30p' v3/wep/proposals/wails-mobile/proposal.md
# Check what the repo actually uses for the “local” domain
rg -n "wails\.local(\b|/)|wails\.localhost" v3 | head -n 50 || true
rg -n "WebViewAssetLoader\.Builder\(\)|setDomain\(|setScheme\(" v3 | head -n 50 || true
# Look for embed.FS mention near Android asset serving
rg -n "embed\.FS" v3 | head -n 50 || trueRepository: wailsapp/wails
Length of output: 8289
🌐 Web query:
Android WebViewAssetLoader https local domain setDomain best practices certificate/TLS needed
💡 Result:
Best-practice answer (AndroidX WebViewAssetLoader local “web origin” for assets): 1) Prefer the default domain/origin - WebViewAssetLoader is meant to serve app local files/resources using http(s):// URLs (not file://), because that keeps behavior compatible with the Same-Origin policy [1][2]. - It uses the reserved default domain appassets.androidplatform.net unless you override it [1][2]. That default domain is described as an unused domain reserved for Android applications to intercept requests for app assets [1][2]. 2) If you setDomain(...), use a domain you control - If you use custom http(s) origins, the docs warn this can “conflict with a real website”, so local files should be hosted only on domains your organization owns (at paths reserved for this purpose) or on the default reserved domain [1][2]. - Therefore: use setDomain with a hostname you own and that you use exclusively for your app’s local asset origin (so same-origin behavior matches your loaded HTML/app), rather than a random existing public hostname [1][2]. 3) Certificate/TLS needed for the setDomain hostname? - WebViewAssetLoader generates http(s):// URLs for local resources [1][2]. Android’s HTTPS/TLS behavior involves certificate/hostname validation (and untrusted/self-signed certs can fail unless you explicitly trust them) [3]. - The WebViewAssetLoader documentation does not specifically say “install a custom certificate for your custom setDomain” or provide a built-in certificate mechanism for the custom hostname; it mainly specifies origin/domain selection and Same-Origin compatibility [1][2]. - Practical guidance consistent with the docs and Android TLS validation: - Safest option: stick with the default reserved domain (so you don’t have to manage certificate trust for an arbitrary new hostname) [1][2]. - If you must use a custom domain: ensure the HTTPS certificate chain/hostname validation will succeed under that domain using normal Android/WebView trust rules (i.e., avoid relying on self-signed/untrusted certs) [3]. 4) Where it should be wired - WebViewAssetLoader is expected to be used within WebViewClient.shouldInterceptRequest(...) [1][2]. That callback runs off the UI thread, so keep it thread-safe and avoid UI/private view-system access there [1][2]. Bottom line - Best practice: don’t invent a new local hostname; use WebViewAssetLoader’s default domain appassets.androidplatform.net, and load your page using the corresponding https://appassets.androidplatform.net/... URLs [1][2]. - If you do use setDomain: only use domains you own, and make sure HTTPS/TLS is valid for that hostname under normal Android trust/verification behavior [1][2][3].
Citations:
- 1: https://developer.android.com/reference/kotlin/androidx/webkit/WebViewAssetLoader
- 2: https://developer.android.google.cn/reference/androidx/webkit/WebViewAssetLoader
- 3: https://developer.android.com/privacy-and-security/security-ssl
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the exact proposal lines again (for accuracy)
nl -ba v3/wep/proposals/wails-mobile/proposal.md | sed -n '15,35p'
# Inspect Android asset server comment / URL construction
nl -ba v3/internal/assetserver/assetserver_android.go | sed -n '1,120p'
# Inspect ANDROID_ARCHITECTURE.md sections that mention URL scheme/domain + same-origin/security
rg -n "wails\.localhost|WebViewAssetLoader|Same-origin policy|Interc(ept|eption)|TLS|certificate" v3/ANDROID_ARCHITECTURE.md
rg -n "Same-origin policy" -n v3/ANDROID_ARCHITECTURE.md
nl -ba v3/ANDROID_ARCHITECTURE.md | sed -n '650,820p'
# Inspect Go-side base URL/host usage for Android
nl -ba v3/pkg/application/application_android.go | sed -n '520,620p'Repository: wailsapp/wails
Length of output: 101
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== proposal.md (lines 15-30) ==="
cat -n v3/wep/proposals/wails-mobile/proposal.md | sed -n '15,35p'
echo "=== assetserver_android.go (1-120) ==="
cat -n v3/internal/assetserver/assetserver_android.go | sed -n '1,140p'
echo "=== ANDROID_ARCHITECTURE.md security/url parts (50 lines around matches) ==="
rg -n "wails\.localhost|appassets\.androidplatform\.net|WebViewAssetLoader|Same-origin policy|TLS|certificate" v3/ANDROID_ARCHITECTURE.md || true
# show relevant sections (best-effort)
for r in 90 140 280 420 670 690 770 780 930 950; do
echo "=== ANDROID_ARCHITECTURE.md around $r ==="
cat -n v3/ANDROID_ARCHITECTURE.md | sed -n "$r,$((r+40))p"
done
echo "=== application_android.go base URL (520-620) ==="
cat -n v3/pkg/application/application_android.go | sed -n '520,620p'
echo "=== MainActivity.java where WebViewAssetLoader is built (if present in internal build_assets) ==="
cat -n v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java | sed -n '1,130p'Repository: wailsapp/wails
Length of output: 28835
🌐 Web query:
WebViewAssetLoader setDomain custom domain https certificate TLS requirements appassets.androidplatform.net
💡 Result:
Using WebViewAssetLoader with a custom domain means the WebView will request your local app assets over http(s):///… (the domain is configured via setDomain). By default, WebViewAssetLoader uses the reserved domain appassets.androidplatform.net for intercepting app assets [1][2]. 1) Domain / HTTPS expectations - appassets.androidplatform.net: Android’s default reserved domain is intended to be used over http(s)://appassets.androidplatform.net/assets/... [1]. - If you call setDomain("example.com"), that host name is the origin the WebView will use for intercepted asset requests [1]. Your HTTPS/TLS is therefore the standard HTTPS requirement for that host: the server certificate must be valid for the exact hostname the WebView connects to (hostname/SAN match) and chain trust must succeed. If you serve your custom domain over HTTPS with a mismatched or untrusted certificate, WebView/Chrome will fail the connection during TLS validation (typical hostname/certificate errors) [3][4]. 2) Do you need to “install a certificate for setDomain”? - For the built-in default domain (appassets.androidplatform.net), you generally do not manage a custom TLS certificate yourself; the domain is reserved for Android’s app-asset interception and is used as the default [1][2]. - For a custom domain, you still typically do not need to run an origin server for the assets themselves because WebViewAssetLoader intercepts those requests. However, the custom domain still participates in origin/URL handling and HTTPS validation semantics as a normal host: you must ensure whatever scheme you use (HTTP or HTTPS) is allowed and that certificates/hostname verification behavior are compatible. 3) HTTP vs HTTPS policy knob (re: setHttpAllowed) - WebViewAssetLoader.Builder has setHttpAllowed(boolean) “Allow using the HTTP scheme in addition to HTTPS. The default is to not allow HTTP.” [2]. So: - If you rely on HTTPS, keep the default (do not enable HTTP unless you intentionally need it). - If you enable HTTP (setHttpAllowed(true)), your app must also allow cleartext/HTTP networking for that host via Android network security settings; otherwise WebView may block it. 4) Practical example - Custom domain usage is explicitly documented like this: setDomain("example.com") and then addPathHandler("/assets/",...), and load URLs under that domain (e.g., https://example.com/assets/…) [5]. Answer to your specific phrase “setDomain custom domain … certificate TLS requirements” - No special “WebViewAssetLoader-specific certificate file” exists for setDomain. The TLS requirement is the same as HTTPS for any hostname: the certificate presented must be trusted and valid for the hostname (SAN/hostname match) [3][4]. - If you keep HTTPS and your custom domain is consistent with your URL/origin, WebView will behave as expected; if you attempt to use HTTP without enabling it (setHttpAllowed) and/or without cleartext being permitted, requests can fail [2]. If you tell me whether you are (a) using the reserved default domain or a fully custom host, and (b) whether you’re loading assets over https:// or http://, I can give a more exact checklist (certificate/SAN vs cleartext policy) for your case.
Citations:
- 1: https://developer.android.com/reference/kotlin/androidx/webkit/WebViewAssetLoader
- 2: https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader.Builder
- 3: https://dev.to/devhelm/what-ssl-error-means-and-how-to-fix-it-1joi
- 4: https://auth0.com/blog/using-https-in-your-development-environment/
- 5: https://developer.android.com/develop/ui/views/layout/webapps/load-local-content
Update the proposed asset-serving URL to match the WebViewAssetLoader domain (and clarify the interception/security model).
- The proposal example uses
https://wails.local, but the Android design/implementation useshttps://wails.localhost/(WebViewAssetLoader.Builder#setDomain("wails.localhost"), and base URL construction). - Security clarification should emphasize that assets are served via
WebViewAssetLoader/PathHandlerfor requests tohttps://wails.localhost/*(same-origin / in-process, no external network), so any request that falls through should be treated as potential DNS/TLS/network exposure.
🤖 Prompt for 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.
In `@v3/wep/proposals/wails-mobile/proposal.md` around lines 20 - 23, Update the
proposal to use the exact domain used by the Android implementation: change any
occurrences of "https://wails.local" to "https://wails.localhost/" and note that
WebViewAssetLoader.Builder#setDomain("wails.localhost") and the base URL
construction must match; explicitly state that assets are served in-process via
WebViewAssetLoader/PathHandler for requests to https://wails.localhost/*
(same-origin, no external network) and that WailsWebViewActivity should
intercept only those requests while any request that falls through must be
treated as potential DNS/TLS/network exposure; keep the NativeCallHandler
description but add this security clarification.
| 3. **Plugin Architecture:** | ||
| * Native features (Camera, Permissions, Biometrics) are implemented as "Plugins" in Java. | ||
| * Go orchestrates these plugins. JS calls Go -> Go calls Native Plugin -> Result returns to Go -> Go returns to JS. | ||
| * This ensures business logic stays in Go, while platform-specific UI or hardware logic stays in Java. |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for existing plugin or service patterns in v3 Android implementation
rg -n --type=go -C5 'Plugin|Service.*Bind|RegisterService' v3/pkg/application/
rg -n --type=go -C3 'type.*Plugin.*interface' v3/Repository: wailsapp/wails
Length of output: 14075
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Inspect the referenced Android application implementation file (if present)
ls -la v3/pkg/application/ || true
if [ -f v3/pkg/application/application_android.go ]; then
echo "---- application_android.go (head) ----"
sed -n '1,200p' v3/pkg/application/application_android.go
echo "---- application_android.go (tail) ----"
sed -n '200,420p' v3/pkg/application/application_android.go
else
echo "application_android.go not found at v3/pkg/application/application_android.go"
fi
# 2) Look for any "plugin" concept (Java/plugins/JNI/bridge) in v3
echo "---- rg for plugin(s) in repo (v3) ----"
rg -n --hidden --glob '!**/node_modules/**' -t go -i 'plugin|plugins' v3/ || true
rg -n --hidden --glob '!**/node_modules/**' -t java -i 'plugin|plugins' v3/ || true
rg -n --hidden --glob '!**/node_modules/**' -t kt -i 'plugin|plugins' v3/ || true
# 3) Check for Android/JNI/WebView bridge keywords that would indicate a different extension mechanism
echo "---- rg for JNI/WebView/bridge in repo (v3) ----"
rg -n --hidden -i -t java -e 'JNI|native|System\.loadLibrary|WebView' v3/ || true
rg -n --hidden -i -t go -e 'jni|JNICALL|JNIEXPORT' v3/ || trueRepository: wailsapp/wails
Length of output: 50415
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Android reference Java bridge code (built assets + example)
BRIDGE_FILES=(
"v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsBridge.java"
"v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsJSBridge.java"
"v3/examples/android/build/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/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsJSBridge.java"
"v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java"
)
for f in "${BRIDGE_FILES[@]}"; do
if [ -f "$f" ]; then
echo "===== $f (relevant excerpt) ====="
# Print a compact excerpt: class header + native methods + key call sites
sed -n '1,220p' "$f" | nl -ba | sed -n '1,220p'
echo
fi
done
# Go-side: find the JNI-exported functions and where messages/assets are handled.
echo "===== Go JNI exports (android) ====="
rg -n --type=go "export Java_com_wails_app_WailsBridge_nativeInit|nativeHandleMessage|nativeServeAsset|nativeGetAssetMimeType" v3/pkg/application/application_android.go
echo "===== Go message handling/service binding (v3) ====="
# Keep these small and targeted
rg -n --type=go -S "HandleMessage|ServeAsset|GetAssetMimeType|messageprocessor|RegisterService\\(" v3/pkg/application/ | head -n 80Repository: wailsapp/wails
Length of output: 234
🏁 Script executed:
#!/bin/bash
set -euo pipefail
print_file_excerpt () {
f="$1"
echo "===== $f ====="
# show first ~220 lines if file small enough, otherwise show top+tail sections
lines=$(wc -l < "$f")
if [ "$lines" -le 240 ]; then
sed -n '1,240p' "$f"
else
sed -n '1,140p' "$f"
echo "..."
sed -n "$((lines-80)),$((lines))p" "$f"
fi
echo
}
BRIDGE_FILES=(
"v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsBridge.java"
"v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsJSBridge.java"
"v3/examples/android/build/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/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsJSBridge.java"
"v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java"
)
for f in "${BRIDGE_FILES[@]}"; do
if [ -f "$f" ]; then
print_file_excerpt "$f"
else
echo "===== $f (missing) ====="
fi
done
echo "===== Go JNI exports (android) ====="
rg -n --type=go "export Java_com_wails_app_WailsBridge_nativeInit|nativeHandleMessage|nativeServeAsset|nativeGetAssetMimeType" v3/pkg/application/application_android.go
echo "===== Go message handling assets/service binding (v3) ====="
rg -n --type=go "ServeAsset|GetAssetMimeType|HandleMessage|RegisterService\\(" v3/pkg/application | head -n 80Repository: wailsapp/wails
Length of output: 42787
Plugin Architecture description doesn’t match the v3 Android reference flow
The v3 Android reference uses a thin Java bridge to call Go directly via JNI: window.wails.invoke() goes through WailsJSBridge.invoke() → WailsBridge.handleMessage() → nativeHandleMessage (and asset requests go through nativeServeAsset), with JNI exports implemented in v3/pkg/application/application_android.go and the WebView/JS interface wiring in v3/examples/android/build/android/app/src/main/java/com/wails/app/{WailsJSBridge,WailsBridge,MainActivity}.java. I don’t see a “Go orchestrates Java feature plugins” layer in this reference; “plugins” in v3 appears to refer to Go services/modules rather than Java-side plugins.
Update the proposal to reflect the actual v3 bridge/service binding model, or add concrete references for where Java feature plugins are defined/registered and how Go dispatches to them.
🤖 Prompt for 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.
In `@v3/wep/proposals/wails-mobile/proposal.md` around lines 25 - 28, The Plugin
Architecture section is inaccurate: update the text to reflect that v3 uses a
thin Java-to-Go JNI bridge rather than Java-side feature plugins by
default—mention the exact JS→Java→Go call chain (WailsJSBridge.invoke →
WailsBridge.handleMessage → nativeHandleMessage) and asset handling via
nativeServeAsset, and reference the JNI exports implemented in
v3/pkg/application/application_android.go and the JS/Java wiring in
v3/examples/android/.../WailsJSBridge, WailsBridge, MainActivity; alternatively,
if you intend a Java plugin layer, add concrete references showing where Java
plugins are defined/registered and how Go dispatches to them (file/class names
and dispatch functions) so the proposal matches the v3 reference implementation.
| 4. **Frontend Bridge (`wails.js`):** | ||
| * A simplified contract providing `Wails.CallGo(method, ...args)` and `Wails.on(event, callback)`. |
There was a problem hiding this comment.
Reconcile frontend bridge API naming with actual implementation.
The proposal describes Wails.CallGo(method, ...args) as the frontend API, but the existing v3 Android runtime (see context snippet from v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts:30) uses window.wails.invoke(msg) for Android WebView communication. Please clarify:
- Is
Wails.CallGoa proposed higher-level wrapper aroundwindow.wails.invoke? - Or should the proposal document the actual API contract used by the runtime?
Consistent API documentation will help developers understand the integration surface.
🤖 Prompt for 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.
In `@v3/wep/proposals/wails-mobile/proposal.md` around lines 30 - 31, The proposal
currently names the frontend bridge API as Wails.CallGo(method, ...args) but the
runtime actually exposes window.wails.invoke(msg); update the proposal to
reconcile these: either (A) explicitly state that Wails.CallGo is a higher-level
wrapper implemented on top of window.wails.invoke (describe mapping:
Wails.CallGo serializes method+args into the invoke message and forwards to
window.wails.invoke), or (B) replace all references to Wails.CallGo with the
concrete runtime API window.wails.invoke and document the required message shape
and helper patterns; reference the symbols Wails.CallGo and window.wails.invoke
so readers can find the implementation and/or wrapper code.
| **Cons:** | ||
| * **Build Toolchain Complexity:** Requires Android SDK/NDK(Ultimately Android Studio) and `gomobile`(`wailsm` CLI helper exists to automate `gomobile` complexity) |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Clarify build toolchain requirements and introduce wailsm CLI.
Two concerns:
- NDK requirement: The proposal states "Requires Android SDK/NDK" but the existing architecture principle (v3/ANDROID_ARCHITECTURE.md:36) specifies using
-buildmode=c-shared, which typically requires CGO but not the full NDK. Please clarify if NDK is genuinely required or if this overstates the dependencies. - Unexplained
wailsmCLI: This is the first mention ofwailsmin the document without introduction. Consider adding a brief explanation of what it is (e.g., "a CLI helper tool that automatesgomobilesetup and AAR generation").
🤖 Prompt for 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.
In `@v3/wep/proposals/wails-mobile/proposal.md` around lines 40 - 41, Clarify the
toolchain paragraph to accurately state that using -buildmode=c-shared requires
CGO and gomobile for cross-compiling Go into Android artifacts but does not
necessarily require the full Android NDK/Android Studio for all workflows
(explain when the NDK is only needed, e.g., for native C/C++ code or custom
toolchains), and add a one-line introduction of the wailsm CLI (e.g., "wailsm: a
CLI helper that automates gomobile setup and AAR generation") so readers
understand it automates gomobile and Android packaging; update the sentence that
currently reads "Requires Android SDK/NDK" to mention CGO/-buildmode=c-shared
and conditional NDK need, and insert the wailsm description next to the gomobile
mention.
Description
LINK TO REPO: https://github.com/its-ernest/wails-mobile
The
wails-mobileproject already implemented a working prototype of the bridge and plugin system(For third-party Go packages to extend the capabilities for biometircs, camera, other hardware, deep native integrations, without writing a single JNI, just pure Java/Kotlin and Go wrappepr)Summary by CodeRabbit