Device supports x86_64,but APK only supports armeabi

Device supports x86_64,but APK only supports armeabi

今天在创建虚拟机的时候发现这么一句话,于是我就开始思考,这话什么意思?为什么我在真机上没有看到过这样的意思。于是我就开始google之。现在将我的调查结果记录如下

第一篇-记录so文件一些问题

简介:做项目的时候经常会使用到so文件。例如使用高德地图,其SDK中就包含了armeabi、armeabi-v7a、arm64-v8a、x86等其他文件夹,里面通常放着同样名称、同样数量的so文件。实际使用过程中,关于这些so文件引发的问题确实不少,也不好解决。写下此文,希望以后遇到相关的问题,能有个大概的思路。

名词解析:
NDK:Native Development Kit
JNI:Java Native Interface
ABI: Application Binary Interface 应用二进制接口

Android Studio使用so库
1、使用和eclipse一样在libs目录下新建armeabi目录的方式
需要在build.gradle中添加指定jni库目录的语句
sourceSets {
main.jniLibs.srcDirs = ['libs'] //指定libs为jni的存放目录
}
2、使用AS默认的位置:src/main/jniLibs
直接在src/main/下新建jniLibs目录,将armeabi等目录放到该目录下即可
备注:AS可以直接右键新建同目录下的jniLibs目录,但该目录不是编译好的库文件目录,而是未编译的本地代码文件的目录(这里指的是与java同级的jni目录,放置cpp代码的)

android支持的cpu架构(目前是七种)

架构 说明
armeabi 第5代 ARM v5TE,使用软件浮点运算,兼容所有ARM设备,通用性强,速度慢
armeabi-v7a 第7代 ARM v7,使用硬件浮点运算,具有高级扩展功能
arm64-v8a 第8代,64位,包含AArch32、AArch64两个执行状态对应32、64bit
x86 intel 32位,一般用于平板
x86_64 intel 64位,一般用于平板
mips 少接触
mips64 少接触

安装时的兼容性检查:
安装到系统中后,so文件会被提取在:data/app/com.xxxxxxxx.app-x/lib/目录下(5.0版本)、/data/app-lib/目录下(4.2版本),其中armeabi和armeabi-v7a会生成arm目录,arm64-v8a会生成arm64目录。
安装app的时候,如果app使用了so文件,而不存在适合本机cpu架构的so文件,会报如下错误:
Installation failed with message INSTALL_FAILED_NO_MATCHING_ABIS.
例如:在x86模拟器上就必须有x86版本的so文件夹。不然无法安装成功。

运行时的兼容性检查:
1、检查目标目录下是否存在的so库文件
2、检查存在的so文件是否符合当前cpu架构。
对于情况一,一般规避的做法是:保证jnilibs目录下x86、x84_64、armeabi、armeabi-v7a、arm64-v8a等目录下的文件名称数量是一致的。
例如:项目中使用了A、B、C三个第三方库。其中A、B提供了armebi以及arm64-v8a版本的库文件,而C只提供了armebi、armebi-v7a版本的库文件。这时候只能够删除原有的arm64-v8a目录,保留armeabi目录,一般arm64的手机都能兼容使用armeabi版本的库。或者复制一份armeabi的so文件到缺少的目录中(推荐)。

生成so文件:
NDK交叉编译时选定APP_ABI := armeabi x86 ...可以生成支持相应芯片的so文件。APP_ABI := all生成支持所有芯片指令集(目前七种)so文件。

Android加载so文件规则:
当你只提供了armeabi目录时,armeabi-v7a、arm64-v8a架构的程序都会去armeabi里寻找,而当你同时也提供了armeabi-v7a、armeabi-v8a目录,而里面又不存在对应的so库时,系统就不会再去armeabi里面寻找了,直接找不到报错。其他平台也是如此。这里我踩了不少的坑,切记。
一般来说,一些比较有名的第三方库都会提供armeabi、armeabi-v7a、x86这三种类型的so文件,同时拥有这三种版本的app可以在所有机型上运行。另外,越来越多的SDK会同时提供arm64-v8a版本。只包含armeabi的项目也可以在所有设备上运行。

现实案例:
我的项目中使用了armeabi、arm64-v8a两种类型,而当我需要使用某语音第三方库的时候,发现只提供了armeabi、armeabi-v7a两种类型的so文件,而我的手机是arm64-v8a的。所以只会使用arm64-v8a里面的so文件,当使用到该语音库时找不到对应的so库,就会报错。理论上有以下两种解决方法:
一、删除所有arm64-v8a,只保留armeabi,全部使用兼容性最高的版本,但也运行速度最慢。
二、将该语音库的armeabi版本的so复制到arm64-v8a中。单一so文件使用armeabi兼容版本。

