建立可支援多種尺寸的多個 APK

如果您將應用程式發布到 Google Play,應建構並上傳 Android App Bundle。這樣一來,Google Play 會為每位使用者的裝置設定自動產生並提供最佳化 APK,使用者就能僅下載執行應用程式所需的程式碼和資源。如果您未將應用程式發布到 Google Play,發布多個 APK 是非常實用的做法,但請注意您必須自行建構、簽署及管理各個 APK。

當您開發 Android 應用程式以利用 Google Play 上的多個 APK 時,請務必從一開始就採用一些最佳做法,避免在開發過程中出現不必要的頭痛。本課程將說明如何為應用程式建立多個 APK,每個 APK 涵蓋不同的螢幕大小類別。您也將取得一些必要工具,盡可能輕鬆維護多個 APK 程式碼集。

確認需要使用多個 APK

如果您嘗試建立適用於各種可用 Android 裝置的應用程式,您自然會希望應用程式在各種裝置上都能呈現最佳效果。您可能希望利用大螢幕的空間,但仍在小螢幕上工作,以便使用最新 Android API 功能或最先進裝置提供的視覺紋理,但不會捨棄舊裝置。一開始,這可能就像多個 APK 支援是最好的解決方案,但通常並非如此。多個 APK 指南的「改用單一 APK」一節提供了一些實用資訊,說明如何透過單一 APK 完成上述所有操作,包括使用我們的支援資料庫,以及 Android 開發人員指南中的資源連結。

如果您可以管理,將應用程式限制為單一 APK 有幾項好處,包括:

  • 發布與測試更容易
  • 只有一個程式碼集需要維護
  • 您的應用程式可根據裝置設定變更進行調整
  • 在所有裝置上還原應用程式的功能皆可正常運作
  • 您不必擔心市場偏好、從一個 APK 的「升級」到下一個 APK 的行為,以及哪些 APK 會與哪類裝置搭配使用

本課程的其餘部分假設您已研究過主題,工作室確實吸收連結資源中的素材,並判定多個 APK 是應用程式的正確路徑。

繪製資格條件圖表

您可以先建立簡單的圖表,快速判斷需要多少 APK 數量,以及每個 APK 涵蓋的螢幕尺寸。幸好,您可以輕鬆快速地規劃需求,以便日後參考。假設您想要將 APK 分割成兩個維度:API 和螢幕大小。請為每種可能的值組合加入資料列和資料欄,在某些「blob」中,每個顏色代表一個 APK。

3 4 5 6 7 8 9 10 11 12 +
正常
特大

以上是包含四個 APK 的範例。藍色代表所有小型/一般螢幕裝置,綠色代表大螢幕裝置,紅色代表超大型螢幕裝置,API 範圍為 3 至 10。紫色是一種特殊情況,適用於所有螢幕大小,但僅適用於 API 11 以上版本。更重要的是,只要查看這張圖表,您就能立即知道哪個 APK 涵蓋了任何指定 API/螢幕尺寸的組合。此外,每個啟動階段也都有酷炫的程式碼名稱,因為「我們曾在 裝置上測試紅色?」請列印這個圖表,並交給處理程式碼集的每位人員。生活變得更輕鬆了。

將所有通用程式碼和資源放在程式庫專案中

無論是修改現有的 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-purple
foo-red

建立專案後,請將程式庫專案做為對每個 APK 專案的參照。如果可行,請在程式庫專案中定義起始活動,然後在 APK 專案中擴充該活動。在程式庫專案中定義的起始活動可以把所有應用程式初始化作業放在同一個位置,這樣每個 APK 就不必重新實作「通用」工作,例如初始化 Analytics (分析)、執行授權檢查,以及其他不會大幅從 APK 變更為 APK 的任何其他初始化程序。

調整資訊清單

如果使用者透過 Google Play 下載使用多個 APK 的應用程式,系統會透過兩個簡單規則選擇要使用的正確 APK:

  • 資訊清單必須表明特定 APK 符合資格
  • 在符合資格的 APK 中,採用最高版本號碼的 SDK 將勝出。

舉例來說,我們以前述的多個 APK 組合為例,假設每個 APK 都設定為支援大於「目標」螢幕大小的所有螢幕大小。我們先來看看前述的範例圖表:

3 4 5 6 7 8 9 10 11 12 +
正常
特大

由於涵蓋率可以重疊,因此我們可以描述每個 APK 所涵蓋的區域,如下所示:

  • 藍色會涵蓋所有螢幕,minSDK 3。
  • 綠色適用於大螢幕及 minSDK 3。
  • 紅色涵蓋 XLarge 螢幕 (一般為平板電腦),minSDK 為 9。
  • 紫色涵蓋所有螢幕,minSDK 為 11。

