支援多個 APK

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

Google Play 可支援多個 APK,使用這項功能,您可以為應用程式發布不同的 APK,每個 APK 針對不同的裝置設定。每個 APK 都是應用程式的完整、獨立的版本,但會在 Google Play 中分享相同的應用程式資訊,而且必須分享相同的套件名稱,並使用相同的版本金鑰簽署。當應用程式無法透過單一 APK 支援所需的全部裝置時,這項功能很實用。

Android 裝置可能在某些方面存在差異,因此您應確保應用程式支援盡可能多的裝置,這對應用程式的成功運作很重要。Android 應用程式通常可透過單一 APK 在大多數相容的裝置上執行,方法是為不同的設定提供額外資源 (例如,針對不同的螢幕尺寸提供不同的版面配置),並且 Android 系統會在執行階段為裝置選取適當的資源。但在少數情況下,單一 APK 無法支援所有裝置設定,原因是額外資源會導致 APK 檔案過大,或發生其他技術性問題,導致單一 APK 無法在所有裝置上運作。

Google Play 允許您在相同的應用程式資訊下發布多個 APK,以協助您為盡可能多的裝置發布應用程式。然後,Google Play 會根據您在各 APK 資訊清單檔案中宣告的設定支援,將每個 APK 提供給適當的裝置。

透過多個 APK 發布應用程式,您可以:

  • 透過每個 APK 支援不同的 OpenGL 紋理壓縮格式。
  • 透過每個 APK 支援不同的螢幕尺寸和密度。
  • 透過每個 APK 支援不同的裝置功能集。
  • 透過每個 APK 支援不同的平台版本。
  • 透過每個 APK 支援不同的 CPU 架構 (例如,當應用程式使用 Android NDK 時,為 ARM 或 x86 提供不同的 ARM)。
  • 針對入門級裝置進行最佳化調整,例如搭載 Android (Go 版本) 的裝置。

目前,將多個 API 作爲同一應用程式發布時,Google Play 僅支援裝置特性。

注意:如要瞭解如何在 Google Play 上準備並發布 APK,請參閱「 準備作業與發布版本」支援文章。

多個 APK 的運作方式

在 Google Play 上使用多個 APK 的概念如下:應用程式在 Google Play 中只有一個項目,但不同的裝置可以下載不同的 APK。這就表示:

  • 您只須維護一組產品詳細資料 (應用程式說明、圖示、螢幕截圖等)。這也表示您「無法」針對不同的 APK 收取不同的價格。
  • 所有使用者在 Google Play 上只會看到應用程式的一個版本,因此即使您發布「平板電腦專用」或「手機專用」版本,使用者也不會因為不同的版本感到困惑。
  • 即使不同裝置的使用者可能有不同的 APK,系統仍會將所有使用者評論套用到相同的應用程式資訊。
  • 如果您為不同的 Android 版本發布不同的 APK (不同的 API 級別),則使用者的裝置收到系統更新時,如果他們符合使用您發布的另一個 APK 的條件,Google Play 就會更新將該使用者的應用程式更新至專為更高版本的 Android 設計的 APK。系統會保留與該應用程式關聯的所有系統資料 (與使用單一 APK 時的正常應用程式更新相同)。

支援的篩選器

