跳至主要內容

建置和發布 Android 應用程式

若要測試應用程式,您可以在命令列中使用 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. 若要驗證圖示是否已替換,請執行您的應用程式並檢查啟動器中的應用程式圖示。

啟用 Material Components

#

如果您的應用程式使用平台檢視,您可能會想依照Android 入門指南中所述的步驟啟用 Material Components。

例如

  1. <my-app>/android/app/build.gradle 中新增 Android Material 的依附元件
kotlin
dependencies {
    // ...
    implementation("com.google.android.material:material:<version>")
    // ...
}

若要找出最新版本,請造訪 Google Maven

  1. <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">
  1. <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 商店上發佈,您需要使用數位憑證簽署您的應用程式。

Android 使用兩個簽署金鑰:上傳應用程式簽署

  • 開發人員會將使用上傳金鑰簽署的 .aab.apk 檔案上傳到 Play 商店。
  • 終端使用者會下載使用應用程式簽署金鑰簽署的 .apk 檔案。

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

若要簽署您的應用程式,請使用下列指示。

建立上傳金鑰儲存庫

#

如果您有現有的金鑰儲存區,請跳至下一步。如果沒有,請使用下列其中一種方法建立一個

  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 檔案設為私密;不要將其簽入公用原始碼控制!

從應用程式參考金鑰儲存庫

#

建立一個名為 [project]/android/key.properties 的檔案,其中包含對您金鑰儲存區的參考。不要包含角括號 (< >)。它們表示文字是您值的預留位置。

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

storeFile 可能位於 macOS 上的 /Users/<使用者名稱>/upload-keystore.jks 或 Windows 上的 C:\\Users\\<使用者名稱>\\upload-keystore.jks

在 gradle 中設定簽署

#

當以發行模式建置您的應用程式時,請設定 Gradle 以使用您的上傳金鑰。若要設定 Gradle,請編輯 <project>/android/app/build.gradle 檔案。

  1. android 屬性區塊之前定義並載入金鑰儲存區屬性檔案。

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

    [project]/android/app/build.gradle
    kotlin
    def keystoreProperties = new Properties()
    def keystorePropertiesFile = rootProject.file('key.properties')
    if (keystorePropertiesFile.exists()) {
        keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    }
    
    android {
       ...
    }
  3. android 屬性區塊內的 buildTypes 屬性區塊之前新增簽署設定。

    [project]/android/app/build.gradle
    kotlin
    android {
        // ...
    
        signingConfigs {
            release {
                keyAlias = keystoreProperties['keyAlias']
                keyPassword = keystoreProperties['keyPassword']
                storeFile = keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
                storePassword = keystoreProperties['storePassword']
            }
        }
        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
                signingConfig = signingConfigs.release
            }
        }
    ...
    }

Flutter 現在會簽署所有發行版本。

若要深入瞭解如何簽署您的應用程式,請查看 developer.android.com 上的簽署您的應用程式

使用 R8 縮減程式碼

#

R8 是 Google 推出的新程式碼縮減器。當您建置發行 APK 或 AAB 時,預設會啟用它。若要停用 R8,請將 --no-shrink 旗標傳遞至 flutter build apkflutter build appbundle

啟用 multidex 支援

#

在編寫大型應用程式或使用大型外掛程式時,當目標為 API 20 或更低的最低 API 時,您可能會遇到 Android 64k 方法的 dex 限制。當使用未啟用縮減功能的 flutter run 執行應用程式的偵錯版本時,也可能會遇到此情況。

Flutter 工具支援輕鬆啟用 multidex。最簡單的方法是在系統提示時選擇加入 multidex 支援。該工具會偵測 multidex 建置錯誤,並在變更您的 Android 專案之前徵詢您的意見。選擇加入可讓 Flutter 自動依附於 androidx.multidex:multidex,並使用產生的 FlutterMultiDexApplication 作為專案的應用程式。

當您嘗試使用 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 的指南並修改專案的 Android 目錄設定來手動支援 multidex。必須指定 multidex 保留檔案以包含

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

此外,還請包含應用程式啟動時使用的任何其他類別。如需有關手動新增 multidex 支援的更詳細指南,請查看官方 Android 文件

檢閱應用程式資訊清單

#

檢閱預設的應用程式資訊清單檔案。

