支援 64 位元架構

Stay organized with collections Save and categorize content based on your preferences.

在 Google Play 上發布的應用程式必須支援 64 位元架構。為應用程式新增 64 位元版本,不僅能提升效能,還能為使用 64 位元硬體的裝置提前做好準備。

請按照下列步驟操作,確保 32 位元應用程式支援 64 位元的裝置。

評估應用程式

如果應用程式只使用以 Java 程式設計語言或 Kotlin 編寫的程式碼 (包括所有程式庫或 SDK),則應用程式支援 64 位元裝置。如果應用程式使用到任何原生程式碼,或您不確定是否已使用,請評估應用程式。

快速檢查狀態

前往 Play 管理中心查看現有版本,確認其是否符合規定。

如果草稿版本有與 64 位元版本要求相關的任何問題,Play 管理中心也會顯示警告,參見下圖示例。

如果系統顯示快訊,請按照下列步驟,讓應用程式與 64 位元裝置相容。

應用程式是否使用原生程式碼?

如果符合下列條件,即表示應用程式使用原生程式碼:

  • 在應用程式中使用任何 C/C++ (原生) 程式碼。
  • 連結到任何第三方原生資料庫。
  • 由使用原生資料庫的第三方應用程式建構工具所建構。

應用程式中是否有 64 位元程式庫?

檢查 APK 檔案的結構。建構完成後,APK 會連同應用程式所需的所有原生資料庫一併封裝。原生資料庫則會根據 ABI 儲存在多個資料夾中。系統不必支援每一個 64 位元架構,但每個支援的原生 32 位元架構都必須納入對應的 64 位元架構。

如果是 ARM 架構,32 位元程式庫位於 armeabi-v7a。 相應的 64 位元程式庫則位於 arm64-v8a

如果是 x86 架構,請為 32 位元尋找 x86,64 位元則尋找 x86_64

確認這兩個資料夾中都有原生資料庫。一起來複習:

平台 32 位元程式庫資料夾 64 位元程式庫資料夾
ARM lib/armeabi-v7a lib/arm64-v8a
x86 lib/x86 lib/x86_64

請注意,每個資料夾中的程式庫組合可能完全相同,也可能不完全相同,這取決於應用程式的實際情況。您應達成的目標是確保應用程式在僅限 64 位元的環境中能正確執行。

在一般情況下,同時針對 32 位元和 64 位元架構建構的 APK 或軟體包會有這兩種 ABI 的資料夾,每個資料夾中都有一組對應的原生資料庫。如果系統不支援 64 位元版本,您可能會看到 32 位元的 ABI 資料夾,而非 64 位元資料夾。

使用 APK 分析工具尋找原生資料庫

APK 分析工具是一項可讓您評估所建立 APK 各項層面的工具。可用它來尋找任何原生資料庫,並確保存在 64 位元程式庫。

  1. 開啟「Android Studio」,然後開啟任何專案
  2. 從選單中依序選取「Build」>「Analyze APK」

    啟動 APK 分析工具

  3. 選擇要評估的 APK。

  4. 查看「lib」資料夾,其中會代管「.so」檔案 (如有)。如果沒有,則您的應用程式支援 64 位元裝置,不需要採取進一步行動。如果看到 armeabi-v7ax86,就表示有 32 位元程式庫。

  5. 查看「arm64-v8a」或「x86_64」資料夾中是否有類似的「.so」檔案。

    啟動 APK 分析工具

  6. 如果沒有看到任何 arm64-v8ax86_64 程式庫,請更新建構程序,以便開始在 APK 中建構並封裝這些構件。

  7. 如果兩個程式庫都已封裝完畢,就可以略過這個步驟並直接在 64 位元硬體上測試應用程式

透過解壓縮 APK 尋找原生資料庫

APK 檔案結構與 ZIP 檔案類似。使用指令列或其他擷取工具解壓縮 APK 檔案。視擷取工具而定,您可能需要將檔案重新命名為 .zip。

按照上述指南瀏覽解壓縮的檔案,確認應用程式是否支援 64 位元裝置。您可以在指令列中執行下列指令:

:: Command Line
> zipinfo -1 YOUR_APK_FILE.apk | grep \.so$
lib/armeabi-v7a/libmain.so
lib/armeabi-v7a/libmono.so
lib/armeabi-v7a/libunity.so
lib/arm64-v8a/libmain.so
lib/arm64-v8a/libmono.so
lib/arm64-v8a/libunity.so

在這個範例中,您可以發現有 armeabi-v7aarm64-v8a 程式庫,這表示應用程式支援 64 位元架構。

透過 64 位元程式庫建構應用程式

下列操作說明概述如何建構 64 位元程式庫。請注意,以下步驟僅涵蓋您可以透過原始碼建構的建構程式碼和程式庫。

如果使用任何外部 SDK 或程式庫,請按照上述步驟操作,確保使用的是 64 位元版本。如果無法取得 64 位元版本,請與 SDK 或程式庫擁有者聯絡,並在規劃支援 64 位元裝置時將這一點納入考量。

使用 Android Studio 或 Gradle 進行建構

大部分的 Android Studio 專案都使用 Gradle 做為基礎建構系統,因此本節適用於使用這兩種工具進行建構的情況。依據您想支援的架構而定,為原生程式碼啟用版本和在應用程式「build.gradle」檔案的 ndk.abiFilters 設定中加入 arm64-v8a 和/或 x86_64 一樣簡單:

Groovy

// Your app's build.gradle
plugins {
  id 'com.android.app'
}