接收每個 APK 的裝置由 Google Play 篩選器 (透過每個 APK 的資訊清單檔案中的元素指定) 決定。不過,只有在每個 APK 使用篩選器來支援以下裝置特性的變化時,Google Play 才會讓您發布多個 APK:

  • OpenGL 紋理壓縮格式

    系統使用資訊清單檔案的 <supports-gl-texture> 元素作爲判定依據。

    舉例來說,當開發使用 OpenGL ES 的遊戲時,您可以為支援 ATI 紋理壓縮的裝置提供一個 APK,並為支援 PowerVR 壓縮等的裝置提供獨立的 APK。

  • 螢幕大小 (及螢幕密度 (選用))

    系統使用資訊清單檔案的 <supports-screens><compatible-screens> 元素作爲判定依據。您不得同時使用這兩個元素,應盡可能只使用 <supports-screens>

    例如,您可以提供一個支援小尺寸和中等尺寸螢幕的 APK,以及另一個支援大尺寸和特大尺寸螢幕的 APK。如要進一步瞭解如何根據螢幕大小或密度產生獨立的 APK,請參閱「建立多個 APK」。

    請考慮採用下列最佳做法來支援所有螢幕尺寸:

    • Android 系統為應用程式提供強大支援,透過單一 APK 即可支援所有螢幕設定。除非絕對必要,否則請避免建立多個 APK 來支援不同的螢幕;請遵循「支援多種螢幕」指南,確保應用程式可彈性調整,並可透過單一 APK 因應所有螢幕設定。
    • 根據預設,如果您未另外宣告,則 <supports-screens> 元素中的所有螢幕尺寸屬性都將設為「true」。不過,由於 Android 2.3 (API 級別 9) 已新增 android:xlargeScreens 屬性,因此應用程式未將 android:minSdkVersionandroid:targetSdkVersion 設定為「9」或更高值時,Google Pla 會假設它為「false」。
    • 不得在資訊清單檔案中同時合併 <supports-screens><compatible-screens> 元素。如果同時使用這兩個元素,會提高由於兩個元素相衝突而發生錯誤的可能性。如需如何選擇元素的協助,請閲讀「發布到特定螢幕」。如果無法避免同時使用這兩個元素的情況,請注意,如果指定螢幕大小之間的協議發生衝突,系統會以「false」為準。
  • 裝置功能集

    系統使用資訊清單檔案的 <uses-feature> 元素作爲判定依據。

    舉例來說,您可以為支援多點觸控功能的裝置提供一個 APK,為不支援多點觸控功能的裝置提供另一個 APK。如需平台支援的功能清單,請參閱「功能參考資料」。

  • Android (Go 版本)

    如要針對搭載 Android (Go 版本) 的裝置,APK 必須宣告 <uses-feature android:name="android.hardware.ram.low" android:required="true">,目標 API 級別至少須為 26,並且版本代碼高於非 Go 版本 APK。

  • API 級別

    系統使用資訊清單檔案的 <uses-sdk> 元素作爲判定依據。您可以使用 android:minSdkVersionandroid:maxSdkVersion 屬性來指定不同 API 級別的支援。

    舉例來說,您可以使用以下兩個 APK 發布應用程式:一個 APK 支援 API 級別 16 - 19 (Android 4.1.x - 4.4.4) (僅使用 API 級別為 16 或更低時可用的 API),另一個 APK 支援 API 級別 21 及以上 (Android 5.0+) (使用 API 級別為 21 或更低時可用的 API)。如要瞭解如何建立獨立的 APK 並且每個 APK 針對不同的 API 級別範圍,請前往「設定變種版本」。

    如果您使用這個特性做為區分多個 APK 的因素,則 android:minSdkVersion 值較高的 APK 必須有較高的 android:versionCode 值。如果根據不同的支援篩選器,兩個 APK 的裝置支援有所重疊,情況也是如此。這樣可以確保只要裝置收到系統更新,Google Play 就會將應用程式更新提供給使用者 (因為系統會根據版本代碼數值的提高情況判定更新)。下方有關「多個 APK 的規則」部分中將進一步説明該要求。

    一般而言,應避免使用 android:maxSdkVersion,因為只要您使用公用 API 正確開發應用程式,就總是能與日後推出的 Android 版本相容 如果您想針對更高的 API 級別發布不同的 APK,則無須指定最高版本,因為如果 android:minSdkVersion 在一個 APK 中為 "16",在另一個 APK 中為 "21",支援 API 級別 21 或更高級別的裝置將一律收到第二個 APK (因爲根據先前的説明,這個 APK 的版本代碼更高)。


  • CPU 架構 (ABI)

    部分原生程式庫會針對特定 CPU 架構或應用程式二進位檔介面 (ABI) 提供獨立的套件。您無須將所有可用程式庫封裝到一個 APK 中,而是可以為每個 ABI 建立獨立的 APK,其中僅包含該 ABI 所需的程式庫。如要進一步瞭解如何根據目標 ABI 產生獨立的 APK,請前往「建立多個 APK」。

啟用 Google Play 篩選器 (但上方未列出) 的其他資訊清單元素仍會照常套用到每個 APK。不過,Google Play 不允許您根據這些裝置特性的變化發布獨立的 APK。因此,如果每個 APK 的上述篩選器相同,則您無法發布這些 APK (但 APK 會根據資訊清單或 APK 中的其他特性而有所不同)。例如,您無法提供 <uses-configuration> 特性完全不同的其他 APK。

