`
bugtags
  • 浏览: 30317 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

NDK SO 库开发与使用中的 ABI 构架选择

 
阅读更多

 

Bugtags V1.2.7 引入了 NDK SO 库,在集成的时候,遇到不同的 SO 库打包到 APK 时,安装在某些机器上,出现 java.lang.UnsatisfiedLinkError 加载失败。

为此,深究了一下原理,和给出了解决方案。

<!-- more -->

原理

Android 系统本质是一个经过改造的 Linux 系统。最早,Android 系统只支持 ARMv5 的 CPU 构架,随着 Android 系统的发展,又加入了 ARMv7 (2010), x86 (2011), MIPS (2012), ARMv8, MIPS64 和 x86_64 (2014)。

每一种 CPU 构架,都定义了一种 ABI(Application Binary Interface),ABI 决定了二进制文件如何与系统进行交互。

一般情况下,你不需要关注这些。当你的 APP 中用到了些包含 SO 库第三方库,或者自己使用 NDK 来实现了某些功能,你就需要认真阅读接下来的教程。

NDK SO 支持不同的 CPU 构架

在使用 NDK 开发包含 c/c++ 代码的 SO 库的时候,你可以选择输出支持如下 ABI CPU 构架:

armeabi
armeabi­v7a
arm64­v8a
x86
x86_64
mips
mips64

Bugtags 的 NDK 库支持如上所有的 CPU 构架:

bugtags-ndk

但不是所有人的开发者提供的 NDK 库都支持所有的 CPU 构架:

other-ndk

上面的这个开发者提供的库,就只支持 armeabi。

其实一般情况下,是没有问题的,x86 的设备,也会兼容 armeabi 的 SO 库。

合并打包到 APK 中

如果不做任何设置,Android 的构建系统会把这些来自不同开发者的 SO 库都合并在一起,打进 APK 压缩包中。

├── AndroidManifest.xml
├── classes.dex
├── lib
│   ├── arm64-v8a
│   │   └── libBugtags.so
│   ├── armeabi
│   │   ├── libhyphenate.so
│   │   └── libBugtags.so
│   ├── armeabi-v7a
│   │   └── libBugtags.so
│   ├── mips
│   │   └── libBugtags.so
│   ├── mips64
│   │   └── libBugtags.so
│   ├── x86
│   │   └── libBugtags.so
│   └── x86_64
│       └── libBugtags.so
├── res

系统安装 APK

根据官方 ndk-abi 文档, Android 系统在安装一个 APK 的时候,会考虑当前的设备的 CPU 构架和配置(称为所谓的 primary-abi 和 secondary-abi),去该 APK 文件的对应文件夹去寻找 SO 库。

假设当前设备是 x86 机器,会优先去 lib/x86 文件夹下寻找 SO 库:

lib/<primary-abi>/lib<name>.so

如果找不到,同时定义了 secondary-abi,则去如下文件夹寻找:

lib/<secondary-abi>/lib<name>.so

如果找到了,就将文件拷贝到 APK 的安装目录的如下文件夹中:

 /lib/lib<name>.so

找不到对应的 SO,安装正常,但是当这个 SO 在运行时被使用时,会崩溃。

问题来了

可能你已经发现问题了,当一个 APK 是这种情况:

├── AndroidManifest.xml
├── classes.dex
├── lib
│   ├── arm64-v8a
│   │   └── libBugtags.so
│   ├── armeabi
│   │   ├── libhyphenate.so
│   │   └── libBugtags.so
│   ├── armeabi-v7a
│   │   └── libBugtags.so
│   ├── mips
│   │   └── libBugtags.so
│   ├── mips64
│   │   └── libBugtags.so
│   ├── x86
│   │   └── libBugtags.so
│   └── x86_64
│       └── libBugtags.so
├── res

同时 APK 被安装到一个 x86 的设备上的时候,以上的寻找过程,将会失败,运行时,将出现如下报错:

D/xxx   (10674): java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/xxx-2/base.apk"],nativeLibraryDirectories=[/data/app/xxx-2/lib/x86, /vendor/lib, /system/lib]]] couldn't find "libirdna_sdk.so"
D/xxx   (10674):     at java.lang.Runtime.loadLibrary(Runtime.java:366)

此处,笔者有点费解,既然在 x86 文件夹中找不到,应该去 armeabi 文件夹中自动寻找啊,此处留一个 TODO,需要接下来去确认是否是某些机器的原因。

解决方案

准则

NDK SO 开发者应该遵循一个准则:支持所有的平台,否则将会搞砸你的用户。

NDK SO 使用者应该遵循一个准则:要么支持所有平台,要么都不支持。

然而,事与愿违,因为种种原因(遗留 SO、芯片市场占有率、APK 包大小等),并不是所有人都遵循这样的原则。

折中方案

Android Studio

  • Android Gradle 插件中,可以使用如下方式对 abi 进行过滤:
android {
    ...

    defaultConfig {    
        ...
        ndk {
            // 设置支持的 SO 库构架,注意这里要根据你的实际情况来设置
            abiFilters 'armeabi'// 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
        }
    }

}

关键行:

abiFilters 'armeabi'// 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'

根据你的 APP 中使用的 SO 库所支持的构架具体情况,你可以进行具体设置。最终输出的 apk 中,将会包含你所选择的 abi。

像前面举出的例子,就应该只允许 armeabi。

  • 如果在添加 “abiFilter” 之后 Android Studio 出现以下提示:
NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin

则在项目根目录的 gradle.properties 文件中添加:

    android.useDeprecatedNdk=true

Eclipse

Eclipse 中,你需要手动控制你的工程中的这个文件夹里面的内容:

eclipse-libs

以达到上述的原则,使得在不同的构架的设备上运转正常。

参考文献

What you should know about .so files

关于Android的.so文件你所需要知道的)

ABI Management

 

分享到:
评论

相关推荐

    android ndk jni so库生成

    NDK(Native Development Kit)是Google提供的一套工具集,用于让开发者在Android应用中使用C/C++代码,实现性能优化或者调用特定硬件功能。本篇我们将深入探讨如何使用Android NDK和JNI来生成本地动态链接库(so库)。 ...

    NDK_CMAKE生成so库+调用so库.rar

    本教程将详细介绍如何使用NDK结合CMake构建共享库(.so文件),以及如何在JNI(Java Native Interface)中调用已有的.so库中的test()函数。 首先,我们需要理解NDK的作用。NDK主要用途有:提高计算密集型任务的性能...

    NDK开发so层与java代码相互调用

    本文将深入探讨如何在Android项目中进行NDK开发,使得Java代码能够调用SO(Shared Object)库中的原生函数,同时SO库也能反向调用Java代码。 ### NDK简介 NDK提供了一组工具,使得开发者能够在Android平台上编译和...

    ndk 编译so库以及java调c、c调java

    总的来说,掌握NDK编译SO库和Java与C/C++交互是Android高级开发中的重要技能。这不仅能够优化性能,还能实现一些Java无法直接处理的任务,如图形处理、游戏引擎、机器学习库等。在实践中,开发者应熟练运用NDK提供的...

    NDK之打包so库

    在Android开发中,NDK(Native Development Kit)是一个重要的工具集,它允许开发者使用C/C++编写部分或全部应用,以提升性能或利用特定硬件功能。本教程将深入讲解如何利用NDK打包.so库,主要关注如何处理.c或.cpp...

    在Linux下编译FFmpeg+android ndk成功的脚本及so库

    2. **Android NDK**:NDK允许开发者在Android应用中使用C/C++代码,提供了一个交叉编译环境,将源代码编译为Android目标平台的二进制文件。NDK包含了针对不同Android架构(armeabi、armeabi-v7a、arm64-v8a、x86、...

    androidNDK 打so

    综上所述,使用NDK打包SO文件是Android开发中的一个重要环节,通过NDK和JNI,开发者可以充分利用C/C++的优势,提高应用性能,实现复杂功能。在实际操作中,理解并熟练掌握NDK开发流程和技巧,对于提升Android应用的...

    Android_NDK.zip_Android so库_NDK SO_android_android so_调用.so

    总之,Android_NDK.zip中的文档"Android_NDK开发实例.doc"应当详细阐述了如何运用NDK创建.so库,以及如何在Android应用中通过JNI调用这些库进行文件操作。通过学习这些知识,开发者能够提升Android应用的性能,并...

    Android Studio NDK及so文件开发

    - **编译与链接**:使用`ndk-build`命令编译C/C++源文件,生成so文件,并将其与Java应用一起打包成APK。 #### 五、总结 通过本文的介绍,我们了解了NDK和JNI的基本概念及其在Android开发中的应用场景。掌握了NDK和...

    android使用NDK编译curl库源码

    在这个场景中,我们将探讨如何在Android环境下使用NDK(Native Development Kit)编译Curl库源码。 首先,NDK是Google提供的一个工具集,允许开发者在Android应用中集成原生代码。通过NDK,我们可以编写C和C++代码...

    AndroidStudio中 NDK开发

    本文将详细介绍在Android Studio中进行NDK开发,特别是如何创建和管理动态共享库(.so文件)。 1. **NDK简介** NDK是Google提供的一个开源工具集,用于构建原生代码库,这些库可以与Java代码一起在Android应用中...

    pcl-1.9.1 for android ndk21库

    这个"pcl-1.9.1 for android ndk21库"是专门为Android平台编译的PCL版本,它基于NDK21,这是Google发布的Android NDK的一个特定版本,提供了C和C++的交叉编译工具链,用于在Android应用中使用原生代码。NDK21支持...

    Android NDK开发动态加载so

    动态加载.so库是NDK开发中的一个重要技术,它使得应用程序在运行时按需加载库文件,而不是在安装时静态链接。这种方式可以减小APK的大小,提高应用程序的启动速度,以及便于更新和管理库文件。 Android系统提供了`...

    unity-调用动态库so-android篇(NDK)

    unity-调用动态库so-android篇, so示例制作,ndk-build生成so动态库, unity调用so动态库

    NdkJni编写so库demo

    在Android开发中,Native Development Kit(Ndk)和Java Native Interface(Jni)是两个重要的工具,用于在Java代码和本地C/C++代码之间建立桥梁。本教程将深入讲解如何利用Ndk和Jni来创建一个.so库,并展示Java如何...

    使用Android NDK编译Android平台的eXosip库

    Android NDK则是一个让开发者能够在Android应用中使用C和C++原生代码的工具集。通过NDK,我们可以编译像eXosip这样的C/C++库,使其能在Android设备上运行。这通常比使用Java进行底层性能优化更为有效。 接下来,...

    ndk使用std标准库.7z

    在Android NDK环境中使用这些库时,需要注意以下几点: 1. **C++ ABI兼容性**:Android NDK支持多种C++ ABI(Application Binary Interface),包括armeabi-v7a、arm64-v8a、x86和x86_64等。确保你的代码兼容目标...

    Android_NDK_android端_图片处理_android_NDK_ndk开发_

    Android NDK是一套工具,允许开发者在Android应用中使用C和C++代码。它提供了头文件和库,使得在原生环境中调用Android API成为可能。使用NDK的优点包括性能提升、减少内存消耗和利用已有的C/C++库。 2. **JNI...

    AndroidStudio-NDK开发 编译c代码提供so库和jar包 另外一个app调用,实例源码

    本实例源码提供了完整的流程,展示了如何在Android Studio中进行NDK开发,编译C代码生成.so库和.jar包,并在另一个应用中调用。 首先,我们需要理解NDK的核心概念。NDK是一组工具,允许开发者使用C和C++编写部分...

Global site tag (gtag.js) - Google Analytics