---
tags: Flutter
---
# Flutter 之發布 APP 到商店中
在完成一個可完整使用的應用程式後
就可以開始進行發布的動作了
發布一個 APP 的程序主要如下:
1. 測試與優化性能
2. 確認 APP 的配置
## 測試與優化性能
### 測試
- 在安卓模擬器與 IOS 模擬器中測試
- 這邊要注意有些功能在模擬器中無法進行測試,比如 IOS 模擬器就無法拍照等等
- 連結真實設備進行測試(如有平板或不同尺寸、不同新舊版本的設備,盡可能都拿來測試一輪)
- 確認樣式是否有問題
- 按鈕放置在畫面正下方時,於 IOS 設備上是否會被切邊
- 當文字長度過長時是否會自動換行或出現 overflow 的警告
- 確認運行狀況是否良好
- 速度是否夠快、會不會卡頓
- 是否有出現任何功能上的錯誤
### 優化
- 可以使用 const 宣告不被重構的內容一律都加上 const
- 較大的小部件可嘗試進行有意義的拆分,讓小部件盡可能的縮小
## 確認 APP 配置
- 確認 APP 的 ID 是否為唯一值,更改方式有以下幾種
1. 在創建 flutter 項目,通過指令設定 ID 前綴: `flutter create appname --org com.{yourname or companyname}`
2. IOS 開啟 Xcode 到 `Signing & Capabilities` 中重設 Bundle identifier
3. android 開啟&更改以下檔案:
- `android/app/build.gradle` => `defaultConfig` 更改 `applicationId`
- `android/app/src/debug/AndroidManifest.xml` 更改 `package="..."`
- `android/app/src/main/AndroidManifest.xml` 更改 `package="..."`
- `android/app/src/main/kotlin/com/example/flutter_meals_app/MainActivity.kt` 更改 package
- `android/app/src/profile/AndroidManifest.xml` 更改 `package="..."`
- 設置 APP 的顯示名稱
- android: 開啟檔案 `android/app/src/main/AndroidManifest.xml` 於 `android:label="XXXX"` 設置 APP 的顯示名稱
- IOS: 用 Xcode 開啟檔案 `ios/Runner.xcworkspace`,點擊左側 `Runner`,在 identity 裡面的 Display Name 設置 APP 的顯示名稱
- 設置需要的權限
- 開啟檔案 `android/app/src/main/AndroidManifest.xml` 於 `manifest` 標籤中添加需要的權限:
- 需要擁有網路連線:`<uses-permission android:name="android.permission.INTERNET"/>`
- 所有權限清單:https://developer.android.com/reference/android/Manifest.permission
- 設定應用程式執行所需 API 級別
- 開啟檔案 `android/app/build.gradle` 更改 `defaultConfig` 中的內容:
1. `minSdkVersion`: 指定應用程序設計運行的最低 API 級別,假設你的設備低於此級別,商店就不會讓你安裝應用
2. `targetSdkVersion`: 指定應用程序設計運行的目標 API 級別,默認值通常就是正確的不需要更改
- 確認第三方服務的設置是否完善,比如各種服務的 key 或 rules 等等
## 為應用程式加上圖標與初始畫面
### 設置圖標
#### 安裝及使用 flutter_launcher_icons
安裝方式:
開啟項目中的 pubspec.yaml 檔案,
於 dev_dependencies 處添加 flutter_launcher_icons: ^0.13.1
> 通常透過指令安裝的 package 會被放置在 dependencies 中
> 而放置在 dev_dependencies 中的 package,則表示只會在開發模式下使用
設置方式:
開啟項目中的 pubspec.yaml 檔案,
於 dev_dependencies 區塊下面添加一段設置內容
如下:
```yaml=
dev_dependencies:
flutter_lints: ^2.0.1
flutter_test:
sdk: flutter
flutter_launcher_icons: ^0.13.1
flutter_launcher_icons: # 設置 flutter_launcher_icons 套件內容
android: true # 告知 flutter_launcher_icons 要創建安卓的圖標
ios: true # 告知 flutter_launcher_icons 要創建 IOS 的圖標
image_path: "assets/images/icon.png" # 設定圖標檔案(開圖尺寸 432x432px 內容尺寸 230x230px)
adaptive_icon_background: "#ffffff" # 針對安卓設置圖標背景顏色(也可以是一張圖片),假設安卓手機有套用主題,則可以自適應產生新的圖標
adaptive_icon_foreground: "assets/images/icon_adaptive.png" # 針對安卓設置無背景的圖標檔案,自適應圖標(開圖尺寸 432x432px 內容尺寸 164x164px)
remove_alpha_ios: true # 針對 IOS 設置移除透明度
```
接著於終端機開啟項目,
執行命令 `https://pub.dev/packages/flutter_launcher_icons` 即可
最後就可以開啟 IOS 與安卓模擬器確認是否有成功顯示圖標囉!
### 設置初始畫面
#### Android
1. 製作要用的 splash_icon:
用剛才製作的 icon 另外生成一個 1024x1024px 的大小
將圖片存為 `splash_icon.png` 檔案
並放置到以下五個資料夾中:
`drawable-hdpi` 、 `drawable-mdpi` 、 `drawable-xhdpi` 、 `drawable-xxhdpi` 、 `drawable-xxxhdpi`
2. 設置 splash 畫面
將 `android/app/src/main/res/drawable/launch_background.xml` 檔案更改為:
```xml=
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item> <!-- 新增一個 item -->
<color android:color="@color/splash_background" /> <!-- 新增這行,設置 splash 畫面的背景色為顏色參數 splash_background -->
</item>
<!-- You can insert your own image assets here -->
<item> <!-- 註解打開 -->
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" /> <!-- @mipmap/launch_image 改為 @drawable/splash_icon -->
</item>
</layer-list>
```
接著將檔案內容全部拷貝,覆蓋原本的 `android/app/src/main/res/drawable-v21/launch_background.xml` 檔案內容
3. 設置 splash 畫面的背景顏色參數
將 `android/app/src/main/res/values/colors.xml` 檔案更改為:
```xml=
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#8BC34A</color>
<color name="splash_background">#8BC34A</color> <!-- 新增這行,設置新的顏色參數 splash_background -->
</resources>
```
4. 使用安卓模擬器開啟 APP 確認是否正確顯示 splash 畫面(如果看不到,請先在模擬器中將自己的 APP 解除安裝再重新啟動)
#### IOS
1. 製作要用的 splash_icon:
用剛才製作的 icon 生成:
512x512px 大小的圖片,存為 `splash_icon3x.png` 檔案
256x256px 大小的圖片,存為 `splash_icon2x.png` 檔案
64x64px 大小的圖片,存為 `splash_icon1x.png` 檔案
2. 上傳 icon
用 Xcode 開啟專案項目中的 ios/Runner.xcworkspace
開啟 Runner/Runner/Assets,點選 LaunchImage
將剛才製作的三個檔案依照檔名分別對應上傳至 1x 、 2x 、 3x 中
3. 連結真實 iPhone 進行測試
將 iPhone 連結你的電腦
於 Xcode 中選取你的 iPhone 裝置
點擊左上角的播放鍵進行編譯並啟動 APP 即可看到 splash 畫面
## 正式發佈 APP 到商店中
### Google Play
首先要為應用程式設置簽名,步驟如下:
1. 創建&上傳 keystore
於專案項目中執行指令:
`keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload`
接著回答問題:
```
Enter keystore password: # 設置密碼
Re-enter new password: #再次輸入密碼
Enter the distinguished name. Provide a single dot (.) to leave a sub-component empty or press ENTER to use the default value in braces.
What is your first and last name? # 輸入姓名
[Unknown]: Xuan Wang
What is the name of your organizational unit? # 輸入職位名稱
[Unknown]: Front-end Developer
What is the name of your organization? # 輸入公司或組織名稱
[Unknown]:
What is the name of your City or Locality? # 所在城市或地區
[Unknown]: Taoyuan
What is the name of your State or Province? # 所在州或省
[Unknown]: Taiwan
What is the two-letter country code for this unit? # 輸入二位國家代碼
[Unknown]: TW
Is CN=Xuan Wang, OU=Front-end Developer, O=Unknown, L=Taoyuan, ST=Taiwan, C=TW correct? # 確認資訊是否都正確,如無誤就輸入 y 進行創建;如需修改則輸入 n 會重新再問一次問題
[no]: y
Generating 2,048 bit RSA key pair and self-signed certificate (SHA384withRSA) with a validity of 10,000 days
for: CN=Xuan Wang, OU=Front-end Developer, O=Unknown, L=Taoyuan, ST=Taiwan, C=TW
[Storing /Users/{username}/upload-keystore.jks] # 看到這邊就表示創建完成了
```
>附上 [二位國家代碼查詢網站](https://payroll.nsysu.edu.tw/pay/rcxf_COUCODE.php?s_ENGNAME=&s_COU=) (感謝谷歌大神🙏)
2. 於 APP 中引用 keystore
創建檔案 /android/key.properties 並放入以下內容:
```
storePassword=<password from previous step> # 這邊改為稍早設置的密碼
keyPassword=<password from previous step> # 這邊再次填入密碼
keyAlias=upload
storeFile=<location of the key store file, such as /Users/<user name>/upload-keystore.jks> # 這邊改為你存放 .jks 檔案的完整路徑
```
>這邊要注意如有使用 GitHub 等儲存原始碼,請於 .gitignore 中確保加入:
>`**/android/key.properties`
3. 配置 keystore
更新檔案 /android/app/build.gradel
首先在 `android { ... }` 的前一行加入以下內容:
```
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
...
}
```
接著往下找到內容:
```
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
}
}
```
完成上述步驟後,發布應用程式時就會自動進行簽名了。
接著請先於項目中執行指令: `flutter clean` 清除所有緩存,確保正確執行到稍早配置的 keystore
然後執行指令: `flutter build appbundle` 建立發布應用程序用的 app bundle
最後進入 Google Play Console 網站,註冊成為開發者帳號(需支付 25 美金)
點擊建立應用程式,並按照一系列的說明進行資訊的填寫以及設置
接著可於左側選單點擊測試,選擇其中一種測試方式,
上傳你的 app bundle 檔案,檔案路徑為你的項目目錄中的:
`/build/app/outputs/bundle/release/app-release.aab`
### App Store
1. 登入蘋果開發者帳號,並於此頁面新增 App IDs:https://developer.apple.com/account/resources/identifiers/list
2. 登入 App Store Connect:https://appstoreconnect.apple.com/login
3. 點擊我的 APP => 點擊+號新增 => 勾選 IOS、填入資訊
4. 開啟 Xcode 確認 Bundle ID 與應用程式名稱是否符合剛才填入的資訊內容
5. 開啟終端機輸入: `flutter build ios`
6. 終端機跑完後,將 Xcode 關閉再用 Xcode 重新打開 ios/Runner.xcworkspace
7. 於選單列點擊 Prouct>Scheme>Runner 、 Prouct>Destination>Any iOS Device 、 Prouct>Archive
8. Archive 跑完後會開啟新視窗,可進行驗證與分發,這邊點分發後回到 App Store Connect 進行發布設置即可