iT邦幫忙

2023 iThome 鐵人賽

DAY 25
0
Mobile Development

單人開發者之路:React Native 與 Expo 帶你從開發到上架系列 第 25

Day 25 - 使用Expo專案建置你的第一支Android APP

  • 分享至 

  • xImage
  •  

在你的APP有一定的規模後
就是要建置給內部人員 or 客戶測試使用
本篇會使用Expo專案
搭著React Native官方Android打包說明
帶你完成建置Android APP

※本篇使用環境為Windows PC & Visual Studio Code IDE

建置前簡介

稍微講解一下Android建置原理
(iOS建置概念相同,本篇一併介紹)
以及為何Expo有推出EAS CI/CD建置工具而不使用

Android、iOS建置APP原理

雙平台差不多,這邊就一併講解
手做一張建置流程圖提供參考

https://ithelp.ithome.com.tw/upload/images/20230929/20130821XA3DHw2mSW.png

  1. Expo專案使用預建(prebuild)系統,快速產出Android/iOS原生專案
  2. React Native 內建一個 JavaScript 打包工具,稱為 Metro Bundler
    這個工具將 JavaScript 代碼打包成一個綑綁(bundle)文件。
    Gradle(Android建置工具) 會將這個bundle文件包括到生成的 APK 文件中
    而iOS建置是使用XCode協助轉譯
  3. 平常使用的<View> <Text> 實際上是在底層原生代碼中使用的
    原生編譯時會直接轉譯
  4. Gradle 和 Xcode 編譯綑綁(bundle)文件及原生代碼後
    依照平台生成可執行的程式
    Android APP副檔名:APK/AAB
    iOS APP副檔名:IPA

為何不使用EAS Build建置

Expo專案對Android打包手冊參考:
https://docs.expo.dev/build-reference/apk/

使用免費版EAS Build雲端建置時
曾經排隊建置時間(Quene time)等了3h 9m 0s
建置時間(Build time)也長達10m 41s
排隊時間還會隨著建置時間逐漸累加😡

https://ithelp.ithome.com.tw/upload/images/20230929/20130821wVe45oF047.png

金錢成本吃緊的情況下
打消了Expo EAS雲端建置上架的念頭

事前準備

調整app.json相關設定

在新增Android專案前
得先調整好APP的名稱、LOGO、版本、權限

Expo對於app.json的所有設定講解
https://docs.expo.dev/versions/latest/config/app/
這邊只列出Expo在新增專案時所使用的

"name": "我是Expo系統",
"slug": "TestExpoApp",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./img/logo.jpg",
"splash": {
  "image": "./img/logo2.jpg",
  "resizeMode": "contain",
  "backgroundColor": "#000000"
}
  • name 應用程式名稱,在使用者安裝APP後會看到此名稱
  • slug 識別專案名稱,通常用於APP建置在Expo服務器中使用
    https://expo.io/@你的用戶名/你的slug
  • version 版本號,讓Play商店知道你現在的APP版本
    日後還有修改需求,請記得修改此欄位
  • orientation APP方向,可以設定APP要直向還是橫向,預設雙向可用
  • icon APP的圖示,一定要記得修改圖示
    使用者才找的到APP在哪裡
  • userInterfaceStyle 介面外觀,可調整深色、淺色模式(預設為淺色)
  • splash 啟動畫面圖示

另外針對android部分,進行細節設定

"android": {
  "package": "com.xxx.TestxxxAPP",
  "permissions":["ACCESS_COARSE_LOCATION","ACCESS_FINE_LOCATION","ACCESS_BACKGROUND_LOCATION"],
  "versionCode": 1
},
  • package Android應用程式 ID,參考下方命名方式

應用程式 ID 的命名規則比較嚴格:
必須包含至少兩個區隔 (一或多個點)。
每個區隔的開頭都必須是英文字母。
所有字元都必須為英數字元或底線 [a-zA-Z0-9_]。

安裝JDK

React Native Android專案使用Gradle建置工具
在下載Android Studio時,Gradle也會一併被下載

Windows使用者:需先安裝JavaJDK (Java Development Kit)後才能使用建置工具
MAC使用者:可參考Mac 上用 Homebrew 安裝 Java 的方式

設置 JAVA_HOME 環境變數

在安裝Java完成後
需手動設定JAVA_HOME環境變數
才能在VS Code終端機直接使用Java相關功能

