要測試應用程式,你可以在命令列使用 flutter run, 或在你的 IDE 中使用 RunDebug 選項。

當你準備好要建立應用程式的 發佈 版本時, 例如要發佈到 Google Play 商店, 本頁將提供協助。在發佈之前, 你可能會想為應用程式做一些最後的修飾。 本指南將說明如何執行以下任務:

新增啟動器圖示

#

當你建立新的 Flutter 應用程式時,會有一個預設的啟動器圖示。 若要自訂這個圖示,你可以參考 flutter_launcher_icons 套件。

另外,你也可以依照以下步驟手動設定:

  1. 參閱 Material Design 產品圖示設計指引,了解圖示設計原則。

  2. [project]/android/app/src/main/res/ 目錄下, 將你的圖示檔案放在以 設定限定詞命名的資料夾中。 預設的 mipmap- 資料夾展示了正確的 命名規則。

  3. AndroidManifest.xml 中,更新 application 標籤的 android:icon 屬性,讓它參考前一步驟中的圖示(例如, <application android:icon="@mipmap/ic_launcher" ...)。

  4. 為確認圖示已被替換, 請執行你的應用程式並檢查 Launcher 中的應用程式圖示。

啟用 Material 元件 (Material components)

#

如果你的應用程式使用了 平台視圖 (platform views),你可能會想要依照 Android 入門指南中的步驟啟用 Material 元件 (Material components)。

例如:

  1. <my-app>/android/app/build.gradle.kts 中新增 Android Material 的相依套件:

    groovy
    dependencies {
        // ...
        implementation("com.google.android.material:material:<version>")
        // ...
    }

    若要查詢最新版本,請造訪 Google Maven

  2. <my-app>/android/app/src/main/res/values/styles.xml 中設定亮色主題:

    xml
    <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
    <style name="NormalTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
  3. <my-app>/android/app/src/main/res/values-night/styles.xml中設定深色主題:

    xml
    <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <style name="NormalTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">

簽署應用程式

#

若要在 Play 商店(Play Store)發佈,您需要使用數位憑證簽署您的應用程式。

Android 會使用兩種簽署金鑰:上傳金鑰(upload key)與 應用程式簽署金鑰(app signing key)。

  • 開發者需將以 上傳金鑰 簽署的 .aab.apk 檔案上傳至 Play 商店。
  • 最終用戶會下載以 應用程式簽署金鑰 簽署的 .apk 檔案。

如需建立您的應用程式簽署金鑰,請依照 官方 Play 商店文件 中所述,使用 Play App Signing。

如需簽署您的應用程式,請依照以下說明操作。

建立上傳 keystore

#

如果您已有現有的 keystore,請跳至下一步。 若沒有,請使用下列其中一種方式建立:

  1. 依照 Android Studio 金鑰產生步驟 操作。

  2. 在命令列執行下列指令:

    在 macOS 或 Linux 上,請使用以下指令:

    keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA \
            -keysize 2048 -validity 10000 -alias upload

    在 Windows 上,請在 PowerShell 中使用以下指令:

    keytool -genkey -v -keystore $env:USERPROFILE\upload-keystore.jks `
            -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 `
            -alias upload

    此指令會將 upload-keystore.jks 檔案儲存在你的家目錄。如果你想將其儲存在其他位置,請更改傳遞給 -keystore 參數的引數。 不過,請務必將 keystore 檔案保密;不要將它提交到公開的原始碼控管系統!

從應用程式參考 keystore

#

建立一個名為 [project]/android/key.properties 的檔案,內容包含對你的 keystore 的參考。 不要包含尖括號(< >)。 這些尖括號表示該文字僅為你的值的佔位符。

properties
storePassword=<password-from-previous-step>
keyPassword=<password-from-previous-step>
keyAlias=upload
storeFile=<keystore-file-location>

