針對不同螢幕大小建立多個 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 and all else」或「xlarge and all the otherfing」)。上色圖表也能簡化團隊內部通訊流程。您現在可以直接將每個 APK 稱為「藍色」、「綠色」或「紅色」,不論 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 的可能範圍如下:

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

但是,如果根據「使版本號碼最高的版本數」規則設定每個 APK 的 versionCode 屬性,例如紅色 ≥ 綠色 ≥ 藍色,圖表就會有效收合如下:

正常 特大

現在,讓我們進一步假設該紅色 APK 有部分要求,但是另外兩個 APK 無法這麼做。Android 開發人員指南的「Google Play 篩選器」頁面提供了完整的可能問題清單。例如,我們假設紅色需要使用前置鏡頭。事實上,紅色 APK 的全部點,是使用額外的可用的螢幕空間,透過前置鏡頭享受娛樂內容。但事實證明,並非所有大型裝置 (甚至具備前置鏡頭) 都具備!真糟糕!

幸好,當使用者透過這類裝置瀏覽 Google Play 時,Google Play 會查看資訊清單,系統會依照紅色列出前置鏡頭,並靜默忽略 (經判定紅色和該裝置並非數位天堂) 的要求。您會發現,Green 不僅與超大型裝置相容,也不在意是否具備前置鏡頭!使用者仍可從 Google Play 下載應用程式,因為即使前置鏡頭未正常運作,仍有 APK 支援該特定螢幕大小。

如要將所有 APK 保存在獨立的「測試群組」上,請務必採用良好的版本代碼配置。請參閱開發人員指南的「版本代碼」區域,即可找到建議採用的代碼。由於一組 APK 範例僅處理 3 種可能維度的其中一種,因此可以將每個 APK 1 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 都能與支援畫面標記或相容畫面標記搭配運作。一般建議使用支援螢幕, 因此最好不要在同一份資訊清單中使用這兩種標記這樣可以簡化作業,並增加錯誤發生的機會。另請注意,資訊清單不會利用預設值 (根據預設,S 和一般為 true 一律為 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 輸出內容時,請務必確認支援畫面和相容畫面的值沒有衝突,且您沒有因您在資訊清單中設定的權限而新增的非預期「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