第19章 - 打包与发布
嗨,朋友!我是长安。
终于到了最激动人心的一章!经过前面的学习,你已经可以开发出一个完整的 App 了。现在,让我们学习如何将应用打包发布到各大应用商店!
📋 发布前准备
1. 检查 pubspec.yaml
name: my_app
description: 一个优秀的 Flutter 应用
publish_to: 'none'
# 版本号格式:major.minor.patch+buildNumber
# major: 重大更新
# minor: 新功能
# patch: Bug 修复
# buildNumber: 构建号(每次发布递增)
version: 1.0.0+1
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
# 只保留必要的依赖...
flutter:
uses-material-design: true
assets:
- assets/images/
- assets/icons/
2. 更换应用图标
推荐使用 flutter_launcher_icons 包:
# pubspec.yaml
dev_dependencies:
flutter_launcher_icons: ^0.13.1
flutter_launcher_icons:
android: true
ios: true
image_path: "assets/icon/app_icon.png" # 1024x1024 PNG
adaptive_icon_background: "#FFFFFF"
adaptive_icon_foreground: "assets/icon/app_icon_foreground.png"
# 生成图标
flutter pub get
flutter pub run flutter_launcher_icons
3. 更换启动页
推荐使用 flutter_native_splash 包:
# pubspec.yaml
dev_dependencies:
flutter_native_splash: ^2.3.10
flutter_native_splash:
color: "#FFFFFF"
image: assets/splash/logo.png
android_12:
color: "#FFFFFF"
image: assets/splash/logo.png
# 生成启动页
flutter pub run flutter_native_splash:create
🤖 Android 打包
1. 创建签名密钥
签名密钥用于证明 App 是你发布的,非常重要,请妥善保管!
# Windows
keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-key-alias
# macOS/Linux
keytool -genkey -v -keystore ~/my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-key-alias
按提示输入:
- 密钥库口令(记住这个密码!)
- 姓名、组织、城市等信息
- 密钥口令(可以与密钥库口令相同)
2. 配置签名
创建 android/key.properties(不要提交到 Git!):
storePassword=你的密钥库密码
keyPassword=你的密钥密码
keyAlias=my-key-alias
storeFile=../my-release-key.jks
修改 android/app/build.gradle:
// 在 android { 之前添加
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
// ...已有配置
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
// 启用代码混淆
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
3. 配置应用信息
修改 android/app/build.gradle:
android {
namespace "com.example.myapp" // 应用包名
compileSdkVersion 34
defaultConfig {
applicationId "com.example.myapp" // 应用 ID(必须唯一)
minSdkVersion 21
targetSdkVersion 34
versionCode 1 // 构建号,每次发布递增
versionName "1.0.0" // 版本号
}
}
修改 android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="我的应用"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- ... -->
</application>
<!-- 声明需要的权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
4. 生成 APK / AAB
# 生成 APK(用于测试或直接分发)
flutter build apk --release
# 生成 APK(分别生成不同架构,包更小)
flutter build apk --split-per-abi
# 生成 AAB(Google Play 推荐格式)
flutter build appbundle --release
输出位置:
- APK:
build/app/outputs/flutter-apk/app-release.apk - AAB:
build/app/outputs/bundle/release/app-release.aab
5. 发布到应用商店
Google Play
- 注册 Google Play Console($25 一次性费用)
- 创建应用
- 填写应用信息(标题、描述、截图等)
- 上传 AAB 文件
- 设置定价和分发范围
- 提交审核
国内应用商店
各大应用商店(华为、小米、OPPO、vivo 等)流程类似:
- 注册开发者账号
- 创建应用
- 填写应用信息
- 上传 APK
- 提交审核
注意事项
- 国内应用商店需要软件著作权证书
- 部分商店需要ICP 备案
- 各商店审核标准不同,可能需要多次修改
🍎 iOS 打包
1. 准备工作
- 一台 Mac 电脑(必须)
- Apple Developer 账号($99/年)
- Xcode(最新版本)
2. 配置 Xcode
用 Xcode 打开 ios/Runner.xcworkspace:
- 选择 Runner 项目
- 在 Signing & Capabilities 中:
- 选择你的开发者账号
- 填写 Bundle Identifier(如
com.example.myapp)
- 在 General 中:
- 设置 Display Name(应用名称)
- 设置 Version 和 Build
3. 配置应用信息
修改 ios/Runner/Info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>我的应用</string>
<key>CFBundleDisplayName</key>
<string>我的应用</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<!-- 权限说明(必填,否则审核不通过) -->
<key>NSCameraUsageDescription</key>
<string>需要访问相机来拍照</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问相册来选择图片</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要获取位置来提供附近服务</string>
</dict>
</plist>
4. 构建 iOS 应用
# 构建 release 版本
flutter build ios --release
# 如果遇到签名问题,先清理
flutter clean
cd ios && pod install && cd ..
flutter build ios --release
5. 上传到 App Store
方式一:使用 Xcode
- 在 Xcode 中选择
Product→Archive - 等待构建完成
- 在 Organizer 中选择刚才的 Archive
- 点击
Distribute App - 选择
App Store Connect - 按提示完成上传
方式二:使用命令行
# 安装上传工具
gem install fastlane
# 初始化 fastlane
cd ios
fastlane init
# 上传到 TestFlight
fastlane pilot upload
6. App Store Connect 配置
- 登录 App Store Connect
- 创建新 App
- 填写应用信息:
- 名称、副标题
- 描述(至少写清楚功能)
- 关键词(用于搜索)
- 截图(各种尺寸)
- 隐私政策 URL
- 选择上传的构建版本
- 提交审核
iOS 审核注意事项
- 提供测试账号 - 如果有登录功能
- 隐私政策 - 必须有隐私政策页面
- 敏感权限说明 - 清晰说明为什么需要权限
- 内容合规 - 不能有违规内容
- 功能完整 - 不能有明显的 Bug 或崩溃
🌐 Web 部署
1. 构建 Web 应用
# 构建 Web 版本
flutter build web --release
# 指定渲染引擎(推荐 canvaskit,效果更好)
flutter build web --web-renderer canvaskit
# 使用 HTML 渲染(首次加载更快,但效果稍差)
flutter build web --web-renderer html
输出位置:build/web/
2. 配置 Web 应用
修改 web/index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的应用</title>
<meta name="description" content="应用描述">
<!-- PWA 配置 -->
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<!-- 加载动画 -->
<style>
.loading {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
</style>
</head>
<body>
<div id="loading" class="loading">
<img src="loading.gif" alt="Loading...">
</div>
<script src="flutter.js" defer></script>
<script>
window.addEventListener('load', function() {
_flutter.loader.loadEntrypoint({
onEntrypointLoaded: function(engineInitializer) {
engineInitializer.initializeEngine().then(function(appRunner) {
document.getElementById('loading').remove();
appRunner.runApp();
});
}
});
});
</script>
</body>
</html>
3. 部署选项
部署到静态托管
# Vercel
npm i -g vercel
cd build/web
vercel
# Netlify
npm i -g netlify-cli
cd build/web
netlify deploy --prod
# GitHub Pages
# 1. 创建 gh-pages 分支
# 2. 将 build/web 内容推送到该分支
# 3. 在仓库设置中启用 GitHub Pages
部署到自己的服务器
# 使用 Nginx
server {
listen 80;
server_name your-domain.com;
root /var/www/flutter-app;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
# 上传文件
scp -r build/web/* user@server:/var/www/flutter-app/
🔢 版本管理
版本号规范
# pubspec.yaml
version: 1.2.3+45
# │ │ │ │
# │ │ │ └── buildNumber: 构建号,每次发布递增
# │ │ └───── patch: Bug 修复
# │ └─────── minor: 新功能,向后兼容
# └───────── major: 重大更新,可能不兼容
自动递增版本号
# 使用脚本自动递增
# build.sh
#!/bin/bash
# 读取当前版本
current_version=$(grep 'version:' pubspec.yaml | sed 's/version: //')
version_name=$(echo $current_version | cut -d'+' -f1)
build_number=$(echo $current_version | cut -d'+' -f2)
# 递增构建号
new_build_number=$((build_number + 1))
new_version="$version_name+$new_build_number"
# 更新 pubspec.yaml
sed -i '' "s/version: .*/version: $new_version/" pubspec.yaml
echo "Version updated to $new_version"
版本更新日志
# CHANGELOG.md
## [1.2.0] - 2024-03-15
### 新增
- 支持深色模式
- 新增用户反馈功能
### 修复
- 修复登录页面闪退问题
- 修复列表加载缓慢问题
### 变更
- 优化启动速度
- 更新 UI 设计
## [1.1.0] - 2024-02-01
...
🚀 CI/CD 自动化
GitHub Actions 示例
创建 .github/workflows/release.yml:
name: Build and Release
on:
push:
tags:
- 'v*'
jobs:
build-android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.16.0'
channel: 'stable'
- name: Get dependencies
run: flutter pub get
- name: Build APK
run: flutter build apk --release
- name: Upload APK
uses: actions/upload-artifact@v4
with:
name: android-release
path: build/app/outputs/flutter-apk/app-release.apk
build-ios:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.16.0'
channel: 'stable'
- name: Get dependencies
run: flutter pub get
- name: Build iOS
run: flutter build ios --release --no-codesign
- name: Upload iOS
uses: actions/upload-artifact@v4
with:
name: ios-release
path: build/ios/iphoneos
build-web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.16.0'
channel: 'stable'
- name: Get dependencies
run: flutter pub get
- name: Build Web
run: flutter build web --release
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: build/web
📝 小结
这一章我们学习了应用打包和发布:
Android 打包
- 创建签名密钥
- 配置签名信息
- 生成 APK/AAB
- 发布到应用商店
iOS 打包
- 配置开发者账号
- 配置 Xcode 项目
- 构建并上传
- App Store Connect 配置
Web 部署
- 构建 Web 应用
- 选择部署平台
- 配置服务器
发布建议
- 版本管理规范 - 使用语义化版本号
- 保护签名密钥 - 妥善保管,不要泄露
- 测试充分 - 发布前在真机上充分测试
- 更新日志 - 记录每次更新的内容
- CI/CD 自动化 - 减少人工操作,避免错误
💪 练习题
- 为你的应用创建签名并生成 APK
- 配置 CI/CD 自动构建
- 尝试发布一个 Web 版本
🎉 恭喜完成教程!
到这里,Flutter 基础教程就全部完成了!你已经掌握了:
- ✅ Flutter 开发环境搭建
- ✅ Dart 语言基础
- ✅ Widget 和布局系统
- ✅ 状态管理和页面导航
- ✅ 网络请求和本地存储
- ✅ 动画和用户反馈
- ✅ 性能优化
- ✅ 打包发布
现在你已经具备了开发和发布一个完整 App 的能力!🚀
接下来,建议你前往 项目实战 章节,用实际项目来巩固所学知识。
由 编程指南 提供
