打包和发布到 Android 平台
在一般的开发过程中,我们可以使用 flutter run
命令,或者 IntelliJ 工具栏中的 Run 和 Debug 来测试 app。这时候,Flutter 默认会为我们构建 app 的调试版本。
当想要发布 app 时,比如 发布到 Google Play Store,可以按照以下步骤来准备 Android 平台的 发布 版本。本页面的内容包含如下主题:
添加启动图标
当我们创建一个新的 Flutter app 的时候,它会有一个默认的启动图标。要自定义这个图标,可以参考[Flutter Launcher Icons][]。
或者,如果我们想手动操作,可以参考以下方法:
查看 Material Design Product Icons 指南中图标设计部分。
在
<app dir>/android/app/src/main/res/
目录下,把我们的图标文件放在以 配置限定符 命名的文件夹中。类似默认的mipmap-
文件夹这样的命名方式。在
AndroidManifest.xml
中,更新application
标签中的android:icon
属性来引用上一步骤中我们自己的图标文件(例如,<application android:icon="@mipmap/ic_launcher" …
)。用
flutter run
运行 app,检查启动程序中的 app 图标是否已经替换成我们自己的图标文件。
为 app 签名
要想把 app 发布到 Play store,还需要给 app 一个数字签名。我们可以采用以下步骤来为 app 签名:
创建一个密钥库
如果我们已经有一个密钥库,可以跳到下一步。如果没有,在命令行中运行以下的命令来创建一个:
在 macOS 或者 Linux 系统上,执行下面的代码
```terminal
keytool -genkey -v -keystore ~/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key
On Windows, use the following command:
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。
从 app 中引用密钥库
创建一个名为 <app dir>/android/key.properties
的文件,它包含了密钥库位置的定义:
storePassword=<上一步骤中的密码>
keyPassword=<上一步骤中的密码>
keyAlias=key
storeFile=<密钥库的位置,e.g. /Users/<用户名>/key.jks>
备忘
(再次)请保证这个文件的私有性,不要将它提交到公共的代码管理空间。
在 gradle 中配置签名
通过编辑 <app dir>/android/app/build.gradle
文件来为我们的 app 配置签名:
- 将如下内容:
android {
替换为我们的 properties 文件的密钥库信息:
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
- 将如下内容:
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 的发布版本就会被自动签名了。
启用混淆器
默认情况下,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'
}
}
}
备忘
混淆和压缩会大大地延长安卓应用程序的编译时间。
检查 app manifest 文件
检查位于 <app dir>/android/app/src/main
的默认 App Manifest 文件 AndroidManifest.xml
,并确认各个值都设置正确,特别是:
application
Edit the
android:label
in theapplication
tag to reflect the final name of the app.application
:编辑application
标签中的android:label
来设置 app 的最终名字。uses-permission
- Add the
android.permission.INTERNET
permission if your application code needs Internetaccess. The standard template does not include this tag but allowsInternet access during development to enable communication betweenFlutter tools and a running app.uses-permission
:如果你的代码需要互联网交互,请加入android.permission.INTERNET
权限标签。标准开发模版里并未加入这个权限(但是 Flutter debug 模版加入了这个权限),加入这个权限是为了允许 Flutter 工具和正在运行的 app 之间的通信,详情见 Issue 22139。
检查构建配置
检查位于 <app dir>/android/app
的默认 Gradle build file,并确认各个值都设置正确,特别是下面 defaultConfig
块中的值:
applicationId
- Specify the final, unique (Application Id)appid
applicationId
:指定最终的,唯一的(Application Id)appid。
versionCode
&versionName
- Specify the internal app version number,and the version number display string. You can do this by settingthe
version
property in the pubspec.yaml file. Consult the versioninformation guidance in the versions documentation.
versionCode
& versionName
:指定 app 的内部版本号,以及用于显示的版本号,这可以通过设置 pubspec.yaml 文件中 version
属性来做。具体可以参考 版本文档 中的版本信息指南。
minSdkVersion
&targetSdkVersion
- Specify the minimum API level,and the API level on which the app is designed to run.Consult the API level section in the versions documentationfor details.
minSdkVersion
& targetSdkVersion
:指定支持的最低 API 版本,以及我们 app 的目标 API 版本。具体可以参考 版本文档 中的 API 版本部分。
为发布构建应用程序
当要发布到 Play Store 时,你有两种可能的发布方式
App bundle (推荐)
APK
备忘
Google Play Store 更推荐 app bundle 方式. 更多信息可以参考 Android App Bundle and About Android App Bundles.
构建一个 app bundle
这个部分描述了如何构建一个发布的 app bundle。如果在前面的部分已经完成了签名步骤,发布的 bundle 会被签名。
请注意 Recently, the Flutter team has received several reports from developers indicating they are experiencing app crashes on certain devices on Android 6.0 when building an app bundle.
最近 Flutter team 收到的几份开发者反馈显示,他们在尝试构建 app bundle 的时候,会在某些 Android 6.0 某些设备上崩溃。
在 Android team 努力寻找可行的解决方案时,你可以先尝试将 APK 拆分作为临时解决方案。更多有关信息请查看 Issue 36822。
使用如下命令:
运行
cd <app dir>
。(将<app dir>
替换为我们 app 的目录)。运行
flutter build appbundle
。(运行flutter build
默认构建一个发布版本。)
你的应用的 release bundle 会被创建到<app dir>/build/app/outputs/bundle/release/app.aab
.
此 app bundle 会默认地包含为 armeabi-v7a (32-bit) 和 arm64-v8a (64-bit) 编译的 Dart 和 Fluter 运行时代码。
测试 app bundle
一个 app bundle 可以用多种方法测试,这里介绍两种。
离线使用 bundle tool
如果你还没准备好,可以从 GitHub repository 下载
bundletool
从你的 app bundle Generate a set of APKs
Deploy the APKs to connected devices.
Deploy the APKs 连接到你的设备
在线使用 Google Play
上传你的 bundle 到 Google Play 去测试它。或者在正式发布之前用 alpha 或 beta 频道去测试。
按照 these steps to upload your bundle 上传到 Play Store。
构建一个 APK
虽然 app bundle 比 APKs 更被推荐使用,但是有一些 Store 目前还不支持 app bundle方式。这种情况下,要为各种目标 ABI (Application Binary Interface) 分别构建发布的 APK 文件。
如果你完成签名步骤, APK 就被签名了。
使用如下命令:
cd <app dir>
(将<app dir>
替换为我们 app 的目录)。运行
flutter build apk
(flutter build
默认带有—release
参数)。
这个命令会生成两个 APK 文件:
<app dir>/build/app/outputs/apk/release/app-armeabi-v7a-release.apk
<app dir>/build/app/outputs/apk/release/app-arm64-v8a-release.apk
如果移除 —split-per-abi
将会生成一个包含所有目标 ABI 的 fat APK 文件。这种 APK 文件将会在比单独构建的 APK 文件尺寸要大,会导致用户下载一些不适用于其设备架构的二进制文件。
在设备上安装 APK 文件
按照如下这些步骤,将前一步中构建出来的 APK 安装到 Android 设备上。
使用如下命令:
用 USB 线将 Android 设备连接到电脑上。
cd <app dir>
,<app dir>
是我们 app 的目录。运行
flutter install
。
发布到 Google Play Store
要了解如何发布一个 app 到 Google Play Store,可以参考 Google Play publishing documentation。
当你创建了应用之后,你可以通过 Google Ads 吸引更多用户,Google Ads 平台可以通过机器学习帮助你以非常高的性价比吸引到更多用户。
通过以下几步创建一个广告宣传:
创建广告—我们会根据您的应用信息帮您制作广告。另外,您还可以添加图片和视频。
决定推广预算—对于以提高应用安装量为主要目标的广告系列,您需要为其设置应用安装出价,也就是“目标每次安装费用”,同时设置每日推广支出预算。
选择目标地区—让我们知道你希望触达哪些区域的用户。
设定用户行动—决定你希望用户要做什么,比如安装,应用内操作或者目标广告支出回报率 (ROAS)。
更新应用版本号
每个应用默认的初始版本号是 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 文档中的为你的应用添加版本。
Android发布常见问题
这里是一些关于安卓应用程序发布的常见问题。
我应该什么时候构建 app bundles 而不是 APKs?
Google Play Store 相对于 APKs 更建议你发布 app bundles,因为那样应用程序会更有效率地交付给你的用户。但是,如果你想将应用程序发布到其他的应用商店, APK可能是唯一选项。
什么是 fat APK?
一个 fat APK 是一个包含了支持多个 ABI 架构的 APK 文件。这样做的好处是单个 APK 可以运行在多个架构上,因此具有更广泛的兼容性。但同时缺点就是文件体积会比较大,导致用户在安装你的应用程序时会下载和储存更多的字节。当构建 APKs 而不是app bundles 时强烈建议分开构建 APKs,如 build an APK 所描述的那样,使用 —split-per-abi
指令。
哪些目标架构是被支持的?
当使用 release 模式构建你的应用程序时, Flutter app 可以基于 armeabi-v7a (32-bit)和 arm64-v8a (64-bit)被编译。Flutter 目前不支持 x86 Android (参考 Issue 9253).
如何为一个使用 flutter build appbundle 创建的 app bundle 签名?
See Signing the app.
如何使用 Android Studio 构建一个发布?
在Android Studio中, 打开你的 app 文件夹下的 android/
文件夹. 然后在项目面板中选择 build.gradle (Module: app) :
接下来,选择构建变体。在主菜单中点击 Build > Select Build Variant。从 Build Variants 面板中选择任意一个变体(默认是 debug)。
生成的 app bundle 或 APK 文件会在你的 app 所在文件夹下的 build/app/outputs
文件夹下。