storeFile 可能位於 macOS 的 /Users/<user name>/upload-keystore.jks 或 Windows 的 C:\\Users\\<user name>\\upload-keystore.jks

在 Gradle 中設定簽章

#

當你以 release 模式建置應用程式時,需要設定 Gradle 使用你的上傳金鑰(upload key)。 要設定 Gradle,請編輯 <project>/android/app/build.gradle.kts 檔案。

  1. android 屬性區塊之前,定義並載入 keystore 屬性檔案。

  2. 設定 keystoreProperties 物件以載入 key.properties 檔案。

    [project]/android/app/build.gradle.kts
    kotlin
    import java.util.Properties
    import java.io.FileInputStream
    
    plugins {
       ...
    }
    
    val keystoreProperties = Properties()
    val keystorePropertiesFile = rootProject.file("key.properties")
    if (keystorePropertiesFile.exists()) {
        keystoreProperties.load(FileInputStream(keystorePropertiesFile))
    }
    
    android {
       ...
    }
  3. android屬性區塊內,於buildTypes屬性區塊之前新增簽章(signing)設定。

    [project]/android/app/build.gradle.kts
    kotlin
    android {
        // ...
    
        signingConfigs {
            create("release") {
                keyAlias = keystoreProperties["keyAlias"] as String
                keyPassword = keystoreProperties["keyPassword"] as String
                storeFile = keystoreProperties["storeFile"]?.let { file(it) }
                storePassword = keystoreProperties["storePassword"] as String
            }
        }
        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.getByName("debug")
                signingConfig = signingConfigs.getByName("release")
            }
        }
    ...
    }

Flutter 現在會為所有 release 版本進行簽章。

想進一步了解如何為你的應用程式簽章,請參考 Android 開發者文件中的 Sign your app

使用 R8 壓縮你的程式碼

#

R8 是 Google 推出的新一代程式碼壓縮工具。 當你建置 release APK 或 AAB 時,R8 會預設啟用。 若要停用 R8,請在執行 flutter build apkflutter build appbundle 時加入 --no-shrink 旗標。

啟用 multidex 支援

#

當你開發大型應用程式或使用大型插件時, 如果目標最低 API 為 20 或以下,可能會遇到 Android 的 64k 方法數限制。 在使用未啟用壓縮的 flutter run 執行應用程式的 debug 版本時,也可能遇到此限制。

Flutter 工具支援輕鬆啟用 multidex。 最簡單的方式是依照提示選擇啟用 multidex 支援。 工具會偵測到 multidex 建置錯誤,並在修改你的 Android 專案前詢問你。 選擇啟用後,Flutter 會自動依賴 androidx.multidex:multidex,並使用產生的 FlutterMultiDexApplication 作為專案的 application。

當你在 IDE 中使用 RunDebug 選項嘗試建置並執行應用程式時,建置可能會失敗,並出現以下訊息:

Build failure because Multidex support is required

若要從命令列啟用 multidex,請執行 flutter run --debug 並選擇一台 Android 裝置:

Selecting an Android device with the flutter CLI.

當系統提示時,請輸入 y。 Flutter 工具會啟用 multidex 支援並重新嘗試建置:

The output of a successful build after adding multidex.

你也可以選擇依照 Android 官方指南手動支援 multidex, 並修改專案的 Android 目錄設定。 必須指定一個 multidex keep file,內容需包含:

io/flutter/embedding/engine/loader/FlutterLoader.class
io/flutter/util/PathUtils.class

同時,也請包含應用程式啟動時所使用的其他類別。 如需手動新增 multidex 支援的詳細指引,請參考官方 Android documentation

檢查 App Manifest

#

請檢查預設的 App Manifest 檔案。

[project]/android/app/src/main/AndroidManifest.xml
xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:label="[project]"
        ...
    </application>
    ...
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

請確認下列數值:

標籤屬性
application編輯 application 標籤中的 android:label,以反映應用程式的最終名稱。
uses-permission如果您的應用程式需要存取網際網路,請在 android:name 屬性中新增 android.permission.INTERNET permission 值。標準範本並未包含此標籤,但在開發期間允許網際網路存取,以便 Flutter 工具與執行中的應用程式進行通訊。

檢查或變更 Gradle 建置組態

#

若要確認 Android 建置組態,請檢查預設 Gradle 建置腳本中的 android 區塊。 預設的 Gradle 建置腳本位於 [project]/android/app/build.gradle.kts。 您可以變更這些屬性的任何值。

[project]/android/app/build.gradle.kts
kotlin
android {
    namespace = "com.example.[project]"
    // Any value starting with "flutter." gets its value from
    // the Flutter Gradle plugin.
    // To change from these defaults, make your changes in this file.
    compileSdk = flutter.compileSdkVersion
    ndkVersion = flutter.ndkVersion

    ...

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId = "com.example.[project]"
        // You can update the following values to match your application needs.
        minSdk = flutter.minSdkVersion
        targetSdk = flutter.targetSdkVersion
        // These two properties use values defined elsewhere in this file.
        // You can set these values in the property declaration
        // or use a variable.
        versionCode = flutterVersionCode.toInteger()
        versionName = flutterVersionName
    }

    buildTypes {
        ...
    }
}

在 build.gradle.kts 中可調整的屬性

#
屬性目的預設值
compileSdk您的應用程式所編譯的 Android API 等級。這應設為可用的最高版本。如果您將此屬性設為 31,只要您的應用程式未使用專屬於 31 的 API,即可在運行 API 30 或更早版本的裝置上執行。
defaultConfig
.applicationId最終且唯一的 application ID,用以識別您的應用程式。
.minSdk您設計應用程式可運行的 最低 Android API 等級flutter.minSdkVersion
.targetSdk您測試應用程式可運行的 Android API 等級。您的應用程式應可在所有低於或等於此等級的 Android API 上運行。flutter.targetSdkVersion
.versionCode設定 內部版本號 的正整數。此數值僅用於判斷哪個版本較新。數值越大代表版本越新。應用程式使用者不會看到此值。
.versionName您的應用程式顯示的版本號字串。可設為原始字串或參考字串資源。
.buildToolsVersionGradle 外掛指定專案所使用的 Android build tools 預設版本。若需指定不同版本的 build tools,請變更此值。

若需進一步瞭解 Gradle,請參閱 Gradle build file 中的模組層級 build 章節。

建立發行版應用程式

#

當您要發佈至 Play 商店時,有兩種發行格式可選:

  • App bundle(建議使用)
  • APK

建立 app bundle

#

本節說明如何建立發行版 app bundle。 如果您已完成簽署步驟, 則 app bundle 會被簽署。 此時,您可以考慮混淆您的 Dart 程式碼, 以增加逆向工程的難度。 混淆程式碼需在 build 指令中加入額外旗標, 並維護額外檔案以還原堆疊追蹤。

在命令列執行:

  1. 輸入 cd [project]
  2. 執行 flutter build appbundle
    (執行 flutter build 預設為發行版 build。)

您的應用程式發行 bundle 會建立於 [project]/build/app/outputs/bundle/release/app.aab

預設情況下,app bundle 內含您的 Dart 程式碼與 Flutter 執行時,並針對 armeabi-v7a (ARM 32-bit)、arm64-v8a (ARM 64-bit) 和 x86-64 (x86 64-bit) 進行編譯。

測試 app bundle

#

app bundle 可透過多種方式測試。 本節介紹其中兩種。

使用 bundle tool 離線測試

#
  1. 若尚未下載,請從其 GitHub repository 下載 bundletool
  2. 從 app bundle 產生 APK 集合
  3. 將 APK 部署 至連接的裝置。

使用 Google Play 線上測試

