Share via


建置特定 ABI 的 APK

本文將討論如何使用 Xamarin.Android 建置瞄準單一 ABI 的 APK。

概觀

在某些情況下,讓應用程式具備多重 APK,其中每個 APK 都使用相同的金鑰儲存區簽署並共用相同的套件名稱,但針對特定裝置或 Android 組態進行編譯,可能會比較有利。 這並非建議的方法 - 只有一個 APK 並讓其支援多個裝置和組態通常會比較簡單。 在某些情況下,建立多重 APK 會很有用,例如:

  • 縮小 APK 的大小 - Google Play 針對 APK 檔案具有 100 MB 的大小限制。 建立特定裝置的 APK 可以縮小 APK 的大小,因為您只需要為應用程式提供資產和資源的子集。

  • 支援不同的 CPU 架構 - 若您的應用程式具有適用於特定 CPU 的共用程式庫,您只能散發該 CPU 的共用程式庫。

多重 APK 可能會使散發變得更複雜 - 由 Google Play 提及的一項問題。 Google Play 會根據應用程式的版本代碼和其他與 AndroidManifest.XML 包含一起的中繼資料,來確保傳遞到裝置的是正確的 APK。 如需 Google Play 針對應用程式支援多重 APK 之方式的特定詳細資料,請查閱 Google Play 的多重 APK 支援相關文件

本指南會說明如何編寫指令碼為 Xamarin.Android 應用程式建置多重 APK,並使每個 APK 都瞄準特定的 ABI。 它涵蓋了下列主題:

  1. 為 APK 建立唯一的「版本代碼」
  2. 建立會用於此 APK 的 AndroidManifest.XML 暫存版本。
  3. 使用先前步驟中的 AndroidManifest.XML 來建置應用程式。
  4. 透過簽署及 Zipalign 來準備 APK。

本指南的最後會提供展示如何使用 Rake 來為這些步驟撰寫指令碼的逐步解說。

為 APK 建立版本代碼

Google 建議針對使用七位數版本代碼的版本代碼使用特定的演算法 (請參閱 Multiple APK Support (多重 APK 支援) 文件中的<Using a version code scheme> U (使用版本代碼配置) 一節。 藉由將此版本代碼配置展開至八位數,您可以在版本代碼中包含一些 ABI 資訊,以確保 Google Play 將正確的 APK 散發到裝置。 下列清單說明這個八位數版本代碼的格式 (已由左至右編製索引):

  • 索引 0 (下圖中的紅色) - ABI 的整數:

    • 1 – armeabi
    • 2 – armeabi-v7a
    • 6 – x86
  • 索引 1-2 (下圖為橙色) – 應用程式支援的 API 層級下限。

  • 索引 3-4 (下圖為藍色) – 支援的螢幕大小:

    • 1 – 小
    • 2 – 一般
    • 3 – 大型
    • 4 – xlarge
  • 索引 5-7 (下圖為綠色) - 版本代碼的唯一號碼。 這是由開發人員所設定。 它應在每一次應用程式公開發行後增加。

下列圖表說明在上述清單中描述之每一個代碼的位置:

八位數版本代碼格式的圖表,以顏色進行編碼

Google Play 會根據 versionCode 及 APK 組態來確保傳遞到裝置的是正確的 APK。 具有最高版本代碼的 APK 會傳遞到裝置。 例如,應用程式可能會有三個 APK,並具有下列版本代碼:

  • 11413456 - ABI 是 armeabi ;以 API 層級 14 為目標;小型到大型螢幕;版本號碼為 456。
  • 21423456 - ABI 是 armeabi-v7a ;以 API 層級 14; 一般和大型螢幕為目標;版本號碼為 456。
  • 61423456 - ABI 是 x86 ;以 API 層級 14; 一般和大型螢幕為目標;版本號碼為 456。

繼續進行此範例,假設針對 armeabi-v7a 修正了一個 Bug)。 應用程式版本會增加到 457,並且新的 APK 會將 android:versionCode 設為 21423457 進行建置。 armeabix86 版本的版本代碼維持不變。

現在,想像 x86 版本接收到一些針對更新版本 API (API 層級 19) 的更新或 Bug 修正,使其成為應用程式的版本 500。 新的 versionCode 會變更為 61923500,armeabi/armeabi-v7a 的版本代碼則維持不變。 此時,版本代碼將為:

  • 11413456 - ABI 是 armeabi ;以 API 層級 14 為目標;小型到大型螢幕;版本名稱為 456。
  • 21423457 - ABI 是 armeabi-v7a ;以 API 層級 14; 一般和大型螢幕為目標;版本名稱為 457。
  • 61923500 - ABI 是 ;目標為 x86 API 層級 19;一般和大型螢幕;版本名稱為 500。

手動維持這些版本代碼對開發人員來說將會是沉重的負擔。 計算正確 android:versionCode 及建置 APK 的程序應該自動化。 本文的最後的逐步解說會說明如何進行此動作。

建立暫存 AndroidManifest.XML

