建構和釋出為 Android 應用
在一般的開發過程中,我們可以使用 flutter run
命令,或者 IntelliJ 工具欄中的 Run 和 Debug 來測試 app。這時候,Flutter 預設會為我們建構 app 的除錯版本。
當想要釋出 app 時,比如 釋出到 Google Play Store,可以按照以下步驟來準備 Android 平台的 釋出 版本。本頁面的內容包含如下主題:
新增啟動畫標
當我們建立一個新的 Flutter app 的時候,它會有一個預設的啟動畫標。要自訂這個圖示,可以參考使用 flutter_launcher_icons 這個 package。
或者,如果我們想手動操作,可以參考以下方法:
-
檢視 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 圖示是否已經替換成我們自己的圖示檔案。
啟用 Material 元件
如果你的應用使用了 平臺視圖 (Platform Views),你可能要透過 Android 平台的入門指南文件 中的步驟使用 Material 元件:
舉個例子:
-
在
<my-app>/android/app/build.gradle
檔案中新增 Android Material 元件依賴:
dependencies {
// ...
implementation 'com.google.android.material:material:<version>'
// ...
}
檢視最新的版本,請存取 Google Maven 儲存庫。
-
在
<my-app>/android/app/src/main/res/values/styles.xml
檔案中設定亮色主題:
-<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+<style name="NormalTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
- Set the dark theme in
<my-app>/android/app/src/main/res/values-night/styles.xml
-<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+<style name="NormalTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
為 app 簽名
要想把 app 釋出到 Play store,還需要給 app 一個數字簽名。我們可以採用以下步驟來為 app 簽名:
Android 中有兩種簽名金鑰: 部署和上傳。終端使用者下載到的 .apk 檔案是被部署金鑰簽名過的檔案,上傳金鑰用於驗證開發者上載到 Play 商店的 .aab 或 .apk 檔案。上傳金鑰是給予部署金鑰重新簽名的金鑰,上載 Play 商店時候需要用到。
-
嚴重推薦你選擇雲託管的方式來管理部署金鑰,更多相關資訊,請參閱官方文件 使用 Play 應用簽名功能。
建立一個用於上傳的金鑰庫
如果你已經有一個金鑰庫了,可以直接跳到下一步,如果還沒有,需要參考下面的方式建立一個:
-
在命令列視窗執行如下的命令:
在 macOS 或者 Linux 系統上,執行下面的程式碼:
keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
在 Windows 系統上,執行下述程式碼:
keytool -genkey -v -keystore %userprofile%\upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload
該命令將會把
upload-keystore.jks
檔案儲存在你的主資料夾中。如果你想要儲存在其他地方,請透過指定-keystore
傳入引數。 注意,請保證這個檔案的私有性,不要將它提交到公共的程式碼管理空間。
從 app 中參考金鑰庫
建立一個名為 [project]/android/key.properties
的檔案,它包含了金鑰庫位置的定義:
storePassword=<上一步驟中的密碼>
keyPassword=<上一步驟中的密碼>
keyAlias=upload
storeFile=<金鑰庫的位置,e.g. /Users/<使用者名稱>/upload-keystore.jks>
在 gradle 中配置簽名
在以 release 模式下建構你的應用時,修改 [project]/android/app/build.gradle
檔案,以透過 gradle 配置你的上傳金鑰。
-
在
android
程式碼塊之前將你 properties 檔案的金鑰庫資訊新增進去:def keystoreProperties = new Properties() def keystorePropertiesFile = rootProject.file('key.properties') if (keystorePropertiesFile.exists()) { keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) } android { ... }
將
key.properties
檔案載入到keystoreProperties
物件中。 -
找到
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 } }
將其替換為我們的配置內容:
signingConfigs { release { keyAlias keystoreProperties['keyAlias'] keyPassword keystoreProperties['keyPassword'] storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] } } buildTypes { release { signingConfig signingConfigs.release } }
現在我們 app 的釋出版本就會被自動簽名了。
有關應用簽名的更多資訊,請檢視 developer.android.com 的 為您的應用設定簽名。
使用 R8 壓縮你的程式碼
R8 是谷歌推出的最新程式碼壓縮器,當你打包 release 版本的 APK 或者 AAB 時會預設開啟。要關閉 R8,請執行 flutter build apk
或
flutter build appbundle
時加上 --no-shrink
引數。
啟用 multidex 支援
當你在編寫較大的應用或使用體量較大的外掛時,你可能會在最低的 API 目標版本低於 20 時,遇到 Android 的 dex 的 64k 方法數限制問題。當 flutter run
以除錯模式執行應用時,由於縮減機制沒有執行,該問題也有可能發生。
Flutter 工具支援以便捷的方式啟用 multidex 支援。當工具提示你需要支援時,跟隨工具的指示進行調整,是最快的方式。
Flutter 工具會檢測 multidex 的建構錯誤,並提示你是否要更改 Android 專案。在同意的情況下,專案會自動依賴 androidx.multidex:multidex
,並且讓專案的 Application
繼承於 FlutterMultiDexApplication
。
你也可以根據 Android 的指南,手動配置你的 Android 專案以支援 multidex。請務必指定 multidex keep 檔案 以包含以下內容:
io/flutter/embedding/engine/loader/FlutterLoader.class
io/flutter/util/PathUtils.class
同時也要包含所有在應用啟動時載入的其他類別。參考 multidex 文件 瞭解更詳細的手動適配指南。
檢查 app manifest 檔案
檢查位於 <app dir>/android/app/src/main
的預設 App Manifest
檔案 AndroidManifest.xml
,並確認各個值都設定正確,特別是:
application
編輯 application
標籤中的 android:label
來設定 app 的最終名字。
uses-permission
:
如果你的程式碼需要網際網路互動,請加入 android.permission.INTERNET
許可權標籤。標準開發模版裡並未加入這個許可權(但是 Flutter debug 模版加入了這個許可權),加入這個許可權是為了允許 Flutter 工具和正在執行的 app 之間的通訊。
檢查 Gradle 建構配置
檢查位於 [project]/android/app
的預設 Gradle 建構檔案 (build.gradle
)
並確認各個值都設定正確:
defaultConfig
配置中
在 applicationId
指定唯一的 應用 ID。
minSdkVersion
指定應用適配的最低 SDK 版本。預設為 flutter.minSdkVersion
。
targetSdkVersion
指定應用適配的目標 SDK 版本。預設為 flutter.targetSdkVersion
。
versionCode
用於內部版本號的正整數。該數字僅用於比較兩個版本間數字較大的為更新版本。該版本不會對使用者展示。
versionName
向用戶展示的版本號。該欄位必須設定為原始字串或字串資源的參考。
buildToolsVersion
If you’re using Android plugin for Gradle 3.0.0 or higher, your project
automatically uses the default version of the build tools that the
plugin specifies. Alternatively, you can specify a version of the build tools.
buildToolsVersion
如果你正在使用高於 3.0.0 版本的 Android Gradle Plugin,你的專案會自動使用 AGP 預設指定的建構工具版本。你也可以手動指定建構工具的版本。
android
配置中
在 compileSdkVersion
指定 Gradle 用於編譯應用的 API 版本。預設為 flutter.compileSdkVersion
。
更多資訊可以參考 Gradle 建構檔案 文件中模組級建構的部分。
建構生產版本應用
當要釋出到 Play Store 時,你有兩種釋出方式的選擇:
-
App bundle (推薦)
-
APK
建構一個 app bundle
這個部分描述瞭如何建構一個釋出的 app bundle。如果在前面的部分已經完成了簽名步驟,釋出的 bundle 會被簽名。這時你也許想要 混淆你的 Dart 程式碼 以加大反編譯難度。混淆你的程式碼需要在 build 的時候新增一些標誌,並維護其他檔案以消除反編譯的堆疊追蹤。
使用如下命令:
-
執行
cd [project]
。 -
執行
flutter build appbundle
。 (執行flutter build
預設建構一個釋出版本。)
你的應用的 release bundle 會被建立到
<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 執行時程式碼。
測試 app bundle
一個 app bundle 可以用多種方法測試,這裡介紹兩種。
離線使用 bundle tool
-
如果你還沒準備好,可以從 GitHub 儲存庫 下載
bundletool
。 -
從你的 app bundle 產生 APKs。
-
將這 APKs 部署到 已連線的裝置。
線上使用 Google Play
-
上傳你的 bundle 到 Google Play 去測試它。或者在正式釋出之前用 alpha 或 beta 頻道去測試。
-
按照 這些步驟把你的 bundle 上傳到 Play Store。
建構一個 APK
雖然 app bundle 比 APKs 更被推薦使用,但是有一些 Store 目前還不支援 app bundle方式。這種情況下,要為各種目標 ABI (Application Binary Interface) 分別建構釋出的 APK 檔案。
如果你完成簽名步驟,APK 就被簽名了。這時你也許想要 混淆你的 Dart 程式碼 以加大反編譯難度。混淆你的程式碼需要在建構時新增一些引數。
使用如下命令:
-
輸入命令
cd [project]
-
執行
flutter build apk --split-per-abi
(flutter build
預設帶有--release
引數。)
這個命令會產生如下三個 APK 檔案
[project]/build/app/outputs/apk/release/app-armeabi-v7a-release.apk
[project]/build/app/outputs/apk/release/app-arm64-v8a-release.apk
[project]/build/app/outputs/apk/release/app-x86_64-release.apk
如果移除 --split-per-abi
將會產生一個包含 所有 目標 ABI 的 fat APK 檔案。這種 APK 檔案將會在比單獨建構的 APK 檔案尺寸要大,會導致使用者下載一些不適用於其裝置架構的二進位制檔案。
在裝置上安裝 APK 檔案
按照如下這些步驟,將前一步中構建出來的 APK 安裝到 Android 裝置上。
使用如下命令:
-
用 USB 線將 Android 裝置連線到電腦上;
-
輸入命令
cd [project]
; -
執行
flutter install
。
釋出到 Google Play Store
要了解如何釋出一個 app 到 Google Play Store,可以參考 Google Play 釋出文件。
更新應用版本號
每個應用預設的初始版本號是 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 應用後,任何在 pubspec 檔案所做的版本號更新,都將會更新 local.properties
檔案中的
versionName
和 versionCode
。
Android 釋出常見問題
這裡是一些關於 Android 應用釋出的常見問題。
我應該什麼時候建構 app bundles 而不是 APKs?
Google Play Store 相對於 APKs 更建議你釋出 app bundles,因為那樣應用會更有效率地交付給你的使用者。但是,如果你想將應用釋出到其他的應用商店,APK可能是唯一選項。
什麼是 fat APK?
一個 fat APK 是一個包含了支援多個 ABI 架構的 APK 檔案。這樣做的好處是單個 APK 可以執行在多個架構上,因此具有更廣泛的相容性。但同時缺點就是檔案體積會比較大,導致使用者在安裝你的應用時會下載和儲存更多的位元組。當建構 APK 而不是 app bundles 時強烈建議分開建構 APK,如 build an APK 所描述的那樣,使用 --split-per-abi
指令。
哪些目標架構是被支援的?
當使用 release 模式建構你的應用時, Flutter app 可以基於 armeabi-v7a (ARM 32 位)、 arm64-v8a (ARM 64 位) 以及 x86-64 (x86 64 位) 被編譯。 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
資料夾下。