# Flutter 打包 APK 与真机安装指南 > 项目:强宝小助手(qiangbao_accounting) > 环境:Windows 11 + Flutter 3.47.4 / Dart 3.13.3 > 测试机:小米 M2007J22C(Android 12 / MIUI 14,设备号 `9dr4gyqgivl7tw5l`) --- ## 0. 快速开始(最常用的三条命令) ```bash # ① 开发调试:热重载,改代码存盘即生效 flutter run -d 9dr4gyqgivl7tw5l # ② 打包正式包 flutter build apk --release # ③ 装到手机 flutter install -d 9dr4gyqgivl7tw5l ``` --- ## 1. 前置检查 ```bash # 环境是否齐全(应全绿) flutter doctor # 手机是否连上(应看到设备号,状态为 device 而不是 unauthorized) adb devices # 依赖是否安装 flutter pub get ``` 如果 `adb devices` 显示 `unauthorized`,在手机上确认「允许 USB 调试」弹窗。 如果是 `offline`,拔插数据线或执行 `adb kill-server && adb start-server`。 --- ## 2. 场景一:开发调试(日常用这个) ```bash cd /d/nzy/workspace_nzy/qiangbao_accounting flutter run -d 9dr4gyqgivl7tw5l ``` 启动后终端会进入交互模式,这些键最常用: | 按键 | 作用 | |---|---| | `r` | **热重载** —— 改完代码存盘后按一下,约 0.5 秒看到效果(不重启 App) | | `R` | 热重启 —— 状态重置,但比重装快得多 | | `q` | 退出并断开 | | `p` | 显示 Widget 布局网格(调样式时很有用) | | `o` | 切换 iOS/Android 平台预览模式 | **默认是 debug 模式**,特点: - 启动慢、体积大(本项目 debug APK 81MB),但支持热重载 - 后端地址:Android 真机走 `http://localhost:12345/api`(依赖 adb reverse,见第 6 节) 想跑 release 模式验证性能(无热重载): ```bash flutter run --release -d 9dr4gyqgivl7tw5l ``` --- ## 3. 场景二:打包 APK ### 3.1 通用包(最省事,能装到任何 Android 手机) ```bash flutter build apk --release ``` 产物:`build/app/outputs/flutter-apk/app-release.apk` ### 3.2 按 CPU 架构拆分(体积更小,推荐) ```bash flutter build apk --release --split-per-abi ``` 产物(三个文件):`build/app/outputs/flutter-apk/` - `app-arm64-v8a-release.apk` —— **现代手机装这个**(小米 M2007J22C 就是 arm64) - `app-armeabi-v7a-release.apk` —— 老设备 - `app-x86_64-release.apk` —— 模拟器 体积对比:通用包约为单架构包的 **2~3 倍**(因为把所有架构的原生库都塞进去了)。 ### 3.3 只出指定架构 ```bash flutter build apk --release --target-platform android-arm64 ``` ### 3.4 其他选项 ```bash flutter build apk --release -v # 显示详细日志(排查构建失败用) flutter clean && flutter pub get # 构建异常时清缓存重来 ``` --- ## 4. 场景三:安装到手机 ### 方式 A:Flutter 命令(推荐) ```bash flutter install -d 9dr4gyqgivl7tw5l ``` 会自动找最近构建的 APK 并安装。想指定安装 debug 包: ```bash flutter install --debug -d 9dr4gyqgivl7tw5l ``` ### 方式 B:adb 直接安装 ```bash adb install -r build/app/outputs/flutter-apk/app-release.apk ``` - `-r` = 覆盖安装(保留数据) - `-d` = 允许降级安装 - 指定手机:`adb -s 9dr4gyqgivl7tw5l install -r xxx.apk` ### 方式 C:文件管理器手动安装(绕开 USB 限制) ```bash # 先把 APK 推到手机存储 MSYS_NO_PATHCONV=1 adb push build/app/outputs/flutter-apk/app-release.apk /sdcard/Download/qiangbao.apk ``` 然后在手机上: 1. 打开「**文件管理**」 2. 进入 **手机存储 → Download** 3. 点击 `qiangbao.apk` 4. 若提示「禁止安装未知来源应用」→ 点提示里的**设置**,允许「文件管理」安装应用 5. MIUI 安全检测后选「**继续安装**」 > ⚠️ Windows 上用 Git Bash 执行 `adb push` 必须加 `MSYS_NO_PATHCONV=1`,否则 `/sdcard/...` 会被错误转换成 `C:/Program Files/Git/sdcard/...`。 ### 卸载 ```bash adb uninstall com.qiangbao.qiangbao_accounting ``` --- ## 5. 小米 MIUI 特殊设置(必读) 如果没有开启下面这个开关,安装会被拦截并报: ``` Failure [INSTALL_FAILED_USER_RESTRICTED: Install canceled by user] ``` **开启路径**: ``` 设置 → 更多设置 → 开发者选项 → 「USB 安装」→ 打开 ``` 在「调试」分组里,位于「USB 调试」下方。 注意: - MIUI 通常要求**登录小米账号 + 插入 SIM 卡**才能开启该开关(防刷机策略) - 同时看到「**USB 调试(安全设置)**」也建议打开(模拟点击需要) - 看到 `USER_RESTRICTED` 就是厂商安全策略拦截,**不是代码或命令的问题** --- ## 6. 开发环境的后端连接(重要) App 里的 API 地址会**按构建模式自动切换**(见 `lib/core/network/api_env.dart`): | 构建模式 | 使用的后端地址 | |---|---| | debug | `http://localhost:12345/api`(本地后端) | | release | `https://accounting.aqroid.cn/api`(**生产环境**) | ### 6.1 真机 debug 连本地后端:用 adb reverse 真机的 `localhost` 指向手机自己,不是你的电脑。用端口转发让手机的 localhost 映射到电脑: ```bash adb reverse tcp:12345 tcp:12345 # 每次插拔设备/重启 adb 后都要重新执行 adb reverse --list # 确认映射存在 ``` 好处:不受 Windows 防火墙影响,也不要求手机和电脑在同一 Wi-Fi。 ### 6.2 不想用 adb reverse 时:改用局域网 IP ```bash # 查电脑局域网 IP(本项目实测为 192.168.50.182) ipconfig | grep -A2 IPv4 flutter run -d 9dr4gyqgivl7tw5l --dart-define=API_BASE_URL=http://192.168.50.182:12345/api ``` `--dart-define` 在 debug 和 release 下都生效,优先级最高: ```bash flutter build apk --release --dart-define=API_BASE_URL=http://192.168.50.182:12345/api ``` > 服务端 Spring Boot 需监听 `0.0.0.0`(默认即是),且 Windows 防火墙需放行 java 的入站。 --- ## 7. 正式发布前要做的事 ### 7.1 配置签名(自己测试可跳过,上架必须) 当前 `android/app/build.gradle.kts` 用的是 **debug 签名**(模板默认,仅供自测,应用商店会拒收): ```kotlin buildTypes { release { // TODO: Add your own signing config for the release build. signingConfig = signingConfigs.getByName("debug") } } ``` **① 生成密钥库(一次性,务必备份 + 记住密码)** ```bash keytool -genkey -v -keystore D:/keys/qiangbao-release.jks \ -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias qiangbao ``` **② 新建 `android/key.properties`(⚠️ 加入 .gitignore,不要提交)** ```properties storePassword=你的密码 keyPassword=你的密码 keyAlias=qiangbao storeFile=D:/keys/qiangbao-release.jks ``` **③ 修改 `android/app/build.gradle.kts`** ```kotlin import java.util.Properties import java.io.FileInputStream val keystoreProperties = Properties() val keystorePropertiesFile = rootProject.file("key.properties") if (keystorePropertiesFile.exists()) { keystoreProperties.load(FileInputStream(keystorePropertiesFile)) } android { signingConfigs { create("release") { keyAlias = keystoreProperties["keyAlias"] as String keyPassword = keystoreProperties["keyPassword"] as String storeFile = file(keystoreProperties["storeFile"] as String) storePassword = keystoreProperties["storePassword"] as String } } buildTypes { release { signingConfig = signingConfigs.getByName("release") } } } ``` **④ 打包** ```bash flutter build apk --release # 国内应用商店用 APK flutter build appbundle --release # Google Play 用 AAB(产物在 build/app/outputs/bundle/release/) ``` ### 7.2 版本号 `pubspec.yaml`: ```yaml version: 1.0.0+1 # ↑ ↑ # 版本名 版本号(versionCode) ``` **每次发版必须让 `+` 后面的数字递增**(否则应用商店/手机认为不是新版本,无法覆盖安装)。 产物中的体现:`versionName=1.0.0`、`versionCode=1`。 ### 7.3 应用名称与图标 **应用名称**(已配置好,改名字动这几处): | 平台 | 位置 | 当前值 | |---|---|---| | Android 桌面名 | `android/app/src/main/AndroidManifest.xml` 的 `android:label` | `强宝小助手` | | iOS 桌面名 | `ios/Runner/Info.plist` 的 `CFBundleDisplayName` | `强宝小助手` | | Web 标签页 | `web/index.html` 的 `