多個 APK 的規則

在發布應用程式的多個 APK 之前,您必須瞭解以下規則:

  • 您為同一個應用程式發布的所有 APK 都必須使用相同的套件名稱,並使用同一個憑證金鑰簽署
  • 每個 APK 都必須有不同的版本代碼 (透過 android:versionCode 屬性指定)。
  • 每個 APK 支援的設定不得與其他 APK 完全一致

    也就是說,每個 APK 都必須針對至少一個支援的 Google Play 篩選器 (如上所列) 宣告略有不同的支援。

    通常您會根據特定特性 (例如支援的紋理壓縮格式) 來區別 APK,因此每個 APK 都會宣告支援不同的裝置。不過,您可以發布支援稍有重叠的多個 APK。當兩個 APK 重疊 (支援部分相同的裝置設定) 時,適用於該重疊範圍的裝置會收到版本代碼較高的 APK (由android:versionCode 定義)。

  • 如果新的 APK 版本代碼低於要取代的 APK,則無法啟用。舉例來說,假設您啟用一個 APK,該 APK 適用於小型到中型螢幕,且版本代碼為 0400。接著您嘗試將該 APK 替換成適用於相同螢幕尺寸,且版本代碼為 0300 的 APK。這會引發錯誤,因為上一個 APK 的使用者將無法更新應用程式。
  • 要求 API 級別較高的 APK 必須採用更高的版本代碼

    但只有在以下任一情況下才是如此:APK「僅」在支援的 API 級別上有所不同 (不再使用其他支援的篩選器區分 APK),「或者」APK 使用其他支援的篩選器,但該篩選器內的 APK 有所重疊。

    這是很重要的,因為只有在 Google Play 上的 APK 版本代碼高於裝置目前使用的 APK 版本代碼時,使用者的裝置才會從 Google Play 收到應用程式更新。這樣可以確保如果裝置收到系統更新後,符合安裝 API 級別更高的 APK 的條件,則裝置會收到應用程式更新,因為版本代碼有所增加。

    注意:版本代碼增加多少無關緊要;只要支援更高 API 級別的版本更高即可。

    例如:

    • 如果您為 API 級別 16 及以上 (Android 4.1.x+) 上傳的 APK 採用版本代碼 0400,則為 API 級別 21 及以上 (Android 5.0+) 上傳的 APK 必須採用版本代碼 0401 或更大值。在這種情況下,由於 API 級別是唯一支援的篩選器,因此增加版本代碼時必須與每個 APK 的 API 級別支援關聯,以便使用者在收到系統更新後可以進行更新。
    • 如果您有一個 APK 適用於 API 級別 16 (及以上) 「和」小尺寸到大尺寸螢幕,而另一個 APK 適用於 API 級別 21 (及以上)「和」大尺寸到特大尺寸螢幕,則增加版本代碼時必須與 API 級別相關聯。在這種情況下,系統會使用 API 級別篩選器來區分各個 APK,螢幕尺寸也是如此。由於螢幕尺寸有所重疊 (兩個 APK 都支援大尺寸螢幕),因此必須按順序排列版本代碼。這樣可確保收到系統更新 (更新至 API 級別 21) 的大尺寸螢幕裝置能收到第二個 APK 的更新。
    • 如果您有一個 APK 適用於 API 級別 16 (及以上) 「和」小尺寸到中等尺寸螢幕,而另一個 APK 適用於 API 級別 21 (及以上)「和」大尺寸到特大尺寸螢幕,則增加版本代碼時無須與 API 級別相關聯。由於螢幕尺寸篩選器並未重疊,沒有任何裝置會在這兩個 APK 之間搖擺不定,因此無須按從較低 API 級別到較高 API 級別的順序增加版本代碼。
    • 如果您有一個 APK 適用於 API 級別 16 (及以上) 「和」ARMv7 CPU,而另一個 APK 適用於 API 級別 21 (及以上)「和」ARMv5TE CPU,則增加版本代碼時必須與 API 級別相關聯。在這種情況下,系統會使用 API 級別篩選器來區分各個 APK,CPU 架構也是如此。由於使用 ARMv5TE 程式庫的 APK 與搭載 ARMv7 CPU 的裝置相容,因此這些 APK 的特性有所重叠。因此,支援 API 級別 21 及以上的 APK 必須採用更高的版本代碼。這樣可確保搭載 ARMv7 CPU、收到系統更新 (更新至 API 級別 21) 的裝置能收到適用於 API 級別 21 的第二個 APK 的更新。不過,由於這類更新會導致 ARMv7 裝置使用未針對裝置 CPU 進行最佳化調整的 APK,因此您應在每個 API 級別為 ARMv5TE 和 ARMv7 架構提供 APK,以便最佳化每個 CPU 的應用程式效能。注意:這種做法「僅」適用於比較 ARMv5TE 和 ARMv7 程式庫的 APK,不適用於比較其他原生程式庫。

