跳至內容
2026年8月8日.上架

無痛打造原生應用程式

本文所描述的產品內容以發布當時為準。如需目前功能,請參閱 AI 建構器智慧代理團隊

無痛打造原生應用程式

假設你已經在對話框裡打造一款待辦事項清單應用程式好幾週了。它目前是個網站——React、一個資料庫,沒什麼特別的。你輸入「幫我做一個 Android 版本」然後按下 Enter。以下是從那次按鍵到一個 .aab 檔案出現在你下載資料夾之間,實際發生的事,因為大多數平台不會讓你看到這部分,而它們隱藏起來的這部分,正是過去所有痛苦的來源。

Android .aab 檔案

Gradle 先接手處理。你應用程式裡的原生模組——相機存取、本機儲存,或是建構過程拉進來的任何外掛——各自宣告自己是針對哪個 NDK 版本編譯的,而這些宣告不一定彼此一致。我親眼見過一個針對 NDK r25 建構的模組,拒絕跟一個假設是 r26 的模組連結,而它丟出的錯誤訊息不會說「版本不符」,而是說某個 .so 檔案深處缺少某個符號之類的話。Kotlin 版本的問題更陰險:一個 Gradle 模組內部固定的版本,可能會悄悄覆蓋掉你建構腳本頂端宣告的版本,而建構過程依然成功——只是產出的執行檔在特定 Android 版本上,實際使用時會當機。這些都不是什麼罕見情況,這是發布原生 Android 應用程式的標準代價,也是為什麼團隊要雇用一個專門知道「這週的錯誤要調哪個參數才會消失」的人。

這裡的建構流程執行的是真正的工具鏈,並且自行吸收這些解析工作:

15–25 分鐘原生編譯階段,使用真正的 Gradle 工具鏈
  • 在依賴衝突變成執行期當機之前就先攔截
  • 工具鏈設定會在每次遇到新的失敗狀況時持續改善

一個更快的假版本——只是塑造一個 .aab 而不執行真正的 Gradle 任務——不到一分鐘就能完成。但它會在你的應用程式需要背景服務或原生加密函式庫的那一刻崩潰,而 Play Store 審核會在一天內就標記出來。我們寧願多花那二十分鐘。

macOS .dmg 檔案

這一個檔案裡包含了兩個建置版本。Xcode 的命令列工具分別編譯出一個 Apple Silicon 二進位檔和一個 Intel 二進位檔,然後 lipo 把它們黏合成一個單一的通用執行檔。

90%以上的新 Mac 銷售是 Apple Silicon

這很誘人——只出一個二進位檔然後收工——直到你想起很多人用的是雇主配發的筆電,而不是自己選的硬體,那台筆電可能已經三年了還是 Intel 晶片。與其讓使用者自己搞清楚自己的晶片是哪種(大多數人根本說不出來),我們兩種都出,讓作業系統靜靜地自己挑。另一個方案,我們早期試過,是在 Linux 主機上用模擬工具鏈交叉編譯所有東西。速度是快,但也因此在正式上市六週後,才在真正的 macOS 12 硬體上冒出一個程式碼簽署的邊緣案例,由一位完全搞不懂為什麼應用程式打不開的困惑使用者回報。

Windows 安裝程式

這正是決定使用者是否信任這個應用程式的第一印象時刻。Windows SmartScreen 還不認識你的安裝程式——它還沒在微軟伺服器上累積信譽——所以會顯示一個藍色的「Windows 已保護你的電腦」畫面,上面有個粗體的「不要執行」按鈕,以及一個幾乎看不見的「其他資訊」連結,點下去才會出現「仍要執行」。macOS 也有自己版本的類似流程:按右鍵、打開、確認,因為 App Store 以外的應用程式預設也不受信任。早期我們把這兩個都連到一個通用的常見問題頁面。客服工單告訴我們這行不通——一個盯著螢幕看到「你的下載檔案可能是惡意軟體」的人不會去讀說明文件,他們會截圖然後問自己是不是被駭了。所以安裝流程會偵測作業系統並直接顯示所需的那三個確切點擊步驟,不需要常見問題頁面。這是個小細節,但檔案本身也很重要:下載的檔名是以你的產品命名,而不是建置產物的名稱。沒有人應該要在客服對話中解釋自己下載的是「app-release-signed-v2-final.exe」,還搞不清楚是不是正確的檔案。

瀏覽器擴充功能清單檔

這是整個流程裡的異類——沒有 Gradle、沒有 NDK、也沒有一般意義上的編譯步驟。取而代之的是一份清單檔,而這份清單檔其實是在跟一位你永遠不會直接對話的 Chrome 線上應用程式商店審核員談判。

請求的權限審核結果
<all_urls>(比功能實際需要的範圍更廣)跟不願明說具體反對理由的審核員來回拉鋸兩週
activeTab(限定在實際需要的範圍)當天就過關

MV3 也讓 MV2 原本輕鬆的一件事變複雜了:背景 service worker 會依設計在任務執行到一半時被卸載,這是 Google 為了電池續航力做的政策決定,需要撐過這種狀況的功能必須順著這個限制設計,而不是硬碰硬對抗。我們預設每個擴充功能都採用其實際功能所需的最小權限集合,只有在特定功能真的需要時才擴大範圍。

簽署金鑰庫

在 Android 建置的底層,藏著一個你永遠看不到、卻也絕對輸不起的產物:簽署金鑰。一旦弄丟,你失去的不只是更新應用程式的能力——你會永久失去以現有身分更新它的能力,Google 不會給你任何復原途徑。這不是什麼光鮮亮麗的基礎設施,就是一個檔案。但它決定了你六個月後推出新版本時,是無縫更新,還是變成一個全新上架項目,安裝次數和評論數都從零開始。我們為每個專案產生一把金鑰並妥善保管,讓每一次未來的建置都用和第一天相同的金鑰簽署。

貫穿一切的對話串

以上這些都不是活在另一個獨立的「行動裝置專案」裡,而是同一段建構出網頁應用程式的對話。要求做 UI 變更,網頁版就會更新;接著要求產生 Android 應用套件,它會從那個同樣的最新狀態編譯,而不是從三週前就已經脫節的分支。我看過大多數團隊事後才想把原生應用硬接上去,結果變成同時維護兩套逐漸分歧的程式碼——每天都在出版的網頁應用,以及某人得記得在每次發佈前手動追進度的原生外殼。這個落差正是過時問題滋生的地方,而單一的建置歷程正好消除了它。不過這也是雙面刃:如果最近的對話一直很隨性、不嚴謹,Android 建置也會直接繼承這一點。這不是另一道打磨工序,而是對目前實際狀態的直接編譯——實務上這反而讓人更誠實,因為沒有「送審前再來清一清」這種可以蒙混過關的支線任務。

當準備好上架時,上架流程會交棒給你自己的 Play Store 上架資訊和你自己的 Apple 開發者帳號,而不是我們的。我們不想插在你和你自己的發行通路之間。

即將推出:iOS 和 macOS App Store 版本。打包機制的架構基本上和上面所述相同——Apple 的簽署與審核流程是另一個獨立的專案,我們寧願確定能用了才推出,也不要趕著推出。
發布上架
分享XLinkedInFacebookRedditQuoraWhatsAppTelegram電子郵件
← 所有文章