Files
ts-mobile-go/BUILD.md
T
2026-07-20 19:01:03 +08:00

477 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ts-mobile-go 构建指南(新手向)
本文档面向没有 Android 开发经验的同学,手把手教你从零把这个项目跑起来。
---
## 目录
1. [项目是什么](#1-项目是什么)
2. [需要安装哪些软件](#2-需要安装哪些软件)
3. [安装步骤详解](#3-安装步骤详解)
4. [第一次构建(全流程)](#4-第一次构建全流程)
5. [在 IDEA 中打开和运行](#5-在-idea-中打开和运行)
6. [日常开发流程](#6-日常开发流程)
7. [常见问题排查](#7-常见问题排查)
---
## 1. 项目是什么
这是一个 TeamSpeak 客户端的 Android 手机应用,架构分两层:
```
┌─────────────────────────────────────────────┐
│ Android 层(Kotlin + Jetpack Compose
│ 负责:界面显示、用户交互、状态管理 │
├─────────────────────────────────────────────┤
│ Go 层(gomobile 编译成 .aar 库) │
│ 负责:TeamSpeak 协议通信、加密、数据处理 │
└─────────────────────────────────────────────┘
```
**关键概念:**
- **Go** — 一门编程语言,这里用来写 TeamSpeak 的底层通信逻辑
- **gomobile** — Go 官方工具,能把 Go 代码编译成 Android 能用的库文件(`.aar`
- **AAR** — Android ArchiveAndroid 的库文件格式,类似于 Windows 的 `.dll`
- **Gradle** — Android 的构建工具,类似前端的 Webpack/Vite,负责编译、打包、生成 APK
- **APK** — Android Package,安卓手机上安装的应用文件,类似 Windows 的 `.exe`
- **Kotlin** — Android 官方推荐的编程语言(类似 Java,但更现代)
- **Jetpack Compose** — Android 的现代 UI 框架(类似 React/Vue,用代码写界面)
---
## 2. 需要安装哪些软件
| 软件 | 用途 | 必须? |
|---|---|---|
| **Go 1.26+** | 编译 Go 通信层代码 | ✅ 是 |
| **IntelliJ IDEA****Android Studio** | 打开项目、编写代码、运行应用 | ✅ 是 |
| **Android SDK** | Android 开发工具包(IDEA/Android Studio 会自带) | ✅ 是 |
| **JDK 17+** | Java 运行环境,Gradle 构建需要 | ✅ 是 |
| **ADB** | 把 APK 安装到手机上(IDEA 自带) | 手机调试需要 |
**你大概率已经有了:** 如果你电脑上已经装过 IntelliJ IDEA 或 Android StudioJDK 和 Android SDK 应该已经自带了,只需要额外装一个 Go。
---
## 3. 安装步骤详解
### 3.1 安装 Go
1. 打开 https://go.dev/dl/
2. 下载 Windows 的 `.msi` 安装包(选 `go1.26.x.windows-amd64.msi`
3. 双击安装,全部默认下一步即可
4. 安装完成后,**关闭并重新打开** 命令行(CMD 或 PowerShell),验证:
```bash
go version
# 应该输出类似:go version go1.26.0 windows/amd64
```
### 3.2 安装 gomobile
gomobile 是 Go 的官方工具,用来把 Go 代码编译成 Android 能用的 `.aar` 文件。
打开命令行(CMD 或 PowerShell),执行:
```bash
# 1. 安装 gomobile
go install golang.org/x/mobile/cmd/gomobile@latest
# 2. 初始化 gomobile(下载 Android 相关的工具链)
gomobile init
```
验证:
```bash
gomobile version
# 应该输出版本号,没有报错就说明成功了
```
> **如果 `gomobile` 命令找不到:** 说明 Go 的 `bin` 目录没加到系统 PATH。
> 默认路径是 `C:\Users\你的用户名\go\bin`,把它加到系统环境变量 PATH 里,
> 然后重新打开命令行。
### 3.3 安装 IntelliJ IDEA 或 Android Studio
二选一:
- **IntelliJ IDEA**(推荐,你可能已经有了)— 需要 Ultimate 版或安装 Android 插件
- **Android Studio**(免费)— https://developer.android.com/studio
安装时确保勾选了以下组件:
- ✅ Android SDK
- ✅ Android SDK PlatformAPI 26 以上)
- ✅ Android SDK Build-Tools
- ✅ JDK 17+(通常会自动安装)
安装完成后,确认 Android SDK 路径:
- **IDEA**: File → Settings → Languages & Frameworks → Android SDK
- **Android Studio**: 自动配置
记下这个路径(类似 `C:\Users\你的用户名\AppData\Local\Android\Sdk`),后面可能用到。
### 3.4 设置环境变量
打开系统环境变量设置(Win + S 搜索"环境变量"):
| 变量名 | 值 | 说明 |
|---|---|---|
| `ANDROID_HOME` | `C:\Users\你的用户名\AppData\Local\Android\Sdk` | Android SDK 路径 |
| `JAVA_HOME` | `C:\Program Files\JetBrains\IntelliJ IDEA xxx\jbr` | JDK 路径(IDEA 自带的 JBR 即可) |
> **怎么找到 JAVA_HOME**
> 如果你用的是 IntelliJ IDEA,它自带了一个 JDK(叫 JBR)。
> 路径类似:`C:\Program Files\JetBrains\IntelliJ IDEA 2024.3\jbr`
> 在 IDEA 的 File → Project Structure → SDK 里可以看到具体路径。
把以下路径加到系统 `PATH` 变量中:
```
%ANDROID_HOME%\platform-tools
%ANDROID_HOME%\tools
```
---
## 4. 第一次构建(全流程)
### 4.1 理解构建流程
整个构建分两步:
```
第一步:Go 代码 → .aar 文件
go/teamspeak/bridge.go ──(gomobile编译)──> android/app/libs/teamspeak.aar
第二步:Android 代码 + .aar → .apk 文件
android/app/src/**/*.kt + teamspeak.aar ──(Gradle构建)──> app-debug.apk
```
**必须先完成第一步,才能做第二步。** 因为 Android 代码依赖 Go 编译出来的 `.aar` 文件。
### 4.2 一键构建(推荐)
项目根目录下有一个构建脚本,自动完成所有步骤:
**Windows**
```bash
cd E:\MyProject\ts-mobile\ts-mobile-go
build.bat
```
**Linux / macOS**
```bash
cd /path/to/ts-mobile-go
chmod +x build.sh
./build.sh
```
脚本会自动:
1. ✅ 检查 Go、gomobile、Android SDK 是否已安装
2. ✅ 下载 Go 依赖
3. ✅ 编译 Go 代码为 `.aar` 文件
4. ✅ 调用 Gradle 构建 APK
构建成功后,APK 文件在:
```
android/app/build/outputs/apk/debug/app-debug.apk
```
### 4.3 手动构建(了解原理)
如果你想了解每一步在做什么,可以手动执行:
**第一步:编译 Go → AAR**
```bash
# 进入 Go 目录
cd E:\MyProject\ts-mobile\ts-mobile-go\go
# 下载 Go 依赖(类似 npm install
go mod tidy
# 编译为 AAR(这是关键命令)
set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
gomobile bind -target=android -androidapi=26 -ldflags="-linkmode=external -extldflags=-Wl,--hash-style=both" -o ../android/app/libs/teamspeak.aar ./teamspeak
```
命令解释:
- `gomobile bind` — 把 Go 代码编译成 Android 库
- `-target=android` — 目标平台是 Android(自动包含所有架构:arm64、arm、x86、x86_64
- `-androidapi=26` — 最低支持 Android 8.0API 26
- `-ldflags="-linkmode=external -extldflags=-Wl,--hash-style=both"` — **重要!** 两个关键标志:
- `-linkmode=external` — 使用外部链接器(NDK 的 clang),避免 Go 内置链接器与 Android 信号处理冲突导致 SIGSEGV 崩溃
- `-extldflags=-Wl,--hash-style=both` — 强制生成兼容 Android 的 ELF hash 格式
- `-o ../android/app/libs/teamspeak.aar` — 输出文件路径
- `./teamspeak` — 要编译的 Go 包路径
> **为什么要设置 `JAVA_TOOL_OPTIONS`**
> gomobile 内部会调用 `javac`(Java 编译器)来生成 Java 接口代码。
> Windows 下 javac 默认用 GBK 编码,但我们的 Go 源码注释里有中文,是 UTF-8 编码。
> 不设置这个会导致编译报错"非法字符"。
**第二步:构建 Android APK**
```bash
# 进入 Android 目录
cd E:\MyProject\ts-mobile\ts-mobile-go\android
# 构建 debug 版本的 APK
gradlew.bat assembleDebug
```
构建成功后,APK 在 `app\build\outputs\apk\debug\app-debug.apk`。
### 4.4 安装到手机
#### 方法 A:用 ADB 命令安装
1. 手机开启 **USB 调试**
- 进入手机 **设置 → 关于手机**
- 连续点击 **版本号** 7 次,会提示"你已进入开发者模式"
- 返回设置,进入 **开发者选项**
- 打开 **USB 调试**
2. 用 USB 数据线连接手机到电脑
3. 手机上弹出"允许 USB 调试"的提示,点 **允许**
4. 在命令行执行:
```bash
# 查看是否识别到手机
adb devices
# 应该显示类似:
# List of devices attached
# XXXXXXXX device
# 安装 APK
adb install E:\MyProject\ts-mobile\ts-mobile-go\android\app\build\outputs\apk\debug\app-debug.apk
```
5. 安装成功后,手机上找到 "ts-mobile-go" 应用,点击打开即可
#### 方法 B:直接把 APK 传到手机
1. 构建完成后,找到 `app-debug.apk` 文件
2. 通过微信/QQ/邮件/数据线 发送到手机
3. 手机上点击 APK 文件,允许安装未知来源应用,完成安装
---
## 5. 在 IDEA 中打开和运行
### 5.1 打开项目
1. 启动 IntelliJ IDEA
2. **File → Open**
3. 选择 `E:\MyProject\ts-mobile\ts-mobile-go\android\` 目录(注意是 `android` 子目录,不是根目录)
4. 弹出提示框,点击 **Trust Project**
5. 等待右下角进度条走完(Gradle Sync,首次可能需要 2-5 分钟下载依赖)
> **如果提示安装 Android 插件:** 点击安装,然后重启 IDEA。
### 5.2 配置运行设备
#### 使用模拟器(推荐新手)
1. 在 IDEA 中:**Tools → Device Manager**(或工具栏上的手机图标)
2. 点击 **Create Virtual Device**
3. 选择一个手机型号(比如 Pixel 7),点 Next
4. 选择系统镜像:选 **API 34** 或更高版本(需要先点击 Download 下载)
5. 点 Next → Finish
6. 在 Device Manager 中点击 ▶ 启动模拟器
#### 使用真机
1. 手机开启 USB 调试(见 4.4 节)
2. USB 连接电脑
3. IDEA 工具栏的设备下拉框中应该能看到你的手机
### 5.3 运行应用
1. 确保 IDEA 工具栏的设备下拉框中选择了你的手机或模拟器
2. 确保运行配置选择的是 **app**
3. 点击绿色三角 **▶** 按钮(或按 `Shift + F10`
4. IDEA 会自动编译并安装到设备上
> **注意:** 首次运行前,必须先完成 Go → AAR 的编译(第 4.2 或 4.3 节)。
> IDEA 只负责 Android 部分的构建,不会自动编译 Go 代码。
### 5.4 查看运行日志
在 IDEA 底部面板找到 **Logcat** 标签页,可以看到应用的运行日志,方便调试。
---
## 6. 日常开发流程
### 改了 Go 代码(`go/` 目录下的文件)
```bash
# 重新编译 AAR
cd E:\MyProject\ts-mobile\ts-mobile-go\go
set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
gomobile bind -target=android -androidapi=26 -ldflags="-linkmode=external -extldflags=-Wl,--hash-style=both" -o ../android/app/libs/teamspeak.aar ./teamspeak
```
然后在 IDEA 中重新运行应用(点 ▶)即可。IDEA 会自动检测到 `.aar` 文件变化并重新打包。
### 改了 Kotlin 代码(`android/` 目录下的文件)
直接在 IDEA 中点 ▶ 运行,IDEA 会自动增量编译。
### 常用 IDEA 快捷键
| 操作 | 快捷键 |
|---|---|
| 运行 | `Shift + F10` |
| 调试 | `Shift + F9` |
| 全局搜索 | `Shift + Shift` |
| 格式化代码 | `Ctrl + Alt + L` |
| 查看当前文件结构 | `Ctrl + F12` |
---
## 7. 常见问题排查
### Q: Gradle Sync 失败,提示 "Unresolved reference: dependencyResolutionManagement"
**原因:** `settings.gradle.kts` 中的 API 名称写错了。
**解决:** 确认 `android/settings.gradle.kts` 第 9 行是:
```kotlin
dependencyResolutionManagement { // ← 不是 dependencyResolution
```
### Q: gomobile bind 报错 "missing golang.org/x/mobile dependency"
**原因:** Go 模块缺少 `golang.org/x/mobile` 依赖。
**解决:**
```bash
cd E:\MyProject\ts-mobile\ts-mobile-go\go
go get -tool golang.org/x/mobile/cmd/gobind
go mod tidy
```
### Q: gomobile bind 报错 "unknown revision v0.0.0"
**原因:** `go.mod` 中的依赖版本号不存在。
**解决:** 确认 `go/go.mod` 中的版本号是有效的:
```
require github.com/honeybbq/teamspeak-go v0.2.0
```
而不是 `v0.0.0`
### Q: javac 报错 "非法字符" 或 "GBK 不可映射字符"
**原因:** Go 源码中的中文注释在 Windows 下被 javac 当作 GBK 编码处理。
**解决:** 在执行 gomobile 之前设置环境变量:
```bash
set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
```
### Q: gomobile bind 报错 "math.MaxUint32 overflows int"
**原因:** 上游 `teamspeak-go` 库在 32 位目标平台上有整数溢出问题。
**解决:** 这个问题已经通过本地 patch 修复了(见 `go/_patches/` 目录)。如果仍然遇到,可以只编译 64 位版本:
```bash
gomobile bind -target=android/arm64 ...
```
注意是 `android/arm64`,不是 `android`(后者会同时编译 32 位和 64 位)。
### Q: adb devices 显示 "unauthorized"
**原因:** 手机上没有授权这台电脑的 USB 调试。
**解决:** 检查手机屏幕,应该有一个"允许 USB 调试"的弹窗,点击允许。如果没有弹窗,拔掉 USB 重新插入。
### Q: 安装 APK 时提示 "安装包似乎已损坏"
**原因:** 可能是构建过程中出了问题,或者手机架构不匹配。
**解决:**
1. 在 IDEA 中执行 **Build → Clean Project**,然后重新构建
2. 确认手机是 64 位 ARM 架构(2018 年以后的手机基本都是)
### Q: IDEA 提示 "SDK not found" 或 "JAVA_HOME not set"
**解决:**
1. **File → Project Structure → SDKs**,添加 Android SDK 路径
2. **File → Project Structure → Project**,设置 JDK 为 17 或更高
3. 确认系统环境变量中 `ANDROID_HOME``JAVA_HOME` 已正确设置
### Q: 应用安装后打开闪退,Logcat 显示 "dlopen failed: empty/missing DT_HASH/DT_GNU_HASH"
**原因:** Go 1.24+ 编译器生成的 .so 文件使用了 Android 链接器不认识的新 hash 格式(`DT_SUNW_HASH`)。Android 需要传统的 `DT_HASH``DT_GNU_HASH` 格式。
**解决:** 重新编译 AAR 时加上 `-ldflags` 标志(构建脚本已包含):
```bash
cd E:\MyProject\ts-mobile\ts-mobile-go\go
set JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8
gomobile bind -target=android -androidapi=26 -ldflags="-linkmode=external -extldflags=-Wl,--hash-style=both" -o ../android/app/libs/teamspeak.aar ./teamspeak
```
然后重新构建 APK 并安装。
### Q: 应用启动后几秒闪退,Logcat 显示 "Fatal signal 11 (SIGSEGV), code 2 (SEGV_ACCERR)"
**原因:** Go 运行时的信号处理与 Android 内存保护机制冲突。Go 使用 SIGSEGV 做垃圾回收和协程调度,但 Android 的 SEGV_ACCERR 策略会阻止这种用法。
**解决:** 重新编译 AAR 时加上 `-linkmode=external` 标志(构建脚本已包含):
```bash
gomobile bind ... -ldflags="-linkmode=external -extldflags=-Wl,--hash-style=both" ...
```
`-linkmode=external` 强制 Go 使用 NDK 的外部链接器,避免内置链接器的信号处理冲突。
### Q: 应用安装后打开闪退(其他原因)
**可能原因:** Go 编译的 `.aar` 文件有问题,或者没有 `.aar` 文件。
**排查:**
1. 确认 `android/app/libs/teamspeak.aar` 文件存在且大小不为 0
2. 重新执行 Go 编译步骤
3. 在 IDEA 的 Logcat 中查看崩溃日志
4. 如果看到 `UnsatisfiedLinkError`,说明 .aar 中的 .so 文件架构不匹配或格式有问题
---
## 附录:项目目录结构说明
```
ts-mobile-go/
├── go/ ← Go 源码(底层通信)
│ ├── go.mod ← Go 的依赖声明(类似 package.json
│ ├── go.sum ← Go 的依赖锁文件(类似 package-lock.json
│ └── teamspeak/
│ └── bridge.go ← 核心:TeamSpeak 客户端桥接代码
├── android/ ← Android 项目(IDEA 打开这个目录)
│ ├── build.gradle.kts ← 根级构建配置(定义 Kotlin、AGP 版本)
│ ├── settings.gradle.kts ← 项目设置(仓库地址、模块声明)
│ ├── gradle.properties ← Gradle 参数(内存、编码等)
│ ├── gradle/wrapper/ ← Gradle 版本管理(自动下载指定版本的 Gradle)
│ └── app/
│ ├── build.gradle.kts ← 应用级构建配置(依赖、SDK 版本、签名等)
│ ├── libs/
│ │ └── teamspeak.aar ← ← ← Go 编译产物,放在这里!
│ ├── proguard-rules.pro ← 代码混淆规则
│ └── src/main/
│ ├── AndroidManifest.xml ← 应用声明(权限、入口 Activity 等)
│ └── java/com/tsmobile/app/
│ ├── MainActivity.kt ← 应用入口
│ ├── TSBridge.kt ← Kotlin 调用 Go 的桥接层
│ ├── ui/
│ │ ├── components/ ← 可复用 UI 组件
│ │ ├── screens/ ← 各页面(连接、频道、聊天等)
│ │ ├── navigation/ ← 页面路由
│ │ └── theme/ ← 主题颜色、字体
│ └── viewmodel/ ← 状态管理(ViewModel
├── build.bat ← Windows 一键构建脚本
├── build.sh ← Linux/macOS 一键构建脚本
└── BUILD.md ← 本文件
```