[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.permission.INTERNET 權限值新增至 android:name 屬性。標準範本不包含此標籤,但在開發期間允許網際網路存取,以啟用 Flutter 工具與執行中的應用程式之間的通訊。

檢閱或變更 Gradle 建置設定

#

若要驗證 Android 建置設定,請檢閱預設 Gradle 建置腳本中的 android 區塊。預設的 Gradle 建置腳本位於 [project]/android/app/build.gradle。您可以變更其中任何這些屬性的值。

[project]/android/app/build.gradle
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 中調整的屬性

#
屬性用途預設值
compileSdk您的應用程式所編譯依據的 Android API 層級。這應為可用的最高版本。如果您將此屬性設定為 31,只要您的應用程式沒有使用 31 特有的 API,您就可以在執行 API 30 或更早版本的裝置上執行您的應用程式。
defaultConfig
.applicationId識別您應用程式的最終、唯一的應用程式 ID
.minSdk您設計應用程式執行所使用的最低 Android API 層級flutter.minSdkVersion
.targetSdk您測試您的應用程式所依據的 Android API 層級。您的應用程式應在所有 Android API 層級上執行,直到此層級為止。flutter.targetSdkVersion
.versionCode設定內部版本號碼的正整數。這個數字僅決定哪個版本比另一個版本更新。較大的數字表示較新的版本。應用程式使用者永遠看不到這個值。
.versionName您的應用程式顯示為其版本號碼的字串。將此屬性設定為原始字串或對字串資源的參考。
.buildToolsVersionGradle 外掛程式指定您的專案使用的 Android 建置工具預設版本。若要指定不同版本的建置工具,請變更此值。

若要深入瞭解 Gradle,請查看Gradle 建置檔案中的模組層級建置區段。

建置用於發佈的應用程式

#

當您發佈到 Play 商店時,您有兩種可能的發行格式。

  • 應用程式套件(偏好)
  • APK

建置應用程式套件

#

本節說明如何建置發佈應用程式套件。如果您已完成簽署步驟,則應用程式套件將會被簽署。此時,您可能會考慮混淆您的 Dart 程式碼,使其更難以反向工程。混淆您的程式碼需要向您的建置命令新增幾個標記,並維護額外的檔案來反混淆堆疊追蹤。

從命令列

  1. 輸入 cd [專案]
  2. 執行 flutter build appbundle
    (執行 flutter build 預設為發佈版本建置。)

您的應用程式的發佈套件會建立在 [專案]/build/app/outputs/bundle/release/app.aab

預設情況下,應用程式套件包含您的 Dart 程式碼和為 armeabi-v7a (ARM 32 位元)、arm64-v8a (ARM 64 位元) 和 x86-64 (x86 64 位元) 編譯的 Flutter 執行環境。

測試應用程式套件

#

應用程式套件可以使用多種方式進行測試。本節說明兩種方式。

使用 bundle 工具離線測試

#
  1. 如果您尚未下載,請從 GitHub 儲存庫下載 bundletool
  2. 從您的應用程式套件產生一組 APK
  3. 將 APK 部署到已連接的裝置。

使用 Google Play 線上測試

#
  1. 將您的套件上傳到 Google Play 以進行測試。您可以使用內部測試軌道,或 alpha 或 beta 頻道,在正式發佈之前測試套件。
  2. 依照這些步驟將您的套件上傳到 Play 商店。

建置 APK

#

雖然應用程式套件優於 APK,但有些商店尚不支援應用程式套件。在這種情況下,請為每個目標 ABI(應用程式二進位介面)建置發佈 APK。

如果您已完成簽署步驟,則 APK 將會被簽署。此時,您可能會考慮混淆您的 Dart 程式碼,使其更難以反向工程。混淆您的程式碼需要向您的建置命令新增幾個標記。

從命令列

  1. 輸入 cd [專案]

  2. 執行 flutter build apk --split-per-abi。(flutter build 命令預設為 --release。)

此命令會產生三個 APK 檔案

  • [專案]/build/app/outputs/apk/release/app-armeabi-v7a-release.apk
  • [專案]/build/app/outputs/apk/release/app-arm64-v8a-release.apk
  • [專案]/build/app/outputs/apk/release/app-x86_64-release.apk

移除 --split-per-abi 標記會產生一個包含為所有目標 ABI 編譯的程式碼的 fat APK。此類 APK 的大小比分割後的 APK 大,導致使用者下載不適用於其裝置架構的原生二進位檔。

在裝置上安裝 APK

#

依照這些步驟在已連線的 Android 裝置上安裝 APK。

從命令列

  1. 使用 USB 連接線將您的 Android 裝置連接到您的電腦。
  2. 輸入 cd [專案]
  3. 執行 flutter install

發佈到 Google Play 商店

#

有關將您的應用程式發佈到 Google Play 商店的詳細說明,請查看Google Play 發佈文件。

更新應用程式的版本號碼

#

應用程式的預設版本號碼為 1.0.0。若要更新它,請導覽至 pubspec.yaml 檔案並更新以下行

version: 1.0.0+1

版本號碼是由點分隔的三個數字,例如上述範例中的 1.0.0,後面可以選擇性地加上一個建置編號,例如上述範例中的 1,並以 + 分隔。

版本和建置編號都可以在 Flutter 的建置中分別指定 --build-name--build-number 來覆寫。

在 Android 中,build-name 用作 versionName,而 build-number 用作 versionCode。如需更多資訊,請查看 Android 文件中的版本化您的應用程式

當您為 Android 重建應用程式時,來自 pubspec 檔案的版本號碼中的任何更新都將更新 local.properties 檔案中的 versionNameversionCode

Android 發佈常見問題

#

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

我應該在什麼時候建置應用程式套件,而不是 APK?

#

Google Play 商店建議您部署應用程式套件而不是 APK,因為它們允許更有效率地將應用程式交付給您的使用者。但是,如果您透過 Play 商店以外的方式發佈您的應用程式,則 APK 可能是您的唯一選擇。

什麼是胖 APK?

#

fat APK 是一個單一 APK,其中包含多個嵌入其中的 ABI 的二進位檔。這樣做的好處是單一 APK 可以在多個架構上執行,因此具有更廣泛的相容性,但缺點是其檔案大小要大得多,導致使用者在安裝應用程式時下載和儲存更多位元組。當建置 APK 而不是應用程式套件時,強烈建議建置分割 APK,如建置 APK中所述,使用 --split-per-abi 標記。

支援的目標架構有哪些?

#

當您在發佈模式下建置您的應用程式時,可以為 armeabi-v7a (ARM 32 位元)、arm64-v8a (ARM 64 位元) 和 x86-64 (x86 64 位元) 編譯 Flutter 應用程式。

我如何簽署由 flutter build appbundle 建立的應用程式套件?

#

請參閱簽署應用程式

我該如何從 Android Studio 中建置發行版本?

#

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

The Gradle build script menu in Android Studio.

接下來,選取建置變體。在主選單中按一下 Build > Select Build Variant。在 Build Variants 面板中選取任何變體(debug 是預設值)

The build variant menu in Android Studio with Release selected.

產生的應用程式套件或 APK 檔案位於您應用程式資料夾內的 build/app/outputs 中。