依赖ndk动态库(.so)

一、集成到apk中

1.首先将需要的.so库复制到工程目录中。

我觉得放到什么路径都是可以的,只要你在mk文件中指定对了路径就行。而在Eclipse和Android studio这些开发环境,可能相对路径是写死的,需要把.so库放到具体开发环境指定的路径下,如Android studio中放在工程目录下的jniLibs中,而

Eclipse放在工程目录下的libs中。当时libs或者jniLibs下的文件夹(目录)的命名必须要对应上设备所使用CPU的ABI,不同的CPU架构对应不同的ABI。命名如下所示

libs
|
├── arm64-v8a
│   └── libBugtags.so
├── armeabi
│   └── libBugtags.so
├── armeabi-v7a
│   └── libBugtags.so
├── mips
│   └── libBugtags.so
├── mips64
│   └── libBugtags.so
├── x86
│   └── libBugtags.so
└── x86_64
    └── libBugtags.so

我们建立什么ABI对应的目录,在打包apk时就会打包到lib下,目录结构如下

lib
|
├── arm64-v8a
│   └── libBugtags.so
├── armeabi
│   └──  libBugtags.so
│   
├── armeabi-v7a
│   └──  libBugtags.so
│   
├── mips
│   └── libBugtags.so
├── mips64
│   └── libBugtags.so
├── x86
│   └── libBugtags.so
└── x86_64
    └── libBugtags.so

注意:只有.so库才会打包到lib下,Java动态库并没有在该目录下。静态链接库已经在编译时跟代码混(链接)在一起了。

在动态链接时,会去首先检查有没有对应ABI的目录。若有则只在该目录下找,找不到就报错。从级别高到底找,最后会找armeabi,这个是公共的,不对应任何ABI,所以可以只要这个armeabi目录,把需要的.so都弄到这个文件夹下。建立ABI目录时,必须
把该工程所有.so都放进来,否则会由于某些ABI目录不存在某些.so,而设备选中该ABI目录,出现couldn't find xxx.so的错误。.so库是可以根据具体ABI作优化的,如果.so只有对应一种ABI的版本,则会出现效率上的损失,还有存在兼容性问题的
风险。
更详细的信息和注意事项查看以下这两个链接
http://www.cnblogs.com/liushilin/p/6292263.html#_label7_2
http://www.jianshu.com/p/cb05698a1968

二、放在平台系统库中
就是.so库存在于/system/lib64/等目录中,在apk目录中找不到时,就会去系统库中找,但是平台系统库的访问在N平台中比较受限,除非是系统应用,就是卸载不了,放在/system/app/下的应用。如果不是系统应用,只能访问公开 ndk api,就是系统
允许访问的.so库。如需链接 /system/lib/libfoo.so,则向
Android.mk 文件添加以下行:
LOCAL_LDLIBS := -lfoo
由此看来,公开 ndk api的.so库应该是放在/system/lib/下的。
若是出现如下报错,则是代码中动态链接到了私有平台库(.so库),且是运行环境处在N或者之后的平台中。则此时是apk中没有打包该库,系统中有该库,但是私有的。
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace" at java.lang.Runtime.loadLibrary0(Runtime.java:977) at java.lang.System.loadLibrary(System.java:1602)

而出现couldn't find xxx.so的报错则是系统中或者apk所属的目录中都没有这个库。

在用项目单编apk时,是不会帮你将.so库打包到apk的,解压apk并没有lib目录。无论你在mk文件中指定了.so的路径且在工程目录下建了ABI目录,并放入了.so库。

对于明明打包了.so到apk下,运行时仍报错说找不到的情况,可看下面分析:
用mmm命令单编apk和用eclipse/AS编译的区别是,mmm编译时不会将.so打包到apk中。在编译源码时,如果apk的源码有参与编译的话,会打包到apk所在目录的lib/ABI下,如果是armeabi的话,就放到lib/arm/下。
需要注意的是32位的.so和64位的,必须把32位的放到32位的ABI文件夹下。在编译打包.so到apk时,只会选择一个ABI文件夹。如果把一个32位的.so放arm64-v8a,那么运行时会报错,说找不到该.so。因为一个ABI为arm64-v8a的设备,
刚好该apk的.so打包在arm64-v8a下,那么该设备便会以64位的方式运行该.so,所以会去找64位的.so,最后系统会找不到,然后就报错。64位的设备理论是可以运行32位的.so,因为.so是先前兼容的(低版本.so可以运行在高版本设备上),
只是效率没有那么高,但是有时会出错。ABI为ARMv5的设备,就是32位,对应的ABI文件夹名是armeabi。
具体N平台的NDK应用链接至平台库的行为变化的官方文档点击以下链接
https://developer.android.google.cn/about/versions/nougat/android-7.0-changes.html#accessibility
NDK公开api官方文档
https://developer.android.google.cn/ndk/guides/stable_apis.html#purpose

工程mk文件配置参考以下链接
http://www.cnblogs.com/zhangjinbiao/articles/6835109.html

 

posted on 2017-05-10 16:28  淡淡的宁静  阅读(990)  评论(0编辑  收藏  举报

导航