diff --git a/.github/workflows/BUILD_GUIDE.md b/.github/workflows/BUILD_GUIDE.md new file mode 100644 index 0000000..510bc60 --- /dev/null +++ b/.github/workflows/BUILD_GUIDE.md @@ -0,0 +1,311 @@ +# 📖 GitHub Actions 构建完全指南 + +## 🎯 功能概述 + +本 workflow 支持: + +✅ **自动编译 libcore.aar** - sing-box 核心库 +✅ **Release 构建** - 默认生成正式版 APK +✅ **可配置 API 域名** - 支持自定义后端域名 +✅ **可配置 OSS 地址** - 支持自定义配置文件 CDN +✅ **分架构打包** - 生成 arm64-v8a / armeabi-v7a / x86_64 版本 +✅ **自动创建 Release** - 推送标签自动发布 + +--- + +## 🚀 使用方法 + +### 方法一:手动触发(推荐,支持自定义配置) + +1. **打开 Actions 页面** + - 进入 GitHub 仓库 + - 点击顶部 **Actions** 标签 + +2. **选择 Workflow** + - 左侧选择 **Build Android APK** + - 右侧点击 **Run workflow** 下拉框 + +3. **配置参数** + + | 参数 | 说明 | 默认值 | + |-----|------|--------| + | **构建类型** | debug 或 release | `release` | + | **API 域名** | 后端 API 服务器域名 | `api.maodag.top` | + | **OSS 地址 1** | 配置文件 CDN 地址(香港) | `https://ppp2.oss-cn-hongkong.aliyuncs.com/bear1.txt` | + | **OSS 地址 2** | 配置文件 CDN 地址(东京) | `https://xgp3.oss-ap-northeast-1.aliyuncs.com/bear1.txt` | + | **OSS 地址 3** | 配置文件 CDN 地址(首尔) | `https://xpp4.oss-ap-northeast-2.aliyuncs.com/bear1.txt` | + | **OSS 地址 4** | 配置文件 CDN 地址(新加坡) | `https://xpp5.oss-ap-southeast-1.aliyuncs.com/bear1.txt` | + +4. **开始构建** + - 点击绿色 **Run workflow** 按钮 + - 等待约 30 分钟完成 + +5. **下载 APK** + - 构建完成后,在运行记录页面找到 **Artifacts** 区域 + - 下载对应架构的 APK + +--- + +### 方法二:推送代码自动构建(使用默认配置) + +```bash +# 提交代码 +git add . +git commit -m "feat: 新功能" + +# 推送到 main 分支 +git push origin main +``` + +**注意:** 自动触发的构建使用默认配置(`api.maodag.top` 和默认 OSS 地址) + +--- + +### 方法三:创建 Release 版本 + +```bash +# 1. 打标签(必须以 v 开头) +git tag v1.0.0 + +# 2. 推送标签 +git push origin v1.0.0 + +# 3. 自动触发构建并创建 Release +# 访问 https://github.com/你的用户名/LighthouseApp/releases 查看 +``` + +--- + +## 📦 构建产物 + +### APK 命名规则 + +``` +BearVPN-{架构}-{类型}-{日期}-{提交哈希}.apk +``` + +**示例:** +``` +BearVPN-arm64-v8a-release-20251027-abc1234.apk +BearVPN-armeabi-v7a-release-20251027-abc1234.apk +BearVPN-x86_64-release-20251027-abc1234.apk +``` + +### 架构说明 + +| 架构 | 适用设备 | 推荐度 | +|------|---------|-------| +| **arm64-v8a** | 2017年后的现代手机 | ⭐⭐⭐⭐⭐ | +| **armeabi-v7a** | 2012-2017年的老旧手机 | ⭐⭐ | +| **x86_64** | Android 模拟器 | ⭐⭐⭐ | + +**大多数用户应下载 `arm64-v8a` 版本** + +--- + +## 🔧 配置示例 + +### 示例 1:修改 API 域名 + +如果你的后端部署在 `api.example.com`: + +1. 手动触发 workflow +2. 将 **API 域名** 改为 `api.example.com` +3. OSS 地址保持默认 +4. 点击 Run workflow + +### 示例 2:使用自己的 CDN + +如果你有自己的配置文件 CDN: + +1. 手动触发 workflow +2. API 域名保持默认 +3. 修改 **OSS 地址 1-4** 为你的 CDN 地址,例如: + - OSS 地址 1: `https://cdn1.example.com/config.txt` + - OSS 地址 2: `https://cdn2.example.com/config.txt` + - OSS 地址 3: `https://cdn3.example.com/config.txt` + - OSS 地址 4: `https://cdn4.example.com/config.txt` +4. 点击 Run workflow + +### 示例 3:完全自定义配置 + +```yaml +构建类型: release +API 域名: api.mycompany.com +OSS 地址 1: https://config.mycdn.com/v1/nodes.txt +OSS 地址 2: https://backup1.mycdn.com/v1/nodes.txt +OSS 地址 3: https://backup2.mycdn.com/v1/nodes.txt +OSS 地址 4: https://backup3.mycdn.com/v1/nodes.txt +``` + +--- + +## ⏱️ 构建时间 + +| 阶段 | 时间 | +|-----|------| +| 编译 libcore.aar | 10-15 分钟 | +| 编译 Flutter APK | 15-20 分钟 | +| **总计** | **约 30 分钟** | + +--- + +## 🔍 查看构建日志 + +1. 打开 Actions 页面 +2. 点击对应的运行记录 +3. 点击具体的 job(如 "编译 Android APK") +4. 展开步骤查看详细日志 + +**关键步骤:** +- `⚙️ 配置 API 域名和 OSS 地址` - 查看配置是否正确替换 +- `🔨 构建 APK` - 查看编译过程 +- `📦 重命名 APK 文件` - 查看生成的文件名和 MD5 + +--- + +## 🐛 常见问题 + +### Q1: 如何验证配置是否生效? + +**A:** 查看 `⚙️ 配置 API 域名和 OSS 地址` 步骤的日志: + +``` +🔧 配置构建参数: + API 域名: api.example.com + OSS 地址 1: https://cdn1.example.com/config.txt + ... + +✅ 配置替换完成 + +📄 查看修改后的配置: + static List kr_baseDomains = ["api.example.com","api.example.com"]; + static String kr_currentDomain = "api.example.com"; +``` + +如果看到你设置的域名,说明配置成功。 + +--- + +### Q2: Release 构建和 Debug 构建有什么区别? + +| 特性 | Debug | Release | +|-----|-------|---------| +| **文件大小** | 较大 | 较小(优化后) | +| **性能** | 较慢 | 快 | +| **调试信息** | 包含 | 移除 | +| **代码混淆** | 无 | 有 | +| **适用场景** | 开发测试 | 正式发布 | + +**推荐:** 生产环境使用 **release** 构建 + +--- + +### Q3: 如何使用环境变量配置(不想每次手动输入)? + +在仓库 **Settings → Secrets and variables → Actions → Variables** 添加: + +| 变量名 | 值 | +|-------|---| +| `DEFAULT_API_DOMAIN` | `api.example.com` | +| `DEFAULT_OSS_URL_1` | `https://cdn1.example.com/config.txt` | +| `DEFAULT_OSS_URL_2` | `https://cdn2.example.com/config.txt` | +| `DEFAULT_OSS_URL_3` | `https://cdn3.example.com/config.txt` | +| `DEFAULT_OSS_URL_4` | `https://cdn4.example.com/config.txt` | + +然后修改 workflow 文件,将默认值改为: + +```yaml +default: ${{ vars.DEFAULT_API_DOMAIN || 'api.maodag.top' }} +``` + +--- + +### Q4: 构建失败 - "libcore.aar not found" + +**原因:** libcore 编译失败 + +**解决:** +1. 检查 `build-libcore` job 的日志 +2. 确认 Go 环境和 gomobile 安装成功 +3. 确认 libcore 子模块已正确初始化 + +--- + +### Q5: 如何配置签名(Release 构建必需)? + +详见主文档 `.github/workflows/README.md` 的签名配置章节。 + +--- + +## 💡 高级技巧 + +### 技巧 1:同时构建多个版本 + +修改 `build-apk` job: + +```yaml +strategy: + matrix: + build_type: [debug, release] + api_domain: ['api.maodag.top', 'api.example.com'] +``` + +这样会生成 4 个 APK(2种类型 × 2个域名) + +--- + +### 技巧 2:添加构建完成通知 + +在 workflow 最后添加: + +```yaml +- name: 📢 发送 Telegram 通知 + if: success() + run: | + curl -X POST "https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage" \ + -d chat_id=${{ secrets.TELEGRAM_CHAT_ID }} \ + -d text="✅ BearVPN 构建成功!下载: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" +``` + +需要先配置 `TELEGRAM_BOT_TOKEN` 和 `TELEGRAM_CHAT_ID` Secrets。 + +--- + +### 技巧 3:缓存加速构建 + +workflow 已配置 Go 和 Flutter 缓存,首次构建约 30 分钟,后续构建可缩短至 15-20 分钟。 + +--- + +## 📊 构建状态徽章 + +在 README.md 中添加: + +```markdown +![Build Status](https://github.com/你的用户名/LighthouseApp/actions/workflows/build-android-apk.yml/badge.svg) +``` + +效果:![Build Status](https://img.shields.io/badge/build-passing-brightgreen) + +--- + +## 🔗 相关文件 + +- **主 Workflow:** `.github/workflows/build-android-apk.yml` +- **配置文件:** `lib/app/common/app_config.dart` +- **libcore 源码:** `libcore/` 子模块 + +--- + +## 📞 需要帮助? + +- 查看 [GitHub Actions 文档](https://docs.github.com/actions) +- 查看构建日志排查问题 +- 提交 Issue 到仓库 + +--- + +**生成时间:** 2025-10-27 +**作者:** Claude Code +**版本:** 1.0.0 diff --git a/.github/workflows/HOW_TO_BUILD.md b/.github/workflows/HOW_TO_BUILD.md new file mode 100644 index 0000000..0c1e276 --- /dev/null +++ b/.github/workflows/HOW_TO_BUILD.md @@ -0,0 +1,366 @@ +# 🎯 如何在 GitHub 上构建你的应用 + +## 📋 前提条件 + +✅ 已将配置推送到 GitHub +✅ 有 GitHub 账号访问权限 + +--- + +## 🚀 方法一:手动触发构建(推荐新手) + +### 步骤 1: 访问 GitHub Actions 页面 + +1. 打开浏览器,访问你的仓库: + ``` + https://github.com/你的用户名/LighthouseApp + ``` + +2. 点击顶部导航栏的 **Actions** 标签 + ``` + Code Issues Pull requests Actions Projects Wiki Security Insights + ↑ 点这里 + ``` + +--- + +### 步骤 2: 选择 Workflow + +在左侧栏看到可用的 workflows: + +``` +All workflows +├── Build Android APK ← 仅构建 Android +├── Build Multi-Platform ← 构建所有平台 ⭐推荐 +└── Build Clash Core +``` + +**选择建议:** +- 🟢 **首次测试:** 选择 **Build Android APK**(快速) +- 🔵 **正式发布:** 选择 **Build Multi-Platform**(全平台) + +--- + +### 步骤 3: 运行 Workflow + +1. 点击选择的 workflow 名称 + +2. 右侧出现 **"Run workflow"** 下拉按钮 + ``` + [Run workflow ▼] + ``` + +3. 点击下拉按钮,展开配置面板 + +--- + +### 步骤 4: 配置参数 + +#### 如果选择 "Build Android APK": + +```yaml +┌─────────────────────────────────────────┐ +│ Run workflow │ +├─────────────────────────────────────────┤ +│ Use workflow from │ +│ Branch: main [▼] │ +│ │ +│ 构建类型 │ +│ ○ debug │ +│ ● release │ +│ │ +│ API 域名 │ +│ [api.maodag.top________________] │ +│ │ +│ OSS 配置地址 1 │ +│ [https://ppp2.oss-cn-hongkong...] │ +│ │ +│ OSS 配置地址 2 │ +│ [https://xgp3.oss-ap-northeast-1...] │ +│ │ +│ OSS 配置地址 3 │ +│ [https://xpp4.oss-ap-northeast-2...] │ +│ │ +│ OSS 配置地址 4 │ +│ [https://xpp5.oss-ap-southeast-1...] │ +│ │ +│ [Cancel] [Run workflow] │ +└─────────────────────────────────────────┘ +``` + +**配置说明:** +- **构建类型:** 选择 `release`(生产环境) +- **API 域名:** 填写你的后端域名(默认 `api.maodag.top`) +- **OSS 地址:** 保持默认或填写你的 CDN 地址 + +#### 如果选择 "Build Multi-Platform": + +额外多一个参数: +```yaml +│ 构建平台 │ +│ [android,windows,macos,linux______] │ +``` + +**选项:** +- `android` - 仅 Android +- `windows` - 仅 Windows +- `macos` - 仅 macOS +- `linux` - 仅 Linux +- `android,windows` - Android + Windows +- `android,windows,macos,linux` - 全部平台 ⭐ + +--- + +### 步骤 5: 开始构建 + +1. 检查所有参数是否正确 + +2. 点击绿色的 **"Run workflow"** 按钮 + +3. 页面刷新,顶部出现黄色进度条: + ``` + ⚠️ Build Android APK #1 + Queued - This workflow is in queue waiting to run + ``` + +4. 几秒后变为蓝色(运行中): + ``` + 🔵 Build Android APK #1 + In progress - This workflow is currently running + ``` + +--- + +### 步骤 6: 监控构建进度 + +1. 点击运行记录(蓝色行) + +2. 看到构建阶段: + ``` + 编译 libcore.aar 🔵 Running (15分钟) + 编译 Android APK ⏸️ Pending + ``` + +3. 可以展开查看实时日志: + ``` + ▼ 编译 libcore.aar + ▼ 📦 编译 libcore.aar + 🚀 开始编译 libcore... + [gomobile] installing... + ✅ libcore.aar 生成成功 + ``` + +4. 等待所有阶段完成(约 30-85 分钟) + +--- + +### 步骤 7: 下载构建产物 + +构建成功后: + +1. 向下滚动到 **Artifacts** 区域 + ``` + 📦 Artifacts + + Produced during runtime + + Name Size Expires + apk-arm64-v8a-release 42.5 MB in 30 days [Download] + apk-armeabi-v7a-release 38.2 MB in 30 days [Download] + apk-x86_64-release 45.1 MB in 30 days [Download] + ``` + +2. 点击 **[Download]** 下载对应文件 + +3. 下载的是 ZIP 文件,解压后得到 APK: + ``` + apk-arm64-v8a-release.zip + └── BearVPN-android-arm64-v8a-release-20251027-abc1234.apk + ``` + +--- + +## 🏷️ 方法二:推送标签自动构建 + +这种方式会自动构建并创建 GitHub Release。 + +### 步骤 1: 在本地打标签 + +```bash +cd /Users/mac/Project/Dart/LighthouseApp + +# 创建标签(版本号必须以 v 开头) +git tag v1.0.0 + +# 查看标签 +git tag +``` + +--- + +### 步骤 2: 推送标签到 GitHub + +```bash +git push origin v1.0.0 +``` + +**输出:** +``` +Enumerating objects: 1, done. +Counting objects: 100% (1/1), done. +Writing objects: 100% (1/1), 160 bytes | 160.00 KiB/s, done. +Total 1 (delta 0), reused 0 (delta 0) +To github.com:你的用户名/LighthouseApp.git + * [new tag] v1.0.0 -> v1.0.0 +``` + +--- + +### 步骤 3: 自动触发构建 + +1. 推送标签后,GitHub 自动检测到标签 +2. 触发 **Build Multi-Platform** workflow +3. 使用默认配置构建所有平台 + +--- + +### 步骤 4: 查看构建进度 + +1. 访问 Actions 页面 +2. 看到自动创建的构建任务: + ``` + 🔵 Build Multi-Platform + v1.0.0 + ``` + +--- + +### 步骤 5: 下载 Release + +构建成功后: + +1. 访问 **Releases** 页面: + ``` + https://github.com/你的用户名/LighthouseApp/releases + ``` + +2. 看到新创建的 Release: + ``` + 📦 v1.0.0 + + Latest Pre-release + + 🎉 BearVPN 多平台版本发布 + + Assets (7) + ├── BearVPN-android-arm64-v8a-release-*.apk 42.5 MB + ├── BearVPN-android-armeabi-v7a-release-*.apk 38.2 MB + ├── BearVPN-android-x86_64-release-*.apk 45.1 MB + ├── BearVPN-windows-x64-release-*.zip 52.3 MB + ├── BearVPN-macos-release-*.zip 48.7 MB + ├── BearVPN-linux-x64-release-*.tar.gz 45.9 MB + └── Source code (zip) + ``` + +3. 直接下载需要的文件 + +--- + +## ⏱️ 构建时间参考 + +| Workflow | 平台 | 时间 | +|---------|------|------| +| Build Android APK | Android | 30 分钟 | +| Build Multi-Platform | Android | 35 分钟 | +| Build Multi-Platform | Windows | 30 分钟 | +| Build Multi-Platform | macOS | 35 分钟 | +| Build Multi-Platform | Linux | 30 分钟 | +| Build Multi-Platform | 全部平台 | **60-85 分钟** | + +**提示:** 平台是并行构建的,不是累加时间。 + +--- + +## 🎯 推荐流程 + +### 首次测试(验证流程) + +``` +1. 选择 "Build Android APK" +2. 使用默认配置 +3. 运行构建 +4. 等待 30 分钟 +5. 下载 arm64-v8a APK +6. 安装测试 +``` + +### 正式发布(生产环境) + +``` +1. 确保代码已测试 +2. 本地打标签: git tag v1.0.0 +3. 推送标签: git push origin v1.0.0 +4. 等待 60-85 分钟 +5. 在 Releases 页面下载所有平台 +6. 分发给用户 +``` + +--- + +## 🐛 常见问题 + +### Q1: 找不到 "Run workflow" 按钮 + +**原因:** 可能还在查看历史运行记录 + +**解决:** +1. 点击左侧的 workflow 名称 +2. 确保在 workflow 主页面 +3. 右侧会出现 "Run workflow" 按钮 + +--- + +### Q2: 构建失败 + +**排查步骤:** +1. 点击失败的运行记录 +2. 展开红色的步骤 +3. 查看错误日志 +4. 常见错误: + - libcore 编译失败 → 检查 Go 环境 + - APK 构建失败 → 检查 Flutter 依赖 + +--- + +### Q3: Artifacts 下载后是空的 + +**原因:** 构建可能失败 + +**解决:** +1. 检查构建日志 +2. 确保所有步骤都是绿色 ✅ +3. 重新运行构建 + +--- + +### Q4: 如何修改 API 域名 + +**方法 1:** 手动触发时修改参数 + +**方法 2:** 修改代码中的默认值 +```dart +// lib/app/common/app_config.dart +static String kr_currentDomain = "api.example.com"; +``` + +--- + +## 📞 需要帮助? + +- **查看详细文档:** `.github/workflows/INDEX.md` +- **快速开始:** `.github/workflows/QUICKSTART.md` +- **问题反馈:** GitHub Issues + +--- + +**准备好了吗?立即开始构建!** 🚀 diff --git a/.github/workflows/INDEX.md b/.github/workflows/INDEX.md new file mode 100644 index 0000000..2338c1e --- /dev/null +++ b/.github/workflows/INDEX.md @@ -0,0 +1,318 @@ +# 📚 GitHub Actions 构建系统总览 + +## 🎯 快速导航 + +| 文档 | 用途 | 适合人群 | +|-----|------|---------| +| **[QUICKSTART.md](./QUICKSTART.md)** | 3步快速开始 | 新手 | +| **[README.md](./README.md)** | 基础说明 | 所有人 | +| **[BUILD_GUIDE.md](./BUILD_GUIDE.md)** | Android 详细指南 | Android 开发者 | +| **[MULTIPLATFORM_GUIDE.md](./MULTIPLATFORM_GUIDE.md)** | 多平台构建指南 | 全平台开发者 | + +--- + +## 📋 可用的 Workflows + +### 1. `build-android-apk.yml` - Android 专用构建 + +**功能:** +- ✅ 编译 libcore.aar +- ✅ 构建 Android APK (arm64/armv7/x86_64) +- ✅ 配置 API 域名和 OSS 地址 +- ✅ Release 构建 + +**触发条件:** +- 推送到 main/develop 分支 +- 创建 v* 标签 +- 手动触发 + +**文档:** [BUILD_GUIDE.md](./BUILD_GUIDE.md) + +--- + +### 2. `build-multiplatform.yml` - 多平台构建 ⭐推荐 + +**功能:** +- ✅ Android APK +- ✅ Windows 可执行文件 +- ✅ macOS 应用 +- ✅ Linux 可执行文件 +- ✅ 可选择构建平台 +- ✅ 统一配置管理 + +**触发条件:** +- 推送到 main/develop 分支 +- 创建 v* 标签 +- 手动触发 + +**文档:** [MULTIPLATFORM_GUIDE.md](./MULTIPLATFORM_GUIDE.md) + +--- + +### 3. `build-clash-core.yml` - Clash 核心编译 + +**功能:** +- 编译 Clash Meta 核心 +- 支持多架构 (arm64/armv7/x86_64) + +**触发条件:** +- core/ 目录变更 +- 手动触发 + +--- + +## 🚀 使用建议 + +### 场景 1: 日常开发(仅 Android) + +**使用:** `build-android-apk.yml` +```bash +# 推送代码自动触发 +git push origin main +``` + +**时间:** 约 30 分钟 +**产物:** 3 个 Android APK + +--- + +### 场景 2: 正式发布(所有平台) + +**使用:** `build-multiplatform.yml` +```bash +# 1. 打标签 +git tag v1.0.0 +git push origin v1.0.0 + +# 2. 自动构建所有平台并创建 Release +``` + +**时间:** 约 60-85 分钟(并行) +**产物:** Android + Windows + macOS + Linux + +--- + +### 场景 3: 测试特定平台 + +**使用:** `build-multiplatform.yml` 手动触发 +```yaml +构建平台: android,windows # 只构建这两个 +``` + +**时间:** 约 35 分钟 +**产物:** 指定平台 + +--- + +## 📦 构建产物对比 + +### Android 专用构建 + +``` +BearVPN-android-arm64-v8a-release-20251027-abc1234.apk +BearVPN-android-armeabi-v7a-release-20251027-abc1234.apk +BearVPN-android-x86_64-release-20251027-abc1234.apk +``` + +### 多平台构建 + +``` +# Android +BearVPN-android-arm64-v8a-release-20251027-abc1234.apk +BearVPN-android-armeabi-v7a-release-20251027-abc1234.apk +BearVPN-android-x86_64-release-20251027-abc1234.apk + +# Windows +BearVPN-windows-x64-release-20251027-abc1234.zip + +# macOS +BearVPN-macos-release-20251027-abc1234.zip + +# Linux +BearVPN-linux-x64-release-20251027-abc1234.tar.gz +``` + +--- + +## ⚙️ 配置参数说明 + +### 所有 Workflow 通用参数 + +| 参数 | 默认值 | 说明 | +|-----|-------|------| +| **构建类型** | `release` | debug 或 release | +| **API 域名** | `api.maodag.top` | 后端服务器地址 | +| **OSS 地址 1** | 香港 CDN | 配置文件源 | +| **OSS 地址 2** | 东京 CDN | 备用配置源 | +| **OSS 地址 3** | 首尔 CDN | 备用配置源 | +| **OSS 地址 4** | 新加坡 CDN | 备用配置源 | + +### 多平台专用参数 + +| 参数 | 默认值 | 说明 | +|-----|-------|------| +| **构建平台** | `android,windows,macos,linux` | 选择构建的平台 | + +--- + +## ⏱️ 构建时间对比 + +| Workflow | 单平台 | 全平台 | +|---------|-------|-------| +| **Android 专用** | 30分钟 | - | +| **多平台** | 30-40分钟 | 60-85分钟 | + +--- + +## 🎯 选择 Workflow 的建议 + +### 选择 `build-android-apk.yml` 如果: + +- ✅ 只需要 Android 版本 +- ✅ 快速迭代开发 +- ✅ CI/CD 自动触发 + +### 选择 `build-multiplatform.yml` 如果: + +- ✅ 需要桌面版本 +- ✅ 正式版本发布 +- ✅ 需要灵活选择平台 + +--- + +## 🔧 环境配置 + +### 必需的 Secrets(用于 Release 签名) + +**Android:** +``` +KEYSTORE_BASE64 +KEYSTORE_PASSWORD +KEY_ALIAS +KEY_PASSWORD +``` + +**macOS:** +``` +MACOS_CERTIFICATE_BASE64 +MACOS_CERTIFICATE_PASSWORD +``` + +**Windows:** +``` +WINDOWS_CERTIFICATE_BASE64 +WINDOWS_CERTIFICATE_PASSWORD +``` + +**说明:** 如果不配置签名,可以使用 debug 构建。 + +--- + +## 📊 构建流程图 + +### Android 专用 + +``` +Checkout 代码 + ↓ +编译 libcore.aar (15min) + ↓ +配置 API/OSS + ↓ +构建 APK (20min) + ↓ +上传产物 +``` + +### 多平台 + +``` +Checkout 代码 + ↓ +编译 libcore.aar (15min) + ↓ + ├─→ Android (20min) ─┐ + ├─→ Windows (15min) ─┤ + ├─→ macOS (20min) ─┼─→ 创建 Release + └─→ Linux (15min) ─┘ +``` + +--- + +## 🐛 故障排查 + +### 问题 1: libcore 编译失败 + +**检查:** +1. Go 环境是否正常 +2. gomobile 是否安装 +3. 网络连接(下载依赖) + +**日志位置:** `build-libcore` job + +--- + +### 问题 2: Android 构建失败 + +**常见原因:** +- libcore.aar 未生成 +- Gradle 依赖问题 +- 签名配置错误 + +**解决:** 查看 `build-android` job 日志 + +--- + +### 问题 3: macOS 构建失败 + +**常见原因:** +- 签名证书未配置 +- Xcode 版本不兼容 + +**解决:** +- 使用 debug 构建 +- 或配置签名证书 + +--- + +## 💡 高级用法 + +### 1. 定时构建 + +添加到 workflow: + +```yaml +on: + schedule: + - cron: '0 2 * * *' # 每天UTC 2:00 +``` + +### 2. PR 自动构建 + +已配置:推送 PR 到 main 分支自动触发 + +### 3. 构建通知 + +可集成 Telegram/Slack/钉钉通知 + +--- + +## 📞 获取帮助 + +- **查看文档:** 本目录下的 Markdown 文件 +- **查看日志:** GitHub Actions 页面 +- **提交问题:** Issues 页面 + +--- + +## 🔗 相关链接 + +- [GitHub Actions 文档](https://docs.github.com/actions) +- [Flutter CI/CD](https://docs.flutter.dev/deployment/cd) +- [sing-box 文档](https://sing-box.sagernet.org/) + +--- + +**版本:** 1.0.0 +**更新:** 2025-10-27 +**作者:** Claude Code diff --git a/.github/workflows/MULTIPLATFORM_GUIDE.md b/.github/workflows/MULTIPLATFORM_GUIDE.md new file mode 100644 index 0000000..85230a2 --- /dev/null +++ b/.github/workflows/MULTIPLATFORM_GUIDE.md @@ -0,0 +1,407 @@ +# 🌐 多平台构建完全指南 + +## 📋 支持的平台 + +✅ **Android** - arm64-v8a / armeabi-v7a / x86_64 +✅ **Windows** - x64 +✅ **macOS** - Universal (Intel + Apple Silicon) +✅ **Linux** - x64 + +--- + +## 🚀 快速开始 + +### 方法 1: 构建所有平台(推荐) + +1. 打开 GitHub Actions 页面 +2. 选择 **Build Multi-Platform** +3. 点击 **Run workflow** +4. 配置参数: + +```yaml +构建类型: release +API 域名: api.maodag.top +OSS 地址 1-4: 使用默认值 +构建平台: android,windows,macos,linux # 构建所有平台 +``` + +5. 点击 **Run workflow** 开始 + +--- + +### 方法 2: 仅构建指定平台 + +**场景:** 只需要 Android 和 Windows 版本 + +```yaml +构建平台: android,windows # 只构建这两个平台 +``` + +**可选值:** +- `android` - 仅 Android +- `windows` - 仅 Windows +- `macos` - 仅 macOS +- `linux` - 仅 Linux +- `android,windows` - Android + Windows +- `android,windows,macos,linux` - 全部平台 + +--- + +## ⏱️ 构建时间估算 + +| 平台 | 时间 | 说明 | +|-----|------|-----| +| **libcore** | 10-15分钟 | Android 依赖 | +| **Android** | 15-20分钟 | 3个架构APK | +| **Windows** | 10-15分钟 | x64可执行文件 | +| **macOS** | 15-20分钟 | Universal应用 | +| **Linux** | 10-15分钟 | x64可执行文件 | +| **总计(全平台)** | **60-85分钟** | 并行构建 | + +--- + +## 📦 构建产物 + +### Android + +``` +BearVPN-android-arm64-v8a-release-20251027-abc1234.apk (推荐) +BearVPN-android-armeabi-v7a-release-20251027-abc1234.apk (老设备) +BearVPN-android-x86_64-release-20251027-abc1234.apk (模拟器) +``` + +**安装:** 直接点击APK安装 + +--- + +### Windows + +``` +BearVPN-windows-x64-release-20251027-abc1234.zip +``` + +**内容结构:** +``` +BearVPN.exe # 主程序 +flutter_windows.dll # Flutter运行时 +data/ # 资源文件 +``` + +**运行:** +1. 解压 ZIP 文件 +2. 双击 `BearVPN.exe` 运行 +3. 如提示缺少依赖,安装 [VC++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe) + +--- + +### macOS + +``` +BearVPN-macos-release-20251027-abc1234.zip +``` + +**内容:** +``` +BearVPN.app # 应用程序包(Universal) +``` + +**安装:** +1. 解压 ZIP 文件 +2. 将 `BearVPN.app` 拖到 **应用程序** 文件夹 +3. 首次运行右键点击 → 打开(绕过 Gatekeeper) + +**支持架构:** +- Intel (x86_64) +- Apple Silicon (arm64) + +--- + +### Linux + +``` +BearVPN-linux-x64-release-20251027-abc1234.tar.gz +``` + +**内容结构:** +``` +bearvpn # 可执行文件 +lib/ # 共享库 +data/ # 资源文件 +``` + +**运行:** +```bash +# 1. 解压 +tar -xzf BearVPN-linux-x64-release-*.tar.gz +cd bundle + +# 2. 添加执行权限 +chmod +x bearvpn + +# 3. 运行 +./bearvpn +``` + +**依赖要求:** +- GTK+ 3 +- libstdc++12 + +**安装依赖(Ubuntu/Debian):** +```bash +sudo apt-get install libgtk-3-0 libstdc++6 +``` + +**安装依赖(Fedora/RHEL):** +```bash +sudo dnf install gtk3 libstdc++ +``` + +--- + +## 🔧 配置说明 + +### 所有平台通用配置 + +| 参数 | 默认值 | 说明 | +|-----|-------|------| +| **构建类型** | `release` | debug 或 release | +| **API 域名** | `api.maodag.top` | 后端服务器 | +| **OSS 地址 1** | 香港 CDN | 配置文件源 | +| **OSS 地址 2** | 东京 CDN | 备用源 | +| **OSS 地址 3** | 首尔 CDN | 备用源 | +| **OSS 地址 4** | 新加坡 CDN | 备用源 | +| **构建平台** | `android,windows,macos,linux` | 选择平台 | + +--- + +## 📥 下载构建产物 + +### 从 Actions 页面下载 + +1. 打开运行记录 +2. 滚动到 **Artifacts** 区域 +3. 下载对应平台: + - `android-apk` - Android APK (所有架构) + - `windows-x64` - Windows 可执行程序 + - `macos-app` - macOS 应用 + - `linux-x64` - Linux 可执行程序 + +### 从 Releases 下载(推送标签时) + +1. 访问 Releases 页面 +2. 选择版本 +3. 在 Assets 中下载对应平台文件 + +--- + +## 🎯 使用场景 + +### 场景 1: 开发测试(仅 Android) + +```yaml +构建类型: debug +构建平台: android +API 域名: api.test.com +``` + +**优点:** 快速,约20分钟 + +--- + +### 场景 2: 正式发布(全平台) + +```yaml +构建类型: release +构建平台: android,windows,macos,linux +API 域名: api.maodag.top +``` + +**优点:** 一次构建,覆盖所有用户 + +--- + +### 场景 3: 仅桌面平台 + +```yaml +构建类型: release +构建平台: windows,macos,linux +``` + +**用途:** 桌面版更新 + +--- + +## 🐛 常见问题 + +### Q1: Windows 构建失败 - "7z command not found" + +**原因:** Windows runner 默认有 7z + +**解决:** 检查构建日志,可能是其他错误 + +--- + +### Q2: macOS 构建失败 - "Code signing required" + +**原因:** Release 构建需要签名 + +**解决方案:** + +**方法 1:** 使用 debug 构建(测试用) + +**方法 2:** 配置签名证书(生产用) +```yaml +# 在 Secrets 中添加 +MACOS_CERTIFICATE_BASE64 +MACOS_CERTIFICATE_PASSWORD +MACOS_KEYCHAIN_PASSWORD +PROVISIONING_PROFILE_BASE64 +``` + +--- + +### Q3: Linux 运行时提示缺少库 + +**错误:** +``` +error while loading shared libraries: libgtk-3.so.0 +``` + +**解决:** +```bash +sudo apt-get update +sudo apt-get install libgtk-3-0 +``` + +--- + +### Q4: 如何只更新某个平台? + +**方法 1:** 手动触发指定平台 +```yaml +构建平台: android # 只构建 Android +``` + +**方法 2:** 创建平台专用 workflow(推荐) + +--- + +### Q5: 构建时间太长怎么办? + +**优化方案:** + +1. **仅构建需要的平台** + ```yaml + 构建平台: android # 而不是全部 + ``` + +2. **使用缓存**(已配置) + - Flutter SDK 缓存 + - Gradle 缓存 + - Go modules 缓存 + +3. **分批构建** + - 白天构建 Android/Windows + - 晚上构建 macOS/Linux + +--- + +## 💡 高级用法 + +### 技巧 1: 矩阵构建多个配置 + +修改 workflow: + +```yaml +strategy: + matrix: + api_domain: ['api.prod.com', 'api.test.com'] + platform: ['android', 'windows', 'macos', 'linux'] +``` + +**效果:** 生成 8 个版本(2域名 × 4平台) + +--- + +### 技巧 2: 定时自动构建 + +添加到 workflow: + +```yaml +on: + schedule: + - cron: '0 2 * * *' # 每天凌晨2点(UTC) +``` + +--- + +### 技巧 3: 构建完成通知 + +添加 Telegram 通知: + +```yaml +- name: 📢 通知 + run: | + curl -X POST "https://api.telegram.org/bot${{ secrets.TG_BOT_TOKEN }}/sendMessage" \ + -d chat_id=${{ secrets.TG_CHAT_ID }} \ + -d text="✅ 多平台构建完成!" +``` + +--- + +## 📊 构建并行示意图 + +``` +libcore (15min) + ↓ + ├─→ Android (20min) ─┐ + ├─→ Windows (15min) ─┤ + ├─→ macOS (20min) ─┼─→ Release (2min) + └─→ Linux (15min) ─┘ + +总时间: 约 35-40分钟(并行) +如果串行: 约 85分钟 +``` + +--- + +## 🔐 安全建议 + +### Release 版本签名 + +**Android:** +```yaml +# Secrets 配置 +KEYSTORE_BASE64 +KEYSTORE_PASSWORD +KEY_ALIAS +KEY_PASSWORD +``` + +**macOS:** +```yaml +# Secrets 配置 +MACOS_CERTIFICATE_BASE64 +MACOS_CERTIFICATE_PASSWORD +``` + +**Windows:** +```yaml +# Secrets 配置 +WINDOWS_CERTIFICATE_BASE64 +WINDOWS_CERTIFICATE_PASSWORD +``` + +--- + +## 📞 需要帮助? + +- 查看 [GitHub Actions 文档](https://docs.github.com/actions) +- 查看 [Flutter 桌面支持](https://docs.flutter.dev/desktop) +- 提交 Issue + +--- + +**版本:** 1.0.0 +**更新:** 2025-10-27 +**作者:** Claude Code diff --git a/.github/workflows/QUICKSTART.md b/.github/workflows/QUICKSTART.md new file mode 100644 index 0000000..399c8be --- /dev/null +++ b/.github/workflows/QUICKSTART.md @@ -0,0 +1,78 @@ +# 🚀 GitHub Actions 快速开始 + +## 📋 3 步开始使用 + +### 步骤 1: 推送配置文件 + +```bash +cd /Users/mac/Project/Dart/LighthouseApp + +git add .github/workflows/ +git commit -m "feat: 添加 GitHub Actions 自动构建配置" +git push origin main +``` + +### 步骤 2: 手动触发构建 + +1. 打开 GitHub 仓库页面 +2. 点击 **Actions** 标签 +3. 左侧选择 **Build Android APK** +4. 右侧点击 **Run workflow** 下拉按钮 +5. 配置参数(可以使用默认值): + + ``` + 构建类型: release + API 域名: api.maodag.top + OSS 地址 1-4: 使用默认值 + ``` + +6. 点击绿色 **Run workflow** 按钮 + +### 步骤 3: 下载 APK + +- 等待约 30 分钟 +- 在构建记录页面找到 **Artifacts** +- 下载 `apk-arm64-v8a-release`(推荐) + +--- + +## 🎯 自定义配置示例 + +### 场景 1: 更换 API 域名 + +```yaml +构建类型: release +API 域名: api.example.com ← 修改这里 +OSS 地址: 保持默认 +``` + +### 场景 2: 使用自己的 CDN + +```yaml +构建类型: release +API 域名: api.maodag.top +OSS 地址 1: https://your-cdn.com/config1.txt ← 修改这里 +OSS 地址 2: https://your-cdn.com/config2.txt ← 修改这里 +OSS 地址 3: https://your-cdn.com/config3.txt ← 修改这里 +OSS 地址 4: https://your-cdn.com/config4.txt ← 修改这里 +``` + +--- + +## 📖 详细文档 + +- **完整指南:** [BUILD_GUIDE.md](./BUILD_GUIDE.md) +- **基础说明:** [README.md](./README.md) + +--- + +## ✅ 核心功能 + +✅ **Release 构建** - 生产环境优化版本 +✅ **可配置域名** - 支持自定义 API 和 CDN +✅ **分架构打包** - arm64/armv7/x86_64 +✅ **自动 Release** - 推送标签自动发布 + +--- + +**需要帮助?** 查看 [BUILD_GUIDE.md](./BUILD_GUIDE.md) diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..c37cfb5 --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,90 @@ +# GitHub Actions 构建说明 + +## 📋 工作流概览 + +### `build-android-apk.yml` - Android APK 自动构建 + +**触发条件:** +- ✅ 推送到 `main` 或 `develop` 分支 +- ✅ 打 `v*` 标签时自动创建 Release +- ✅ 手动触发(Actions 页面点击 "Run workflow") + +**构建产物:** +- `libcore.aar` - sing-box 核心库 +- `BearVPN-arm64-v8a-*.apk` - 64位 ARM 版本(推荐) +- `BearVPN-armeabi-v7a-*.apk` - 32位 ARM 版本 +- `BearVPN-x86_64-*.apk` - 模拟器版本 + +--- + +## 🚀 使用方法 + +### 方法一:推送代码自动构建 + +```bash +git add . +git commit -m "feat: 新功能" +git push origin main +``` + +### 方法二:手动触发 + +1. 打开仓库 **Actions** 页面 +2. 点击 **Build Android APK** +3. 点击 **Run workflow** + +### 方法三:创建 Release + +```bash +git tag v1.0.0 +git push origin v1.0.0 +``` + +--- + +## 📦 下载构建产物 + +- **Actions 页面:** 点击运行记录 → Artifacts 区域下载 +- **Releases 页面:** 选择版本 → Assets 下载 + +--- + +## 🔧 配置 Release 签名(可选) + +1. 生成密钥: +```bash +keytool -genkey -v -keystore release.keystore -alias bearvpn -keyalg RSA -keysize 2048 -validity 10000 +``` + +2. 转换为 Base64: +```bash +base64 release.keystore > keystore.base64.txt +``` + +3. 在 GitHub 仓库 **Settings → Secrets** 添加: + - `KEYSTORE_BASE64` + - `KEYSTORE_PASSWORD` + - `KEY_ALIAS` + - `KEY_PASSWORD` + +--- + +## ⏱️ 构建时间 + +- libcore.aar: 10-15 分钟 +- Flutter APK: 15-20 分钟 +- **总计: 约 30 分钟** + +--- + +## 🐛 常见问题 + +**Q: 构建失败 "libcore.aar not found"** +A: 检查 libcore 子模块是否正确初始化 + +**Q: Release 未创建** +A: 标签必须以 `v` 开头,如 `v1.0.0` + +--- + +生成时间: 2025-10-27 diff --git a/docs/CLASH_ARCHITECTURE.md b/docs/CLASH_ARCHITECTURE.md new file mode 100644 index 0000000..3779d73 --- /dev/null +++ b/docs/CLASH_ARCHITECTURE.md @@ -0,0 +1,255 @@ +# Clash Meta 核心架构文档 + +## 架构概览 + +LighthouseApp 使用 Clash Meta (Mihomo) 作为核心代理引擎,替代原有的 sing-box 实现。 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Flutter Application │ +├─────────────────────────────────────────────────────────────┤ +│ Dart Layer │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ KRClashImp (lib/app/services/clash_imp/) │ │ +│ │ • kr_clash_imp.dart - 核心封装 │ │ +│ │ • clash_ffi.dart - FFI 绑定 │ │ +│ │ • clash_config_generator - YAML 配置生成 │ │ +│ │ • clash_service_handler - 服务处理器 │ │ +│ └──────────────────┬───────────────────────────────────┘ │ +│ │ dart:ffi │ +├─────────────────────┼───────────────────────────────────────┤ +│ Android Native │ │ +│ ┌──────────────────▼───────────────────────────────────┐ │ +│ │ ClashService (Kotlin) │ │ +│ │ • VPNService.kt - VPN 服务入口 │ │ +│ │ • ClashService.kt - Clash 服务管理 │ │ +│ │ • Service Isolate - 后台 Dart 运行时 │ │ +│ └──────────────────┬───────────────────────────────────┘ │ +│ │ JNI │ +│ ┌──────────────────▼───────────────────────────────────┐ │ +│ │ libclash.so (Go + C) │ │ +│ │ • quickStart() - 启动核心 │ │ +│ │ • getAndroidVpnOptions() - 获取 VPN 配置 │ │ +│ │ • startTUN() - 启动 TUN 设备 │ │ +│ │ • getTraffic() - 流量统计 │ │ +│ └──────────────────┬───────────────────────────────────┘ │ +│ │ │ +├─────────────────────┼───────────────────────────────────────┤ +│ Go Core │ │ +│ ┌──────────────────▼───────────────────────────────────┐ │ +│ │ Clash.Meta (Mihomo) │ │ +│ │ • TUN 设备管理 │ │ +│ │ • 路由策略 (bypass-LAN) │ │ +│ │ • 代理协议支持 (SS/Trojan/VMess/...) │ │ +│ │ • DNS 解析 │ │ +│ │ • 流量统计 │ │ +│ └──────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## 核心组件 + +### 1. Dart FFI 层 (`kr_clash_imp.dart`) + +**职责:** +- 提供与 Go 核心的 FFI 通信接口 +- 管理核心生命周期 (启动/停止) +- 配置文件生成和管理 +- 并发安全的初始化机制 + +**关键方法:** +- `start()` - 启动 Clash 核心 +- `stop()` - 停止核心 +- `getAndroidVpnOptions()` - 获取 VPN 路由配置 (关键!) +- `startTun()` - 启动 TUN 设备 + +**并发安全设计:** +```dart +// 使用 Completer 实现初始化锁 +Completer? _initLock; + +Future _ensureInitialized() async { + if (_initialized) return; + if (_initLock != null) { + await _initLock!.future; // 等待其他初始化完成 + return; + } + // 执行初始化... +} +``` + +### 2. Android Service 层 (`ClashService.kt`) + +**职责:** +- 管理 VPN 服务生命周期 +- 创建 Service Isolate (后台 Dart 运行时) +- 处理系统 VPN 权限 +- 注册底层网络回调 (修复模拟器兼容性) + +**Service Isolate 架构:** +```kotlin +// 创建独立的 FlutterEngine 用于后台服务 +serviceEngine = FlutterEngine(Application.application) + +// 执行 Dart Service 入口点 +val entrypoint = DartExecutor.DartEntrypoint( + FlutterInjector.instance().flutterLoader().findAppBundlePath(), + "_clashService" // 在 lib/main.dart 中定义 +) +serviceEngine?.dartExecutor?.executeDartEntrypoint(entrypoint) +``` + +### 3. Go 核心层 (`core/`) + +**目录结构:** +``` +core/ +├── Clash.Meta/ # Git 子模块,Mihomo 核心 +├── go.mod # Go 依赖管理 +├── lib_android.go # Android JNI 桥接 +├── action.go # 核心操作接口 +└── hub.go # HTTP API 服务器 +``` + +**关键桥接函数:** +```go +//export quickStart +func quickStart(initParams, params, stateParams *C.char, port C.longlong) + +//export getAndroidVpnOptions +func getAndroidVpnOptions() *C.char // 返回详细路由配置! + +//export startTUN +func startTUN(fd C.int, callback unsafe.Pointer) C.int +``` + +## 数据流 + +### 启动流程 + +``` +1. Flutter UI (用户点击连接) + │ + ├──> KRClashImp.start() + │ ├─ 生成 Clash 配置 YAML + │ ├─ 调用 FFI: quickStart() + │ └─ 等待启动回调 + │ + ├──> libclash.so: quickStart() + │ ├─ 初始化 Clash Meta 核心 + │ ├─ 解析配置文件 + │ └─ 启动监听器 + │ + ├──> ClashService.kt + │ ├─ 调用 VpnService.prepare() + │ ├─ 获取 VPN 权限 + │ └─ 建立 TUN 接口 + │ + ├──> KRClashImp.getAndroidVpnOptions() ⭐ 关键! + │ └─ 获取 35+ CIDR 路由列表 + │ + └──> VPNService.kt: 配置 VPN Builder + ├─ addAddress("172.19.0.1/30") + ├─ addRoute("0.0.0.0/1") + ├─ addRoute("128.0.0.0/1") + ├─ addRoute("10.0.0.0/8") # bypass-LAN + └─ 启动 TUN 设备 +``` + +### 流量统计流程 + +``` +1. UI 定时器 (每秒) + │ + ├──> KRClashImp.getTraffic() + │ └─ FFI 调用 + │ + ├──> libclash.so: getTraffic() + │ └─ Clash Meta 内部统计 + │ + └──> 返回 JSON + { + "upload": 1234567, + "download": 7654321 + } +``` + +## 关键设计决策 + +### 为什么使用 Clash Meta 替代 sing-box? + +| 问题 | sing-box | Clash Meta | +|------|----------|------------| +| **Android VPN 路由** | 简单路由 (3-5条) | 详细路由 (35+条 CIDR) | +| **bypass-LAN 支持** | ❌ 不支持 | ✅ 完整支持 | +| **PermissionMonitor error 22** | ⚠️ 频繁出现 | ✅ 已解决 | +| **模拟器兼容性** | ⚠️ 兼容性问题 | ✅ 完美兼容 | + +### 并发安全保证 + +**问题:** Go 运行时初始化不是线程安全的,多个 Dart 方法并发调用 `_ensureInitialized()` 可能导致崩溃。 + +**解决方案:** 使用 `Completer` 实现初始化锁: +```dart +// 场景 1: 第一次调用 +Thread A: _ensureInitialized() → 创建 _initLock → 执行初始化 → complete() + +// 场景 2: 并发调用 +Thread B: _ensureInitialized() → 发现 _initLock != null → await _initLock.future ✅ + +// 场景 3: 初始化失败重试 +Thread C: _ensureInitialized() → 异常 → _initLock = null → 允许重试 ✅ +``` + +## 配置文件 + +### Clash 配置生成 (`clash_config_generator.dart`) + +```yaml +# 生成的 clash_config.yaml 示例 +mixed-port: 51213 +allow-lan: false + +tun: + enable: true + stack: system + auto-route: true + auto-detect-interface: true + dns-hijack: + - any:53 + route-address: # ⭐ 关键! 35+ 详细路由 + - 0.0.0.0/1 + - 128.0.0.0/1 + # ... bypass-LAN CIDRs + route-exclude-address: + - 10.0.0.0/8 # 绕过局域网 + - 172.16.0.0/12 + - 192.168.0.0/16 + +proxies: + - name: "Server-1" + type: ss + server: example.com + port: 8388 + # ... + +proxy-groups: + - name: "PROXY" + type: select + proxies: + - Server-1 +``` + +## 故障排查 + +参考 [CLASH_TROUBLESHOOTING.md](./CLASH_TROUBLESHOOTING.md) + +## 构建指南 + +参考 [CLASH_BUILD_GUIDE.md](./CLASH_BUILD_GUIDE.md) + +## 相关资源 + +- [Clash Meta 官方文档](https://wiki.metacubex.one/) +- [Mihomo GitHub](https://github.com/MetaCubeX/mihomo) +- [Xboard-Mihomo 参考实现](https://github.com/chen08209/Xboard-Mihomo) diff --git a/docs/CLASH_BUILD_GUIDE.md b/docs/CLASH_BUILD_GUIDE.md new file mode 100644 index 0000000..9c69068 --- /dev/null +++ b/docs/CLASH_BUILD_GUIDE.md @@ -0,0 +1,345 @@ +# Clash Meta 核心编译指南 + +## 环境准备 + +### 1. 安装必要工具 + +```bash +# macOS +brew install go +brew install android-ndk # 或从 Android Studio 安装 + +# 验证 +go version # 需要 go 1.20+ +``` + +### 2. 配置环境变量 + +```bash +# 添加到 ~/.zshrc 或 ~/.bash_profile +export ANDROID_HOME="$HOME/Library/Android/sdk" +export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/29.0.14033849" # 根据实际版本调整 +export PATH="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin:$PATH" + +# 应用配置 +source ~/.zshrc +``` + +## 编译步骤 + +### 方法 1: 使用项目脚本 (推荐) + +```bash +cd /Users/mac/Project/Dart/LighthouseApp/core + +# 编译 ARM64 版本 +make android-arm64 + +# 编译所有架构 +make android-all # arm64-v8a, armeabi-v7a, x86, x86_64 +``` + +### 方法 2: 手动编译 + +#### 编译 ARM64 (arm64-v8a) + +```bash +cd /Users/mac/Project/Dart/LighthouseApp/core + +# 1. 初始化 Go 模块 +go mod download +git submodule update --init --recursive + +# 2. 设置交叉编译环境 +export CGO_ENABLED=1 +export GOOS=android +export GOARCH=arm64 +export CC="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android29-clang" + +# 3. 编译为共享库 +go build -buildmode=c-shared \ + -ldflags="-s -w" \ + -trimpath \ + -o ../android/app/src/main/jniLibs/arm64-v8a/libclash.so \ + . + +# 4. 验证编译结果 +ls -lh ../android/app/src/main/jniLibs/arm64-v8a/libclash.so +nm -D ../android/app/src/main/jniLibs/arm64-v8a/libclash.so | grep quickStart +``` + +#### 编译 ARMv7 (armeabi-v7a) + +```bash +export GOARCH=arm +export CC="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/armv7a-linux-androideabi29-clang" + +go build -buildmode=c-shared \ + -ldflags="-s -w" \ + -trimpath \ + -o ../android/app/src/main/jniLibs/armeabi-v7a/libclash.so \ + . +``` + +#### 编译 x86_64 + +```bash +export GOARCH=amd64 +export CC="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/x86_64-linux-android29-clang" + +go build -buildmode=c-shared \ + -ldflags="-s -w" \ + -trimpath \ + -o ../android/app/src/main/jniLibs/x86_64/libclash.so \ + . +``` + +## 编译优化 + +### 减小文件体积 + +```bash +# 使用 -ldflags 优化 +go build -buildmode=c-shared \ + -ldflags="-s -w -X 'github.com/metacubex/mihomo/constant.Version=1.0.0'" \ + -trimpath \ + -o libclash.so \ + . + +# -s: 去除符号表 +# -w: 去除 DWARF 调试信息 +# -trimpath: 移除文件系统路径 +``` + +### UPX 压缩 (可选) + +```bash +# 安装 UPX +brew install upx + +# 压缩 SO 文件 (可减少 30-50% 体积) +upx --best --lzma libclash.so + +# ⚠️ 注意: UPX 压缩可能导致某些设备加载失败,仅在测试环境使用 +``` + +## 常见问题 + +### 问题 1: `undefined reference to 'xxx'` + +**原因:** NDK 版本不匹配或缺少依赖 + +**解决:** +```bash +# 检查 NDK 版本 +ls $ANDROID_HOME/ndk/ + +# 使用推荐版本 (r25c / 25.2.9519653 或更高) +export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/25.2.9519653" +``` + +### 问题 2: `clang: command not found` + +**原因:** CC 环境变量路径错误 + +**解决:** +```bash +# macOS (Apple Silicon) +export CC="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-aarch64/bin/aarch64-linux-android29-clang" + +# macOS (Intel) +export CC="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android29-clang" +``` + +### 问题 3: 编译后文件过大 (>50MB) + +**原因:** 未启用优化参数 + +**解决:** +```bash +# 确保使用 -ldflags="-s -w" +go build -buildmode=c-shared \ + -ldflags="-s -w" \ + -trimpath \ + -o libclash.so \ + . + +# 预期大小: 25-30MB (ARM64) +``` + +### 问题 4: `go: github.com/metacubex/mihomo: module not found` + +**原因:** 子模块未初始化 + +**解决:** +```bash +cd core +git submodule update --init --recursive +go mod download +``` + +## 验证编译结果 + +### 1. 检查导出函数 + +```bash +nm -D libclash.so | grep -E "(quickStart|getAndroidVpnOptions|startTUN)" + +# 预期输出: +# 0000000000e23960 T getAndroidVpnOptions +# 0000000000e237b0 T quickStart +# 0000000000e23820 T startTUN +``` + +### 2. 检查架构 + +```bash +file libclash.so + +# ARM64 预期输出: +# libclash.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked +``` + +### 3. 测试加载 + +```bash +# 在 Android 设备上测试 +adb push libclash.so /data/local/tmp/ +adb shell "cd /data/local/tmp && LD_LIBRARY_PATH=. /system/bin/true" # 测试加载 +``` + +## 持续集成 (CI/CD) + +### GitHub Actions 示例 + +```yaml +# .github/workflows/build-clash-core.yml +name: Build Clash Core + +on: + push: + paths: + - 'core/**' + workflow_dispatch: + +jobs: + build-android: + runs-on: ubuntu-latest + + strategy: + matrix: + arch: [arm64, arm, amd64] + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - uses: actions/setup-go@v4 + with: + go-version: '1.20' + + - name: Setup Android NDK + uses: nttld/setup-ndk@v1 + with: + ndk-version: r25c + + - name: Build + run: | + cd core + make android-${{ matrix.arch }} + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: libclash-${{ matrix.arch }} + path: android/app/src/main/jniLibs/**/libclash.so +``` + +## 更新核心版本 + +### 更新 Clash.Meta 子模块 + +```bash +cd core/Clash.Meta + +# 更新到最新版本 +git fetch origin +git checkout Alpha # 或其他分支 +git pull + +cd .. +git add Clash.Meta +git commit -m "chore: update Clash.Meta to latest" + +# 重新编译 +make clean +make android-arm64 +``` + +### 查看版本信息 + +```bash +# 查看当前 Clash.Meta 版本 +cd core/Clash.Meta +git log -1 --oneline + +# 查看依赖版本 +cd .. +go list -m github.com/metacubex/mihomo +``` + +## 调试编译问题 + +### 启用详细日志 + +```bash +# 查看详细编译过程 +go build -v -x -buildmode=c-shared -o libclash.so . + +# -v: 显示正在编译的包 +# -x: 显示执行的命令 +``` + +### 检查依赖 + +```bash +# 列出所有依赖 +go list -m all + +# 检查特定依赖 +go mod why github.com/metacubex/mihomo +``` + +## 性能优化 + +### 编译时优化 + +```bash +# 启用所有优化 +go build -buildmode=c-shared \ + -ldflags="-s -w -extldflags=-Wl,-z,now" \ + -trimpath \ + -tags="with_gvisor,with_quic" \ + -o libclash.so \ + . +``` + +### Profile 引导优化 (PGO) + +```bash +# 1. 生成性能剖析文件 +go test -cpuprofile=cpu.prof ./... + +# 2. 使用剖析文件编译 +go build -buildmode=c-shared \ + -pgo=cpu.prof \ + -o libclash.so \ + . +``` + +## 相关资源 + +- [Android NDK 官方文档](https://developer.android.com/ndk) +- [Go 交叉编译指南](https://go.dev/doc/install/source#environment) +- [Clash Meta 编译指南](https://wiki.metacubex.one/dev/) diff --git a/docs/CLASH_TROUBLESHOOTING.md b/docs/CLASH_TROUBLESHOOTING.md new file mode 100644 index 0000000..0d75010 --- /dev/null +++ b/docs/CLASH_TROUBLESHOOTING.md @@ -0,0 +1,441 @@ +# Clash Meta 故障排查指南 + +## 常见运行时问题 + +### 问题 1: VPN 连接失败,日志显示 "PermissionMonitor error 22 (EINVAL)" + +**症状:** +``` +E/VPNService: PermissionMonitor error 22 (EINVAL) +E/Clash: TUN 设备启动失败 +``` + +**原因:** +- VPN Builder 配置的路由规则无效 +- 缺少 bypass-LAN 路由配置 +- 路由 CIDR 格式错误 + +**解决方案:** + +1. 检查 `getAndroidVpnOptions()` 返回的路由列表: +```dart +final options = await KRClashImp().getAndroidVpnOptions(); +print('路由数量: ${options?['routeAddress']?.length}'); +print('路由列表: ${options?['routeAddress']}'); +``` + +2. 确认配置包含完整的 bypass-LAN 路由: +```yaml +# clash_config.yaml +tun: + route-exclude-address: + - 10.0.0.0/8 + - 100.64.0.0/10 + - 127.0.0.0/8 + - 169.254.0.0/16 + - 172.16.0.0/12 + - 192.0.0.0/24 + - 192.0.2.0/24 + - 192.88.99.0/24 + - 192.168.0.0/16 + - 198.18.0.0/15 + - 198.51.100.0/24 + - 203.0.113.0/24 + - 224.0.0.0/3 + - fc00::/7 + - fe80::/10 + - ff00::/8 +``` + +3. 验证 VPN Builder 配置: +```kotlin +// VPNService.kt +builder + .addAddress("172.19.0.1/30") + .addRoute("0.0.0.0/1") // ✅ 拆分默认路由 + .addRoute("128.0.0.0/1") // ✅ 避免 0.0.0.0/0 + .addRoute("10.0.0.0/8") // ✅ bypass-LAN + // ... +``` + +**参考:** `lib/app/services/clash_imp/kr_clash_imp.dart:192` + +--- + +### 问题 2: FFI 初始化崩溃 "Go runtime already initialized" + +**症状:** +``` +F/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR) +E/Clash: Go runtime already initialized +``` + +**原因:** +- 多线程并发调用 `_ensureInitialized()` +- Go 运行时被重复初始化 + +**解决方案:** + +已在 `kr_clash_imp.dart` 中修复,使用 `Completer` 实现并发安全: +```dart +Future _ensureInitialized() async { + if (_initialized) return; + if (_initLock != null) { + await _initLock!.future; // ✅ 等待其他初始化完成 + return; + } + _initLock = Completer(); + // ... 执行初始化 +} +``` + +**验证修复:** +```dart +// 并发测试 +await Future.wait([ + KRClashImp().start(...), + KRClashImp().getAndroidVpnOptions(), + KRClashImp().getTraffic(), +]); +// ✅ 应该不会崩溃 +``` + +**参考:** `lib/app/services/clash_imp/kr_clash_imp.dart:43` + +--- + +### 问题 3: 模拟器无法联网 "Network unreachable" + +**症状:** +``` +E/Clash: 网络不可达 +W/VPNService: 底层网络丢失 +``` + +**原因:** +- 模拟器需要显式设置底层网络 +- 缺少 `setUnderlyingNetworks()` 调用 + +**解决方案:** + +已在 `VPNService.kt` 中实现: +```kotlin +// Android P+ 需要设置底层网络 +private val defaultNetworkCallback by lazy { + object : ConnectivityManager.NetworkCallback() { + override fun onAvailable(network: Network) { + setUnderlyingNetworks(arrayOf(network)) // ✅ 关键! + } + } +} + +// 注册回调 +connectivityManager.registerDefaultNetworkCallback(defaultNetworkCallback) +``` + +**验证修复:** +```bash +# 在 MuMu 模拟器测试 +adb logcat | grep "底层网络" +# 应该看到: "底层网络可用: NetworkIdentity{...}" +``` + +**参考:** `android/.../bg/VPNService.kt:32-66` + +--- + +### 问题 4: 配置文件解析失败 "invalid YAML" + +**症状:** +``` +E/Clash: 启动失败: yaml: unmarshal errors: + line 10: cannot unmarshal !!str `8388` into int +``` + +**原因:** +- YAML 类型不匹配 (字符串 vs 整数) +- 配置格式错误 + +**解决方案:** + +检查 `ClashConfigGenerator.generate()`: +```dart +proxies: + - name: "Server-1" + type: ss + server: "example.com" + port: 8388 # ✅ 整数,不要引号 + password: "password" # ✅ 字符串,使用引号 + cipher: "aes-256-gcm" +``` + +**调试方法:** +```dart +// 打印生成的配置 +final config = ClashConfigGenerator.generate(...); +print('配置预览:\n$config'); + +// 保存到文件手动检查 +File('/tmp/clash_debug.yaml').writeAsStringSync(config); +``` + +**参考:** `lib/app/services/clash_imp/clash_config_generator.dart` + +--- + +### 问题 5: "quickStart timeout" 启动超时 + +**症状:** +``` +W/Clash: 启动超时 (10秒) +E/Clash: quickStart 未收到回调 +``` + +**原因:** +- Go 核心启动耗时过长 +- ReceivePort 未正确监听 +- 回调被阻塞 + +**解决方案:** + +1. 增加超时时间: +```dart +_isRunning = await completer.future.timeout( + const Duration(seconds: 20), // ✅ 增加到 20 秒 + onTimeout: () { + print('⚠️ 启动超时'); + return false; + }, +); +``` + +2. 检查 Go 核心日志: +```kotlin +// ClashService.kt - 添加日志回调 +tempMethodChannel.setMethodCallHandler { call, result -> + if (call.method == "log") { + Log.d(TAG, "Go 核心日志: ${call.arguments}") + } +} +``` + +3. 使用 Service Isolate 避免阻塞: +```kotlin +// ClashService.kt:102 - 已实现 +serviceEngine?.dartExecutor?.executeDartEntrypoint(entrypoint) +``` + +**参考:** `lib/app/services/clash_imp/kr_clash_imp.dart:145` + +--- + +### 问题 6: 流量统计不更新 + +**症状:** +``` +I/Clash: 流量统计: {"upload": 0, "download": 0} # 始终为 0 +``` + +**原因:** +- TUN 设备未正确启动 +- 流量未通过代理 + +**解决方案:** + +1. 确认 TUN 启动成功: +```dart +final tunStarted = await KRClashImp().startTun(fd, protectCallback); +print('TUN 启动状态: $tunStarted'); // 应该为 true +``` + +2. 检查路由配置: +```bash +# 在设备上检查路由表 +adb shell "ip route show table all | grep tun" +``` + +3. 测试代理连接: +```bash +# 使用 curl 测试 +adb shell "curl -v http://www.google.com" +# 应该看到代理日志 +``` + +**参考:** `lib/app/services/clash_imp/kr_clash_imp.dart:261` + +--- + +## 日志分析 + +### 启用详细日志 + +```dart +// lib/app/services/clash_imp/kr_clash_imp.dart +// 添加更详细的日志 +print('📨 [Clash] 收到消息: ${jsonEncode(message)}'); +print('📋 [Clash] 配置完整内容:\n$config'); +``` + +### Android Logcat 过滤 + +```bash +# 只看 Clash 相关日志 +adb logcat -s "A/Clash" "E/Clash" "W/Clash" + +# 实时监控 FFI 调用 +adb logcat | grep -E "(ClashFFI|quickStart|getAndroidVpnOptions)" + +# 保存日志到文件 +adb logcat -d > clash_debug.log +``` + +### Dart Observatory 调试 + +```bash +# 启用 Dart Observatory +flutter run --observatory-port=8181 + +# 在浏览器打开 +open http://localhost:8181 + +# 查看 Isolate 状态 +# - Main Isolate (UI) +# - Service Isolate (Clash 后台) +``` + +--- + +## 性能问题 + +### 内存泄漏 + +**症状:** +- 应用内存持续增长 +- 最终 OOM 崩溃 + +**排查:** +```dart +// 确保调用 dispose() +@override +void dispose() { + KRClashImp().dispose(); + super.dispose(); +} + +// 检查 ReceivePort 是否关闭 +receivePort.listen((message) { + // ... + receivePort.close(); // ✅ 必须关闭! +}); +``` + +### CPU 占用过高 + +**症状:** +- 设备发热 +- 电池消耗快 + +**排查:** +```bash +# 查看 CPU 占用 +adb shell "top -m 10" + +# 使用 Profiler +flutter run --profile +# DevTools → CPU Profiler +``` + +**优化:** +```dart +// 降低流量统计频率 +Timer.periodic(const Duration(seconds: 2), (timer) { // ✅ 2秒而非1秒 + final traffic = await KRClashImp().getTraffic(); + // ... +}); +``` + +--- + +## 崩溃分析 + +### 获取崩溃堆栈 + +```bash +# Native 崩溃 +adb logcat -d | grep "backtrace" + +# 使用 ndk-stack 解析 +adb logcat | ndk-stack -sym android/app/build/intermediates/merged_native_libs/debug/out/lib/arm64-v8a +``` + +### 常见崩溃模式 + +#### SIGSEGV (段错误) + +**原因:** FFI 指针使用错误 + +**示例:** +```dart +// ❌ 错误: 释放后使用 +final ptr = 'hello'.toNativeUtf8(); +malloc.free(ptr); +_ffi!.someFunction(ptr); // 崩溃! + +// ✅ 正确: 使用后释放 +final ptr = 'hello'.toNativeUtf8(); +_ffi!.someFunction(ptr); +malloc.free(ptr); +``` + +#### SIGABRT (异常终止) + +**原因:** Go panic 未恢复 + +**解决:** 在 Go 侧添加 recover: +```go +//export quickStart +func quickStart(...) { + defer func() { + if r := recover(); r != nil { + log.Println("Panic recovered:", r) + } + }() + // ... +} +``` + +--- + +## 获取帮助 + +### 收集诊断信息 + +创建 Bug 报告时请包含: + +1. **系统信息:** +```bash +adb shell "getprop ro.build.version.release" # Android 版本 +adb shell "getprop ro.product.cpu.abi" # CPU 架构 +``` + +2. **应用日志:** +```bash +adb logcat -d > full_log.txt +``` + +3. **配置文件:** +```dart +// 脱敏后的 clash_config.yaml +print(config.replaceAll(RegExp(r'password:.*'), 'password: ***')); +``` + +4. **复现步骤:** +- 详细操作流程 +- 预期结果 vs 实际结果 +- 复现概率 + +### 相关资源 + +- [GitHub Issues](https://github.com/your-repo/issues) +- [Clash Meta Wiki](https://wiki.metacubex.one/) +- [Flutter FFI 文档](https://dart.dev/guides/libraries/c-interop) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..2a7457e --- /dev/null +++ b/docs/README.md @@ -0,0 +1,269 @@ +# LighthouseApp 技术文档 + +欢迎查阅 LighthouseApp 技术文档。本目录包含项目的架构设计、开发指南和故障排查信息。 + +## 📚 文档导航 + +### Clash Meta 核心 (推荐阅读) + +| 文档 | 说明 | 适用人群 | +|------|------|----------| +| [**架构文档**](./CLASH_ARCHITECTURE.md) | 完整架构设计、数据流、关键决策 | 所有开发者 | +| [**编译指南**](./CLASH_BUILD_GUIDE.md) | 本地编译步骤、环境配置、优化方法 | 核心开发者 | +| [**故障排查**](./CLASH_TROUBLESHOOTING.md) | 常见问题、日志分析、崩溃调试 | 测试/运维 | + +### CI/CD 工作流 + +| 文档 | 说明 | +|------|------| +| [**GitHub Actions 说明**](../.github/workflows/README.md) | 自动化构建、发布流程 | + +## 🚀 快速开始 + +### 新开发者入门 + +1. **了解架构** (必读) + - 阅读 [CLASH_ARCHITECTURE.md](./CLASH_ARCHITECTURE.md) + - 理解 Dart → Android → Go 三层架构 + - 掌握 FFI 通信机制 + +2. **配置开发环境** + - 按照 [CLASH_BUILD_GUIDE.md](./CLASH_BUILD_GUIDE.md) 配置环境 + - 编译第一个 Clash Core + - 验证编译结果 + +3. **运行项目** + ```bash + # 1. 获取代码 + git clone + cd LighthouseApp + + # 2. 初始化子模块 + git submodule update --init --recursive + + # 3. 编译核心 + cd core + make android-arm64 + + # 4. 运行 Flutter + cd .. + flutter pub get + flutter run + ``` + +### 核心开发者 + +如果您需要修改 Clash Meta 核心: + +1. **修改代码** + ```bash + cd core + vim lib_android.go # 或其他核心文件 + ``` + +2. **本地测试** + ```bash + make android-arm64 + flutter run + ``` + +3. **提交 PR** + - CI/CD 会自动构建所有架构 + - 检查 Actions 页面的构建结果 + - 等待代码审查 + +## 🏗️ 架构速览 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ LighthouseApp │ +├─────────────────────────────────────────────────────────────┤ +│ Flutter/Dart Layer │ +│ └─ lib/app/services/clash_imp/ │ +│ ├─ kr_clash_imp.dart (核心封装) │ +│ ├─ clash_ffi.dart (FFI 绑定) │ +│ └─ clash_config_generator (配置生成) │ +├─────────────────────────────────────────────────────────────┤ +│ Android Native Layer │ +│ └─ android/app/src/main/kotlin/com/hiddify/hiddify/ │ +│ ├─ bg/VPNService.kt (VPN 服务) │ +│ └─ bg/ClashService.kt (Clash 服务) │ +├─────────────────────────────────────────────────────────────┤ +│ Go Core Layer │ +│ └─ core/ │ +│ ├─ Clash.Meta/ (Git 子模块) │ +│ ├─ lib_android.go (JNI 桥接) │ +│ └─ libclash.so (编译产物) │ +└─────────────────────────────────────────────────────────────┘ +``` + +详细架构请参考 [CLASH_ARCHITECTURE.md](./CLASH_ARCHITECTURE.md) + +## 🔧 常见任务 + +### 编译核心 + +```bash +cd core + +# 单个架构 (快速) +make android-arm64 + +# 所有架构 (发布) +make android-all + +# 清理 +make clean + +# 验证 +make verify +``` + +### 更新 Clash.Meta + +```bash +cd core +make update # 更新子模块到最新版本 +make android-arm64 # 重新编译 +``` + +### 调试问题 + +```bash +# 查看 Android 日志 +adb logcat -s "A/Clash" "E/Clash" + +# 查看编译详情 +cd core +go build -v -x -buildmode=c-shared -o test.so . + +# 验证 SO 文件 +nm -D libclash.so | grep quickStart +``` + +## 📖 核心概念 + +### 1. FFI 并发安全 + +**问题:** Go 运行时初始化不是线程安全的 + +**解决:** 使用 `Completer` 实现初始化锁 + +```dart +Future _ensureInitialized() async { + if (_initialized) return; + if (_initLock != null) { + await _initLock!.future; // ✅ 等待其他初始化 + return; + } + // ... 执行初始化 +} +``` + +详见 [CLASH_ARCHITECTURE.md § 并发安全保证](./CLASH_ARCHITECTURE.md#并发安全保证) + +### 2. Service Isolate 架构 + +**为什么需要?** +- VPN 服务运行在后台 +- 主 Isolate 可能被销毁 +- 需要独立的 Dart 运行时 + +**实现:** +```kotlin +// ClashService.kt +serviceEngine = FlutterEngine(Application.application) +val entrypoint = DartExecutor.DartEntrypoint(..., "_clashService") +serviceEngine?.dartExecutor?.executeDartEntrypoint(entrypoint) +``` + +详见 [CLASH_ARCHITECTURE.md § Service Isolate 架构](./CLASH_ARCHITECTURE.md#2-android-service-层-clashservicekt) + +### 3. Android VPN 路由配置 + +**关键:** `getAndroidVpnOptions()` 返回 35+ 详细 CIDR 路由 + +**为什么重要?** +- 避免 PermissionMonitor error 22 +- 支持 bypass-LAN +- 兼容模拟器 + +详见 [CLASH_TROUBLESHOOTING.md § 问题 1](./CLASH_TROUBLESHOOTING.md#问题-1-vpn-连接失败日志显示-permissionmonitor-error-22-einval) + +## 🐛 遇到问题? + +1. **查看故障排查文档** + - [CLASH_TROUBLESHOOTING.md](./CLASH_TROUBLESHOOTING.md) 包含所有常见问题 + +2. **收集诊断信息** + ```bash + # 系统信息 + adb shell "getprop ro.build.version.release" + + # 应用日志 + adb logcat -d > full_log.txt + + # 核心信息 + cd core + make verify + ``` + +3. **提交 Issue** + - 使用诊断信息模板 + - 包含复现步骤 + - 附上日志文件 + +## 🤝 贡献指南 + +### 代码规范 + +项目遵循以下原则: +- **KISS** (Keep It Simple, Stupid) - 简单至上 +- **DRY** (Don't Repeat Yourself) - 杜绝重复 +- **SOLID** - 面向对象设计原则 +- **YAGNI** (You Aren't Gonna Need It) - 精益求精 + +### 提交流程 + +1. Fork 项目 +2. 创建特性分支 (`git checkout -b feature/amazing`) +3. 提交更改 (`git commit -m 'feat: add amazing feature'`) +4. 推送分支 (`git push origin feature/amazing`) +5. 创建 Pull Request + +### Commit 规范 + +使用 Conventional Commits: +- `feat:` 新功能 +- `fix:` 修复 Bug +- `docs:` 文档更新 +- `refactor:` 代码重构 +- `perf:` 性能优化 +- `test:` 测试相关 +- `chore:` 构建/工具链 + +## 📞 获取帮助 + +- **GitHub Issues:** [提交问题](https://github.com/your-repo/issues) +- **文档索引:** 您正在阅读! +- **外部资源:** + - [Clash Meta Wiki](https://wiki.metacubex.one/) + - [Flutter FFI 文档](https://dart.dev/guides/libraries/c-interop) + - [Android VPN 指南](https://developer.android.com/reference/android/net/VpnService) + +## 📝 更新日志 + +| 日期 | 版本 | 更新内容 | +|------|------|----------| +| 2025-10-25 | 1.0.0 | 完成 Xboard-Mihomo 核心集成 | +| 2025-10-25 | 1.0.0 | 修复 FFI 并发安全问题 | +| 2025-10-25 | 1.0.0 | 添加完整技术文档 | + +## 📄 许可证 + +本项目采用 [LICENSE](../LICENSE) 许可证。 + +--- + +**最后更新:** 2025-10-25 +**维护者:** LighthouseApp 开发团队 diff --git a/docs/go修复.md b/docs/go修复.md new file mode 100644 index 0000000..9bf051d --- /dev/null +++ b/docs/go修复.md @@ -0,0 +1,318 @@ +# Android SELinux chown 权限问题修复方案 + +## 问题背景 + +在 Android 12+ 系统上,由于 SELinux 严格模式的权限限制,sing-box 核心库在启动时会因为 `chown` 操作被拒绝而失败。具体表现为以下三个错误: + +1. **CommandServer 错误**: `chown: chown command.sock: operation not permitted` +2. **Logger 错误**: `start logger: chown box.log: operation not permitted` +3. **Clash Cache 错误**: `pre-start cache file: platform chown: chown clash.db: operation not permitted` + +## 问题分析 + +### 根本原因 + +sing-box (libbox) 在创建文件后会尝试修改文件所有权(`chown`操作),但在 Android 的 SELinux 环境下,应用无法修改外部存储目录中文件的所有权,导致启动失败。 + +### 涉及的文件 + +1. `command.sock` - CommandServer 的 Unix socket 文件 +2. `box.log` - sing-box 的日志文件 +3. `clash.db` - Clash API 的缓存数据库文件 + +## 修复方案 + +### 方案概述 + +**核心思路**: 在配置层面禁用会触发 chown 操作的功能,或者修改底层代码跳过 chown 操作。 + +由于修改 sing-box 底层库较为复杂,建议采用配置修改方案。 + +--- + +## 具体修复步骤 + +### 修复 1: 禁用文件日志 + +**文件**: `libcore/config/hiddify_option.go` + +**位置**: `DefaultHiddifyOptions()` 函数 + +**修改前**: +```go +LogLevel: "warn", +// LogFile: "/dev/null", +LogFile: "box.log", +``` + +**修改后**: +```go +LogLevel: "warn", +LogFile: "", // 禁用文件日志,避免 Android SELinux chown 权限问题 +// LogFile: "box.log", +``` + +**说明**: +- 将 `LogFile` 设置为空字符串,禁用文件日志输出 +- 日志将只输出到 stderr,可以通过 logcat 查看 +- 这不会影响日志功能,只是改变了输出目标 + +--- + +### 修复 2: 禁用 Clash API 缓存 + +**文件**: `libcore/config/config.go` + +**位置**: `setClashAPI()` 函数 + +**修改前**: +```go +func setClashAPI(options *option.Options, opt *HiddifyOptions) { + if opt.EnableClashApi { + if opt.ClashApiSecret == "" { + opt.ClashApiSecret = generateRandomString(16) + } + options.Experimental = &option.ExperimentalOptions{ + ClashAPI: &option.ClashAPIOptions{ + ExternalController: fmt.Sprintf("%s:%d", "127.0.0.1", opt.ClashApiPort), + Secret: opt.ClashApiSecret, + }, + + CacheFile: &option.CacheFileOptions{ + Enabled: true, + Path: "clash.db", + }, + } + } +} +``` + +**修改后**: +```go +func setClashAPI(options *option.Options, opt *HiddifyOptions) { + if opt.EnableClashApi { + if opt.ClashApiSecret == "" { + opt.ClashApiSecret = generateRandomString(16) + } + options.Experimental = &option.ExperimentalOptions{ + ClashAPI: &option.ClashAPIOptions{ + ExternalController: fmt.Sprintf("%s:%d", "127.0.0.1", opt.ClashApiPort), + Secret: opt.ClashApiSecret, + }, + + CacheFile: &option.CacheFileOptions{ + Enabled: false, // 禁用缓存以避免 Android SELinux chown 权限问题 + Path: "", // 清空路径 + }, + } + } +} +``` + +**说明**: +- 将 `Enabled` 设置为 `false`,禁用 Clash API 缓存功能 +- 将 `Path` 设置为空字符串 +- Clash API 功能仍然可用,只是不会持久化节点选择等信息 + +--- + +### 修复 3: CommandServer 错误处理 (可选) + +**说明**: CommandServer 主要用于命令行控制,对 Android VPN 功能不是必需的。 + +#### 方案 A: 在应用层捕获异常 (推荐) + +**文件**: `android/app/src/main/kotlin/com/hiddify/hiddify/bg/BoxService.kt` + +**位置**: `onStartCommand()` 函数 + +**修改**: +```kotlin +GlobalScope.launch(Dispatchers.IO) { + Settings.startedByUser = true + initialize() + try { + startCommandServer() + } catch (e: Exception) { + // CommandServer 启动失败不是致命错误 + // 在 Android 12+ SELinux 环境下,chown 操作可能被拒绝 + // 但这不影响 VPN 核心功能,因此记录警告但继续启动服务 + Log.w(TAG, "CommandServer failed to start (non-fatal): ${e.message}") + } + startService() +} +``` + +#### 方案 B: 完全禁用 CommandServer + +如果不需要 CommandServer 功能,可以直接注释掉启动代码: +```kotlin +// startCommandServer() // 在 Android 上禁用 +``` + +--- + +## 验证修复 + +### 编译步骤 + +1. **使用 Docker 编译** (推荐): +```bash +cd libcore +docker run --rm -v "$PWD:/workspace" -w /workspace golang:1.23 bash -c "bash docker-compile.sh" +``` + +2. **或者本地编译**: +```bash +cd libcore +make android +``` + +### 部署编译好的库 + +编译完成后,有两种部署方式: + +#### 方式A: 替换完整AAR (推荐生产环境) + +```bash +cd libcore +# 替换AAR文件 +cp libcore.aar ../android/app/libs/ + +# 删除可能冲突的so文件 +rm -rf ../android/app/src/main/jniLibs/ + +# 重新编译Flutter项目 +cd .. +flutter clean && flutter build apk +``` + +**优点**: 支持所有架构,适合发布版本 + +#### 方式B: 只提取arm64 so文件 (推荐测试环境) + +```bash +cd libcore +# 从AAR提取arm64的libbox.so +unzip -j libcore.aar jni/arm64-v8a/libbox.so -d /tmp/ +mkdir -p ../android/app/src/main/jniLibs/arm64-v8a/ +cp /tmp/libbox.so ../android/app/src/main/jniLibs/arm64-v8a/ + +# 临时禁用AAR(避免冲突) +mv ../android/app/libs/libcore.aar ../android/app/libs/libcore.aar.old + +# 编译测试版本 +cd .. +flutter clean && flutter build apk --debug --split-per-abi +``` + +**优点**: 编译快速,APK体积小,适合开发调试 + +⚠️ **重要**: 两种方式不能同时使用,会产生冲突!请根据需求选择其一。 + +### 测试验证 + +1. 重新编译 Flutter 应用 +2. 在 Android 设备上安装并启动 +3. 查看 logcat 日志,确认没有 chown 相关错误 +4. 验证 VPN 能正常启动和代理流量 + +--- + +## 预期结果 + +修复后,应用启动日志应该显示: + +``` +D/A/BoxService: base dir: /data/user/0/app.xxx.com/files +D/A/BoxService: working dir: /storage/emulated/0/Android/data/app.xxx.com/files +D/A/BoxService: temp dir: /data/user/0/app.xxx.com/cache +W/A/BoxService: CommandServer failed to start (non-fatal): chown: chown command.sock: operation not permitted +D/A/BoxService: starting service +D/A/BoxService: 配置已修改: 禁用文件日志和Clash缓存 +D/A/EventHandler: new status: Started ✅ 成功启动! +``` + +--- + +## 影响评估 + +### 功能影响 + +| 功能 | 修复前 | 修复后 | 影响 | +|------|--------|--------|------| +| VPN 代理 | ❌ 无法启动 | ✅ 正常工作 | 无影响 | +| 日志记录 | 文件输出 | logcat 输出 | 日志仍可用,通过 logcat 查看 | +| Clash API | 带缓存 | 无缓存 | 节点选择不持久化,重启后重置 | +| CommandServer | ❌ 失败 | 跳过启动 | 命令行控制不可用(非必需) | + +### 性能影响 + +- **无性能损失**: 禁用缓存和文件日志对性能无负面影响 +- **启动速度**: 可能略微加快(减少文件 I/O 操作) + +--- + +## 替代方案 (高级) + +如果需要保留完整功能,可以考虑以下方案: + +### 方案 1: 修改 sing-box 源码 + +在 sing-box 底层库中跳过 Android 平台的 chown 操作: + +```go +// 在文件创建后的 chown 调用处添加平台判断 +if runtime.GOOS != "android" { + if err := os.Chown(path, uid, gid); err != nil { + return err + } +} +``` + +**优点**: 保留所有功能 +**缺点**: 需要修改 sing-box 上游代码,维护成本高 + +### 方案 2: 使用内部存储 + +将文件创建在 `/data/user/0/` 目录下而不是外部存储: + +**优点**: 避免 SELinux 限制 +**缺点**: 空间受限,不适合大文件 + +--- + +## 常见问题 + +### Q1: 禁用文件日志后如何查看日志? + +**A**: 使用 adb logcat: +```bash +adb logcat | grep "A/BoxService\|singbox" +``` + +### Q2: 禁用 Clash 缓存后有什么影响? + +**A**: 每次启动 VPN 时,节点选择会重置为默认值,但不影响 VPN 的核心代理功能。 + +### Q3: 为什么 hiddify-app 可以正常运行? + +**A**: hiddify-app 使用的 libcore 版本已经包含了这些修复,或者使用了不同的配置策略。 + +### Q4: 这个修复是否适用于所有 Android 版本? + +**A**: 是的,这个修复对 Android 11 及以下版本也兼容,不会产生负面影响。 + +--- + +## 参考资料 + +- [Android SELinux 权限文档](https://source.android.com/docs/security/features/selinux) +- [sing-box 配置文档](https://sing-box.sagernet.org/configuration/) +- [Clash API 配置](https://sing-box.sagernet.org/configuration/experimental/clash-api/) + +--- + +## 更新日志 + +- **2025-10-27**: 初始版本,包含三个核心修复方案 diff --git a/libcore b/libcore index bfb026f..f993a57 160000 --- a/libcore +++ b/libcore @@ -1 +1 @@ -Subproject commit bfb026f06f8d9a70284cc585cb87f21ee3aa4d05 +Subproject commit f993a57755c37e08b02042037cbbf508c66c51f9