簡體   English   中英

如何制作同時支持 32 位和 64 位架構的 Android 應用程序?

[英]How to make Android apps which support both 32-bit and 64-bit architecture?

我剛剛收到並閱讀了來自 Google Play 的時事通訊,其中提到從明年開始,商店“將要求新應用程序和帶有本機庫的應用程序更新除了提供 32 位版本外還提供 64 位版本”。

對於那些還沒有閱讀它的人,它指出:

2019 年的 64 位支持要求

Android 5.0 中引入了對 64 位架構的平台支持。 今天,超過 40% 的上線 Android 設備支持 64 位,同時仍保持 32 位兼容性。 對於使用本機庫的應用程序,64 位代碼通常會提供明顯更好的性能,並帶有額外的寄存器和新指令。

預計未來的 Android 設備將僅支持 64 位代碼,因此 Play 管理中心將要求新應用和帶有本機庫的應用更新除了提供 32 位版本外還提供 64 位版本。 這可以在單個 APK 中,也可以作為多個發布的 APK 之一。

我們不會移除 32 位支持。 Google Play 將繼續支持 32 位應用和設備。 不包含本機代碼的應用程序不受影響。

此更改將於 2019 年 8 月生效。我們今天提供提前通知,以便尚不支持 64 位的開發人員有足夠的時間來計划過渡。 請繼續關注未來的博文,我們將深入了解 64 位本機庫在 Android 上的性能優勢,並查看 NDK 的 CPU 和架構指南以獲取更多信息。

在適用時,我們需要進行哪些實際更改才能完全符合這一新要求?

根據 Google Play 團隊發送的官方電子郵件,所需的操作是:

如果您還沒有,我們鼓勵您盡快開始為 64 位要求工作。 許多應用程序完全是用非本地代碼(例如 Java 編程語言或 Kotlin)編寫的,不需要更改代碼。

請注意,我們不會更改我們的 32 位支持政策。 Google Play 將繼續向 32 位設備提供帶有 32 位本機代碼的應用程序。 該要求意味着這些應用程序也需要具有 64 位版本。

為幫助您進行轉換,我們准備了有關如何檢查您的應用程序是否已支持 64 位以及如何符合 64 位標准的文檔

我們還在下面提供了一個高級時間表。

因此,鏈接的文檔解釋了:

如果您的應用僅使用以 Java 編程語言或 Kotlin 編寫的代碼(包括任何庫或 SDK),則您的應用已經為 64 位設備做好了准備。 如果您的應用程序使用任何本機代碼,或者您不確定它是否使用,您將需要評估您的應用程序並采取行動。

[...]

檢查 64 位庫的最簡單方法是檢查 APK 文件的結構。 構建后,APK 將與應用程序所需的任何本機庫一起打包。 本機庫存儲在基於 ABI 的各種文件夾中。 不需要支持每個 64 位架構,但是對於您支持的每個原生 32 位架構,您必須包含相應的 64 位架構。

對於 ARM 架構,32 位庫位於 armeabi-v7a 中。 64 位等效項是 arm64-v8a。

對於 x86 體系結構,查找 x86(用於 32 位)和 x86_64(用於 64 位)。

首先要做的是確保您在這兩個文件夾中都有本機庫。[...]

而且,要構建 64 位庫,您基本上需要按照以下說明進行操作:

大多數 Android Studio 項目使用 Gradle 作為底層構建系統,因此本節適用於這兩種情況。 為您的本機代碼啟用構建就像將 arm64-v8a 和/或 x86_64(具體取決於您希望支持的架構)添加到應用程序的“build.gradle”文件中的 ndk.abiFilters 設置一樣簡單:

 // Your app's build.gradle apply plugin: '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' // ...

最后,快速說明:

您的應用程序的 64 位版本應提供與 32 位版本相同的質量和功能集。

順便說一下,這個官方視頻稍微講了一點。

如果您沒有本地(NDK)代碼,即您只編寫 Java/Dex 代碼,那么您不需要做任何事情。

如果您有本機代碼(或庫),那么您需要提供它們的 64 位版本。

根據此處的文檔,如果您的應用程序使用本機代碼或外部庫,例如基於本機的領域(下圖),則應提供對 64 位的支持。 如果您的應用程序中使用任何 C/C++(本機)的任何外部庫都應具有 32 位和 64 位架構支持,否則您應該與庫所有者聯系。 在 Android Studio 中,我們可以通過Build > Analyze APK來檢查兩種架構的版本是否可用,並且會出現以下窗口:

顯示可用架構的 Android Studio 選項卡

如果您正在使用 NDK 並創建本機代碼,您應該通過將它們列入 gradle 來提供對所有架構的支持:

defaultConfig {  
   ndk.abiFilters = 'armeabi-v7a' 'arm64-v8a' 'x86' 'x86_64'
   }

如果您的 Android APK 不包括 64 位支持,您無需擔心。 在 Android Studio 中轉到 Build -> Analyze APK。 您可以看到 APK 結構。 在 lib 下,如果您看到armeabi-v7a庫,而您沒有任何arm64-v8ax86_64庫,那么您的 APK 不支持 64 位架構。

只需轉到應用程序級build.gradle並在defaultConfig下的 NDK 中添加abiFilters ,如下所示:

ndk {
    abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}

添加

ndk {
    abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
} 