請注意,這些規則中有「大量」重疊的規則。舉例來說,搭載 API 11 的 XLarge 裝置可連續執行指定的 4 個 APK 之一。但是,使用「以最高的版本號碼勝出」規則可以設定偏好順序,如下所示:

紫色 ≥ 紅色 ≥ 綠色 ≥ 藍色

為什麼要允許所有重疊內容?假設紫色 APK 有一些要求,但是另外兩個 APK 不需要。Android 開發人員指南的「Google Play 篩選器」頁面提供完整的可能問題清單。例如,假設紫色需要使用前置鏡頭。事實上,Purple 的全貌都是透過前置鏡頭 帶給觀眾歡樂的體驗!不過,並不是所有搭載 API 11 以上版本的裝置 甚至具備前置鏡頭!真糟糕!

幸好,當使用者透過這類裝置瀏覽 Google Play 時,Google Play 會查看資訊清單,您會發現紫色將前置鏡頭列為需求,安靜地忽略,確認「紫色」和該裝置並不屬於數位天堂。然後發現紅色不僅與超大型裝置相容,也不用考量前置鏡頭是否使用。使用者仍可從 Google Play 下載應用程式,因為即使前置鏡頭上無法正常運作,我們仍有 APK 支援該特定 API 級別。

如要將所有 APK 保存在獨立的「測試群組」上,請務必採用良好的版本代碼配置。請參閱開發人員指南的「版本代碼」區域,即可找到建議採用的代碼。建議您閱讀整個段落,但是基本原則適用於這組 APK,我們會使用兩位數代表 minSDK,2 代表螢幕最小/最大尺寸,3 則代表版本號碼。如此一來,當裝置升級至新版 Android (例如 10 至 11) 時,凡是目前符合資格且偏好使用的 APK,裝置都會顯示為「升級」。套用至 APK 範例組合的版本號碼配置可能如下所示:

藍色:0304001、0304002、0304003...
綠色:0334001、0334002、0334003
紅色:0344001、0344002、0344003...
紫色:1104001、1104002、1104003...

總而言之,Android 資訊清單看起來可能如下所示:

藍色:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0304001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

綠色:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0334001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

紅色:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="0344001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="3" />
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="false"
        android:xlargeScreens="true" />
    ...

紫色:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1104001" android:versionName="1.0" package="com.example.foo">
    <uses-sdk android:minSdkVersion="11" />
    <supports-screens android:smallScreens="true"
        android:normalScreens="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />
    ...

請注意,嚴格來說,多個 APK 可與支援畫面標記或相容畫面標記搭配運作。一般而言,建議使用支援螢幕,因此一般不建議同時採用這兩種方式,因為這讓操作變得複雜,並增加錯誤機會。另請注意,資訊清單不會利用預設值 (根據預設,S 和一般皆一律為 true),而是明確設定每個螢幕大小的值。這可以減輕您的負擔:舉例來說,目標 SDK 小於 9 的資訊清單,由於該大小不存在,因此系統會自動將「xlarge」設為「false」。因此請力求明確!

詳閱正式發布前檢查清單

將檔案上傳至 Google Play 前,請仔細檢查下列項目。提醒您,這些資訊特別與多個 APK 相關,無法代表所有上傳至 Google Play 的應用程式完整清單。

  • 所有 APK 都必須使用相同的套件名稱。
  • 所有 APK 都必須使用同一個憑證簽署。
  • 如果 APK 與平台版本重疊,則 minSdkVersion 較高的 APK 必須採用更高的版本代碼。
  • 您希望 APK 支援的每種螢幕大小,請在資訊清單中設為 true。因此,請將所需螢幕大小設為 false。
  • 請仔細檢查資訊清單篩選器是否含有衝突的資訊 (僅支援 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: 'xlarge'
supports-any-density: 'true'
locales: '--_--'
densities: '120' '160' '240'

檢查 aapt 輸出內容時,請務必確認支援畫面和相容畫面的值沒有衝突,且您沒有因您在資訊清單中設定的權限而新增的非預期「uses-feature」值。在上例中,大多數裝置都看不見 APK。

原因是什麼?藉由新增必要權限 SEND_SMS,系統已默示新增 android.hardware.telephony 的功能需求。由於大部分 (不是所有) 超大型裝置都是沒有電話硬體硬體的平板電腦,因此 Google Play 在這些情況下會篩除這個 APK,直到日後的裝置夠大,足以回報為大螢幕尺寸且具備電話硬體設備為止。

不過,只要在資訊清單中新增以下內容,即可輕鬆修正這項問題:

<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 的指定目標裝置是正確的。恭喜,大功告成!