如果無法遵守上述規則,會導致啟用 APK 時 Google Play 管理中心發生錯誤,您必須解決這些錯誤,才能發布應用程式。

啟用 APK 時可能會發生其他衝突,但系統會顯示警告而非錯誤。以下原因可能會導致系統顯示警告:

  • 您修改一個 APK 以「縮減」對裝置特性的支援,並且其他 APK 均不支援超出支援範圍的裝置。舉例來說,如果 APK 目前支援小型和中型螢幕,但您將 APK 變更為僅支援小型螢幕,這樣您就縮減了支援裝置範圍,因此部分裝置的使用者將無法在 Google Play 上看到您的應用程式。如要解決這個問題,請新增另一個支援中等尺寸螢幕的 APK,這樣即可繼續支援先前支援的所有裝置。
  • 兩個或多個 APK 之間有所「重疊」。舉例來說,如果一個 APK 支援小尺寸、中等尺寸和大尺寸螢幕,而另一個 APK 支援大尺寸和特大尺寸螢幕,就會出現重叠的情況,因爲這兩個 APK 均支援大尺寸螢幕。如果無法解決此問題,則符合使用兩個 APK 的條件的裝置 (在此範例中為大尺寸螢幕裝置) 將收到版本代碼最高的 APK。

    注意:如果您為不同的 CPU 架構建立獨立的 APK,則 ARMv5TE 的 APK 會與 ARMv7 的 APK 發生重疊。也就是說,設計用於 ARMv5TE 的 APK 與 ARMv7 裝置相容,反之則不然 (僅使用 ARMv7 程式庫的 APK 與 ARMv5TE 裝置「不」相容)。

發生這類衝突時,系統會顯示警告訊息,但您仍然可以發布應用程式。

建立多個 APK

您決定發布多個 APK 之後,可能需要為您打算發布的每個 APK 建立獨立的 Android 專案,以便採用適當方式單獨開發這些 APK。方法很簡單,只要複製現有的專案,並輸入新名稱即可。(或者,您也可以使用建構系統,根據建構設定輸出不同的資源,例如紋理)。

提示:如要避免複製大量應用程式程式碼,可以使用程式庫專案。程式庫專案保留共用程式碼和資源,供您在實際的應用程式專案中使用。

為同一個應用程式建立多個專案時,建議的做法是使用名稱指出對 APK 設定的裝置限制,以便您輕鬆識別每個專案。例如,針對適用於 API 級別 21 及以上的應用程式,可以使用名稱「HelloWorld_21」。

注意:您為同一個應用程式發布的所有 APK 都必須使用相同的套件名稱,並使用同一個憑證金鑰簽署。請確保您也瞭解多個 APK 的規則

指派版本代碼

同一個應用程式的每個 APK 都必須具有專屬的版本代碼 (透過 android:versionCode 屬性指定)。發布多個 APK 時,必須謹慎指派版本代碼,因為每個版本代碼必須各不相同,但在某些情況下,必須或應該根據每個 APK 支援的設定,按特定順序定義版本代碼。

排列版本代碼的順序

要求 API 級別較高的 APK 必須採用更高的版本代碼。例如,如果您建立兩個 APK 支援不同的 API 級別,API 級別較高的 APK 必須採用更高的版本代碼。這樣可以確保如果裝置收到系統更新後,符合安裝 API 級別更高的 APK 的條件,則使用者會收到更新應用程式的通知。如要進一步瞭解如何套用這項要求,請參閲上文的「多個 APK 的規則」部分。

