準備可供發行的應用程式

應用程式完成編碼和測試之後,必須準備可供散發的套件。 準備此套件的第一項工作是建置可供發行的應用程式,主要是設定一些應用程式屬性。

使用下列步驟建置可供發行的應用程式:

  • 指定應用程式圖示 – 每個 Xamarin.Android 應用程式都應該指定應用程式圖示。 雖非技術上必要,但一些市場有此要求,例如 Google Play。

  • 版本應用程式 – 此步驟牽涉到初始化或更新版本設定資訊。 這對未來應用程式更新很重要,並可確保使用者了解他們已安裝哪個應用程式版本。

  • 壓縮 APK – 使用 Managed 程式代碼上的 Xamarin.Android 連結器和 Java 位元組程式代碼上的 ProGuard,最終 APK 的大小可以大幅減少。

  • 保護應用程式 – 藉由停用偵錯、混淆 Managed 程式代碼、新增反偵錯和反竄改,以及使用原生編譯,防止使用者或攻擊者偵錯、竄改或反向工程應用程式。

  • 設定封裝屬性 – 封裝屬性可控制建立 Android 應用程式套件 (APK)。 此步驟可將 APK 最佳化、保護其資產並視需要將套件模組化。 此外,您可以為使用者提供針對其裝置優化的 Android 應用程式套件組合。

  • 編譯 – 此步驟會編譯程式代碼和資產,以確認其是以發行模式建置。

  • 封存以進行發佈 – 此步驟會建置應用程式,並將它放在封存中以進行簽署和發佈。

每個步驟在下方均會詳細說明。

指定應用程式圖示

強烈建議每個 Xamarin.Android 應用程式指定應用程式圖示。 某些應用程式市集要求一定要有圖示,才能發行 Android 應用程式。 Application 屬性的 Icon 屬性可用來指定 Xamarin.Android 專案的應用程式圖示。

在 Visual Studio 2017 和更新版本中,透過專案 [屬性] 的 [Android 資訊清單] 區段來指定應用程式圖示,如下列螢幕擷取畫面所示:

Set the application icon

在這些範例中,@drawable/icon 指的是位於 Resources/drawable/icon.png 的圖示檔案 (請注意,資源名稱中並沒有包含 .png 副檔名)。 此屬性也可以在 Properties\AssemblyInfo.cs 檔案中宣告,如以下範例程式碼片段所示:

[assembly: Application(Icon = "@drawable/icon")]

一般來說,using Android.App 會在 AssemblyInfo.cs 的上方宣告 (Application 屬性的命名空間為 Android.App),不過若 using 陳述式不存在,您可能需要新增它。

控制應用程式版本

版本控制對於 Android 應用程式維護和發佈至關重要。 如果沒有採取某種版本控制,會很難判斷應用程式是否應該更新和如何更新。 為了協助進行版本控制,Android 可辨識兩種不同類型的資訊:

  • 版本號碼 – 代表應用程式版本的整數值(由 Android 和應用程式在內部使用)。 大部分應用程式一開始都會將此值設定為 1,然後隨每個組建遞增。 此值和版本名稱屬性沒有任何關係或同質性 (請參閱下文)。 應用程式和發佈服務不應對使用者顯示此值。 此值會在 AndroidManifest.xml 檔案中儲存為 android:versionCode

  • 版本名稱 – 字串,僅用於向使用者傳達有關應用程式版本的資訊(如安裝在特定裝置上)。 版本名稱主要是向使用者顯示或在 Google Play 中顯示。 Android 不會在內部使用此字串。 可幫助使用者識別其裝置上所安裝組建的任何字串值,都可以是版本名稱。 此值會在 AndroidManifest.xml 檔案中儲存為 android:versionName

在 Visual Studio 中,可在專案 [屬性] 的 [Android 資訊清單] 區段中設定這些值,如下列螢幕擷取畫面所示:

Set the version number

壓縮 APK

