Vibeloy
注册
全部文章

博客

将 Flutter 应用发布到 Play Store 和 App Store:分步指南

发布日期: 更新日期: 阅读约 9 分钟

上线前检查清单

applicationId(Android)和 Bundle ID(iOS)是你应用在各商店中的永久身份标识;二者在首次上传后都无法更改。请在开始发布前就把两者定下来——之后再改就意味着从零开一个全新的列表,失去现有的评论和安装量。

在 Flutter 中,版本号保存在 pubspec.yaml 的 version: x.y.z+N 字段中;x.y.z 是面向用户显示的版本号,N 是构建号,它同时对应 Android 的 versionCode 和 iOS 的 build number。每次提交新版本时若未递增 N,上传就会被拒绝。

两个商店对图标的要求不同:Play 需要 512x512 像素、带 alpha 通道(透明度)的高分辨率图标,而 App Store 则要求 1024x1024 像素且不含 alpha 通道的 PNG。使用 flutter_launcher_icons 包,你可以用一张源图和一条命令同时生成两种图标。

Android:构建 app bundle 与 Play Console 流程

flutter build appbundle --release 命令会在 build/app/outputs/bundle/release/app-release.aab 生成可直接上架的软件包。Play Store 现在的新上传只接受 .aab 格式;你不需要再单独生成 .apk。

2023 年 11 月 13 日之后开通的个人(个体)Play Console 账号,在获得生产环境访问权限之前,必须完成一次不间断、为期 14 天、至少有 12 名活跃测试者参与的封闭测试。该要求不适用于企业账号或此日期之前开通的个人账号;由于规则会不时调整,申请前请在 Play Console 中查看当前要求。

为某个应用在 Play Console 上传的第一份 .aab 必须始终手动上传——不能用 CLI 或自动化提交;之后的版本才可以使用 CLI 或你自己的集成方案。正式发布到生产环境时,采用分阶段发布(例如先从 5%-20% 开始,一边观察 Android vitals 一边逐步提高比例)而不是一次性面向所有用户发布,能降低风险。

iOS:使用 Xcode/EAS 归档与 TestFlight 流程

flutter build ipa --release 命令会在 build/ios/ipa/ 下生成一个可发布的 .ipa 文件。归档该构建并发送到 App Store Connect 需要一台 Mac(实体机或云端);Xcode 无法在 Windows 或 Linux 上运行。如果你没有 Mac,可以选择 Codemagic、GitHub Actions 的 macOS runner 或 MacStadium 等云端 CI 服务。

你可以通过 Xcode Organizer 的流程(Window > Organizer > Archives > Distribute App),或使用独立的 Transporter 应用,将生成的 .ipa 上传到 App Store Connect;两种方式结果相同。Version(面向用户显示)和 build number(每次上传都必须唯一且递增,同一版本内不能重复使用)是两个独立的字段。

TestFlight 提供两个测试层级:内部测试(App Store Connect 团队内最多 100 人)不需要 Apple 审核,构建处理完成后即可使用。外部测试面向通过邮件或公开链接加入的测试人员(每组最多 10,000 人);添加到应用的第一个构建必须通过 Apple 的"beta review"(通常一天内完成),之后的构建则可能无需完整审核。

商店元数据:视觉素材、描述与数据安全表单

在 Play 上,字符限制非常严格:应用名称最多 30 字符,简短说明最多 80 字符,完整说明最多 4000 字符。在 App Store Connect 上,应用名称必须在整个商店中唯一,还需要填写副标题和关键词字段。截图尺寸(Play 手机截图为 1080x1920,App Store 的 6.9 英寸 iPhone 机型类别要求精确匹配像素)在两家商店中遵循不同规则。

两个商店都要求你申报数据收集行为:Play 的 Data safety 表单,以及 App Store 的 App Privacy 标签(有时被称为"营养标签")。如果你使用了广告 SDK、分析或崩溃报告工具,就必须在两处都准确勾选;若没有一个真正可访问、内容最新的隐私政策 URL,两个后台都不允许发布。

两个后台还都要求填写支持/联系方式字段:Play 上是账号级别的支持邮箱和可选的网站字段;App Store Connect 上是必填的 Support URL 和可选的 Marketing URL。如果你没有网站可填这些字段,我们在另一篇文章中介绍了切实可行的方案。

常见拒绝原因与 Expo(EAS)的差异

Apple 最常见的拒绝原因是:准则 2.1(a)(崩溃、白屏、失效链接、未声明的缺失功能,或未在 Review Notes 中为需要登录的功能提供可用的演示账号)、准则 5.1.1(权限用途说明为空或含糊),以及准则 4.3(套模板、稍作修改就重新提交的应用)。提交前在干净设备上进行端到端测试,能避免这三类问题中的大多数。

在 Play 上,最常见的问题是 Data safety 表单与 SDK 的实际行为不符,或隐私政策 URL 为空/无法访问;这两者都有被拒或日后被暂停的风险。使用 AdMob 却未做 app-ads.txt 验证不会直接导致拒绝,但可能限制广告投放,造成收入损失。

对于使用 Expo(EAS)的项目,流程在很大程度上是自动化的:npx eas-cli build --platform all --profile production 会在云端为两个商店同时构建,npx eas-cli submit 则自动完成提交(Play 的首次上传例外情况除外)。版本号保存在 app.json 中三个独立的字段——expo.version、expo.ios.buildNumber 和 expo.android.versionCode——而不是 Flutter 那样的单一 pubspec.yaml 字段,需要手动保持三者同步。

常见问题

在发布到 Play Store 之前,我应该在 Flutter 中运行什么命令?
flutter build appbundle --release;该命令会在 build/app/outputs/bundle/release/app-release.aab 生成你要上传到 Play Console 的软件包。
发布到 iOS 是否需要 Mac?
需要——归档构建需要 Xcode,而 Xcode 只能在 macOS 上运行。如果你没有实体 Mac,可以用 Codemagic、GitHub Actions 的 macOS runner 或 MacStadium 等云端 CI 服务来替代;如果你使用 Expo(EAS),构建本来就在云端完成,根本不需要自己的 Mac。
上传到 TestFlight 的构建会立即送达测试人员吗?
内部测试组是这样的——不需要 Apple 审核,构建处理完成即可使用。外部测试组则不同,只有添加到应用的第一个构建必须通过 Apple 的"beta review"(通常一天内完成);之后的构建可能无需完整审核。
Play Console 的封闭测试要求适用于所有人吗?
不适用于所有人。它只适用于 2023 年 11 月 13 日之后开通的个人(个体)账号;企业账号以及该日期之前开通的个人账号均不受此限制。
使用 Expo(EAS)和 Flutter 发布之间最大的区别是什么?
Flutter 的构建在本地进行(iOS 严格要求使用 Mac);Expo 则通过 EAS 在云端生成构建,并用其 submit 命令自动化完成大部分提交工作。版本号的管理方式也不同:Flutter 用 pubspec.yaml 中的单一字段,而 Expo 的 app.json 中则是三个独立字段。