如果您將應用程式發布到 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 的 APK。一切順利嗎?只要說出「Blue APK 的進度如何?」即可。
將所有通用程式碼和資源放入程式庫專案
無論您是要修改現有的 Android 應用程式,還是從頭開始建立應用程式,這都是您對程式碼庫應做的第一件事,也是最重要的事。程式庫專案中的所有內容只需更新一次 (例如語言本地化的字串、色彩主題、共用程式碼中修正的錯誤),這麼一來,您就能縮短開發時間,並減少容易避免的錯誤發生機率。
注意:雖然如何建立及加入程式庫專案的實作細節超出本課程範圍,但您可以參閱「建立 Android 程式庫」一文,快速掌握相關資訊。
如果您要將現有應用程式轉換為支援多個 APK,請在程式碼庫中搜尋每個經過本地化的字串檔案、值清單、主題顏色、選單圖示和版面配置 (不會在 APK 之間變更),然後將所有項目放入程式庫專案。不會經常變更的程式碼也應放入程式庫專案中。您可能會擴充這些類別,從 APK 新增一或兩個方法。
另一方面,如果您是從頭開始建立應用程式,請盡可能先在程式庫專案中編寫程式碼,然後只在必要時將程式碼移至個別 APK。長期來說,這比將 Blob 新增至一個、再新增至另一個、再新增至另一個,然後在數月後嘗試判斷 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 有其他兩個 APK 沒有的某些需求。Android 開發人員指南的「Google Play 上的篩選器」頁面列出了可能的肇因。舉例來說,假設紅色需要前置鏡頭。事實上,紅色 APK 的用意在於將前置鏡頭與 API 11 中新增���實用新功能結合。但事實上,並非所有支援 API 11 的裝置都有前置鏡頭!太可怕了!
幸運的是,如果使用者透過這類裝置瀏覽 Google Play,Google Play 會查看資訊清單,發現 Red 列出前置鏡頭為必要條件,並在判斷 Red 與該裝置不相容時,悄悄忽略這項條件。接著,您會發現 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 輸出內容時,請務必確認 supports-screens 和 compatible-screens 的值不會互相衝突,且不會因為您在資訊清單中設定的權限而新增意外的「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 指定的裝置正確無誤。恭喜,你已完成設定!