您還應考慮,由於不同的 APK 的涵蓋範圍可能有所重疊,或者日後您可能會對 APK 進行變更,版本代碼的順序對使用者接收的 APK 可能會有什麼影響。

比方說,如果您根據螢幕尺寸使用不同的 APK (例如,一個 APK 適用於小型到中型螢幕,一個 APK 適用於大型到特大型螢幕),但您預計之後會改為針對小型螢幕使用一個 APK,並針對中型到特大型螢幕使用另一個 APK,則您必須將大型到特大型螢幕適用 APK 的版本代號調高。這樣一來,當您進行變更時,中等尺寸裝置就會收到適當的更新,因為版本代碼會從現有 APK 增加到支援該裝置的新 APK。

此外,根據不同的 OpenGL 紋理壓縮格式建立多個不同的 APK 時,請注意,有許多裝置都支援多種格式。如果兩個 APK 的涵蓋範圍有所重疊,裝置會收到版本代碼最高的 APK,因此建議您排列 APK 的版本代碼的順序,以便向採用偏好壓縮格式的 APK 指派最高的版本代碼。舉例來說,假設您想要使用 PVRTC、ATITC 和 ETC1 壓縮格式為應用程式執行獨立的建構。如果您對這些格式的偏好正好符合此順序,則使用 PVRTC 的 APK 的版本代碼最高,使用 ATITC 的 APK 的版本代碼較低,ETC1 的版本代碼最低。因此,如果裝置同時支援 PVRTC 和 ETC1,則會收到使用 PVRTC 的 APK,這是因爲它的版本代碼最高。

如果 Google Play 商店無法識別要為目標裝置安裝的正確 APK,您也必須建立「通用」APK,其中包含您要支援的各種不同裝置版本的資源。如果提供通用 APK,應向該 APK 指派最低的 versionCode。由於 Google Play 商店安裝的應用程式版本與目標裝置相容,並且 versionCode 最高,因此可以將較低的 versionCode 指派給通用 APK,確保 Google Play 商店會先嘗試安裝其他 APK,然後才會改回使用較大的通用 APK。

使用版本代碼配置

為了讓不同的 APK 獨立更新其版本代碼 (例如,只修正一個 APK 中的錯誤時,無須更新所有 APK),應使用版本代碼配置在各個 APK 之間提供充分的空間,這樣您就可以增加一個 APK 的代碼,無須增加所有 APK 的代碼。您還應在程式碼中包含實際版本名稱 (也就是指派給 android:versionName 的使用者可見版本),以便您輕鬆關聯版本代碼和版本名稱。

注意:當您增加 APK 的版本代碼時,Google Play 會提示上一個版本的使用者更新應用程式。因此,為避免不必要的更新,請不要為實際上不包含變更的 APK 增加版本代碼。

建議你使用包含至少 7 位數的版本代碼:代表支援設定的整數位於較高位元,而版本名稱 (來自 android:versionName) 位於較低位元。例如,應用程式版本名稱為 3.1.0 時,API 級別 4 APK 和 API 級別 11 APK 的版本代碼分別為 0400310 和 1100310。前兩位數代表 API 級別 (分別為 4 和 11),中間兩位數代表螢幕尺寸或 GL 紋理格式 (這些範例中未使用),最後三位數代表應用程式的版本名稱 (3.1.0)。圖 1 顯示根據平台版本 (API 級別) 和螢幕尺寸進行分割的兩個範例。

圖 1 建議的版本代碼配置,使用前兩位數代表 API 級別,中間兩位數代表最小和最大螢幕尺寸 (用 1 - 4 表示四種尺寸) 或紋理格式,最後三位數代表應用程式版本。

此版本代碼配置只是針對隨應用程式不斷擴充應如何建立模式提出的一種建議。此配置無法展示用來辨識不同的紋理壓縮格式的解決方案。您可以選擇定義自己的表格,為應用程式各種不同的壓縮格式指定不同的整數 (例如,1 可對應至 ETC1,2 代表 ATITC,依此類推)。

您可以使用所需的任何配置,但請務必審慎考量調高應用程式日後版本代碼的方式,以及當裝置設定變更 (例如因系統更新而變更) 或您修改一或多個 APK 的設定支援時,裝置該如何接收更新。