总结:
当你使用到so文件时,保证每个子文件夹中文件名称数量都是一致的。
对于只提供armeabi的第三方库,复制一份armeabi的so文件到缺失的其他目录中;或者只保留armeabi目录(不推荐)

第二篇-标题问题解析

Android 的 so 库和 ABI 配置我原先也是没有什么概念的,直到上个周,在我尝试跑一个程序的时候,真机运行没问题,但是用伟大的模拟机的时候,遇到了这么一个错误:

模拟机的下面显示:
Device supports x86,but APK only supports armeabi-v7a,armeabi,x86_64;
模拟机的设备是 x86,但是运行的这个程序的 apk 却只支持 armeabi-v7a,armeabi 和 x86_64 三种。
**这个问题不仅仅是一个问题,它是很多个问题
**
是的,那么问题来了
x86,armeabi-v7a,armeabi,x86_64 到底是什么玩意?
我们的代码是在哪里设置apk对它们支持的?
怎么查看和设置模拟机的支持类型?
为什么我连接的真机大华为 HUAWEI PE-TL20 没有显示这样的错误?

**宝宝发现了真相,快来夸我
**
为了弄明白上面的几个疑问,我 google 了很多相关方面的内容,终于召唤真相~~下面一个个来解释~
1.x86,armeabi-v7a,armeabi,x86_64 到底是什么玩意?
这四个玩意都是 CPU 架构类型的名称。 目前 android 支持的 CPU 架构有有以下几种:

CPU架构 描述
armeabi 第5代 ARM v5TE,使用软件浮点运算,兼容所有ARM设备,通用性强,速度慢
armeabi-v7a 第7代 ARM v7,使用硬件浮点运算,具有高级扩展功能
arm64-v8a 第8代,64位,包含AArch32、AArch64两个执行状态对应32、64bit
x86 intel 32位,一般用于平板
x86_64 intel 64位,一般用于平板
mips 少接触
mips64 少接触

2.我们的代码是在哪里设置apk对它们支持的?
如果你和我用的开发工具都是 Android Studio 的话,那么在程序的主module 的 build.gradle中你会发现有这么个代码:

defaultConfig { ndk { abiFilters "armeabi", "armeabi-v7a", "x86_64" } }

就是这里设置了支持的 CPU 的类型, 和刚才提示的 apk 支持的 CPU的类型是一模一样的. 但是,在这里,我也发现了一个不认识的标签属性 abiFiliter
硬翻过来是 abi 过滤器, abi 是什么?
ABI, (application binary interface,缩写为ABI),应用二进制接口。在计算机中,ABI 描述了应用程序(或者其他类型)和操作系统之间或其他应用程序的低级接口

3.怎么查看和设置模拟机的支持类型?
这个问题非常简单,我们在创建一个模拟机的时候,就有 ABI 的选择,因为粗心,之前一直都没有发现,看下图:

4.为什么我连接的真机大华为 HUAWEI PE-TL20 没有显示这样的错误?
问题解决到这里,我们几乎都猜到了答案,就是大华为 HUAWEI PE-TL20 这个设备支持的CPU 架构 ,肯定是 代码中支持的 armeabi-v7a,armeabi,x86_64 中的一种。
到底是其中的哪一个呢?我们可以通过adb命令行的方式查看。
具体步骤: 1.连接手机到电脑上 2.打开 cmd 命令窗口,输入命令 adb shell
3.然后输入命令 cat /proc/cpuinfo

如果你使用adb的过程中,出现了adb错误“'adb' 不是内部或外部命令,也不是可运行的程序或批处理文件
,不要慌,这是因为没有配置 adb 的环境变量,配置一下,就好了。具体配置步骤,可以移步这里 adb错误“’adb’ 不是内部或外部命令,也不是可运行的程序或批处理文件
大华为 HUAWEI PE-TL20 的结果如下:

显示是ARMv7, 对应的应该是armeabi-v7a,看来我们的猜测果然是对的。

第三篇

Android can run on several different computer architectures. This document discusses the different CPU architectures that may be employed for a Xamarin.Android application. This document will also explain how Android applications are packaged to support different CPU architectures. The Application Binary Interface (ABI) will be introduced, and guidance will be provided regarding which ABIs to use in a Xamarin.Android application.

Overview

Android allows for the creation of "fat binaries," a single .apk file that contains machine code that will support multiple, different CPU architectures. This is accomplished by associating each piece of machine code with an Application Binary Interface. The ABI is used to control which machine code will run on a given hardware device. For example, for an Android application to run on an x86 device, it is necessary to include x86 ABI support when compiling the application.

Specifically, each Android application will support at least one embedded-application binary interface (EABI). EABI are conventions specific to embedded software programs. A typical EABI will describe things such as:

  • The CPU instruction set.
  • The endianness of memory stores and loads at run time.
  • The binary format of object files and program libraries, as well as which type of content is allowed or supported in these files and libraries.
  • The various conventions used to pass data between application code and the system (for example: how registers and/or the stack are used when functions are called, alignment constraints, etc.)
  • Alignment and size constraints for enum types, structures, fields, and arrays.
  • The list of function symbols available to your machine code at run time, generally from a very specific selected set of libraries.