#
  1. 將您的 bundle 上傳至 Google Play 進行測試。 您可以使用內部測試軌道, 或 alpha、beta 頻道先行測試 bundle, 再正式發佈至生產環境。
  2. 依照步驟 上傳您的 bundle 至 Play 商店。

建立 APK

#

雖然 app bundle 為建議格式, 但仍有部分商店尚未支援 app bundle。 此時,請為每個目標 ABI(Application Binary Interface)建立發行版 APK。

如果您已完成簽署步驟,APK 會被簽署。 此時,您可以考慮混淆您的 Dart 程式碼, 以增加逆向工程的難度。 混淆程式碼需在 build 指令中加入額外旗標。

在命令列執行:

  1. 輸入 cd [project]

  2. 執行 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 旗標會產生 fat APK,該檔案包含 針對 所有 目標 ABI 編譯的程式碼。 這類 APK 檔案體積較大, 使用者需下載與其裝置架構不相容的原生二進位檔。

在裝置上安裝 APK

#

請依下列步驟將 APK 安裝至已連接的 Android 裝置。

在命令列執行:

  1. 使用 USB 線將 Android 裝置連接至電腦。
  2. 輸入 cd [project]
  3. 執行 flutter install

發佈至 Google Play 商店

#

如需將應用程式發佈至 Google Play 商店的詳細說明, 請參閱 Google Play launch 文件。

更新應用程式版本號

#

應用程式的預設版本號為 1.0.0。 若要更新,請前往 pubspec.yaml 檔案, 並更新下列這一行:

yaml
version: 1.0.0+1

版本號由三個以點號分隔的數字組成, 例如前述範例中的 1.0.0, 後面可以接一個選填的建置號(build number), 例如前述範例中的 1,兩者之間以 + 分隔。

在 Flutter 的建置過程中,可以分別透過指定 --build-name--build-number 來覆寫 版本號與建置號。

在 Android 中,build-name 會作為 versionName 使用, 而 build-number 則作為 versionCode 使用。更多資訊請參考 Android 文件中的 Version your app

當你為 Android 重新建置應用程式時,來自 pubspec 檔案的 版本號更新會同步到 local.properties 檔案中的 versionNameversionCode

Android 發佈常見問答

#

以下是關於 Android 應用程式部署的一些常見問題。

什麼時候應該建置 app bundle 而不是 APK?

#

Google Play 商店建議你部署 app bundle, 因為這能讓應用程式更有效率地傳送給使用者。 然而,如果你不是透過 Play 商店分發應用程式, 那麼 APK 可能是你唯一的選擇。

什麼是 fat APK?

#

fat APK 是一個單一 APK 檔案,內含多個 ABI 的二進位檔。這樣的好處是單一 APK 可以在多種架構上執行, 因此相容性更廣,但缺點是檔案體積會大很多, 導致使用者安裝應用程式時需要下載與儲存更多資料。 當你選擇建置 APK 而非 app bundle 時, 強烈建議使用分割 APK(split APK)的方式, 詳見 build an APK,並使用 --split-per-abi 旗標。

支援哪些目標架構?

#

當你以 release 模式建置應用程式時, Flutter 應用程式可編譯為 armeabi-v7a (ARM 32-bit)、 arm64-v8a (ARM 64-bit),以及 x86-64 (x86 64-bit)。

如何簽署由 flutter build appbundle 產生的 app bundle?

#

請參考 Sign the app

如何在 Android Studio 中建置 release 版本?

#

在 Android Studio 中,開啟你應用程式資料夾下現有的 android/ 資料夾。然後,在專案面板中選擇 build.gradle (Module: app)

The Gradle build script menu in Android Studio.

接著,選擇建置變體(build variant)。在主選單中點選 Build > Select Build Variant。 在 Build Variants 面板中選擇任一變體(預設為 debug):

The build variant menu in Android Studio with Release selected.

產生的 app bundle 或 APK 檔案會位於你應用程式資料夾下的 build/app/outputs 目錄中。