Android N/O允许NDK应用链接至平台库
Android N平台解决方案
从 Android 7.0 开始,系统将阻止应用动态链接非公开 NDK 库,这种库可能会导致您的应用崩溃。下表描述的是根据应用使用的私有原生库及其目标 API 级别 (android:targetSdkVersion),应用预期显示的行为如下:
库 | 目标 API 级别 | 通过动态链接器进行运行时访问 | N Developer Preview 行为 | 最终 Android N 版本行为 | 未来的 Android 平台行为 |
公开 NDK | 任意 | 可访问 | 合乎预期 | 合乎预期 | 合乎预期 |
私有(暂时可访问的私有库) | 23 或更低 | 暂时可访问 | 合乎预期,但您会在目标设备上收到一个 logcat 警告和一条消息。 | 合乎预期,但您会收到一个 logcat 警告。 | 运行时错误 |
私有(暂时可访问的私有库) | 24 或更高 | 受限 | 运行时错误 | 运行时错误 | 运行时错误 |
私有(其他) | 任意 | 受限 | 运行时错误 | 运行时错误 | 运行时错误 |
所以当我们的NDK应用链接了系统库并且在android7.1上运行的时候,会出现图一的错误的错误提示,提示NDK应用不能连接系统库,为了解决上述问题,可以参考下面图二的修改方式,具体的修改代码路径在bionic/linker/linker/linker.cpp
图一
图二
还有一个问题就是当解除上述的报错以后,android系统会提示如下的对话框,解决上述的办法就是进入基类Activity将对话框注释就OK了
图三
Android O平台解决方案
Android O 版本有个新feature,就是普通应用不能直接引用系统的一些so库了,只能直接引用public.libraries.txt文件中过滤的so库。这个网址有介绍怎么处理。
https://source.android.com/devices/tech/config/namespaces_libraries
但是在实际开发工作中第三方应用需要用到厂商定制的一些系统so库,且so库不能对外提供怎么办呢,下面就具体描述一下解决办法。
一.具体查看一下错误描述
01-01 02:17:24.222 7475 7475 E linker : library "/system/lib64/libxxx.so" ("/system/lib64/libxxx.so") needed or dl
opened by "/system/lib64/libnativeloader.so" is not accessible for the namespace: [name="classloader-namespace", ld_library_paths
="", default_library_paths="/system/fake-libs64:/data/app/com.example.test-1/base.apk!/lib/arm64-v8a", permitted_paths="/dat
a:/mnt/expand:/data/data/com.example.test"]
01-01 02:17:24.223 7475 7475 E System : java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib64/libxxx.so"
needed or dlopened by "/system/lib64/libnativeloader.so" is not accessible for the namespace "classloader-namespace"
下面描述下这个错误的大概的意思就是应用nativeloader打不开libhaha_xxx.so这个so库了,然后应用就奔溃了,但是实际上我们的系统下面有这个库,那为什么第三方应用不能引用到了,这个就是Android平台为了安全等一些方面的考虑,禁止第三方应用引用了。
二.具体解决办法
通过一番百度和谷歌,发现应用可以调用/vendor/etc/public.libraries.txt和/system/etc/public.libraries.txt里面的所有so库,所以就往这个文件写入libxxx.so,这个库就变成共用的了,任意应用就可以找到这个so库了,第三方应用终于可以愉快的使用这个库了,大家可以查看一下这个文件里面具体内容什么,如下所示
上述只是在运行的时候有用,那么有什么一劳永逸的办法呢,那就是在system/core/rootdir/etc/public.libraries.android.txt添加相关的库,以供第三方应用使用,这样就可以编译出相关的固件,而不需要进行手动修改了。