透過結合會移除不必要受控碼的 Xamarin.Android 連結器和會移除未使用 Java 位元組程式碼 Android SDK 的 ProGuard 工具,可讓 Xamarin.Android APK 變小。 建置處理序會先使用 Xamarin.Android 連結器以將受控碼 (C#) 層級的應用程式最佳化,然後使用 ProGuard (已啟用的話) 在 Java 位元組程式碼層級將 APK 最佳化。

設定連結器

[發行] 模式會關閉共用的執行階段並開啟連結,以讓應用程式只隨附 Xamarin.Android 在執行階段所需的項目。 Xamarin.Android 中的「連結器」使用靜態分析以判斷 Xamarin.Android 應用程式所使用或參考的組件、類型及類型成員。 連結器接著會捨棄所有未使用 (或參考) 的組件、類型及成員。 這樣就能大幅縮小套件的大小。 例如,請考慮 HelloWorld 範例,其 APK 最終大小的縮減達到 83%:

  • 設定:無 – Xamarin.Android 4.2.5 大小 = 17.4 MB。

  • 組態:僅限 SDK 元件 – Xamarin.Android 4.2.5 大小 = 3.0 MB。

透過專案 [屬性] 的 [Android 選項] 區段來設定連結器選項:

Linker options

[連結] 下拉式功能表提供下列控制連結器選項:

  • – 這會關閉連結器;不會執行任何連結。

  • 僅限 SDK 元件 – 只會連結 Xamarin.Android 所需的元件。 不會連結其他組件。

  • Sdk 和使用者元件 – 這會連結應用程式所需的所有元件,而不只是 Xamarin.Android 所需的元件。

連結會產生非預期的副作用,因此務必要在實體裝置上以發行模式重新測試應用程式。

ProGuard

ProGuard 是 Android SDK 工具,可連結和混淆 Java 程式碼。 ProGuard 通常會藉由減少 APK 中的大型內含程式庫 (例如 Google Play 服務) 磁碟使用量,來建立較小的應用程式。 ProGuard 可移除未使用的 Java 位元組程式碼,以讓產生的應用程式縮小。 例如,在小型 Xamarin.Android 應用程式上使用 ProGuard 通常會達到大約 24% 的大小減少 – 在具有多個連結庫相依性的較大應用程式上使用 ProGuard 通常可大幅減少大小。

ProGuard 並非要替代 Xamarin.Android 連結器。 Xamarin.Android 受控碼可連結受控碼,而 ProGuard 可連結 Java 位元組程式碼。 建置處理序會先使用 Xamarin.Android 連結器以將應用程式中的受控碼 (C#) 最佳化,然後使用 ProGuard (若已啟用) 於 Java 位元組程式碼層級將 APK 最佳化。

已勾選 [啟用 ProGuard] 時,Xamarin.Android 會在產生的 APK 上執行 ProGuard 工具。 ProGuard 會在建置階段產生並使用 ProGuard 組態檔。 Xamarin.Android 也支援自訂 ProguardConfiguration 建置動作。 您可以將自訂 ProGuard 組態檔加入至專案,以滑鼠右鍵按一下,並選取做為建置動作,如此範例所示:

ProGuard 預設為停用。 只有將專案設定為 [發行] 模式時,才能使用 [啟用 ProGuard] 選項。 除非已勾選 [啟用 ProGuard],否則會忽略所有 ProGuard 建置動作。 Xamarin.Android ProGuard 組態不會混淆 APK,且無法啟用混淆功能,即使是使用自訂的組態檔。 如果您想要使用混淆功能,請參閱使用 Dotfuscator 保護應用程式

如需詳細使用 ProGuard 工具的相關資訊,請參閱 ProGuard

保護應用程式

停用偵錯

在 Android 應用程式開發期間,使用 Java Debug Wire Protocol (JDWP) 來執行偵錯。 基於偵錯用途,這項技術允許如 adb 的工具來與 JVM 通訊。 Xamarin.Android 應用程式的偵錯組建預設會開啟 JDWP。 雖然 JDWP 在開發期間很重要,但其可能對發行的應用程式造成安全性問題。

重要

永遠停用發行應用程式中的偵錯狀態,因為如果未停用此偵錯狀態.,即能 (透過 JDWP) 取得 Java 處理序的完整存取權,並在應用程式的內容中執行任意程式碼。

Android 資訊清單包含 android:debuggable 屬性,可控制是否能對應用程式偵錯。 較好的做法是將 android:debuggable 屬性設定為 false。 最簡單的做法就是在 AssemblyInfo.cs 中新增條件式編譯陳述式:

#if DEBUG
[assembly: Application(Debuggable=true)]
#else
[assembly: Application(Debuggable=false)]
#endif

請注意,偵錯組件會自動設定一些權限以方便偵錯 (例如 InternetReadExternalStorage)。 然而,發行組建只會使用您明確設定的權限。 如果您發現切換至發行組建造成應用程式失去偵錯組建中可用的權限,請確認您已在 [需要的權限] 中明確啟用此權限,如權限所述。

使用 Dotfuscator 保護應用程式

即使已停用偵錯,攻擊者還是可以重新封裝應用程式、新增或移除組態選項或權限。 這可讓他們進行還原工程、偵錯,或竄改應用程式。 Dotfuscator Community Edition (CE) 可用來混淆受控碼,並在建置階段將執行階段安全性狀態偵測程式碼插入 Xamarin.Android 應用程式,以偵測應用程式是否正在 Root 破解的裝置上執行並回應。

Dotfuscator CE 隨附於 Visual Studio 2017 中。 若要使用 Dotfuscator,請按兩下 [工具 > 先佔式保護 - Dotfuscator]。

若要設定 Dotfuscator CE,請參閱搭配 Xamarin 使用 Dotfuscator Community Edition。 一旦設定之後,Dotfuscator CE 會自動保護建立的每個組建。

將組譯碼組合成機器碼

啟用此選項時,系統會將組件組合成原生共用程式庫。 這可讓元件壓縮,允許較小的 .apk 檔案。 元件壓縮也會提供 最基本的 混淆形式;不應依賴這類模糊化。

此選項需要企業授權,並只有在停用 [使用 Fast Deployment] 時才能使用。 [將組件組合成機器碼] 預設為停用。

請注意,[組合成機器碼] 選項「不」代表會將組件編譯成機器碼。 無法使用 AOT 編譯 將元件編譯成機器碼。

AOT 編譯

[AOT 編譯] 選項 (封裝屬性 頁面上) 可啟用組件的預先 (AOT) 編譯。 啟用此選項時,在執行階段之前就會預先編譯組件,進而將 Just In Time (JIT) 啟動負荷降至最低。 產生的機器碼會連同未編譯的組件一起包含在 APK 中。 這樣可讓應用程式啟動時間較短,但代價是 APK 大小稍大。

[AOT 編譯] 選項需要企業授權或更高。 只有將專案設定為 [發行] 模式時才能使用 [AOT 編譯],且該選項預設為停用。 如需 AOT 編譯的詳細資訊,請參閱 AOT \(英文\)。

LLVM 最佳化編譯器

「LLVM 最佳化編譯器」會建立更小且速度更快的編譯程式碼,並將 AOT 編譯的組件轉換成機器碼,但代價是建置時間較慢。 LLVM 編譯器預設為停用。 若要使用 LLVM 編譯器,必須先啟用 [AOT 編譯] 選項 (在封裝屬性頁面上)。

注意

[LLVM 最佳化編譯器] 選項需要企業授權。

設定封裝屬性

封裝屬性可以在專案 [屬性] 的 [Android 選項] 區段中設定,如下列螢幕擷取畫面所示:

Packaging Properties

其中許多屬性都是提供偵錯模式使用,例如 [使用共用執行階段] 和 [使用 Fast Deployment]。 不過,設定應用程式以用於發行模式時,還有其他設定可決定如何將應用程式的大小與執行速度最佳化如何保護以免遭到竄改,以及如何封裝以支援不同架構與大小限制。

指定支援的架構

準備 Xamarin.Android 應用程式以供發行時,必須指定支援的 CPU 架構。 單一 APK 可以包含機器碼,以支援多個不同的架構。 如需支援多個 CPU 架構的詳細資訊,請參閱 CPU 架構

為選取的每一個 ABI 產生一個套件 (.APK)

啟用此選項時,會為每個支援的 ABI 建立一個 APK (於 [進階] 索引標籤上選取,如 CPU 架構中所述) 而不是為所有支援的 ABI 建立單一的大型 APK。 只有將專案設定為 [發行] 模式時才能使用此選項,且該選項預設為停用。

Multi-Dex

當 [啟用 Multi-Dex] 選項已啟用時,Android SDK 工具會用來略過 .dex 檔案格式 6.5 萬個方法的限制。 65K 方法限制是以應用程式所參考的 Java 方法數目為基礎(包括應用程式相依的任何連結庫中的方法),而不是以原始程式碼中寫入的方法數目為基礎。 如果應用程式只定義一些方法,但使用許多方法 (或大型程式庫),則可能會超過 6.5 萬個的限制。

應用程式可能不會使用每個參考程式庫中的每個方法,因此像是 ProGuard (請參閱前述) 等工具能夠從程式碼中移除未使用的方法。 最佳做法是只有在絕對必要時,才將 [啟用 Multi-Dex] 啟用,也就是說即使在使用 ProGuard 之後,應用程式仍參考超過 6.5 萬個 Java 方法。

如需 Multi-Dex 的詳細資訊,請參閱設定應用程式使用超過 6.4 萬個方法 \(英文\)。

Android 應用程式套件組合

應用程式套件組合與 APK 不同,因為它們無法直接部署到裝置。 相反地,這是一種格式,是要隨所有已編譯的程式代碼和資源一起上傳。 上傳已簽署的應用程式套件組合之後,Google Play 將擁有建置和簽署應用程式 APK 所需的一切,並使用動態傳遞將其服務給您的使用者。

若要啟用 Android 應用程式套件組合的支援,您必須選擇加入 bundle Android 專案選項內 Android 套件格式屬性的值。 執行此動作之前,請確定您將專案變更為 Release 設定,因為應用程式套件組合僅適用於發行套件。

您現在可以遵循 封存流程來產生應用程式套件組合。 這會為您的應用程式產生應用程式套件組合。

如需Android應用程式套件組合的詳細資訊,請參閱 Android應用程式套件組合

編譯

上述所有步驟都完成後,應用程式已準備好進行編譯。 選取 [ 建置 > 重建方案 ],確認它在發行模式中成功建置。 請注意,此步驟還不會產生 APK。

簽署應用程式套件會詳細討論封裝和簽署。

封存以供發行

若要開始發行程序,請以滑鼠右鍵按一下 [方案總管] 中的專案,然後選取 [封存] 操作功能表項目:

Archive app

[封存] 會啟動 [封存管理員],並開始封存應用程式套件組合的程序,如以下螢幕擷取畫面所示:

Archive Manager

建立封存的另一種方法是,以滑鼠右鍵按一下 [方案總管] 中的解決方案,然後選取 [全部封存],這樣會建置解決方案,並封存可產生封存的所有 Xamarin 專案:

Archive All

[封存] 與 [全部封存] 都會自動啟動 [封存管理員]。 若要直接啟動封 存管理員 ,請單擊 [工具 > 封存管理員...] 功能表項:

Launch Archive Manager

您可隨時以滑鼠右鍵按一下 [解決方案] 節點並選取 [檢視封存] 來查看解決方案的封存:

View Archives

封存管理員

封存管理員 是由解決方案清單窗格、封存清單詳細資料面板組成:

Archive Manager Panes

解決方案清單會顯示至少有一個封存專案的解決方案。 解決方案清單包括下列區段:

  • 目前的方案 – 顯示目前的方案。 請注意,如果目前的解決方案無現有的封存,此區域可能會是空的。
  • 所有封存 – 顯示具有封存的所有解決方案。
  • 搜尋文字框 (頂端) – 根據文字框中輸入的搜尋字串,篩選 [所有封存] 清單中所列的解決方案。

[封存清單] 顯示所選取解決方案之所有封存的清單。 [封存清單] 包括下列區段:

  • 選擇的解決方案名稱 – 顯示方案清單中選取的解決方案名稱。 [封存清單] 中顯示的所有資訊是指這個選取的解決方案。
  • 平台篩選 – 此欄位可讓您依平台類型篩選封存(例如 iOS 或 Android)。
  • 封存專案 – 所選解決方案的封存清單。 此清單中的每個項目都包括專案名稱、建立日期和平台。 在封存或發佈項目時,也可以顯示其他資訊,例如進度。

詳細資料面板可顯示每個封存的其他相關資訊。 它也可讓使用者開始散發工作流程或開啟散發建立所在的資料夾。 [組建註解] 區段可以在封存中包括組建註解。

Distribution

準備好要發行之應用程式的封存版本時,請選取 [封存管理員] 中的封存,然後按一下 [散發] 按鈕:

Distribute button

[散發通道] 對話方塊顯示應用程式、指出散發工作流程進度,以及所選擇之散發通道的相關資訊。 第一次執行時,會顯示兩個選擇:

Select Distribution Channel

您可選擇下列其中一個散發通道:

  • 臨機操作 – 將已簽署的 APK 儲存至可側載至 Android 裝置的磁碟。 繼續前往簽署應用程式套件,了解如何建立 Android 簽署識別、建立適用於 Android 應用程式的新簽署憑證,並將應用程式的「臨機操作」版本發佈至磁碟。 這是建立 APK 進行測試的好方法。

  • Google Play – 將已簽署的 APK 發佈至 Google Play。 繼續前往發佈至 Google Play,了解如何在 Google Play 商店中簽署和發佈 APK。