如果您將應用程式發布到 Google Play,應建構並上傳 Android App Bundle。這樣一來,Google Play 就會針對每位使用者的裝置設定自動產生並提供最佳化 APK,讓使用者只下載執行應用程式所需的程式碼和資源。如果您未將應用程式發布到 Google Play,發布多個 APK 是非常實用的做法,但您必須自行建構、簽署及管理各個 APK。
開發 Android 應用程式,充分運用 Google Play 上的多個 APK 時,請務必從一開始就採用一些好方法,避免未來開發程序再多麻煩。本課將說明如何為應用程式建立多個 APK,每個 APK 涵蓋的 API 級別範圍略有不同。您也會獲得一些必要工具,盡可能輕鬆地維護多個 APK 程式碼集。
確認您需要多個 APK
當您嘗試建立適用於多代 Android 平台的應用程式時,自然會希望應用程式在不犧牲回溯相容性的情況下,於新裝置使用新功能。乍看之下,多個 APK 支援似乎是最佳解決方案,但這通常並非如此。多個 APK 開發人員指南的「改用單一 APK」一節提供一些實用資訊,說明如何透過單一 APK 達成這項目標,包括使用支援程式庫。您也可以瞭解如何在單一 APK 中編寫僅在特定 API 級別執行的程式碼,而不必採用 這篇文章中的反射相當高昂的技術。
如果您可以管理,將應用程式限定於單一 APK 有幾項優點,包括:
- 發布及測試更簡單
- 只要維護一個程式碼集
- 應用程式可因應裝置設定變更而調整
- 只要在所有裝置上還原應用程式即可
- 您無須擔心市場偏好、從某個 APK「升級」到下一個 APK 的行為,或是要與哪個類別的裝置搭配的 APK
本課程的其餘部分假設您已研究這個主題,並認真吸收連結資源中的內容,且已判斷多個 APK 是應用程式的正確路徑。
繪製需求圖表
首先建立簡單的圖表,快速判斷需要多少個 APK,以及每個 APK 涵蓋的 API 範圍。為方便您參考,Android 開發人員網站的「平台版本」頁面會提供相關資料,說明執行特定 Android 平台版本的使用中裝置數量。此外,雖然一開始聽起來很簡單,但要追蹤每個 APK 要指定哪些 API 級別,很快就會變得相當困難,尤其是如果會出現重疊 (通常都會) 的情況。幸運的是,您可以輕鬆快速地繪製需求圖表,以方便日後參考。
如要建立多個 APK 圖表,請先從一列儲存格開始,代表 Android 平台的各種 API 級別。在結尾處插入額外儲存格,用來代表未來的 Android 版本。
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
接著,請在圖表中填入顏色,讓每種顏色代表一個 APK。以下範例說明如何將每個 APK 套用至特定範圍的 API 級別。
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
建立這張圖表後,請發布給您的團隊。專案的團隊通訊會馬上變得輕鬆許多,因為與其詢問「針對 API 級別 3 到 6 的 APK 如何,Android 1.x 版本」這樣說。一切順利嗎?只要說出「Blue APK 的進度如何?」即可。
將所有通用程式碼和資源放入程式庫專案
無論您要修改現有的 Android 應用程式還是從頭開始,首先在程式碼集執行之前,最需要做的就是。程式庫專案中的所有內容只需更新一次 (例如語言本地化的字串、色彩主題、共用程式碼中修正的錯誤),這麼一來,您就能縮短開發時間,並減少容易發生的錯誤。
注意:雖然如何建立及包含程式庫專案的實作細節並不在本課程的涵蓋範圍內,但您可以閱讀「建立 Android 程式庫」一文,快速掌握相關事項。
如果您要將現有應用程式轉換為支援多個 APK,請在程式碼庫中搜尋每個經過本地化的字串檔案、值清單、主題顏色、選單圖示和不會在 APK 之間變更的版面配置,然後將所有項目放入程式庫專案。不會大幅變更的程式碼也應納入程式庫專案中您可能會擴充這些類別,從 APK 新增一或兩個方法。
另一方面,如果您是從頭開始建立應用程式,請盡可能先在程式庫專案中編寫程式碼,然後只在必要時將程式碼移至個別 APK。長期執行相比,比起新增 ID 來更輕鬆管理,接著幾個月後嘗試確定能否將此 blob 移至程式庫專區,而不需將任何物件向上螺絲就能移至程式庫區段。
建立新的 APK 專案
每個要發布的 APK 都有一個獨立的 Android 專案。為了方便組織,請將程式庫專案和所有相關 APK 專案放在同一個上層資料夾下。另外請注意,每個 APK 都必須使用相同的套件名稱,但不一定需要與程式庫共用套件名稱。如果您要依據上述方案建立 3 個 APK,根目錄可能會如下所示:
alexlucas:~/code/multi-apks-root$ ls foo-blue foo-green foo-lib foo-red
建立專案後,請將程式庫專案新增為每個 APK 專案的參照。請盡可能在程式庫專案中定義啟動活動,並在 APK 專案中擴充該活動。先在程式庫專案中定義啟動活動,即可集中存放所有應用程式初始化,這樣每個 APK 就不需要重新執行「通用」工作,例如初始化 Analytics、執行授權檢查,以及其他在 APK 到 APK 之間沒有大幅變動的初始化程序。
調整資訊清單
如果使用者透過 Google Play 下載使用多個 APK 的應用程式,系統會透過兩項簡單的規則選擇要使用的正確 APK:
- 資訊清單必須顯示特定 APK 符合資格
- 在符合資格的 APK 中,版本號碼最高的 APK 會勝出
例如,讓我們使用前述的多個 APK 組合,並假設我們尚未為任何 APK 設定最高 API 級別。分別擷取每個 APK 的可能範圍如下:
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
由於 minSdkVersion 較高的 APK 也需要版本代碼較高,因此在 versionCode 值方面,紅色 ≥ 綠色 ≥ 藍色。因此,我們可以有效地收合圖表,讓圖表看起來像這樣:
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | + |
接著,我們再假設 Red APK 有一項沒有要求。Android 開發人員指南的「Google Play 上的篩選器」頁面列出了可能的肇因。以紅色為例,假設紅色需要前置鏡頭。事實上,紅色 APK 的用意在於將前置鏡頭與 API 11 中新增的實用新功能結合。但事實證明,並非所有支援 API 11 的裝置都具備前置鏡頭!真是太可怕了!
幸運的是,當使用者透過這類裝置瀏覽 Google Play 時,Google Play 會查看資訊清單,將前置鏡頭列為需求條件,然後安靜地忽略該訊息,判定該紅色及其裝置與數位天堂不相符。接著,您會發現 Green 不僅與搭載 API 11 的裝置相容 (因為未定義 maxSdkVersion),而且不論是否有前置鏡頭,都不會影響相容性!使用者仍可從 Google Play 下載應用程式,因為即使發生前置鏡頭問題,仍有 APK 支援該特定 API 級別。
如要將所有 APK 保留在個別的「測試群組」中,請務必設定良好的版本代碼配置。您可以在開發人員指南的「版本代碼」部分找到我們建議的代碼。範例 APK 僅處理 3 個可能維度中的一個,因此只需將每個 APK 分隔 1000 個、將該特定 APK 的前兩位數設定為 minSdkVersion,然後以此為基礎遞增即可。如下所示:
藍色:03001、03002、03003、03004...
綠色:07001、07002、07003、07004...
紅色:11001、11002、11003、11004...
總而言之,您的 Android 資訊清單看起來會像這樣:
藍色:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="03001" android:versionName="1.0" package="com.example.foo"> <uses-sdk android:minSdkVersion="3" /> ...
綠色:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="07001" android:versionName="1.0" package="com.example.foo"> <uses-sdk android:minSdkVersion="7" /> ...
紅色:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="11001" android:versionName="1.0" package="com.example.foo"> <uses-sdk android:minSdkVersion="11" /> ...
檢查正式發布前檢查清單
上傳到 Google Play 前,請仔細檢查以下項目。請注意,這些項目與多個 APK 特別相關,絕非上傳至 Google Play 的所有應用程式完整檢查清單。
- 所有 APK 的套件名稱都必須相同
- 所有 APK 都必須使用相同的憑證簽署
- 如果平台版本的 APK 重疊, minSdkVersion 較高的 APK 必須採用較高的版本代碼
- 仔細檢查資訊清單篩選器是否有衝突資訊 (在 XLARGE 螢幕上僅支援杯蛋糕的 APK,其他人不會看到)
- 每個 APK 的資訊清單在至少一個支援的螢幕、openGL 紋理或平台版本上都不得重複
- 請嘗試在至少一部裝置上測試每個 APK。除此之外,您還擁有業界最具客製化彈性的裝置模擬器,可在開發機器上使用。盡情享受吧!
您也可以在發布至市場前檢查已編譯的 APK,確保不會有任何意外狀況導致應用程式在 Google Play 上顯示為隱藏狀態。使用「aapt」工具,這其實相當簡單。Aapt (Android 資產封裝工具) 是建構 Android 應用程式及封裝應用程式的建構程序之一,也是檢查應用程式的實用工具。
>aapt dump badging package: name='com.example.hello' versionCode='1' versionName='1.0' sdkVersion:'11' uses-permission:'android.permission.SEND_SMS' application-label:'Hello' application-icon-120:'res/drawable-ldpi/icon.png' application-icon-160:'res/drawable-mdpi/icon.png' application-icon-240:'res/drawable-hdpi/icon.png' application: label='Hello' icon='res/drawable-mdpi/icon.png' launchable-activity: name='com.example.hello.HelloActivity' label='Hello' icon='' uses-feature:'android.hardware.telephony' uses-feature:'android.hardware.touchscreen' main supports-screens: 'small' 'normal' 'large' 'xlarge' supports-any-density: 'true' locales: '--_--' densities: '120' '160' '240'
檢查 aapt 輸出內容時,請務必檢查支援螢幕和相容螢幕的值是否發生衝突,且沒有因您在資訊清單中設定的權限而新增的「uses-feature」值。在上述範例中,許多裝置都不會顯示 APK。
原因是新增必要權限 SEND_SMS 後,系統會隱含新增 android.hardware.telephony 的功能需求。由於 API 11 是 Honeycomb (專為平板電腦最佳化的 Android 版本),且沒有任何 Honeycomb 裝置內含電話硬體,因此 Google Play 會在所有情況下篩除這個 APK,直到日後推出的裝置 API 級別較高且具備電話硬體為止。
不過,只要在資訊清單中加入以下內容,就能輕鬆解決這個問題:
<uses-feature android:name="android.hardware.telephony" android:required="false" />
系統也會隱含新增 android.hardware.touchscreen
需求。如果您想在非觸控螢幕裝置的電視上顯示 APK,請在資訊清單中加入以下內容:
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
完成正式發布前檢查清單後,請將 APK 上傳至 Google Play。瀏覽 Google Play 時,可能需要經過一段時間才會顯示該應用程式,但找到後,請執行最後一次檢查。將應用程式下載到您的任何測試裝置,確保 APK 指定了目標裝置。恭喜!你已完成設定。