這是我在2023第十五屆 iThome 鐵人賽發表的系列文章。https://ithelp.ithome.com.tw/users/20136637/ironman/6408
本篇會分享從生成 APK/AAB、設置應用、測試應用到上架 Play Store 的過程。
- Android 要求所有應用都必須使用憑證進行數位簽署,才能安裝到裝置上或進行更新。
- 自 2021 年 8 月起,Google Play 上的新應用程式都必須以 .AAB (Android App Bundle) 檔案格式發布。
生成 Keystore
Keystore 憑證用於保存加密的金鑰。為驗證開發者身份,應用需要使用 keystore 進行數位簽署。只有擁有憑證私鑰的人才能創建、更新應用,所以必須好好保存。
注意:如果丟失上架應用的 keystore 密碼、私鑰的相關信息,那原本的應用就無法繼續更新,只能創建新的應用或者向 google 申請換成新的 key。
- 使用 keytool 指令產生金鑰組:
keytool -genkeypair -v -storetype PKCS12 -keystore ${KEY_NAME}.keystore -alias ${KEY_ALIAS} -keyalg RSA -keysize 2048 -validity 10000
例如:keytool -genkeypair -v -storetype PKCS12 -keystore pokedex.keystore -alias pokedex -keyalg RSA -keysize 2048 -validity 10000
- keytool: Java 中用於管理金鑰和憑證的命令工具
- -genkeypair: 生成一個金鑰組,即公鑰和私鑰
- -storetype PKCS12: 金鑰的類型為 PKCS12
- -keystore {KEY_NAME.keystore}: 金鑰檔案名稱為
${KEY_NAME}.keystore
- -alias {KEY_ALIAS}: keystore 的別名為
${KEY_ALIAS}
- -keyalg RSA: 指定產生金鑰組使用 RSA 演算法為
- -keysize 2048: 指定產生的每一個金鑰的大小為2048位元,金鑰大小至少為 112 位元,建議設為 2048 位元。
- -validity 10000: 生成的憑證有效期為 10000 天,即憑證將在 10000 天後過期
- 接著會要求你輸入 keystore 的密碼,以及一些發行相關的資訊。
- 發行相關資訊可以都不填直接按下 Enter 跳過
完成後會生成<KEY_NAME>.keystore
在輸入指令的路徑:
- 發行相關資訊可以都不填直接按下 Enter 跳過
注意:記得將
.keystore
加進.gitignore
中,不要上傳。
設置 Gradle 變數
1.把 <KEYSTORE_NAME>.keystore
放到 android/app
下。
2.在 /android 底下新增 keystore.properties
將 keystore 變數存在裡面:
STORE_FILE=KEYSTORE_NAME.keystore
KEY_ALIAS=KEYSTORE_ALIAS
STORE_PASSWORD=******
KEY_PASSWORD=******
STORE_PASSWORD
就是剛剛生成密鑰對時輸入的密碼,KEY_PASSWORD
會和 STORE_PASSWORD
一樣。
注意:記得將
keystore.properties
加進.gitignore
。
把簽署配置添加到 gradle 中
在 android/app/build.gradle
添加以下內容:
- 在 signingConfigs 加上 release 區塊
- 將
buildTypes.release.sigingConfig
改成signingConfigs.release
// android/app/build.gradle
...
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('keystore.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
...
defaultConfig { ... }
signingConfigs {
...
release {
if (keystoreProperties['STORE_FILE']) {
storeFile file(keystoreProperties['STORE_FILE'])
storePassword keystoreProperties['STORE_PASSWORD']
keyAlias keystoreProperties['KEY_ALIAS']
keyPassword keystoreProperties['KEY_PASSWORD']
}
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
...

Expo
只需要將 .jks 或者 .p12 上傳到 Expo project 的 credentials 中,Expo 會自動執行 Android 和 iOS 應用程式的簽署過程。
Project – Credentials – Get Started (或 +Application Identifier)

你需要提供:
- Application Identifier (
android/app/src/main/AndroidManifest.xml
中的package
) - Android Keystore (剛剛生成的 keystore file, keystore password, key alias 和 key password)


設置應用版本
記得修改應用的版本號 versionName, versionCode,上傳到 Play Store 不能有重複的 versionCode,每一次上傳新版本記得都要將 versionCode + 1
android/app/build.gradle
android {
...
defaultConfig {
...
versionCode 1
versionName "1.0.0"
}
}
應用上架前的準備工作: https://ithelp.ithome.com.tw/articles/10329076
生成 APK 或 AAB
使用以下指令開始打包:
APK
- 生成的 .apk 會在
android/app/build/outputs/apk/release
- 這邊指令生成的是 release,如果要打包 debug 版本可以改為
assembledebug
cd android && ./gradlew assembleRelease && cd ..
AAB
- 生成的 .aab 會在
android/app/build/outputs/bundle/release
cd android && ./gradlew bundleRelease && cd ..
Trouble Shooting
有時候打包發生未知的錯誤可以
./gradlew clean
清除 build 資料夾後再重新打包
Gradle version
如果打包時出現下面這個錯誤就代表 java 版本和 gradle 的不適配
* What went wrong:<br>Could not open settings generic class cache for settings file '/android/settings.gradle' (Users/.gradle/caches/8.0.1/scripts/xxxxxxxxx).<br>> BUG! exception in phase 'semantic analysis' in source unit '_BuildScript_' Unsupported class file major version 64

官方有提供 gradle 和 java 版本對應表
https://docs.gradle.org/current/userguide/compatibility.html#java

像我是 java 20 就應該對應 gradle 8.1,所以我使用 8.0.1 會因為版本過低而失敗。
android/gradle/wrapper/gradle-wrapper.properties
可以查看 gradle 版本java -version
可以查看 java 版本


因此將 android/gradle/wrapper/gradle-wrapper.properties
的 distributionUrl 改成 8.1 的連結即可
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-all.zip
查看 gradle 版本: https://services.gradle.org/distributions/
compileReleaseJavaWithJavac
Execution failed for task ':app:compileReleaseJavaWithJavac'.
我自己遇到這個 error 是因為 AndroidManifest.xml
的 package
與 build.gradle
中的 applicationId
不一致,改成一致之後就解決了。
測試應用
在把 release 版本的 AAB 提交到 Play Store 之前,你可以先測試一下應用是否能正常使用:
npx react-native run-android --variant=release
注意:
--variant=release
只能在你完成了上面的簽署配置之後才可以使用。- 在 debug 和 release 版本間來回切換安裝時可能會導致簽署不匹配,需要先卸載前一個版本再安裝一次。
註冊 Play Console 帳戶
如要建立 play console 帳戶需要 $25 USD 的註冊費 (僅須支付一次)。
在 Play Console 建立 developer 帳戶,選擇帳戶類型:

後面步驟按照提示走即可,註冊完需要上傳證件照片驗證身份後才能發布應用(包括內部測試)


可以接受駕照、護照、身分證、居留證。
- 證件照片要能夠看得到證件的四個角。

驗證的過程大概需要 1~2 個工作日,我自己是等了 1 天。
設置應用相關資料
在上架之前可以先進行內部測試,內部測試不需要通過 Google 審核,並且可以將應用分享給 100 位內部測試人員,藉此找出問題並在初期取得意見回饋。
首先建立一個新的應用程式

資訊主頁
就算只是要在內部測試還是得把一系列設定全部設定完,這邊我就不一張一張截圖要不然實在是太多了…各位按照步驟一步一步來吧

如果需要隱私權政策 URL,可以直接使用工具生成:https://app.privacypolicies.com/


設置應用商店資料:

這些圖像是必傳的:
- 應用程式圖示:512*512,JPEG 或 PNG,不能超過 1MB
- 主題圖片:1024*500,JPEG 或 PNG,不能超過 15MB
- 手機螢幕截圖:4 ~ 8 張,PNG 或 JPEG,每張圖片的大小不得超過 8 MB
- 7吋, 10吋平板截圖:2 張以上,PNG 或 JPEG,每張圖片的大小不得超過 8 MB



建立新版本
左側菜單找到「內部測試」點擊「選取測試人員」:

將要測試的 email 添加進測試名單,多個 Email 之間用逗號,
隔開,然後記得按 Enter 新增:

選取好測試的人員之後按下「儲存」

接著「建立新版本」

點擊「選擇簽署金鑰」

這邊我建議是使用 Google 產生的金鑰

上傳 AAB 以及填寫版本資料:

在這邊你能看到與版本相關的錯誤、警告,如果有錯誤的話必須先解決。

內部測試應用
一切設置完成之後在 設定 – 內部應用程式分享 將管理測試人員選為「限制存取電子郵件名單」,然後選擇下載者的清單:


如果你的應用需要登入後才能使用部分功能,需要在「測試 – 正式發布前測試報告 – 設定」中設置「提供測試帳戶憑證」

還有設置 deep link, 多語系

接著回到 內部測試 – 測試人數 下面有一個「複製連結」的按鈕,這個連結就是下載內部應用程式的連結,會導向 Play Store 下載內部測試應用:



刪除 APP bundle 版本
如果想刪除錯誤或不用的 app bundle 版本可以在「應用程式套件探索工具」找到要刪除的版本右側點進去

右側有一個「刪除 app bundle」,刪除即可

上架應用至 Play Store
所有測試和設置都完成後,上架 Play Store 只缺需要提交正式版本以及提交送審即可。

測試 – 正式發布前測試報告 – 詳細資訊 這邊可以看到應用測試的結果,分穩定性、成效、無障礙、螢幕截圖、安全性,Google 會為你的應用在不同設備上進行測試並提供相關建議,你可以調整後再上架應用。

發布總覽 – 將 N 項變更送審 即可提交應用審核,審核通過後應用就會上架 Play Store,第一次送審的時間最長約 7 天,後續送審就不需要這麼久了。