armeabi and Thread Safety

The Application Binary Interface will be discussed in detail below, but it is important to remember that the armeabi runtime used by Xamarin.Android is not thread safe. If an application that has armeabi support is deployed to an armeabi-v7a device, many strange and unexplainable exceptions will occur.

Due to a bug in Android 4.0.0, 4.0.1, 4.0.2, and 4.0.3, the native libraries will be picked up from the armeabi directory even though there is an armeabi-v7a directory present and the device is an armeabi-v7a device.

Note: Xamarin.Android will ensure that .so are added to the APK in the correct order. This bug should not be an issue for users of Xamarin.Android.

ABI Descriptions

Each ABI supported by Android is identified by a unique name.

armeabi

This is the name of an EABI for ARM-based CPUs that support at least the ARMv5TE instruction set. Android follows the little-endian ARM GNU/Linux ABI. This ABI does not support hardware-assisted floating-point computations. All FP operations are performed by software helper functions that come from the compiler's libgcc.a static library. SMP devices are not supported by armeabi.

Note: Xamarin.Android's armeabi code is not thread safe and should not be used on multi-CPU armeabi-v7a devices (described below). Using aremabi code on a single-core armeabi-v7a device is safe.

armeabi-v7a

This is another ARM-based CPU instruction set that extends the armeabi EABI described above. The armeabi-v7a EABI has support for hardware floating-point operations and multiple CPU (SMP) devices. An application that uses the armeabi-v7a EABI can expect substantial performance improvements over an application that uses armeabi.
Note: armeabi-v7a
machine code will not run on ARMv5 devices.

arm64-v8a

This is a 64-bit instruction set that is based on the ARMv8 CPU architecture. This architecture is used in the Nexus 9. Xamarin.Android 5.1 provides experimental support for this architecture (for more information, see Experimental Features).

x86

This is the name of an ABI for CPUs that support the instruction set commonly named x86 or IA-32. This ABI corresponds to instructions for the Pentium Pro instruction set, including the MMX, SSE, SSE2, and SSE3 instruction sets. It does not include any other optional IA-32 instruction set extensions such as:

  • the MOVBE instruction.
  • Supplemental SSE3 extension (SSSE3).
  • any variant of SSE4.

Note: Google TV, although it runs on x86, is not supported by Android's NDK or by Xamarin.Android.

x86_64

This is the name of an ABI for CPUs that support the 64-bit x86 instruction set (also referred to as x64 or AMD64). Xamarin.Android 5.1 provides experimental support for this architecture (for more information, see Experimental Features).

mips

This is the name of an ABI for MIPS-based CPUs that support at least the MIPS32r1 instruction set. Neither MIPS 16 nor micromips are supported by Android.

Note: MIPS devices are not currently supported by Xamarin.Android, but will be in a future release.

APK File Format

The Android Application Package is the file format that holds all of the code, assets,resources, and certificates necessary for an Android application. It is a .zip file, but uses the .apk file name extension. When expanded, the contents of an .apk created by Xamarin.Android can be seen in the screenshot below:
Contents of the .apk
A quick description of the contents of the .apk file:

  • AndroidManifest.xml – This is the AndroidManifest.xml file, in binary XML format.
  • classes.dex – This contains the application code, compiled into the dex file format that is used by the Android runtime VM.
  • resources.arsc – This file contains all of the precompiled resources for the application.
  • lib – This directory holds the compiled code for each ABI. It will contain one subfolder for each ABI that was described in the previous section. In the screenshot above, the .apk
    in question has native libraries for both armeabi-v7a and for x86.
  • META-INF – This directory (if present) is used to store signing information, package, and extension configuration data.
  • res – This directory holds the resources that were not compiled into resources.arsc.

Note: The file libmonodroid.so is the native library required by all Xamarin.Android applications.

Android Device ABI Support

Each Android device supports executing native code in up to two ABIs:

  • The "primary" ABI – This corresponds to the machine code used in the system image.
  • A "secondary" ABI – This is an optional ABI that is also supported by the system image.
    For example, a typical ARMv5TE device will only have a primary ABI of armeabi, while an ARMv7 device would specify a primary ABI of armeabi-v7a and a secondary ABI of armeabi. A typical x86 device would only specify a primary ABI of x86.

Android Native Library Installation

At package installation time, native libraries within the .apk are extracted into the app's native library directory, typically /data/data//lib, and are thereafter referred to as $APP/lib.

Android's native library installation behavior varies dramatically between Android versions.

Installing Native Libraries: Pre-Android 4.0