Windows 10使用者:

  1. 工作列下方找到檔案總管
  2. 本機右鍵點選【內容】
  3. 點選右方【系統保護】
  4. 點選【環境變數】
  5. 新增JAVA_HOME系統變數,變數值為JDK安裝路徑
    C:\Program Files\Java\jdk-17 (JDK版本有更新記得調整此部分)

https://ithelp.ithome.com.tw/upload/images/20231011/20130821auicVE3uUW.png

MAC使用者:
在終端機輸入下方指令就能設定環境變數了
export JAVA_HOME="$(/usr/libexec/java_home)"

建置Android專案

新增Android專案

Expo專案預先是不會幫你建好Android專案
必須先使用該指令:npx expo prebuild
(在MACOS則會新增ios資料夾)

※若你已有Android資料夾,則不一定要使用該指令
通常有SDK升級、新權限才會使用該指令
因為本段指令會將專案重建

其他環境指令參數參考:
https://docs.expo.dev/workflow/prebuild/

指令下達成功後,資料夾內容如圖

https://ithelp.ithome.com.tw/upload/images/20230929/20130821lNYOLJmRzc.png

設定keystore

keystore主要是讓APP識別開發者資訊
以及加密簽署APP、憑證存取、用戶密碼儲存...等
另外keystore是可以簽署多支APP的
設定一次之後,一定要記得保留此簽署檔
Web使用者可以當作是,產出TLS安全協議憑證(https)的概念

Android開發者專區針對keystore介紹:
https://developer.android.com/training/articles/keystore

產生keystore APP簽署

※使用指令前,需使用系統管理員權限之終端機

使用keytool(Java內建公用程式)
keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

  • -genkeypair 告訴keytool需創建一對密鑰
  • -v verbose,詳細列出操作進展
  • -storetype PKCS12 指定密鑰存儲的類型(PKCS12)
  • -keystore my-release-key.keystore keystore檔的檔名,可自行調整
  • -alias my-key-alias 金鑰別名,用於識別 keystore 中的密鑰對
  • -keyalg RSA 加密演算法(RSA)
  • -keysize 2048 演算法密鑰的位數,長度越長,安全性越高,但相對計算更久
  • -validity 10000 證書有效期限(10000天),可依需求自行調整

執行後會需要填入一些公司行號/個人資訊

https://ithelp.ithome.com.tw/upload/images/20230929/20130821cgIthV0IW8.png

設定完後keystore路徑會在
C:\Program Files\Java\jdkx.x.x_x\bin

最後將產出後的keystore檔
放到android\app資料夾中

設定gradle.properties

找到android/gradle.properties gradle配置設定檔
在檔案下方加入以下設定,讓gradle知道要使用哪一份簽署檔

# 以下是發布Keysotre設定
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=qaz555
MYAPP_RELEASE_KEY_PASSWORD=qaz555

設定值會以當時使用keytool產出的內容為主

設定build.gradle

找到android/app/build.gradle 應用程式建置設定

找到下方有一項signingConfigs設定
加上release讀取上方properties的內容值
參數名稱可以自行改掉MYAPP_RELEASE...
只要參數名稱有對應到,就能讀取剛剛設定好的keystore檔了

signingConfigs {
    debug {
        storeFile file('debug.keystore')
        storePassword 'android'
        keyAlias 'androiddebugkey'
        keyPassword 'android'
    }
    release {
        if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
            storeFile file(MYAPP_RELEASE_STORE_FILE)
            storePassword MYAPP_RELEASE_STORE_PASSWORD
            keyAlias MYAPP_RELEASE_KEY_ALIAS
            keyPassword MYAPP_RELEASE_KEY_PASSWORD
        }
    }
}

另外,React Native官方還要求調整buildTypes設定
signingConfigs調整為release
在打包之前確定使用release版本的keystore檔

buildTypes {
    release {
        ...
        signingConfig signingConfigs.release
    }
}

參考:https://reactnative.dev/docs/signed-apk-android

在外層也有一支build.gradle,常常讓開發者混淆
外層build.gradle只能做全域型設定
(Gradle版本、所有子專案的依賴關係、全局的Gradle插件)

打包APK

APK(Android Package)是Android平台的套件檔案格式
Android使用者只要對著APK點一下
就能將APP安裝進去

適用於內部上架
不透過Play商店,讓使用者下載APP

若你自身已有網站
可以將APK檔放到網站主機上,並設定好路徑讓使用者下載APK

產出APK指令:

cd android
./gradlew assembleRelease

成功後APK路徑如下
APP資料夾\android\app\build\outputs\apk\release

打包過程中會看到Expo模組一個個被gradle轉譯

https://ithelp.ithome.com.tw/upload/images/20230929/20130821Se1WtqCGaP.png

打包AAB

AAB(Android APP Bundle)是Android 2018年推出的新版格式
可以縮小APP的容量
Android官方文件對於AAB格式詳細說明:
https://developer.android.com/guide/app-bundle/faq?hl=zh-tw#what_is_the_android_app_bundle_aab

目前上架Play商店時,需使用此格式

產出AAB指令:

cd android
./gradlew bundleRelease

成功後AAB路徑如下
APP資料夾\android\app\build\outputs\bundle\release

建置後注意事項

下圖代表建置成功,你的第一支APP就此誕生👏

https://ithelp.ithome.com.tw/upload/images/20230929/20130821mfGJBllZB8.jpg

※建置時間會取決於電腦處理速度及運算能力

若過程中發生Error,需初步檢查以下內容

  • Java環境設定、是否正確安裝
  • 套件相依性衝突
    因為參考React Native官方說明操作
    而第三方套件皆不在官方維護範圍內
    必要時可能要移除部分Expo套件😱
    或是使用 npx expo-doctor 請醫生診斷整個專案的套件是否衝突
  • npx expo run:android 是否正常在實體手機/模擬器執行
    必要時將 node_modules 資料夾刪除
    在使用 npm install 將套件安裝回來

若還是發生其他不可預期的Error
可以將錯誤訊息貼到Google or ChatGPT查看是否有同樣解法


結語:
Android專案其實還有非常多的設定
都是Expo建置時,就已經設定完成
想了解其他設定值可以參考React Native官方文件
react-native-gradle-plugin

如果你的專案不需上架至Play商店
那麼本篇已經完成你的第一支Android APP了🤟

若你需要上架至Play商店
那麼AAB檔打包後請留在電腦裡,下一篇會使用

下一篇要來講解
讓你的Android APP上架至Play商店,讓大家來安裝。


上一篇
Day 24 - 使用 Fetch 和 MockAPI 模擬真實資料 feat.環境變數
下一篇
Day 26 - React Native Android APP上架至Play商店
系列文
單人開發者之路:React Native 與 Expo 帶你從開發到上架30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
lijun
iT邦新手 5 級 ‧ 2023-10-11 13:40:15

版主辛苦了
以下是我跟著步驟所遇到的問題以及如何解決

第一個是在使用keytool
若是事先沒有先設好JAVA_HOME環境變數且沒有使用系統管理員啟動命令提示字元(CMD),會無法建置keystore。(有可能是因為我跳著看文章導致前面有提過所以沒設置到)

第二個是在設定build.gradle時
根據版主的程式碼:

signingConfigs {
  debug {
              storeFile file('debug.keystore')
              storePassword 'android'
              keyAlias 'androiddebugkey'
              keyPassword 'android'
      }
  }
  release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
  }

會出現錯誤訊息如下:

  • What went wrong:
    A problem occurred evaluating project ':app'.

Could not find method release() for arguments [build_9yszuqzdc3k78iio30o9ei0u6$_run_closure2$_closure7@7aa4ca12] on extension 'android' of type com.android.build.gradle.internal.dsl.BaseAppModuleExtension.

修改程式碼為:

signingConfigs {
    debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
    release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
        }
    }
}

就可以正常建置了。

peterlu iT邦新手 2 級 ‧ 2023-10-11 17:39:59 檢舉

感謝你的測試🙏

  1. JAVA_HOME環境變數的部分真的是少講到
    (太久沒有重新安裝JDK...)
  2. signingConfigs部分是貼Code的時候debug那塊多打一個大括弧😢

皆已調整文章內容了。

0
EugenAchtzehn
iT邦新手 4 級 ‧ 2023-11-27 14:35:15

補充一下(?
當在 app/build.gradle 下放入 signingConfigs 的 release 設定後,還要調整下面的 buildTypes,設定當 release 時 signingConfig 要讀 signingConfigs.release

buildTypes {
    debug {
        signingConfig signingConfigs.debug
    }
    release {
        signingConfig signingConfigs.release
    }
}
peterlu iT邦新手 2 級 ‧ 2023-11-27 17:05:01 檢舉

感謝🙏
文章調整了

我要留言

立即登入留言