When a new Flutter app is created, it has a default launcher icon.
To customize this icon, you might want to check out the
flutter_launcher_icons package.
To publish on the Play Store, you need to give your app a digital
signature. Use the following instructions to sign your app.
If you have an existing keystore, skip to the next step.
If not, create one by running the following at the command line:
备忘
该命令将会把 key.jks
文件储存在你的主文件夹中。如果你想要储存在其他地方,请通过指定 -keystore
传入参数。注意,请保证这个文件的私有性,不要将它提交到公共的代码管理空间。
This command stores the key.jks
file in your home
directory. If you want to store it elsewhere, change
the argument you pass to the -keystore
parameter.
However, keep the keystore
file private;
don’t check it into public source control!
备忘
keytool
可能不在我们的系统路径中。它是 Java 的一部分,在安装 Android Studio 的时候会被一起安装。运行 flutter doctor -v
,’Java binary at:’ 之后打印出来的就是它的路径,然后用 java
来替换以上命令中的 keytool
,并加上 keytool
的完整路径即可。
如果文件路径包含空格,类似 Program Files
这样的,请使用平台允许的命名规则。例如,在 Mac/Linux 上使用 Program\ Files
,而在 Windows 上可以使用
"Program Files"
。
The keytool
command might not be in your path—it’s
part of Java, which is installed as part of
Android Studio. For the concrete path,
run flutter doctor -v
and locate the path printed after
‘Java binary at:’. Then use that fully qualified path
replacing java
(at the end) with keytool
.
If your path includes space-separated names,
such as Program Files
, use platform-appropriate
notation for the names. For example, on Mac/Linux
use Program\ Files
, and on Windows use
"Program Files"
.
只有 Java 9 或更高版本才需要 -storetype JKS
标签。从 Java 9 版本开始,keystore 类型默认为 PKS12。
The -storetype JKS
tag is only required for Java 9
or newer. As of the Java 9 release,
the keystore type defaults to PKS12.
从 app 中引用密钥库
Reference the keystore from the app
创建一个名为 <app dir>/android/key.properties
的文件,它包含了密钥库位置的定义:
Create a file named <app dir>/android/key.properties
that contains a reference to your keystore:
storePassword=<上一步骤中的密码>
keyPassword=<上一步骤中的密码>
keyAlias=key
storeFile=<密钥库的位置,e.g. /Users/<用户名>/key.jks>
备忘
(再次)请保证这个文件的私有性,不要将它提交到公共的代码管理空间。
Keep the key.properties
file private;
don’t check it into public source control.
Configure signing in gradle
通过编辑 <app dir>/android/app/build.gradle
文件来为我们的 app 配置签名:
Configure signing for your app by editing the
<app dir>/android/app/build.gradle
file.
Add code before android
block:
在 android
代码块之前添加:
替换为我们的 properties 文件的密钥库信息:
With the keystore information from your properties file:
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
...
}
将 key.properties
文件加载到 keystoreProperties
对象中。
Load the key.properties
file into the keystoreProperties
object.
Add code before buildTypes
block:
在 buildTypes
代码块之前添加:
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
}
}
替换为我们的配置内容:
With the signing configuration info:
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
在你的 module 的 build.gradle
文件中配置
signingConfigs
部分。
Configure the signingConfigs
block in your module’s build.gradle
file.
</ol>
现在我们 app 的发布版本就会被自动签名了。
Release builds of your app will now be signed automatically.
启用混淆器
Enabling Proguard
默认情况下,Flutter 不会做混淆或者压缩 Android host 的工作。如果 app 使用了第三方的 Java 或者 Android 库,我们会希望减小 APK 的大小,或者保护代码不被反编译出来。
By default, Flutter does not obfuscate or minify the Android host.
If you intend to use third-party Java, Kotlin, or Android libraries,
you might want to reduce the size of the APK or protect that code from
reverse engineering.
要了解混淆 Dart 代码的相关信息,可以参考 Flutter wiki
上的 Obfuscating Dart Code 。
For information on obfuscating Dart code, see Obfuscating Dart
Code
in the Flutter wiki .
Step 1 - Configure Proguard
创建 /android/app/proguard-rules.pro
文件并添加下面的规则:
Create a /android/app/proguard-rules.pro
file and
add the rules listed below.
## 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),需要为它们添加自己的规则。
This configuration only protects Flutter engine libraries.
Any additional libraries (for example, Firebase) require adding
their own rules.
步骤 2 - 启用混淆以及/或压缩
Step 2 - Enable obfuscation and/or minification
在 /android/app/build.gradle
文件找到 buildTypes
的定义。在 release
配置中设置 minifiyEnabled
和 useProguard
为 true。另外我们必须再设置 Proguard 指向步骤 1 中我们创建的文件。
Open the /android/app/build.gradle
file and locate the buildTypes
definition. Inside the release
configuration section,
set the minifiyEnabled
and useProguard
flags to true.
You must also point Proguard to the file you created in step 1:
android {
...
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
useProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
备忘
当你更改 gradle 文件后也许需要运行一下 flutter clean
。这将防止缓存的版本影响签名过程。
You may need to run flutter clean
after changing the gradle file.
This prevents cached builds from affecting the signing process.
有关应用签名的更多信息,请查看 developer.android.com 的为您的应用设置签名 。
For more information on signing your app, see
Sign your app on developer.android.com.
使用 R8 压缩你的代码
Shrinking your code with R8
R8 是谷歌推出的最新代码压缩器,当你打包 release 版本的 APK 或者 AAB 时会默认开启。要关闭 R8,请向 flutter build apk
或 flutter build appbundle
传 --no-shrink
标志。
R8 is the new code shrinker from Google, and it’s enabled by default
when you build a release APK or AAB. To disable R8, pass the --no-shrink
flag to flutter build apk
or flutter build appbundle
.
检查 app manifest 文件
Reviewing the app manifest
检查位于 <app dir>/android/app/src/main
的默认 App Manifest
文件 AndroidManifest.xml
,并确认各个值都设置正确,特别是:
Review the default App Manifest file, AndroidManifest.xml
,
located in <app dir>/android/app/src/main
and verify that the values
are correct, especially the following:
application
编辑 application
标签中的 android:label
来设置 app 的最终名字。
application
Edit the android:label
in the
application
tag to reflect
the final name of the app.
uses-permission
:
如果你的代码需要互联网交互,请加入 android.permission.INTERNET
权限标签 。标准开发模版里并未加入这个权限(但是 Flutter debug 模版加入了这个权限),加入这个权限是为了允许 Flutter 工具和正在运行的 app 之间的通信。
uses-permission
Add the android.permission.INTERNET
permission if your application code needs Internet
access. The standard template does not include this tag but allows
Internet access during development to enable communication between
Flutter tools and a running app.
检查构建配置
Reviewing the build configuration
检查位于 <app dir>/android/app
的默认 Gradle build file ,并确认各个值都设置正确,特别是下面 defaultConfig
块中的值:
Review the default Gradle build file file, build.gradle
,located in <app dir>/android/app
and
verify the values are correct,especially the following
values in the defaultConfig
block:
applicationId
:指定最终的,唯一的(Application Id)appid 。
applicationId
Specify the final, unique (Application Id)appid
versionCode
& versionName
指定 app 的内部版本号,以及用于显示的版本号,这可以通过设置 pubspec.yaml 文件中 version
属性来做。具体可以参考 版本文档 中的版本信息指南。
versionCode
& versionName
Specify the internal app version number,
and the version number display string. You can do this by setting
the version
property in the pubspec.yaml file. Consult the version
information guidance in the versions documentation .
minSdkVersion
、compilesdkVersion
和 targetSdkVersion
指定应用运行所需要的最低 API 级别 minSdkVersion
、编译 API 级别 compilesdkVersion
以及目标 API 级别 targetSdkVersion
。具体可以参考 Android 开发者网站上关于 版本的文档
中的 API 版本的部分。
minSdkVersion
, compilesdkVersion
, & targetSdkVersion
Specify the minimum API level,
the API level on which the app was compiled,
and the maximum API level on which the app is designed to run.
Consult the API level section in the versions documentation
for details.
buildToolsVersion
指定应用所需的 Android SDK 构建工具的版本,或者你可以在 Android Studio 里使用
[Android Gradle 插件][Android Gradle Plugin],它可以自动设置导入你应用所需的构建工具版本,这样就无需过多操心这个属性啦。
buildToolsVersion
Specify the version of Android SDK Build Tools that your app uses.
Alternatively, you can use the [Android Gradle Plugin] in Android Studio,
which will automatically import the minimum required Build Tools for your app
without the need for this property.
为发布构建应用程序
Building the app for release
当要发布到 Play Store 时,你有两种发布方式的选择:
You have two possible release formats when publishing to
the Play Store.
App bundle (推荐)
App bundle (preferred)
APK
请注意
最近,Flutter 团队收到了很多开发者的 报告 ,表示他们在 Android 6.0 的某些设备上遇到了应用崩溃的情况。如果你的目标 API 等级是 Android 6.0,请参考以下步骤:
Recently, the Flutter team has received several reports
from developers indicating they are experiencing app
crashes on certain devices on Android 6.0. If you are targeting
Android 6.0, use the following steps:
如果以 App Bundle 构建发布,编辑 android/gradle.properties
文件,添加一行属性 android.bundle.enableUncompressedNativeLibs=false
;
If you build an App Bundle
Edit android/gradle.properties
and add the flag:
android.bundle.enableUncompressedNativeLibs=false
.
如果以 APK 构建发布,需要确保清单文件 android/app/src/AndroidManifest.xml
的 <application>
标签里不包含 android:extractNativeLibs=false
。
If you build an APK
Make sure android/app/src/AndroidManifest.xml
doesn’t set android:extractNativeLibs=false
in the <application>
tag.
更多内容,请参考这个 错误报告 。
For more information, see the public issue .
构建一个 app bundle
Build an app bundle
这个部分描述了如何构建一个发布的 app bundle。如果在前面的部分已经完成了签名步骤,发布的 bundle 会被签名。这时你也许想要混淆你的 Dart 代码 以加大反编译难度。混淆你的代码需要在 build 的时候添加一些标志,并维护其他文件以消除反编译的堆栈跟踪。
This section describes how to build a release app bundle.
If you completed the signing steps,
the app bundle will be signed.
At this point, you might consider obfuscating your Dart code
to make it more difficult to reverse engineer. Obfuscating
your code involves adding a couple flags to your build command,
and maintaining additional files to de-obfuscate stack traces.
使用如下命令:
From the command line:
运行 cd <app dir>
。(将 <app dir>
替换为我们 app 的目录)。
Enter cd <app dir>
(Replace <app dir>
with your application’s directory.)
运行 flutter build appbundle
。
(运行 flutter build
默认构建一个发布版本。)
Run flutter build appbundle
(Running flutter build
defaults to a release build.)
你的应用的 release bundle 会被创建到
<app dir>/build/app/outputs/bundle/release/app.aab
.
The release bundle for your app is created at
<app dir>/build/app/outputs/bundle/release/app.aab
.
此 app bundle 会默认地包含为
armeabi-v7a (ARM 32-bit)、arm64-v8a (ARM 64-bit)
以及 x86-64 (x86 64-bit) 编译的 Dart 和 Fluter 运行时代码。
By default, the app bundle contains your Dart code and the Flutter
runtime compiled for armeabi-v7a (ARM 32-bit), arm64-v8a
(ARM 64-bit), and x86-64 (x86 64-bit).
测试 app bundle
Test the app bundle
一个 app bundle 可以用多种方法测试,这里介绍两种。
An app bundle can be tested in multiple ways—this section
describes two.
Offline using the bundle tool
如果你还没准备好,可以从 GitHub repository 下载 bundletool
If you haven’t done so already, download bundletool
from the
GitHub repository .
从你的 app bundle 生成 APKs
Generate a set of APKs from your app bundle.
将这 APKs 部署到 已连接的设备
Deploy the APKs to connected devices.
在线使用 Google Play
Online using Google Play
上传你的 bundle 到 Google Play 去测试它。或者在正式发布之前用 alpha 或 beta 频道去测试。
Upload your bundle to Google Play to test it.
You can use the internal test track,
or the alpha or beta channels to test the bundle before
releasing it in production.
按照 这些步骤把你的 bundle 上传到 Play Store。
Follow these steps to upload your bundle
to the Play Store.
构建一个 APK
Build an APK
虽然 app bundle 比 APKs 更被推荐使用,但是有一些 Store 目前还不支持 app bundle方式。这种情况下,要为各种目标
ABI (Application Binary Interface) 分别构建发布的 APK 文件。
Although app bundles are preferred over APKs, there are stores
that don’t yet support app bundles. In this case, build a release
APK for each target ABI (Application Binary Interface).
如果你完成签名步骤, APK 就被签名了。
If you completed the signing steps,
the APK will be signed.
At this point, you might consider obfuscating your Dart code
to make it more difficult to reverse engineer. Obfuscating
your code involves adding a couple flags to your build command.
使用如下命令:
From the command line:
cd <app dir>
(将 <app dir>
替换为我们 app 的目录)。
Enter cd <app dir>
(Replace <app dir>
with your application’s directory.)
运行 flutter build apk
(flutter build
默认带有 --release
参数)。
Run flutter build apk --split-per-abi
(The flutter build
command defaults to --release
.)
这个命令会生成三个 APK 文件:
This command results in three APK files:
<app dir>/build/app/outputs/apk/release/app-armeabi-v7a-release.apk
<app dir>/build/app/outputs/apk/release/app-arm64-v8a-release.apk
<app dir>/build/app/outputs/apk/release/app-x86_64-release.apk
如果移除 --split-per-abi
将会生成一个包含 所有 目标 ABI 的 fat APK 文件。这种 APK 文件将会在比单独构建的 APK 文件尺寸要大,会导致用户下载一些不适用于其设备架构的二进制文件。
Removing the --split-per-abi
flag results in a fat APK that contains
your code compiled for all the target ABIs. Such APKs are larger in
size than their split counterparts, causing the user to download
native binaries that are not applicable to their device’s architecture.
在设备上安装 APK 文件
Install an APK on a device
按照如下这些步骤,将前一步中构建出来的 APK 安装到 Android 设备上。
Follow these steps to install the APK on a connected Android device.
使用如下命令:
From the command line:
用 USB 线将 Android 设备连接到电脑上。
Connect your Android device to your computer with a USB cable.
cd <app dir>
,<app dir>
是我们 app 的目录。
Enter cd <app dir>
where <app dir>
is your application directory.
运行 flutter install
。
Run flutter install
.
发布到 Google Play Store
Publishing to the Google Play Store
要了解如何发布一个 app 到 Google Play Store,可以参考 Google Play publishing documentation 。
For detailed instructions on publishing your app to the Google Play Store,
see the Google Play launch documentation.
当你创建了应用之后,你可以通过 Google Ads 吸引更多用户,
Google Ads 平台可以通过机器学习帮助你以非常高的性价比吸引到更多用户。
Now that you’ve created your app, attract more users with Google Ads.
App campaigns use machine learning to drive more installs and
make the most of your budget.
通过以下几步创建一个广告宣传:
Get your campaign running in a few steps
创建广告—我们会根据您的应用信息帮您制作广告。另外,您还可以添加图片和视频。
Create your ad—we’ll help create your ad from your app
information
决定推广预算—对于以提高应用安装量为主要目标的广告系列,您需要为其设置应用安装出价,也就是“目标每次安装费用”,同时设置每日推广支出预算。
Choose your budget—set your target cost-per-install (tCPI)
and daily budget cap
选择目标地区—让我们知道你希望触达哪些区域的用户。
Select your location—let us know where you’d like your ads to run
设定用户行动—决定你希望用户要做什么,比如安装,应用内操作或者目标广告支出回报率 (ROAS)。
Decide what action you want users to take—choose installs,
in-app actions, or target return on ad spend (ROAS)
[获取 75 美元的赠金(当你消费 25 美金后)][Get $75 app advertising credit when you spend $25.]
[Get $75 app advertising credit when you spend $25.][]
更新应用版本号
Updating the app’s version number
每个应用默认的初始版本号是 1.0.0
。若要更新它,请转到 pubspec.yaml
文件并更新以下内容:
The default version number of the app is 1.0.0
.
To update it, navigate to the pubspec.yaml
file
and update the following line:
version: 1.0.0+1
版本号由三个点分隔的数字组成,例如上面样例中的 1.0.0
。然后是可选的构建号,例如上面样例中的 1
,以 +
分隔。
The version number is three numbers separated by dots,
such as 1.0.0
in the example above, followed by an optional
build number such as 1
in the example above, separated by a +
.
版本号与构建号都可以在 Flutter 打包时分别使用
--build-name
和 --build-number
重新指定。
Both the version and the build number may be overridden in Flutter’s
build by specifying --build-name
and --build-number
, respectively.
在 Android 中,当 build-number
被用作 versionCode
时
build-name
作为 versionName
使用。更多信息请参考 Android 文档中的
为你的应用添加版本 。
In Android, build-name
is used as versionName
while
build-number
used as versionCode
. For more information,
see Version your app in the Android documentation.
在更新完 pubspec 文件中的版本号之后,在项目根目录下运行 flutter pub get
,或者使用 IDE 中的 Pub get 按钮。这将会更新 local.properties
文件中的 versionName
和 versionCode
,之后它会在你构建 Flutter 应用的时候更新 build.gradle
。
After updating the version number in the pubspec file,
run flutter pub get
from the top of the project, or
use the Pub get button in your IDE. This updates
the versionName
and versionCode
in the local.properties
file,
which are later updated in the build.gradle
file when you
rebuild the Flutter app.
Android发布常见问题
Android release FAQ
这里是一些关于安卓应用程序发布的常见问题。
Here are some commonly asked questions about deployment for
Android apps.
我应该什么时候构建 app bundles 而不是 APKs?
When should I build app bundles versus APKs?
Google Play Store 相对于 APKs 更建议你发布 app bundles,因为那样应用程序会更有效率地交付给你的用户。但是,如果你想将应用程序发布到其他的应用商店,APK可能是唯一选项。
The Google Play Store recommends that you deploy app bundles
over APKs because they allow a more efficient delivery of the
application to your users. However, if you’re distributing
your application by means other than the Play Store,
an APK may be your only option.
什么是 fat APK?
What is a fat APK?
一个 fat APK 是一个包含了支持多个 ABI 架构的 APK 文件。这样做的好处是单个 APK 可以运行在多个架构上,因此具有更广泛的兼容性。但同时缺点就是文件体积会比较大,导致用户在安装你的应用程序时会下载和储存更多的字节。当构建 APK 而不是 app bundles 时强烈建议分开构建 APK,如 build an APK 所描述的那样,使用 --split-per-abi
指令。
A fat APK is a single APK that contains binaries for multiple
ABIs embedded within it. This has the benefit that the single APK
runs on multiple architectures and thus has wider compatibility,
but it has the drawback that its file size is much larger,
causing users to download and store more bytes when installing
your application. When building APKs instead of app bundles,
it is strongly recommended to build split APKs,
as described in build an APK using the
--split-per-abi
.
哪些目标架构是被支持的?
What are the supported target architectures?
当使用 release 模式构建你的应用程序时,
Flutter app 可以基于 armeabi-v7a (ARM 32 位)、
arm64-v8a (ARM 64 位) 以及 x86-64 (x86 64 位) 被编译。
Flutter 目前不支持 x86 Android (参考 Issue 9253 ).
When building your application in release mode,
Flutter apps can be compiled for armeabi-v7a (ARM 32-bit),
arm64-v8a (ARM 64-bit), and x86-64 (x86 64-bit).
Flutter does not currently support building for x86 Android
(See Issue 9253 ).
如何为一个使用 flutter build appbundle
创建的 app bundle 签名?
How do I sign the app bundle created by flutter build appbundle
?
See Signing the app .
如何使用 Android Studio 构建一个发布?
How do I build a release from within Android Studio?
在Android Studio中, 打开你的 app 文件夹下的 android/
文件夹. 然后在项目面板中选择 build.gradle (Module: app) :
In Android Studio, open the existing android/
folder under your app’s folder. Then,
select build.gradle (Module: app) in the project panel:
接下来,选择构建变体。在主菜单中点击 Build > Select Build Variant 。从 Build Variants 面板中选择任意一个变体(默认是 debug)。
Next, select the build variant. Click Build > Select Build Variant
in the main menu. Select any of the variants in the Build Variants
panel (debug is the default):
生成的 app bundle 或 APK 文件会在你的 app 所在文件夹下的 build/app/outputs
文件夹下。
The resulting app bundle or APK files are located in
build/app/outputs
within your app’s folder.