docs: 新增完整文档体系(setup-project / setup-android / setup-ios / CLAUDE.md)

This commit is contained in:
SkyJourney
2026-05-14 13:04:51 +08:00
parent bb07828234
commit a266323905
5 changed files with 1065 additions and 169 deletions
+233
View File
@@ -0,0 +1,233 @@
# Android 配置指南
本文档覆盖 Android 端从 Flavor 验证到正式签名发布包所需的全部配置步骤。
---
## 前提
- Android Studio Meerkat (2024.3) 或更高版本
- Android SDKAPI 34compileSdk/ API 21minSdk
- JDK 17Android Gradle Plugin 要求)
- 已完成 [setup-project.md](setup-project.md) 的 Step 14
---
## 1. 验证 Flavor 构建
脚手架预配置了三个 Flavor`dev` / `staging` / `prod`,对应三套应用名和包名后缀。
```bash
# 确认三个 Flavor 都能构建(debug 模式,速度最快)
make build-apk-dev # com.example.sunny_mochi.dev
flutter build apk --flavor staging --debug \
--dart-define-from-file=dart-defines/staging.json
# com.example.sunny_mochi.staging
flutter build apk --flavor prod --debug \
--dart-define-from-file=dart-defines/prod.json
# com.example.sunny_mochi
```
若构建失败,检查 `android/app/build.gradle.kts` 中的 `flavorDimensions``productFlavors` 配置。
---
## 2. 修改包名(业务项目必须)
编辑 `android/app/build.gradle.kts`,找到 `productFlavors``defaultConfig`
```kotlin
defaultConfig {
applicationId = "com.your_company.your_app" // ← 修改
// ...
}
productFlavors {
create("dev") {
applicationIdSuffix = ".dev"
// applicationId 实际为 com.your_company.your_app.dev
resValue("string", "app_name", "YourApp Dev") // ← 修改应用名
}
create("staging") {
applicationIdSuffix = ".staging"
resValue("string", "app_name", "YourApp Beta") // ← 修改应用名
}
create("prod") {
resValue("string", "app_name", "YourApp") // ← 修改应用名
}
}
```
同步修改 `android/app/src/main/AndroidManifest.xml` 确认使用 `@string/app_name`(脚手架默认已使用)。
---
## 3. 配置 Release 签名
### 3.1 生成 Keystore(首次)
```bash
mkdir -p android/keystore
keytool -genkey -v \
-keystore android/keystore/release.jks \
-alias your-key-alias \
-keyalg RSA \
-keysize 2048 \
-validity 10000
```
> ⚠️ **Keystore 丢失无法找回,必须妥善保管。** 建议:
> - 备份到加密云存储(1Password / Bitwarden Vault
> - CI/CD 系统通过 secret 变量注入,不放在仓库中
> - `android/keystore/` 目录已在 `.gitignore` 中
### 3.2 填写 key.properties
```bash
cp android/key.properties.template android/key.properties
```
编辑 `android/key.properties`(相对于 `android/app/` 目录):
```properties
storePassword=your-keystore-password
keyPassword=your-key-password
keyAlias=your-key-alias
storeFile=../keystore/release.jks
```
> `key.properties` 已在 `android/.gitignore` 中,不会被提交。
### 3.3 验证签名配置
```bash
# 构建 staging release APK(使用 release 签名)
make build-staging
# 查看签名信息
apksigner verify --print-certs \
build/app/outputs/flutter-apk/app-staging-release.apk
```
---
## 4. 配置 Firebase(可选)
若业务项目使用 Firebase(推送通知 / Analytics):
1. 在 [Firebase Console](https://console.firebase.google.com) 为每个 Flavor 创建应用(不同包名)
2. 下载各包名对应的 `google-services.json`,放置到对应 Flavor 目录:
```
android/app/src/
├── dev/google-services.json
├── staging/google-services.json
└── main/google-services.json # prod 用 main
```
3.`android/app/build.gradle.kts` 添加 Google Services 插件:
```kotlin
plugins {
// ...
id("com.google.gms.google-services")
}
```
4.`google-services.json` 加入 `.gitignore`(含 API key,勿提交):
```
# 在根 .gitignore 中添加
**/google-services.json
```
> `google-services.json` 已在 `android/.gitignore` 中有注释行,取消注释即可。
---
## 5. 配置 ProGuard / R8Release 混淆)
脚手架的 `android/app/build.gradle.kts` 已预启用 R8
```kotlin
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
```
`android/app/proguard-rules.pro` 中已预留 Drift / Sentry / Riverpod 保留规则注释,按需取消注释。
---
## 6. SQLCipher 注意事项
脚手架已在 `build.gradle.kts` 中处理 SQLCipher 的 native library 冲突:
```kotlin
packaging {
jniLibs {
pickFirsts += setOf("**/libsqlite3.so")
}
}
```
若后续新增包时出现 `libsqlite3.so` 重复错误,在此处追加相同模式即可。
---
## 7. CI/CD 构建(示例:GitHub Actions
以下为生产包构建的 workflow 关键步骤:
```yaml
- name: Decode keystore
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode \
> android/keystore/release.jks
- name: Write key.properties
run: |
cat > android/key.properties <<EOF
storePassword=${{ secrets.KEYSTORE_PASSWORD }}
keyPassword=${{ secrets.KEY_PASSWORD }}
keyAlias=${{ secrets.KEY_ALIAS }}
storeFile=../keystore/release.jks
EOF
- name: Write prod.json
run: |
echo '${{ secrets.PROD_DART_DEFINES }}' > dart-defines/prod.json
- name: Build AAB
run: make build-prod
```
Secrets 清单:`KEYSTORE_BASE64``KEYSTORE_PASSWORD``KEY_PASSWORD``KEY_ALIAS``PROD_DART_DEFINES`
---
## 常见问题
### Gradle sync 失败,报找不到 compileSdk
确认 Android SDK Platform 34 已安装(Android Studio → SDK Manager → Android 14)。
### `libsqlite3.so` duplicate 错误
`build.gradle.kts``packaging.jniLibs.pickFirsts` 中追加冲突的 .so 路径。
### Release APK 运行时崩溃,Debug APK 正常
通常是 ProGuard 混淆了不应混淆的类。查看 `build/outputs/mapping/` 下的 `seeds.txt` 和 Logcat,在 `proguard-rules.pro` 添加对应的 `-keep` 规则。
### 签名 APK 安装时提示"应用已安装但签名不同"
设备上已安装其他签名版本,需先卸载再安装,或换测试设备。
+243
View File
@@ -0,0 +1,243 @@
# iOS 配置指南
本文档覆盖 iOS 端从 CocoaPods 安装到 Archive 发布所需的全部配置步骤。
> **平台要求**macOS 系统 + Xcode 16+。Windows / Linux 无法进行 iOS 开发。
---
## 前提
- macOS 14 (Sonoma) 或更高版本
- Xcode 16.0(从 App Store 安装,包含 iOS 18 SDK
- CocoaPods 1.15+`sudo gem install cocoapods`
- Apple Developer 账户(真机运行需 Free 账户,发布需 Paid 账户 $99/年)
- 已完成 [setup-project.md](setup-project.md) 的 Step 14
---
## 1. 安装 CocoaPods 依赖
```bash
cd ios
pod install
cd ..
```
首次执行会拉取依赖,耗时 5–15 分钟(取决于网络)。成功后生成:
- `ios/Pods/` 目录(gitignore,不提交)
- `ios/Podfile.lock`(版本锁定,**应提交**
> 如果 `pod install` 卡住,检查 CocoaPods 源:
> ```bash
> pod repo update
> ```
---
## 2. 验证基础构建
```bash
# 无签名编译验证(不需要 Apple 账户)
flutter build ios --no-codesign --flavor dev \
--dart-define-from-file=dart-defines/dev.json
# 预期输出:
# ✓ Built build/ios/iphoneos/Runner.app
```
---
## 3. 配置 Bundle Identifier
打开 Xcode**必须通过 .xcworkspace 打开**):
```bash
open ios/Runner.xcworkspace
```
在 Xcode 中:
1. 左侧导航选择 **Runner** 项目
2. 选择 **Runner** Target → **General** 选项卡
3. **Bundle Identifier** 改为业务项目实际 ID
| Build Configuration | Bundle ID |
|---------------------|-----------|
| Debugdev 开发调试)| `com.your_company.your_app.dev` |
| Debug-staging | `com.your_company.your_app.staging` |
| Releaseprod 发布)| `com.your_company.your_app` |
> 脚手架默认使用单个 Bundle IDFlavor 区分由 xcconfig 控制。若需要三个独立 Bundle ID,在 `ios/Flutter/flavors/` 的 xcconfig 文件中添加 `PRODUCT_BUNDLE_IDENTIFIER` 覆盖。
---
## 4. 配置 Xcode Build Configuration 和 Scheme
脚手架已在 `ios/Flutter/flavors/` 中提供三套 xcconfig
| 文件 | 对应 Flavor |
|------|-----------|
| `dev.xcconfig` | 开发包(Debug-dev|
| `staging.xcconfig` | 测试包(Debug-staging / Release-staging|
| `prod.xcconfig` | 正式包(Release|
### 关联 xcconfig 到 Build Configuration
1. Xcode → **Runner** 项目 → **Info** 选项卡 → **Configurations**
2. 展开每个 Configuration,点击 Runner 旁的下拉:
| Configuration 名称 | 关联 xcconfig |
|--------------------|---------------|
| Debug | `Flutter/flavors/dev.xcconfig` |
| Release | `Flutter/flavors/prod.xcconfig` |
| Profile | `Flutter/flavors/prod.xcconfig` |
> 若需要 staging 独立 Configuration,在此添加 `Debug-staging` / `Release-staging`。
### 添加 dev / staging Scheme(推荐)
1. Xcode → **Product****Scheme****Manage Schemes**
2. 复制 `Runner` Scheme,重命名为 `dev`
3. 编辑 `dev` Scheme
- **Build Configuration**Run)→ `Debug`
-**Arguments** 中确认无硬编码的 dart-definesFlutter 通过 `--dart-define-from-file` 注入)
---
## 5. 配置代码签名
### 5.1 自动签名(开发调试,推荐)
1. Xcode → **Runner** Target → **Signing & Capabilities**
2. 勾选 **Automatically manage signing**
3. **Team** 选择你的 Apple Developer 账户
4. Xcode 会自动创建 Provisioning Profile 和 Signing Certificate
### 5.2 手动签名(CI/CD 或发布版)
1. 在 [Apple Developer Portal](https://developer.apple.com/account) 创建:
- Distribution Certificate(可签发 App Store / Ad Hoc 包)
- App ID(对应 Bundle Identifier
- Provisioning ProfileDistribution 类型)
2. 下载 `.mobileprovision` 文件,双击安装到 Xcode
3. 取消勾选 **Automatically manage signing**
4. 选择对应的 **Signing Certificate****Provisioning Profile**
---
## 6. 真机运行
```bash
# 确认设备已连接
flutter devices
# 运行到真机(dev 包)
flutter run --flavor dev \
--dart-define-from-file=dart-defines/dev.json \
-d <device-id>
# 或通过 Xcode 直接运行(选择 dev Scheme + 目标设备)
```
首次在设备上运行需要:
- 设备 → **设置 → 通用 → VPN 与设备管理** → 信任开发者证书
---
## 7. 构建 TestFlight / App Store Archive
```bash
# 1. 确保 prod.json 已配置正确
cat dart-defines/prod.json
# 2. 构建 iOS Release
flutter build ios --flavor prod --release \
--dart-define-from-file=dart-defines/prod.json
# 3. 在 Xcode 中 Archive(需要 Distribution Certificate
# Product → Archive → Distribute App → App Store Connect
```
### CI/CD ArchiveFastlane 示例)
```ruby
# Fastfile
lane :beta do
build_app(
workspace: "ios/Runner.xcworkspace",
scheme: "Runner", # 或 prod scheme
configuration: "Release",
export_method: "app-store",
export_options: {
provisioningProfiles: {
"com.your_company.your_app" => "Your App Store Profile"
}
}
)
upload_to_testflight
end
```
---
## 8. 常用 xcconfig 字段说明
`ios/Flutter/flavors/dev.xcconfig`
```xcconfig
// 覆盖 Display Name(桌面图标显示的应用名)
DISPLAY_NAME=YourApp Dev
// 覆盖 Bundle ID(若三包使用不同 ID
// PRODUCT_BUNDLE_IDENTIFIER=com.your_company.your_app.dev
// 覆盖 App Icon(若三包使用不同图标)
// ASSETCATALOG_COMPILER_APPICON_NAME=AppIconDev
```
---
## 9. 最低 iOS 版本
`Podfile` 已锁定 iOS 15.0
```ruby
platform :ios, '15.0'
```
若业务需要支持更低版本,修改此行并运行 `pod install`。同时在 Xcode → Target → **Deployment Info****iOS Deployment Target** 同步修改。
---
## 常见问题
### `pod install` 报 `CocoaPods could not find compatible versions`
```bash
pod repo update # 更新本地 CocoaPods 源
pod install --repo-update
```
### Xcode 打开 `.xcodeproj` 而非 `.xcworkspace`
必须打开 `.xcworkspace`,否则 CocoaPods 的依赖不会加载:
```bash
open ios/Runner.xcworkspace # ✓ 正确
# 不要 open ios/Runner.xcodeproj ✗
```
### 真机运行报 `Untrusted Developer`
设备 → 设置 → 通用 → VPN 与设备管理 → 找到 Developer App → 信任。
### Archive 失败,报 `Provisioning profile doesn't include the entitlement`
在 Apple Developer Portal 重新生成 Provisioning Profile(选中全部所需 Entitlements),重新下载安装。
### Flutter build 报 `The iOS deployment target is set to xxx, but the range of supported deployment targets is`
更新 `Podfile` 中的 `platform :ios` 版本,运行 `pod install`,并在 Xcode Target → Deployment Info 同步修改。
### 模拟器运行正常,真机崩溃(SecureStorage 相关)
iOS 模拟器的 Keychain 行为与真机不同。确认 Xcode → Target → **Signing & Capabilities** → 已添加 **Keychain Sharing** Capability(脚手架默认不需要,但某些系统版本可能要求)。
+234
View File
@@ -0,0 +1,234 @@
# 项目配置指南(所有开发者必读)
本文档覆盖从克隆脚手架到可以运行第一个 dev 包所需的全部步骤。
Android 和 iOS 的平台专属配置请分别参阅 [setup-android.md](setup-android.md) 和 [setup-ios.md](setup-ios.md)。
---
## 前提条件
| 工具 | 最低版本 | 安装方式 |
|------|---------|---------|
| Flutter SDK | 3.41.0 | [flutter.dev](https://docs.flutter.dev/get-started/install) |
| Dart SDK | 3.7.0 | 随 Flutter 一起安装 |
| Android Studio | Meerkat (2024.3) | [developer.android.com](https://developer.android.com/studio) |
| Xcode | 16.0 | Mac App Store(仅 iOS 开发需要)|
| CocoaPods | 1.15+ | `sudo gem install cocoapods` |
| make | 系统内置 | macOS/Linux 自带;Windows 用 Git Bash 或 WSL |
验证安装:
```bash
flutter --version # 应显示 ≥ 3.41.0
flutter doctor # 确认 Android toolchain + Xcode 全绿
```
---
## Step 1 — 克隆与初始化
```bash
git clone https://gitea.example.com/your-org/your-project.git # TODO: 替换实际地址
cd your-project
flutter pub get # 拉取所有依赖
make gen # 生成 .g.dart / .freezed.dart(约 1 分钟)
make gen-i18n # 生成 lib/i18n/strings.g.dart
```
> **注意**:如果 `make gen` 报错 `build_runner` 找不到,请先确认 `dart` 在 PATH 中:
> ```bash
> dart --version
> ```
---
## Step 2 — 填入项目 API 路径
编辑 `lib/core/config/api_paths.dart`,将所有空字符串替换为实际后端路径:
```dart
// 示例(sa-token + Spring Boot
static const String authLoginSms = '/sys/auth/sms-login';
static const String authLoginPwd = '/sys/auth/password-login';
static const String authSmsSend = '/sys/auth/send-sms';
static const String authLogout = '/sys/auth/logout';
static const String authRefresh = '/sys/auth/refresh-token';
static const String userProfile = '/sys/sys-user/app/userInfo';
// ... 其余路径按业务填写
```
所有 datasource 文件通过 `ApiPaths.xxx` 引用路径,**严禁字符串字面量散落**。
---
## Step 3 — 配置环境变量(dart-defines
### 3.1 开发环境(dev.json
```bash
# 直接编辑,此文件可提交(含占位符,无真实密钥)
nano dart-defines/dev.json
```
需填入的字段:
```json
{
"ENV": "dev",
"USE_MOCK": "true", // true = 使用 Mock Adapter(不调真实服务)
"INTERNAL_BUILD": "true", // true = 显示 Dev Panel 入口
"SENTRY_DSN": "", // dev 通常留空
"PINNED_FINGERPRINTS": "", // 证书指纹(dev 可留空跳过 SSL 绑定)
"API_BASE_URL": "http://192.168.1.100:8080", // TODO: 实际 dev 服务器
"RSA_PUBLIC_KEY": "MIIBIjANBg..." // TODO: 后端 RSA 公钥(Base64 DER
}
```
### 3.2 测试环境(staging.json
```json
{
"ENV": "test",
"USE_MOCK": "false",
"INTERNAL_BUILD": "true",
"SENTRY_DSN": "",
"PINNED_FINGERPRINTS": "",
"API_BASE_URL": "https://staging.your-domain.com", // TODO
"RSA_PUBLIC_KEY": "MIIBIjANBg..." // TODO
}
```
### 3.3 生产环境(prod.json
```bash
cp dart-defines/prod.json.template dart-defines/prod.json
nano dart-defines/prod.json
```
```json
{
"ENV": "prod",
"USE_MOCK": "false",
"INTERNAL_BUILD": "false",
"SENTRY_DSN": "https://xxx@sentry.io/yyy", // TODO: Sentry 项目 DSN
"PINNED_FINGERPRINTS": "AA:BB:CC:...", // TODO: 服务器证书 SHA-256 指纹
"API_BASE_URL": "https://api.your-domain.com",// TODO
"RSA_PUBLIC_KEY": "MIIBIjANBg..." // TODO
}
```
> **prod.json 已在 .gitignore 中**,不会被提交。CI/CD 系统通过 secret 变量注入。
### 获取 RSA 公钥
后端一般提供 RSA 公钥的 Base64 DER 编码。若后端使用 sa-token + RSA
```bash
# Java 后端:从 public.key 文件提取(去掉 PEM header/footer,拼接成单行)
cat public.key | grep -v "BEGIN\|END" | tr -d '\n'
```
### 获取证书 SHA-256 指纹
```bash
# 方法 1openssl(推荐)
echo | openssl s_client -connect api.your-domain.com:443 2>/dev/null \
| openssl x509 -fingerprint -sha256 -noout \
| sed 's/SHA256 Fingerprint=//'
# 方法 2:Chrome → 锁图标 → 证书 → 指纹
```
---
## Step 4 — 验证首次运行
```bash
# 方式 1:使用 Mock(推荐首次验证,不需要后端服务)
# 确保 dart-defines/dev.json 中 USE_MOCK=true
make run-dev
# 方式 2:连接真实后端
# 确保 dart-defines/dev.json 中 USE_MOCK=false + API_BASE_URL 已填入
make run-dev
```
**期望结果:**
- APP 启动,显示登录页(手机号 + SMS/密码双模式)
- 右上角(或侧滑)可进入 Dev Panel(Talker 日志面板)
- `flutter analyze` 输出 `103 issues found`(均为 info 级别,0 errors
---
## Step 5 — 更新包名(业务项目必须)
脚手架默认包名为 `com.example.sunny_mochi`,接手后必须替换:
### Android
编辑 `android/app/build.gradle.kts`
```kotlin
// dev Flavor
applicationId = "com.your_company.your_app.dev"
// staging Flavor
applicationId = "com.your_company.your_app.staging"
// prod / release
defaultConfig {
applicationId = "com.your_company.your_app"
}
```
### iOS
在 Xcode 中修改 Bundle Identifier(见 [setup-ios.md](setup-ios.md) Step 3)。
### pubspec.yaml + Dart 导入路径
```yaml
name: your_app_name # 修改后所有 import 路径也需要更新
```
批量替换导入:
```bash
# macOS / Linux
find lib -name "*.dart" -exec sed -i '' 's/package:sunny_mochi/package:your_app_name/g' {} \;
# Windows PowerShell
Get-ChildItem -Path lib -Recurse -Filter "*.dart" |
ForEach-Object { (Get-Content $_.FullName) -replace 'sunny_mochi', 'your_app_name' |
Set-Content $_.FullName }
```
运行 `make gen` 重新生成后确认无编译错误。
---
## Step 6 — 平台专属配置
- **Android**(签名 / Flavor 验证 / 发布包构建)→ [setup-android.md](setup-android.md)
- **iOS**Xcode Scheme / CocoaPods / 证书 / Archive)→ [setup-ios.md](setup-ios.md)
---
## 常见问题
### `build_runner` 生成失败,报 analyzer 版本冲突
确认 `pubspec.yaml` 中的 `dependency_overrides`
```yaml
dependency_overrides:
drift: 2.31.0
json_serializable: 6.13.0
```
若被修改,恢复后重跑 `flutter pub get && make gen`
### App 启动后 token 丢失 / 每次重启都跳登录
SecureStorage 在 iOS Simulator 上可能行为异常。请在真机测试,或检查 `Keychain Sharing` 是否开启。
### Mock 模式下请求崩溃 `Unable to load asset`
检查 `assets/fixtures/` 下是否有对应的 JSON 文件,且 `pubspec.yaml` 中的 `assets:` 包含了对应子目录。
### `flutter analyze` 报错(非 info 级别)
先运行 `make gen` 确保生成文件是最新的,再重新 analyze。