針對不同螢幕大小建立多個 APK

如果您將應用程式發布到 Google Play,應建構並上傳 Android App Bundle。這樣一來,Google Play 會自動針對每位使用者的裝置設定產生及提供經過最佳化的 APK,讓使用者只下載執行應用程式所需的程式碼和資源。如果您不打算發布至 Google Play,但必須自行建構、簽署及管理每個 APK,則發布多個 APK 就很實用。

開發 Android 應用程式時,如果想充分利用 Google Play 上的多個 APK,請務必從一開始就採用一些良好做法,以免在開發過程中遇到不必要的麻煩。本課程將說明如何為應用程式建立多個 APK,每個 APK 涵蓋不同的螢幕大小類別。您也會獲得一些必要工具,盡可能輕鬆地維護多個 APK 程式碼集。

確認您需要多個 APK

當您嘗試建立可在多種尺寸的 Android 裝置上運作的應用程式時,自然希望應用程式能善用較大裝置上的所有可用空間,同時不犧牲在較小螢幕上的相容性或可用性。一開始可能會覺得支援多個 APK 是最佳解決方案,但實際上並非如此。多個 APK 開發人員指南的「改用單一 APK」一節提供一些實用資訊,說明如何透過單一 APK 達成這項目標,包括使用支援程式庫。您也應參閱支援多個螢幕的指南,甚至可以使用 Android SDK 下載支援資料庫,在 Honeycomb 之前的裝置上使用片段,讓單一 APK 更容易支援多個螢幕。

如果您可以管理,將應用程式限制在單一 APK 中,可享有以下幾項優勢:

  • 發布和測試更輕鬆
  • 只需維護一個程式碼集
  • 應用程式可因應裝置設定變更而調整
  • 跨裝置應用程式還原功能運作正常
  • 您不必擔心市場偏好設定、從一個 APK 升級至另一個 APK 的行為,或是哪個 APK 與哪個裝置類別相符

本課程的其餘部分假設您已研究這個主題,並認真吸收連結資源中的內容,並判斷多個 APK 是應用程式的正確路徑。

繪製需求圖表

首先建立簡單的圖表,快速判斷需要多少個 APK,以及每個 APK 涵蓋的螢幕尺寸。幸好,您可以輕鬆快速地繪製需求表,並將其用於日後參考。首先,請建立一列代表 Android 平台上可用的各種螢幕大小的儲存格。

正常 特大

接著,只需在圖表中填入顏色,讓每種顏色代表一個 APK。以下範例說明如何將各個 APK 套用至特定範圍的螢幕尺寸。

正常 特大

視需求而定,您也可以有兩個 APK,分別是「small 和其他所有內容」或「xlarge 和其他所有內容」。圖表中的顏色也能讓團隊內部溝通更輕鬆,現在無論每個 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 無關的初始化程序。

調整資訊清單

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

  • 資訊清單必須顯示特定 APK 符合資格
  • 在符合資格的 APK 中,版本號碼最高的 APK 會勝出

舉例來說,我們先前提到的多個 APK 組合,假設每個 APK 都已設為支援大於其「目標」螢幕大小的所有螢幕尺寸。個別來說,每個 APK 的可能範圍如下所示:

正常 特大
正常 特大
正常 特大

不過,如果採用「最高版本號碼優先」的規則,只要在每個 APK 中設定 versionCode 屬性,讓紅色 ≥ 綠色 ≥ 藍色,圖表就會精簡為下列內容:

正常 特大

接著,我們再假設紅色 APK 有其他兩個 APK 沒有的某些需求。Android 開發人員指南的「Google Play 上的篩選器」頁面列出了可能的肇因。舉例來說,假設紅色需要前置鏡頭。事實上,紅色 APK 的用意就是利用額外的螢幕空間,透過前置鏡頭進行有趣的操作。但實際上,並非所有 xlarge 裝置都配備前置鏡頭!太可怕了!

幸運的是,如果使用者透過這類裝置瀏覽 Google Play,Google Play 會查看資訊清單,發現 Red 列出前置鏡頭為必要條件,並在判斷 Red 與該裝置不相容時,悄悄忽略這項條件。接著,系統會發現 Green 不僅與 xlarge 裝置相容,而且不論是否有前置鏡頭都沒關係!使用者仍可從 Google Play 下載應用程式,因為即使發生前置鏡頭問題,仍有 APK 支援該特定螢幕尺寸。

為了讓所有 APK 都位於不同的「發布途徑」中,請務必採用良好的版本代碼配置。您可以在開發人員指南的「版本代碼」區域中找到建議的版本代碼。由於範例 APK 套組只處理 3 個可能維度中的一個,因此只要將每個 APK 分隔 1000 次,然後從該點開始遞增即可。可能會像這樣:

藍色:1001、1002、1003、1004...
綠色:2001、2002、2003、2004...
紅色:3001、3002、3003、3004...

將所有內容整合後,您的 Android 資訊清單可能會如下所示:

藍色:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1001" android:versionName="1.0" package="com.example.foo">
    <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="2001" android:versionName="1.0" package="com.example.foo">
    <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="3001" android:versionName="1.0" package="com.example.foo">
    <supports-screens android:smallScreens="false"
        android:normalScreens="false"
        android:largeScreens="false"
        android:xlargeScreens="true" />
    ...

請注意,從技術層面來說,多個 APK 會搭配使用 supports-screens 標記或 compatible-screens 標記。一般來說,建議使用支援螢幕標記,在同一個資訊清單中使用這兩種標記通常不是個好主意。這會讓事情變得過度複雜,並增加出錯的機會。另請注意,代管文件並未利用預設值 (small 和 normal 預設為一律為 true),而是明確設定每個螢幕大小的值。這麼做可以避免日後的麻煩。舉例來說,如果資訊清單的目標 SDK 為 < 9,系統會自動將 xlarge 設為 false,因為該尺寸尚未存在。所以請明確表達!

查看正式發布前檢查清單

上傳至 Google Play 前,請仔細檢查下列項目。請注意,這些項目與多個 APK 特別相關,絕非上傳至 Google Play 的所有應用程式完整檢查清單。

  • 所有 APK 都必須使用相同的套件名稱
  • 所有 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 輸出內容時,請務必確認 supports-screens 和 compatible-screens 的值不會互相衝突,且不會因為您在資訊清單中設定的權限而新增未預期的「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 指定的裝置正確無誤。

如要進一步瞭解如何在 Google Play 發布多個 APK,請參閱「支援多個 APK」。