在一般的开发过程中,我们可以使用 flutter run
命令,或者 IntelliJ 工具栏中的 Run 和 Debug 来测试 app。这时候,Flutter 默认会为我们构建 app 的调试版本。
当想要发布 app 时,比如 发布到 Google Play Store,可以按照以下步骤来准备 Android 平台的 发布 版本。本页面的内容包含如下主题:
1. 添加启动图标
2. 创建一个密钥库
3. 启用混淆器
4. 检查 app manifest 文件
5. 检查构建配置
6. 为发布构建应用程序
7. 发布到 Google Play Store
8. 更新应用版本号
9. 安卓发布常见问题
1. 添加启动图标
当我们创建一个新的 Flutter app 的时候,它会有一个默认的启动图标。
或者,如果我们想手动操作,可以参考以下方法:
(1)查看 Material Design Product Icons 指南中图标设计部分。
(2)在 /android/app/src/main/res/
目录下,把我们的图标文件放在以 配置限定符 命名的文件夹中。类似默认的 mipmap-
文件夹这样的命名方式。
(3)在 AndroidManifest.xml
中,更新 application
标签中的 android:icon
属性来引用上一步骤中我们自己的图标文件 (例如,)。
(4)用 flutter run
运行 app,检查启动程序中的 app 图标是否已经替换成我们自己的图标文件。
2. 为 app 签
要想把 app 发布到 Play store,还需要给 app 一个数字签名。我们可以采用以下步骤来为 app 签名:
2.1 创建一个密钥库
如果我们已经有一个密钥库,可以跳到下一步。如果没有,在命令行中运行以下的命令来创建一个:
在 macOS 或者 Linux 系统上,执行下面的代码
keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
在 Windows 系统上,执行下面的代码
keytool -genkey -v -keystore c:/Users/USER_NAME/key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias key
备忘
保证这个文件的私有性,不要将它提交到公共的代码管理空间。
备忘
keytool
可能不在我们的系统路径中。它是 Java 的一部分,在安装 Android Studio 的时候会被一起安装。运行flutter doctor -v
,’Java binary at:’ 之后打印出来的就是它的路径,然后用java
来替换以上命令中的keytool
,并加上keytool
的完整路径即可。如果文件路径包含空格,类似Program Files
这样的,你需要在路径上加入转义符:/"Program Files"/
。- 只有 Java 9 或更高版本才需要
-storetype JKS
标签。从 Java 9 版本开始,keystore 类型默认为 PKS12。
2.2 从 app 中引用密钥库
创建一个名为 /android/key.properties
的文件,它包含了密钥库位置的定义:
storePassword=
keyPassword=
keyAlias=key
storeFile=/key.jks>
备忘
(再次)请保证这个文件的私有性,不要将它提交到公共的代码管理空间。
2.3 在 gradle 中配置签名
通过编辑 /android/app/build.gradle 文件来为我们的 app 配置签名:
(1)将如下内容:
android {
替换为我们的 properties 文件的密钥库信息:
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
(2)将如下内容:
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now,
// so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
替换为我们的配置内容:
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
现在我们 app 的发布版本就会被自动签名了。
3. 启用混淆器
默认情况下,Flutter 不会做混淆或者压缩 Android host 的工作。如果 app 使用了第三方的 Java 或者 Android 库,我们会希望减小 APK 的大小,或者保护代码不被反编译出来。
要了解混淆 Dart 代码的相关信息,可以参考 Flutter wiki 上的 Obfuscating Dart Code。
步骤1:配置 Proguard
创建 /android/app/proguard-rules.pro
文件并添加下面的规则:
## Flutter wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
-dontwarn io.flutter.embedding.**
以上这样的配置只是对 Flutter 引擎库做保护。如果想要保护其他的库(例如,Firebase),需要为它们添加自己的规则。
步骤2:启用混淆以及/或压缩
在 /android/app/build.gradle
文件找到 buildTypes
的定义。在 release
配置中设置 minifiyEnabled
和 useProguard
为 true。另外我们必须再设置 Proguard 指向步骤 1 中我们创建的文件。
android {
...
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
备忘
混淆和压缩会大大地延长安卓应用程序的编译时间。
4. 检查 app manifest 文件
检查位于 /android/app/src/main
的默认 App Manifest 文件 AndroidManifest.xml
,并确认各个值都设置正确,特别是:
application
:编辑application
标签中的android:label
来设置 app 的最终名字。uses-permission
:如果你的代码需要互联网交互,请加入android.permission.INTERNET
权限标签。标准开发模版里并未加入这个权限(但是 Flutter debug 模版加入了这个权限),加入这个权限是为了允许 Flutter 工具和正在运行的 app 之间的通信。
5. 检查构建配置
检查位于 /android/app
的默认 Gradle build file,并确认各个值都设置正确,特别是下面 defaultConfig
块中的值:
applicationId
:指定最终的,唯一的(Application Id)appid。versionCode
&versionName
:指定 app 的内部版本号,以及用于显示的版本号,这可以通过设置 pubspec.yaml 文件中version
属性来做。minSdkVersion
&targetSdkVersion
:指定支持的最低 API 版本,以及我们 app 的目标 API 版本。
6. 为发布构建应用程序
当要发布到 Play Store 时,你有两种可能的发布方式
- App bundle (推荐)
- APK
备忘
Google Play Store 更推荐 app bundle 方式。更多信息可以参考 Android App Bundle
and About Android App Bundles
。
6.1 构建一个 app bundle
这个部分描述了如何构建一个发布的 app bundle。如果在前面的部分已经完成了签名步骤,发布的 bundle 会被签名。
注意
最近 Flutter team 收到的几份开发者反馈显示,他们在尝试构建 app bundle 的时候,会在某些 Android 6.0 某些设备上崩溃。
在 Android team 努力寻找可行的解决方案时,你可以先尝试将 APK 拆分作为临时解决方案。
使用如下命令:
(1)运行 cd
。(将 替换为我们 app 的目录)。
(2)运行 flutter build appbundle
。(运行 flutter build
默认构建一个发布版本。)
你的应用的 release bundle 会被创建到 /build/app/outputs/bundle/release/app.aab
.
此 app bundle 会默认地包含为 armeabi-v7a (32-bit) 和 arm64-v8a (64-bit) 编译的 Dart 和 Fluter 运行时代码。
6.2 测试 app bundle
一个 app bundle 可以用多种方法测试,这里介绍两种。
6.2.1离线使用 bundle tool
(1)如果你还没准备好,可以从 GitHub repository 下载 bundletool
(2)从你的 app bundle Generate a set of APKs
(3)Deploy the APKs to connected devices.
Deploy the APKs 连接到你的设备
6.2.2 在线使用 Google Play
(1)上传你的 bundle 到 Google Play 去测试它。或者在正式发布之前用 alpha 或 beta 频道去测试。
(2)按照 these steps to upload your bundle 上传到 Play Store。
6.3 构建一个 APK
虽然 app bundle 比 APKs 更被推荐使用,但是有一些 Store 目前还不支持 app bundle方式。这种情况下,要为各种目标 ABI (Application Binary Interface) 分别构建发布的 APK 文件。
如果你完成签名步骤, APK 就被签名了。
使用如下命令:
(1)cd
(将 替换为我们 app 的目录)。
(2)行 flutter build apk
(flutter build
默认带有 --release
参数)。
这个命令会生成两个 APK 文件:
/build/app/outputs/apk/release/app-armeabi-v7a-release.apk
/build/app/outputs/apk/release/app-arm64-v8a-release.apk
如果移除 --split-per-abi
将会生成一个包含_所有_目标 ABI 的 fat APK 文件。这种 APK 文件将会在比单独构建的 APK 文件尺寸要大,会导致用户下载一些不适用于其设备架构的二进制文件。
6.4 在设备上安装 APK 文件
按照如下这些步骤,将前一步中构建出来的 APK 安装到 Android 设备上。
使用如下命令:
(1)用 USB 线将 Android 设备连接到电脑上。
(2)cd
, 是我们 app 的目录。
(3)运行 flutter install
。
7. 发布到 Google Play Store
要了解如何发布一个 app 到 Google Play Store,可以参考 Google Play publishing documentation。
当你创建了应用之后,你可以通过 Google Ads 吸引更多用户, Google Ads 平台可以通过机器学习帮助你以非常高的性价比吸引到更多用户。
通过以下几步创建一个广告宣传:
(1)创建广告—我们会根据您的应用信息帮您制作广告。另外,您还可以添加图片和视频。
(2)决定推广预算—对于以提高应用安装量为主要目标的广告系列,您需要为其设置应用安装出价,也就是“目标每次安装费用”,同时设置每日推广支出预算。
(3)选择目标地区—让我们知道你希望触达哪些区域的用户。
(4)设定用户行动—决定你希望用户要做什么,比如安装,应用内操作或者目标广告支出回报率 (ROAS)。
8. 更新应用版本号
每个应用默认的初始版本号是 1.0.0。若要更新它,请转到 pubspec.yaml 文件并更新以下内容:
version: 1.0.0+1
版本号由三个点分隔的数字组成,例如上面样例中的 1.0.0
。然后是可选的构建号,例如上面样例中的 1
,以 +
分隔。
版本号与构建号都可以在 Flutter 打包时分别使用 --build-name
和 --build-number
重新指定。
在 Android 中,当 build-number
被用作 versionCode
时 build-name
作为 versionName
使用。更多信息请参考 Android 文档中的 为你的应用添加版本。
9. Android发布常见问题
这里是一些关于安卓应用程序发布的常见问题。
9.1 我应该什么时候构建 app bundles 而不是 APKs?
Google Play Store 相对于 APKs 更建议你发布 app bundles,因为那样应用程序会更有效率地交付给你的用户。但是,如果你想将应用程序发布到其他的应用商店, APK可能是唯一选项。
9.2 什么是 fat APK?
一个 fat APK 是一个包含了支持多个 ABI 架构的 APK 文件。这样做的好处是单个 APK 可以运行在多个架构上,因此具有更广泛的兼容性。但同时缺点就是文件体积会比较大,导致用户在安装你的应用程序时会下载和储存更多的字节。当构建 APKs 而不是 app bundles 时强烈建议分开构建 APKs,如 build an APK 所描述的那样,使用 --split-per-abi
指令。
9.3 哪些目标架构是被支持的?
当使用 release 模式构建你的应用程序时, Flutter app 可以基于 armeabi-v7a (32-bit) 和 arm64-v8a (64-bit)被编译。Flutter 目前不支持 x86 Android (参考 Issue 9253).
9.4 如何使用 Android Studio 构建一个发布?
在Android Studio中, 打开你的 app 文件夹下的 android/
文件夹. 然后在项目面板中选择 build.gradle (Module: app) :
接下来,选择构建变体。在主菜单中点击 Build > Select Build Variant。从 Build Variants 面板中选择任意一个变体(默认是 debug)。
生成的 app bundle 或 APK 文件会在你的 app 所在文件夹下的 build/app/outputs
文件夹下。