雖然並非絕對必要,但為每個 ABI 建立暫存的 AndroidManifest.XML 可協助防止資訊從一個 APK 洩漏到另一個 APK 時可能發生的問題。 例如,讓每個 APK 都有唯一的 android:versionCode 屬性是非常重要的。

執行此動作的方法取決於牽涉其中的指令碼系統,但通常會牽涉取得在開發過程中使用的 Android 資訊清單複本,請修改它然後在建置過程中使用該修改過後的資訊清單。

編譯 APK

針對每個 ABI 建置 APK 可透過使用 xbuildmsbuild 來達成,如下列範例命令列所示:

/Library/Frameworks/Mono.framework/Commands/xbuild /t:Package /p:AndroidSupportedAbis=<TARGET_ABI> /p:IntermediateOutputPath=obj.<TARGET_ABI>/ /p:AndroidManifest=<PATH_TO_ANDROIDMANIFEST.XML> /p:OutputPath=bin.<TARGET_ABI> /p:Configuration=Release <CSPROJ FILE>

下列清單說明每個命令列參數:

  • /t:Package – 建立使用偵錯金鑰存放區簽署的 Android APK

  • /p:AndroidSupportedAbis=<TARGET_ABI> – 這是要設為目標的 ABI。 必須為 armeabiarmeabi-v7a,或 x86 中的其中一個

  • /p:IntermediateOutputPath=obj.<TARGET_ABI>/ – 這是將保存建置一部分所建立之中繼檔案的目錄。 若有必要,Xamarin.Android 會根據 ABI 的名稱建立目錄,例如 obj.armeabi-v7a。 通常建議針對每個 ABI 各自使用一個資料夾,因為這可以防止發生檔案從其中一個組建「洩漏」到另一個組建的問題。 請注意,這個值會使用目錄分隔符號來終止 (若為 OS X 則為 /)。

  • /p:AndroidManifest– 這個屬性會指定建置期間將使用之AndroidManifest.XML檔案的路徑

  • /p:OutputPath=bin.<TARGET_ABI> – 這是將容納最終 APK 的目錄。 Xamarin.Android 會根據 ABI 的名稱來建立目錄,例如 bin.armeabi-v7a

  • /p:Configuration=Release – 執行 APK 的發行組建。 偵錯組建無法上傳至 Google Play。

  • <CS_PROJ FILE> – 這是 Xamarin.Android 專案檔案的路徑 .csproj

針對 APK 進行簽署及 Zipalign

在透過 Google Play 散發 APK 之前,必須先簽署 APK。 這可透過使用 jarsigner 應用程式來執行,其為 Java 開發人員套件的一部分。 下列命令列展示如何在命令列中使用 jarsigner

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore <PATH/TO/KEYSTORE> -storepass <PASSWORD> -signedjar <PATH/FOR/SIGNED_JAR> <PATH/FOR/JAR/TO/SIGN> <NAME_OF_KEY_IN_KEYSTORE>

所有的 Xamarin.Android 應用程式都必須經過 Zipalign,才能在裝置上執行。 此為要使用之命令列的格式:

zipalign -f -v 4 <SIGNED_APK_TO_ZIPALIGN> <PATH/TO/ZIP_ALIGNED.APK>

使用 Rake 自動建立 APK

範例專案 OneABIPerAPK \(英文\) 是一個簡單的 Android 專案,它示範如何計算特定 ABI 的版本號碼,並為下列每個 ABI 建置三個獨立的 APK:

  • armeabi
  • armeabi-v7a
  • x86

範例專案中的 rakefile 會執行先前章節中描述的每個步驟:

  1. 為 APK 建立 android:versionCode

  2. 將 android:versionCode 寫入該 APK 的自訂 AndroidManifest.XML

  3. 編譯 Xamarin.Android 專案的發行組建,瞄準單一目標 ABI,並使用先前步驟中建立的 AndroidManifest.XML

  4. 使用生產環境金鑰儲存區簽署 APK \(英文\)。

  5. 針對 APK 進行 Zipalign

若要建置應用程式的所有 APK,請從命令列執行 build Rake 工作:

$ rake build
==> Building an APK for ABI armeabi with ./Properties/AndroidManifest.xml.armeabi, android:versionCode = 10814120.
==> Building an APK for ABI x86 with ./Properties/AndroidManifest.xml.x86, android:versionCode = 60814120.
==> Building an APK for ABI armeabi-v7a with ./Properties/AndroidManifest.xml.armeabi-v7a, android:versionCode = 20814120.

Rake 工作完成之後,便會有三個 bin 資料夾,以及一個 xamarin.helloworld.apk 檔案。 下一個螢幕擷取畫面顯示每個資料夾及其內容:

包含 xamarin.helloworld.apk 的特定平台資料夾位置

注意

本指南中描述的建置過程可在許多不同建置系統的其中一個內實作。 雖然我們並未預先撰寫範例,但它也可以使用 Powershell / psakeFake 來進行。

摘要

本指南提供如何建立瞄準特定 ABI 之 Android APK 的一些建議。 它也討論建立 android:versionCodes 的一個可能配置,其可識別 APK 適用的 CPU 架構。 逐步解說則包含使用 Rake 為建置撰寫指令碼的範例專案。