Android prior to 4.0 Ice Cream Sandwich will only extract native libraries from a single ABI within the .apk. Android apps of this vintage will first try to extract all native libraries for the primary ABI, and if no such libraries exist, Android will then extract all native libraries for the secondary ABI. No "merging" is done.

For example, consider a situation where an application is installed on an armeabi-v7a device. The .apk, which supports both armeabi and armeabi-v7a, has the following ABI lib directories and files in it:

lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libtwo.so

After installation, the native library directory will contain:

$APP/lib/libtwo.so # from the armeabi-v7a directory in the apk

In other words, no libone.so is installed. This will cause problems, as libone.so is not present for the application to load at run time. This behavior, while unexpected, has been logged as a bug and reclassified as "working as intended."

Consequently, when targeting Android versions prior to 4.0, it is necessary to provide all native libraries for each ABI that the application will support, that is, the .apk
should contain:

lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libone.so
lib/armeabi-v7a/libtwo.so

Installing Native Libraries: Android 4.0 – Android 4.0.3

Android 4.0 Ice Cream Sandwich changes the extraction logic. It will enumerate all native libraries, see if the file's basename has already been extracted, and if both of the following conditions are met, then the library will be extracted:

  • It hasn't already been extracted.
  • The native library's ABI matches the target's primary or secondary ABI.
    Meeting these conditions allows "merging" behavior; that is, if we have an .apk
    with the following contents:
lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libtwo.so

Then after installation, the native library directory will contain:

$APP/lib/libone.so
$APP/lib/libtwo.so

Unfortunately, this behavior is order dependent, as described in the following document - Issue 24321: Galaxy Nexus 4.0.2 uses armeabi native code when both armeabi and armeabi-v7a is included in apk.

The native libraries are processed "in order" (as listed by, for example, unzip), and the first match is extracted. Since the .apk contains armeabi and armeabi-v7a versions of libtwo.so, and the armeabi is listed first, it's the armeabi version that is extracted, not the armeabi-v7a version:

$APP/lib/libone.so # armeabi$APP/lib/libtwo.so # armeabi, NOT armeabi-v7a!

Furthermore, even if both armeabi and armeabi-v7a ABIs are specified (as described below in the section Declaring Supported ABIs), Xamarin.Android will create the following element in the . csproj:

<AndroidSupportedAbis>armeabi,armeabi-v7a</AndroidSupportedAbis>

Consequently, the armeabi libmonodroid.so will be found first within the .apk, and the armeabi libmonodroid.so will be the one that is extracted, even though the armeabi-v7a libmonodroid.so is present and optimized for the target. This can also result in obscure run-time errors,as armeabi is not SMP safe.

Installing Native Libraries: Android 4.0.4 and later

Android 4.0.4 changes the extraction logic: it will enumerate all native libraries, read the file's basename, then extract the primary ABI version (if present), or the secondary ABI (if present). This allows "merging" behavior; that is, if we have an .apk
with the following contents:

lib/armeabi/libone.so
lib/armeabi/libtwo.so
lib/armeabi-v7a/libtwo.so

Then after installation, the native library directory will contain:

$APP/lib/libone.so # from armeabi
$APP/lib/libtwo.so # from armeabi-v7a

Xamarin.Android and ABIs

Xamarin.Android supports the following architectures:

  • armeabi
  • armeabi-v7a
  • x86
    Xamarin.Android provides experimental support for the following architectures:
  • arm64-v8a
  • x86_64

Note that 64-bit runtimes are not required in order to run your app on 64-bit devices. For more information about experimental features in Xamarin.Android 5.1, see Experimental Features.
Xamarin.Android does not currently provide support for mips.

Declaring Supported ABI's

By default, Xamarin.Android will default to armeabi-v7a for Release builds, and to armeabi-v7a and x86 for Debug builds. Support for different ABIs can be set through the Project Options for a Xamarin.Android project. In Visual Studio, this can be set in the Android Options page of project Properties, under the Advanced tab, as shown in the following screenshot:
Android Options Advanced properties
In Xamarin Studio, the supported architectures may be selected on the Android Build page of Project Options, under the Advanced tab, as shown in the following screenshot:
Android Build Supported ABIs
There are some situations when it may be necessary to declare additional ABI support such as when:

  • Deploying the application to an x86 device.
  • Deploying the application to an armeabi-v7a device to ensure thread safety.

Summary

This document discussed the different CPU architectures that an Android application may run on. It introduced the Application Binary Interface and how it is used by Android to support disparate CPU architectures. It then went on to discuss how to specify ABI support in a Xamarin.Android application and highlighted the issues that arise when using Xamarin.Android applications on an armeabi-v7a
device that are intended only for armeabi.

posted @ 2018-11-27 17:16  帅不过王力宏  阅读(5482)  评论(0编辑  收藏  举报