首页 / Wails 入门教程 / 移动端概览 Mobile

Wails 入门教程

移动端概览 Mobile

本教程共 42 篇 · 第 41 篇 · 更新于 2026-08-03

Wails桌面开发移动端iOSAndroid

41. 移动端概览 Mobile

本节目标

  • 明确 Wails v2.13.0 的平台边界,知道移动端支持归属哪个版本线
  • 了解 v3 实验性移动端的架构:WebView 选型、桥接方式、产物形态
  • 知道 iOS / Android 各自缺哪些能力,判断自己的需求是否踩线
  • 学会把业务代码分层,为将来可能的移动端复用留出空间

41-1 先说结论

如果你打算用本教程的基线版本做手机 App,答案很直接:Wails v2.13.0 不支持移动端。它的目标平台是 Windows、macOS、Linux 三个桌面系统,wails build -platform 能接受的取值里没有 iosandroid

移动端支持出现在 Wails v3 分支,并且官方明确标注为实验性(EXPERIMENTAL):API 和构建流程在正式发布前都可能大改,不建议用在生产环境。

这一章讲的内容,性质更接近「了解一下技术路线」,而不是「跟着做一遍」。之所以要讲,是因为很多人选型时会问「以后能不能顺手出个手机版」,得先知道这个「以后」大概是什么样子。

Warning

本章出现的 application.New(application.Options{...}) 是 Wails v3 的 API,和 v2.13.0 的 wails.Run(&options.App{...}) 完全不同。别混着写,两套 API 不通用。

41-2 移动端的架构长什么样

v3 移动端的思路和桌面端一脉相承:Go 写业务逻辑,Web 技术写界面,系统原生 WebView 负责渲染。区别在中间那层桥怎么搭。

平台WebView 组件桥接技术构建产物
iOSWKWebViewCGO(C 头文件).app / .ipa
AndroidAndroid WebViewJNI.apk

CGO 是 Go 调用 C 代码的机制。iOS 上 Go 代码被编译成静态库(.a 文件),通过 C 头文件暴露给 Objective-C / Swift 侧,再由原生代码托管 WKWebView 并转发消息。

JNI(Java Native Interface)是 Java 调用本地代码的标准接口。Android 上 Go 代码编译成共享库(.so 文件),Java/Kotlin 层通过 JNI 调用它,同时负责 Android WebView 的生命周期。

两条路径的共同点是:Go 不再是主进程,而是被原生宿主加载的一个库。这跟桌面端「Go 主进程拉起 WebView」的模型正好反过来,也解释了为什么很多桌面 API 在移动端没法直接搬。

41-3 环境前置条件

想跑通实验性移动端构建,环境要求比桌面端重得多。

iOS 侧必须有 Mac。 这是苹果工具链的硬性限制,绕不过去:

  • macOS 12.0 及以上
  • Xcode 14.0 及以上
  • Go 1.21+,且启用 CGO
  • iOS SDK(随 Xcode 附带)

Android 侧三大系统都能做。 需要:

  • Go 1.21+,且启用 CGO
  • Android SDK(含 Platform Tools、Build Tools,模拟器可选)
  • Android NDK r26d 或更新版本
  • Java JDK 11+

环境变量按自己的系统配:

# macOS
export ANDROID_HOME="$HOME/Library/Android/sdk"

# Linux
export ANDROID_HOME="$HOME/Android/Sdk"

# NDK 路径按实际安装版本调整
export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/29.0.14206865"

export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/emulator
Tip

装 Android SDK 最省事的方式是直接装 Android Studio,它把 SDK、Build Tools、NDK、模拟器打包装齐。只想要命令行的话,从官网下 command line tools 再用 SDK Manager 补组件。

41-4 构建与运行

v3 移动端的构建没有走 wails build,而是用 Taskfile 组织的任务。iOS 侧:

# 编译
task ios:build

# 编译并在模拟器上跑
task ios:run

# 为真机构建(需要代码签名)
task ios:build:device

背后做的事情是:把 Go 代码编成静态库 → 生成 Xcode 工程 → 调 xcodebuild 构建 → 产出 .app 包(发布时打成 .ipa)。

Android 侧:

# 默认为真机构建 arm64
task android:build

# 为模拟器构建 x86_64
task android:build ARCH=x86_64

# 打包 APK
task android:package

# 安装并运行
task android:run

# 看日志
task android:logs

流程是:Go 代码编成 .so 共享库 → Gradle 构建 Java/Kotlin 层 → 打包成 APK。

架构对应关系需要留意,选错了装到设备上会直接崩:

Android ABI适用场景对应 GOARCH
arm64-v8a现代设备,最常见arm64
x86_64模拟器amd64
armeabi-v7a老设备,可选arm
x86老模拟器,可选386
Note

UnsatisfiedLinkError: dlopen failed 基本就是架构不匹配。真机用 arm64 重编,模拟器用 x86_64 重编。

41-5 平台差异与能力限制

前端可以在运行时判断自己跑在哪个平台上,按平台走不同分支:

const platform = window.wails.System.Platform();

if (platform === "ios") {
  // iOS 专属逻辑
} else if (platform === "android") {
  // Android 专属逻辑
} else {
  // 桌面
}

但更重要的是知道哪些能力没有

iOS 目前缺的:

  • 系统托盘、菜单栏(移动端本来就没这个概念)
  • 多窗口,只有单个全屏窗口
  • 文件对话框,受 iOS 沙箱限制
  • 窗口操作,位置和尺寸都改不了

Android 目前缺的:

  • 系统托盘
  • 多窗口,同样只有单个全屏窗口
  • 文件对话框,得改用 Storage Access Framework
  • 窗口操作,只有全屏
  • 剪贴板只有部分支持

把这份清单对照一下前面几章的内容就会发现:第 19 到 25 章讲的窗口管理、无边框、菜单、托盘、拖放,在移动端几乎全军覆没。第 17 章的对话框也要另找方案。真正能平移的是绑定、事件、剪贴板这些不依赖窗口形态的能力。

平台配置项也是独立的一套:

// 这是 Wails v3 的实验性 API,与 v2.13.0 不兼容
app := application.New(application.Options{
    Name: "My App",
    Android: application.AndroidOptions{
        DisableOverscroll: true,
        EnableZoom:        false,
        UserAgent:         "MyApp/1.0",
        BackgroundColour:  application.NewRGB(255, 255, 255),
    },
})

调试上,Android 的空白 WebView 可以用 Chrome 的 chrome://inspect/#devices 连上去看,配合 task android:logs 查资源加载有没有出错。这套排查思路和第 39 章讲的桌面端白屏排查是相通的。

41-6 现在能为将来做什么

既然移动端还没稳定,与其等,不如把代码写成「以后好搬」的样子。有两条实用建议。

第一,业务逻辑不要直接依赖 Wails 运行时。 把纯计算、数据处理、网络请求这些放进独立的 package,不引用 wails/v2/pkg/runtime。绑定给前端的那层只做参数转换和调用转发:

// service/notes.go —— 纯业务,不含任何 Wails 依赖
package service

type NotesService struct {
    store Store
}

func (s *NotesService) List() ([]Note, error) {
    return s.store.All()
}
// app.go —— 绑定层,只做转发
package main

type App struct {
    ctx   context.Context
    notes *service.NotesService
}

func (a *App) ListNotes() ([]service.Note, error) {
    return a.notes.List()
}

这样即便将来换到 v3 或者移动端,只需要重写薄薄的绑定层。

第二,界面上把窗口相关的交互隔离出来。 自定义标题栏、托盘菜单、多窗口这些逻辑集中在少数几个组件里,不要散落在业务组件中。将来做移动版,把这几个组件换掉就行。

Tip

如果移动端是明确的需求而不是「顺便」,现阶段更稳妥的做法是评估成熟的跨端方案。Wails 的强项在桌面,这一点在可预见的时间内不会变。

常见误区

以为 wails build -platform android 能用。 v2 的平台列表里没有移动端,这条命令只会报错。

把 v3 的示例代码抄进 v2 项目。 application.Newwails.Run 是两套完全不同的入口,混用必然编译失败。

指望桌面代码原样跑在手机上。 光是「没有多窗口、没有托盘、文件对话框受限」这三条,就足以让一个桌面工具类应用大改。

低估环境搭建成本。 NDK、JDK、SDK 版本互相牵制,第一次配通往往比写代码花的时间还多。

小结

Wails 的移动端支持存在,但停留在 v3 的实验阶段,iOS 靠 CGO + WKWebView,Android 靠 JNI + Android WebView,产物分别是 .ipa.apk。当前版本 v2.13.0 专注桌面三平台。做技术选型时按现状判断,别把实验特性当成路线图承诺。真正能提前做的准备只有一件:把业务逻辑和平台能力分层,让代码将来搬得动。下一章收尾,聊聊模板、社区和一个真实项目的结构。