DefaultConfig下的build.Gradle文件中。 請注意,push to play store 64 位要求即將推出。

第1步 :

app=> build.gradle (put below code in build.gradle)

android {
........

 defaultConfig {

 .........

   ndk {
            abiFilters = []
            abiFilters.addAll(PROP_APP_ABI.split(':').collect{it as String})
        }
........        
}
.......
 packagingOptions {
        exclude 'lib/armeabi-v7a/libARM_ARCH.so'
    }

}

第2步

gradle.properties

(放在 gradle.properties 的下面一行)

PROP_APP_ABI=armeabi-v7a:arm64-v8a

第 3 步:再次構建項目。 嘗試上傳該 apk 以播放商店。

我試過這個 By Official Android Docs 工作出色。 在這個解決方案中,我有構建多個 APK,您可以在附件中看到...確保您的編譯 Skd 版本為 29 或構建工具版本為 29.0.3,如下所示:

    Android {
    compileSdkVersion 29
    buildToolsVersion '29.0.3'
    
    defaultConfig {
        applicationId "com.myapp.sk"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 2
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    
    }
        splits {
            density {
                enable true
                reset()
                include "mdpi", "hdpi"
            }
            abi {
                enable true
                reset()
                include "x86", "x86_64"
            }
        }
    }

// Map for the version code that gives each ABI a value.
ext.abiCodes = ['armeabi-v7a':1, x86:2, x86_64:3]

// For per-density APKs, create a similar map like this:
// ext.densityCodes = ['mdpi': 1, 'hdpi': 2, 'xhdpi': 3]

import com.android.build.OutputFile

// For each APK output variant, override versionCode with a combination of
// ext.abiCodes * 1000 + variant.versionCode. In this example, variant.versionCode
// is equal to defaultConfig.versionCode. If you configure product flavors that
// define their own versionCode, variant.versionCode uses that value instead.
android.applicationVariants.all { variant ->

    // Assigns a different version code for each output APK
    // other than the universal APK.
    variant.outputs.each { output ->

        // Stores the value of ext.abiCodes that is associated with the ABI for this variant.
        def baseAbiVersionCode =
                // Determines the ABI for this variant and returns the mapped value.
                project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))

        // Because abiCodes.get() returns null for ABIs that are not mapped by ext.abiCodes,
        // the following code does not override the version code for universal APKs.
        // However, because we want universal APKs to have the lowest version code,
        // this outcome is desirable.
        if (baseAbiVersionCode != null) {

            // Assigns the new version code to versionCodeOverride, which changes the version code
            // for only the output APK, not for the variant itself. Skipping this step simply
            // causes Gradle to use the value of variant.versionCode for the APK.
            output.versionCodeOverride =
                    baseAbiVersionCode * 1000 + variant.versionCode
        }
    }
}

Multi-Aks 附件

本機代碼:是指直接編譯為運行它的計算機的 CPU 指令的可執行程序。

非本機代碼:是指編譯為 1970 年代末和 80 年代原始 Tandem 架構的 CPU 指令的可執行程序。 當這樣的程序運行時,它不能直接在運行它的計算機的 CPU 上執行。 NonStop 操作系統包含用於原始 Tandem 架構的解釋器,用於運行此類非本機代碼。

如果您的應用僅使用以 Java 編程語言或 Kotlin 編寫的代碼(包括任何庫或 SDK),則您的應用已經為 64 位設備做好了准備。 如果您的應用程序使用任何本機代碼,或者您不確定它是否使用,您將需要評估您的應用程序並采取行動。

您的應用是否使用本機代碼?

首先要做的是檢查您的應用程序是否使用任何本機代碼。 您的應用在以下情況下使用本機代碼:

  • 在您的應用程序中使用任何 C/C++(本機)代碼。
  • 與任何第三方本機庫的鏈接。
  • 由使用本機庫的第三方應用程序構建器構建。

有關更多信息, 請訪問文檔

  • 選項 1 - 從 APK 中刪除 lib。
    • 第 1 步 - 將 APK 轉換為 ZIP 並找到 lib 文件夾; 如果您有 lib 文件夾,請查看庫依賴項。
    • 第 2 步 - 從構建 Gradle 中刪除依賴項。
  • 選項 2 - 下載 64 位和 32 位 JAR 文件,並在 app 和 build.gradle 中添加您的 lib 文件夾。

首先打開 build.gradle 模塊應用程序並添加這些行以刪除 .so 文件並添加 64 位 liobraries 刪除 apk 庫中存在的所有 .so 文件

android {    
    compileSdkVersion 29    
    defaultConfig {    
        -----    
        -----    
        ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'    
        ndk {    
            abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'    
        }    
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"    
    }    
packagingOptions{     
        packagingOptions {    
            exclude 'lib/armeabi-v7a/libvudroid.so'    
            exclude 'lib/x86/libvudroid.so'    
            exclude 'lib/arm64-v8a/libvudroid.so'    
        }    
    }`

就我而言,我使用了一個使用 OpenGL C 庫的庫(ESRI ArcGIS for Android)。 而不是ndk.abiFilters...似乎可以解決其他所有人問題的字符串,我不得不使用以下內容:

ndk { abiFilters "armeabi-v7a", "arm64-v8a" }

將此添加到您的 build.gradle 中

ndk.abiFilters 'arm64-v8a','x86_64'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM