iT邦幫忙

2025 iThome 鐵人賽

DAY 26
0
自我挑戰組

攜手 AI 從零開始打造一款 Flutter 應用程式系列 第 26

Day 26: 邁向市場的第一步 - 打包 Android 發布版 (AAB)

  • 分享至 

  • xImage
  •  

前言

大家好!在 Day 24 和 25,我們為「省錢拍拍」App 設計了專業的圖示和無縫的啟動畫面,完成了 App 的「門面」工程。現在,我們的 App 在視覺和功能上都已準備就緒。

今天,我們將進行從「開發」到「上架」的關鍵轉變。我們不再只是用 flutter run 在模擬器上運行測試版,而是要學習如何將專案打包成一個可以上傳到 Google Play 商店的正式發布版本。

我們將專注於 Android 平台,內容涵蓋:設定版本號、建立數位簽章,並最終生成 Google 官方推薦的 AAB (Android App Bundle) 格式。

Step 1: 設定版本號 - App 的身分證

每一次發布到商店的版本,都必須有一個獨一無二的版本號。
打開專案根目錄下的 pubspec.yaml 檔案,找到 version 這一行:

# pubspec.yaml
version: 1.0.0+1

這個字串由兩部分組成,以 + 分隔:

  • 1.0.0: 這是 versionName,是公開給使用者看的版本名稱,通常遵循「主版號.次版號.修訂號」的語意化版本格式。
  • 1: 這是 versionCode,是一個內部的整數。每一次上傳到 Google Play 的新版本,這個數字都必須比前一個版本大。

對於我們的首次發布,1.0.0+1 是一個完美的起始點。

Step 2: 建立數位簽章金鑰 (Keystore)

為了證明 App 是由你這位合法的開發者所發布,並且保證 App 未被竄改,所有發布版的 Android App 都必須經過數位簽章。這個簽章來自於一個你私人持有的金鑰檔案 (Keystore)。

極度重要警告
這個金鑰檔案是你 App 所有權的唯一證明。一旦遺失,你將永遠無法再更新你的 App。請務必將產生的金鑰檔案(.jks)和密碼,備份到安全、可靠的地方(例如雲端硬碟、密碼管理器等)。

我們使用 Java Development Kit (JDK) 內建的 keytool 指令來產生金鑰。請打開你的電腦終端機(不是 VS Code 內的終端機)來執行。

此指令通用於 Windows / macOS / Linux:

keytool -genkey -v -keystore snapsaver-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias snapsaver_alias

執行後,指令行會要求你設定金鑰庫密碼和金鑰密碼(建議設成一樣方便記憶),以及一些個人資訊。請務必記下你設定的密碼。完成後,一個名為 snapsaver-release-key.jks 的檔案就會出現在你的使用者主目錄下。

Step 3: 讓 Flutter 專案引用簽章金鑰

金鑰檔案已經有了,現在要告訴我們的 Flutter 專案如何找到並使用它。

  1. 建立 key.properties
    在專案的 android 資料夾下,手動建立一個名為 key.properties 的檔案。

這個檔案包含密碼,絕對不能上傳到 Git。請檢查 android/.gitignore 檔案,確保其中包含 key.properties 這一行。

  1. 填寫金鑰資訊
    key.properties 檔案中,填入以下內容,並換成你自己的設定:
# android/key.properties
storePassword=YOUR_KEYSTORE_PASSWORD
keyPassword=YOUR_KEY_PASSWORD
keyAlias=snapsaver_alias
# storeFile 指向你上一步產生的 .jks 檔案的絕對路徑
# Windows 範例: storeFile=C\:\\Users\\YourUser\\snapsaver-release-key.jks (注意斜線需要轉義)
# macOS/Linux 範例: storeFile=/Users/YourUser/snapsaver-release-key.jks

也可以將 .jks 檔案直接移動到 android/app 資料夾下,這樣 storeFile 就可以寫相對路徑,例如 storeFile=../app/snapsaver-release-key.jks

  1. 設定 Gradle
    打開 android/app/build.gradle 檔案,我們需要讓 Gradle 讀取 key.properties 並在打包時使用它。這需要進行幾處修改,請仔細對照:
// android/app/build.gradle
import java.util.Properties
import java.io.FileInputStream

// 1. 在檔案頂部,`apply from` 的下方,加入讀取 key.properties 的程式碼
val keystorePropertiesFile = rootProject.file("key.properties")
val keystoreProperties = Properties()
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}

android {
    // ...
    // 為了避免不同開發環境的 NDK 版本差異導致錯誤,這裡明確指定版本
    ndkVersion = "27.0.12077973" //明確設定

    // 2. 在 android { ... } 區塊內,加入 signingConfigs
    signingConfigs {
        release {
            if (keystorePropertiesFile.exists()) {
                keyAlias = keystoreProperties.getProperty("keyAlias")
                keyPassword = keystoreProperties.getProperty("keyPassword")
                storeFile = file(keystoreProperties.getProperty("storeFile"))
                storePassword = keystoreProperties.getProperty("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.getByName("release")
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

Step 4: 執行打包指令 - 生成 App Bundle (AAB)

萬事俱備!現在,我們回到專案的根目錄,在終端機中執行 Flutter 的打包指令。我們將生成 AAB 格式,這是 Google Play 官方推薦的發布格式。它比傳統的 APK 檔案更小、更優化。

flutter build appbundle

這個指令會執行 release 模式的建構流程,並使用我們剛剛設定好的簽章金鑰。過程會需要幾分鐘。成功後,你會在終端機看到綠色的成功訊息,並且發布檔案會生成在以下路徑:

build/app/outputs/bundle/release/app-release.aab

這個 .aab 檔案,就是我們最終要上傳到 Google Play 商店的成品!

今日結語

今天我們完成了從開發者到發布者的關鍵一步。我們學會了 Android 發布流程中的所有核心環節:

  1. pubspec.yaml 中設定版本號。
  2. 產生並安全保管 App 的數位簽章金鑰 (.jks 檔)。
  3. 設定 Gradle,讓專案能使用金鑰進行簽署。
  4. 執行 flutter build appbundle 指令,生成最終的發布檔案。

我們的 Android App Bundle 已經準備好提交給 Google Play。

我們已經成功打包了 Android 的發布檔案,那麼在真正將這個檔案上傳到商店前,還有幾個至關重要的安全步驟需要完成。

  1. Firestore 資料庫權限:在 Day 11,我們為了開發方便,將資料庫設定為「測試模式」,這意味著任何人只要知道我們的專案 ID,就可以對資料庫進行任意的讀寫刪除。
  2. Gemini API 金鑰:在 Day 17,我們將 API 金鑰直接寫在了程式碼中。如果 App 被反編譯,這個金鑰就有洩漏的風險,可能導致您的 API 額度被盜用。

明天,我們將學習 Firestore 安全規則的基本語法,並撰寫一條核心規則:「使用者只能讀寫屬於自己的消費紀錄」。這將徹底保護我們 App 的使用者資料隱私。


上一篇
Day 25: 上架前置作業 (II) - 告別啟動白屏
下一篇
Day 27: 為資料庫上鎖 - 撰寫 Firestore 安全規則
系列文
攜手 AI 從零開始打造一款 Flutter 應用程式29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言