android {
   compileSdkVersion 27
   defaultConfig {
       appId "com.google.example.64bit"
       minSdkVersion 15
       targetSdkVersion 28
       versionCode 1
       versionName "1.0"
       ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
// ...

Kotlin

// Your app's build.gradle
plugins {
    id("com.android.app")
}

android {
    compileSdkVersion(27)
    defaultConfig {
        appId = "com.google.example.64bit"
        minSdkVersion(15)
        targetSdkVersion(28)
        versionCode = 1
        versionName = "1.0"
        ndk {
            abiFilters += listOf("armeabi-v7a","arm64-v8a","x86","x86_64")
        }
// ...

使用 CMake 進行建構

如果應用程式是透過 CMake 建構,您可以將 arm64-v8a 傳遞到「-DANDROID_ABI」參數,以便針對 64 位元 ABI 進行建構:

:: Command Line
> cmake -DANDROID_ABI=arm64-v8a … or
> cmake -DANDROID_ABI=x86_64 …

如果您使用 externalNativeBuild,這個方法不會起任何作用。詳情請參閱「使用 Gradle 進行建構」一節。

使用 ndk-build 進行建構

如果應用程式是以 ndk-build 建構,您可以透過使用 APP_ABI 變數修改 Application.mk 檔案來為 64 位元 ABI 建構:

APP_ABI := armeabi-v7a arm64-v8a x86 x86_64

如果您使用 externalNativeBuild,這個方法不會起任何作用。詳情請參閱「使用 Gradle 進行建構」一節。

將 32 位元程式碼移植至 64 位元

如果程式碼已經可以在電腦或 iOS 上執行,則不須為 Android 額外進行任何設定。如果這是第一次為 64 位元系統建構程式碼,您必須解決的主要問題是指標無法再納入如 int 這類 32 位元整數。

更新可儲存指標類型 (例如 intunsigneduint32_t) 的程式碼。在 Unix 系統上,long 與指標大小相符,然而在 Windows 上並不是如此。請改用意圖顯而易見的類型 uintptr_tintptr_t。如要儲存兩個指標間的差異,請使用 ptrdiff_t 類型。

請一律優先採用 <stdint.h> 中定義的特定固定寬度整數類型,而非 intlong 等傳統類型,即便是對於非指標類型也是如此。

請使用以下編譯器旗標,找出程式碼在指標和整數之間轉換錯誤的情況:

-Werror=pointer-to-int-cast
-Werror=int-to-pointer-cast
-Werror=shorten-64-to-32

含有 int 欄位 (其中有 C/C++ 物件指標) 的 Java 類別有同樣的問題。在 JNI 原始碼中搜尋 jint,並確定已切換至 long (Java 端) 和 jlong (C++ 端)。

對於 64 位元程式碼,隱式函式宣告更加危險。C/C++ 假設隱式宣告的函式傳回類型 (也就是編譯器未偵測到宣告的函式) 為 int。如果函式的實際傳回類型是指標,這對於在 32 位元系統上運作並沒有問題,在這類系統上,您的指標可在 int 使用。然而,對 64 位元系統來說,這個編譯器在指標執行到一半時就無法正常運作。例如:

// This function returns a pointer:
// extern char* foo();

// If you don't include a header that declares it,
// when the compiler sees this:
char* result = foo();

// Instead of compiling that to:
result = foo();

// It compiles to something equivalent to:
result = foo() & 0xffffffff;

// Which will then cause a SIGSEGV if you try to dereference `result`.

以下編譯器旗標會將隱式函式宣告的警告轉變為錯誤,讓您可以更容易找到和修正這個問題:

-Werror=implicit-function-declaration

如果您有內嵌組合器,請重新編寫或使用一般的 C/C++ 實作。

如果擁有硬式編碼的類型大小 (例如 8 或 16 個位元組),請將其替換為對等的 sizeof(T) 運算式 (例如 sizeof(void*))。

如需有條件地為 32 位元編譯不同於 64 位元的程式碼,可以使用 #if defined(__LP64__) 來處理一般 32/64 間的差異;針對 Android 支援的特定架構,則可以使用 __arm____aarch64__ (arm64)、__i386__ (x86) 和 __x86_64__

由於傳統格式指定碼不允許使用對 32 位元和 64 位元裝置都正確的方式來指定 64 位元類型,因此必須為 printfscanf 這類函式調整格式字串。使用 <inttypes.h> 中的 PRISCN 巨集就能解決這個問題,PRIxPTRSCNxPTR 用於寫入/讀取十六進位指標,而 PRId64SCNd64 則可透過移植的方式寫入/讀取 64 位元值。

轉移時,您可能需要使用 1ULL 取得要轉移的 64 位元常數,而不能使用僅 32 位元的 1

透過 Android App Bundle 減少大小增加量

為應用程式新增 64 位元架構這項支援後,可能會導致 APK 大小增加。我們強烈建議您善用 Android App Bundle 功能,這樣當您在同一個 APK 中納入 32 位元與 64 位元的原生程式碼時,才能將對大小造成的影響減至最低。

遊戲開發人員

目前最常用的三種引擎均支援 64 位元版本:

  • Unreal (自 2015 年開始支援)
  • Cocos2d (自 2015 年開始支援)
  • Unity (自 2018 年開始支援)

Unity 開發人員

升級至支援的版本

Unity 提供 2018.22017.4.16 版本,均支援 64 位元。

如果發現所使用的 Unity 版本不支援 64 位元,請決定要升級的版本,並按照 Unity 提供的指南來遷移環境,確保應用程式升級至可建構 64 位元程式庫的版本。Unity 建議升級至最新 LTS 版本的編輯器,以便取得最新功能和更新。

以下圖表概述各種 Unity 版本和建議做法:

Unity 版本 版本是否支援 64 位元? 建議做法

2020.x

✔️

確保建構設定能夠輸出 64 位元程式庫。

2019.x

✔️

確保建構設定能夠輸出 64 位元程式庫。

2018.4 (LTS)

✔️

確保建構設定能夠輸出 64 位元程式庫。

2018.3

✔️

確保建構設定能夠輸出 64 位元程式庫。

2018.2

✔️

確保建構設定能夠輸出 64 位元程式庫。

2018.1

提供 64 位元實驗性支援。

2017.4 (LTS)

✔️

2017.4.16 起開始支援。 確保建構設定能夠輸出 64 位元程式庫。

2017.3

✖️

升級至支援 64 位元的版本。

2017.2

✖️

升級至支援 64 位元的版本。

2017.1

✖️

升級至支援 64 位元的版本。

<=5.6

✖️

升級至支援 64 位元的版本。

變更建構設定以便輸出 64 位元程式庫

如果使用的是支援 64 位元 Android 資料庫的 Unity 版本,您可以調整版本設定來產生 64 位元的應用程式版本。使用 IL2CPP 後端做為指令碼後端。如要設定 Unity 專案來建構 64 位元架構,請按照下列指示操作:

  1. 前往「Build Settings」,確認 Unity 標誌是否顯示在「Platform」下方的「Android」旁,藉此確定您是針對 Android 進行建構。
    1. 如果 Unity 標誌並未顯示在 Android 平台旁,請選取「Android」,然後按一下「Switch Platform」
  2. 按一下「Player Settings」

    Unity 中的「Player settings」

  3. 依序前往「播放器設定面板」>「Android 設定」>「其他設定」>「設定」

  4. 將「Scripting Backend」設為「IL2CPP」

  5. 勾選「目標架構」>「ARM64」核取方塊。

    在 Unity 中設定目標架構

  6. 照常建構!

請注意,如要針對 ARM64 進行建構,必須為該平台量身打造所有資產。請按照 Unity 的指南來減少 APK 大小,並考慮善用 Android App Bundle 功能來減少大小增加量。

多個 APK 和 64 位元版本遵循

請注意,如果您目前使用 Google Play 支援多個 APK 的機制發布應用程式,系統會根據發布層級來評估 64 位元版本規定的遵循情形。不過,64 位元版本規定不適用於未在 Android 9 Pie 以上版本裝置發行的 APK 或應用程式套件。

如果其中一個 APK 標示為不符合版本要求,但版本已過舊,無法修正為符合要求,其中一種策略是在 APK 資訊清單的 uses-sdk 元素中新增 maxSdkVersion="27" 屬性。如此一來,此 APK 將無法提交至搭載 Android 9 Pie 或以上版本的裝置,也不會再乾擾法規遵循。

RenderScript 和 64 位元版本遵循

如果應用程式使用 RenderScript,並且以舊版 Android 工具建構,則該應用程式可能會遇到 64 位元版本遵循問題。如果使用版本低於 21.0.0 的建構工具,編譯器可能會將產生的中間碼放到外部 .bc 檔案中。64 位元架構不再支援這些舊版 .bc 檔案,因此,如果 APK 中出現這些檔案,就會造成版本遵循的問題。

如要修正問題,請移除專案中的所有 .bc 檔案,將環境升級至 build-tools-21.0.0 以上版本,然後將 Android Studio 中的 renderscriptTargetApi 設為 21+,藉此指示編譯器不要產生 .bc 檔案。接著,重新建構應用程式並檢查是否有 .bc 檔案,然後將其上傳至 Play 管理中心。

在 64 位元硬體上測試應用程式

應用程式的 64 位元版本應與 32 位元版本擁有相同的品質,並提供同樣的功能組合。對應用程式進行測試,確保最新版 64 位元裝置的使用者在使用應用程式時可享有良好體驗。

僅限 64 位元裝置

建議您盡可能使用下列任一選項,在嚴格的 64 位元專屬環境中測試應用程式:

其他裝置選項

如果您沒有上述任一裝置,或無法使用 Android Emulator,下一個最佳做法是使用支援 64 位元的裝置,例如 Google Pixel 或其他裝置製造商在近期推出的旗艦款裝置。

安裝及測試應用程式

測試 APK 最簡單的方法是使用 Android Debug Bridge (ADB) 安裝應用程式。在多數情況下,您可以提供 --abi 做為參數,指出要將哪些程式庫安裝到裝置上。這樣只會在包含 64 位元程式庫的裝置上安裝應用程式。

:: Command Line
# A successful install:
> adb install --abi armeabi-v7a YOUR_APK_FILE.apk
Success

# If your APK does not have the 64-bit libraries:
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
adb: failed to install YOUR_APK_FILE.apk: Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]

# If your device does not support 64-bit, an emulator, for example:
> adb install --abi arm64-v8a YOUR_APK_FILE.apk
ABI arm64-v8a not supported on this device

安裝成功後,請依照平常的方法測試應用程式,確保其品質與 32 位元版本相同。

發布

當您準備好發布應用程式時,請照常發布。一如往常,請繼續按照這些最佳做法部署應用程式。建議您利用封閉測試群組,僅向少數使用者推出應用程式,以確保應用程式的品質一致。

在推出重大更新時,請務必先在支援 64 位元架構的裝置上進行全面測試,再將應用程式發布給更多目標對象。