如何制作同时支持32位和64位架构的安卓应用?
我刚刚收到并阅读了来自 Google Play 的通讯,其中提到从明年开始,该商店 "将要求带有本地库的新应用程序和应用程序更新在其 32 位版本之外还提供 64 位版本"。
对于那些还没有读过的人来说,它指出。
2019年的64位支持要求
64位架构的平台支持是在Android 5.0中引入的。今天,超过 40% 的上线 Android 设备都支持 64 位,同时仍保持 32 位的兼容性。对于使用本地库的应用程序来说,64位代码通常能提供明显更好的性能,因为有额外的寄存器和新指令。
由于预计未来的安卓设备只支持64位代码,Play控制台将要求新的应用程序和带有本地库的应用程序更新在其32位版本之外提供64位版本。这可以是在单个APK内,也可以是作为发布的多个APK中的一个。
我们并没有取消对32位的支持。Google Play将继续支持32位应用程序和设备。不包括本地代码的应用程序不受影响。
这一变化将于2019年8月生效。我们今天提供了提前通知,以便让那些尚未支持 64 位的开发者有足够的时间来计划过渡。请继续关注我们未来的文章,我们将深入研究Android上64位本地库的性能优势,并查看NDK的CPU和架构指南以了解更多信息。
在适用的情况下,我们需要做出哪些实际的改变来完美地遵守这一新的要求?
.so
文件的lib/
目录,那么对于这个即将到来的要求,你不需要做什么。如果你做找到.so
文件,并且在名册中没有看到64位架构,你需要找到这些.so
文件的来源并更新它们。
- CommonsWare 2018-02-01
.so
文件名来识别它。也许这很明显,或者搜索一下就能找到一个匹配的。否则,你可以把你的dependencies
复制到一个废弃的项目中,确认.so
出现在该废弃项目的应用程序中,然后开始注释依赖关系,直到你发现哪个依赖关系拉到了.so
。
- CommonsWare 2019-08-25
根据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架构,32位的要看x86,64位的要看x86_64。
首先要做的是确保你在这两个文件夹中都有本机库,[...] 。
而且,要构建64位库,你基本上需要按照下面的指示来做。
大多数 Android Studio 项目使用 Gradle 作为底层构建系统,因此本节适用于这两种情况。为你的本地代码启用构建,就像在你的应用程序的'build.gradle'文件中的ndk.abiFilters设置中加入arm64-v8a和/或x86_64(取决于你希望支持的架构)一样简单。
// 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.abiFilters = ...
不应该有一个等号=
。我将编辑你的答案,删除这一点。希望你不要介意。BTW,这个答案似乎证实了不需要等号的说法。stackoverflow.com/a/54616385/1072150
- EJK 2019-02-21
ndk.abiFilters = 'armeabi-v7a' 'arm64-v8a' 'x86' 'x86_64
".真是奇怪!不过,由于这个答案对个人使用还没有用处,我无法确认它是否能与信号一起使用。
- JorgeAmVF 2019-02-21
如果你没有本地(NDK)代码,也就是你只写Java/Dex代码,那么你就不需要做任何事情。
如果你有本机代码(或库),那么你需要提供它们的64位版本。
根据文档这里,如果你的应用程序使用本地代码或外部库,例如,基于本地的realm(如下图),那么应该提供对64位的支持。如果你的应用程序中的任何外部库使用任何C/C++(本地),应该同时支持32位和64位架构,否则你应该与库的所有者联系。在Android Studio中,我们可以通过Build > Analyze APK来检查两种架构的版本是否可用,并出现以下窗口:
如果你使用NDK并创建本地代码,你应该通过在gradle中列举它们来提供对所有体系结构的支持。
defaultConfig {
ndk.abiFilters = 'armeabi-v7a' 'arm64-v8a' 'x86' 'x86_64'
}
如果你的安卓APK不包括64位支持,你不必担心。 在安卓工作室中,进入构建->分析APK。你可以看到APK结构。在lib下,如果你看到armeabi-v7a
库,如果你没有任何arm64-v8a
或x86_64
库,那么你的APK不支持64位架构。
只要进入应用层build.gradle
,在NDK的defaultConfig
下添加abiFilters
即可,如下所示:
ndk {
abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_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步: 2
gradle.properties
(把下面一行放在gradle.properties中)
PROP_APP_ABI=armeabi-v7a:arm64-v8a
第3步:再次构建propject。尝试将该apk上传至Play Store。
添加
ndk {
abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
}
在build.Gradle
文件中的DefaultConfig
下。请注意,推送到Play商店的64位要求即将到来。
我通过官方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
}
}
}
原生代码:指的是直接根据所运行的计算机的CPU指令编译的可执行程序。
非本地代码:指的是按照1970年代末和1980年代的原始Tandem架构的CPU指令编译的可执行程序。当这样的程序被运行时,它不能直接在它所运行的计算机的CPU上执行。NonStop操作系统包括一个用于该原始Tandem架构的解释器,它被用来运行这种非本地代码。
如果您的应用只使用以Java编程语言或Kotlin编写的代码,包括任何库或SDK,那么您的应用已经为64位设备做好准备。如果您的应用程序使用任何本地代码,或者您不确定它是否使用,您将需要评估您的应用程序并采取行动。
您的应用程序是否使用了原生代码?
首先要做的是检查您的应用程序是否使用任何本地代码。如果你的应用程序使用了本机代码,那么它就会使用。
- 在你的应用程序中使用任何C/C++(本机)代码。
- 与任何第三方本机库的链接。
- 由使用本地库的第三方应用程序生成器构建。
更多信息,请访问文档。
-
选项 1 - 从 APK 中删除 lib。
- 第一步 - 将 APK 转换为 ZIP 并找到 lib 文件夹;如果你有 lib 文件夹,请查看库依赖项。
- 第2步--从构建Gradle中移除依赖性。
xWalkCore
库,但不幸的是,它提供了32位和64位的独立.aar
文件,当我添加这两个文件时,它给了我重复的库,你能帮助我吗?
- Sultan Ali 2019-09-19
apk
时,它显示了重复文件的错误。
- Sultan Ali 2019-09-20
首先打开build.gradle模块应用程序并添加这些行,以便删除.so文件并添加64位liobraries,删除apk的libs中存在的所有.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'