自Android 7.0起,无法再与非ndk共享库链接(请参见NDK Apps Linking to Platform Libraries)。
一种可能的解决方法是将库包含在apk中(请参见Update your app)。
您要链接的库可能取决于其他非ndk库。在这种情况下,您也应该包括那些库。
就我而言,我一直在开发一个使用OpenCL的应用程序。在ARM设备上,带有正确符号的库是libGLES_mali.so。该应用程序在Android <7.0的设备上运行良好,但在Android> = 7.0的设备上崩溃。我在logcat中可以读取的错误是:
java.lang.UnsatisfiedLinkError: dlopen failed: library "android.hardware.graphics.common@1.0.so" not found
使用命令
readelf -d libGLES_mali.so | grep NEEDED
我可以读取libGLES_mali.so库的名称,并且依赖于android.hardware.graphics.common@1.0.so,其中可预见的是:
0x0000000000000001 (NEEDED) Shared library: [android.hardware.graphics.common@1.0.so]
0x0000000000000001 (NEEDED) Shared library: [liblog.so]
0x0000000000000001 (NEEDED) Shared library: [libnativewindow.so]
0x0000000000000001 (NEEDED) Shared library: [libz.so]
0x0000000000000001 (NEEDED) Shared library: [libc++.so]
0x0000000000000001 (NEEDED) Shared library: [libutils.so]
0x0000000000000001 (NEEDED) Shared library: [libcutils.so]
0x0000000000000001 (NEEDED) Shared library: [libm.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so]
0x0000000000000001 (NEEDED) Shared library: [libdl.so]
我尝试将上述库包含在apk中,但出现相同的错误。奇怪的是,该库是VNDK-SP的一部分(请参见SP-HAL),因此,我的理解是私有库可以自由地依赖它。
有什么建议吗?
编辑31/01/2019:在Android> = 7.0上运行的经过测试的设备均为华为。可能是与供应商有关的问题吗?
答案 0 :(得分:2)
Alex Cohn的评论是正确的。为了解决这个问题,我做了以下事情:
1)在libfoo.so中将android.hardware.graphics.common@1.0.so重命名为
2)像这样在CMakeLists.txt中添加了libfoo.so:
add_library( foo
SHARED
IMPORTED )
set_target_properties( foo
PROPERTIES IMPORTED_LOCATION
${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libfoo.so )
3)针对链接的MyLibrary,其中包含针对libfoo.so(当然还有libGLES_mali.so)的OpenCL调用
target_link_libraries (MyLibrary GLES_mali foo)
4)尽快加载libfoo.so。为此,我在MainActivity中创建了一个静态方法,当应用程序进入onCreate()时便立即调用该方法。
private static void loadLibrary() {
System.loadLibrary("foo");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
loadLibrary();
...
}
这时,应用程序因抱怨找不到某些库而崩溃。使用readelf命令:
./readelf -d /Users/rodolforocco/AndroidProjects/OvermindClient/app/libs/arm64-v8a/android-27/libfoo.so | grep NEEDED
我能够看到这些确实是libfoo.so所依赖的库。这些库还依赖于其他找不到的库。我将它们全部从设备中的文件夹/ system / lib64 /复制到文件夹$ {PROJECT_SOURCE_DIR} / src / main / jniLibs / $ {ANDROID_ABI} /中,其中libfoo.so在那里。
5)最后,像以前一样,我在需要时加载了MyLibrary。
该应用程序不再崩溃,并且可以正常运行。非常感谢!
答案 1 :(得分:1)
我在libOpenCL.so库中遇到了类似的问题,需要libcutils.so,我以稍微不同的方式解决了它:
我选择仅链接我的c ++代码,而不是在.apk中链接和包含libOpenCL.so,然后使用libOpenCL.so在手机上本地安装的库(相同文件-无需将其放在2个不同的位置)。
这对我来说要容易得多,因为通过这样做,我不必在应用启动后立即重命名和加载libcutils(我受到软件设计的限制,无法执行此操作)。
以下是详细信息:
add_library(OpenCL SHARED IMPORTED)
set_target_properties(OpenCL PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/cpp/lib/${ANDROID_ABI}/libOpenCL.so)
有点难过,但在我看来,要使OpenCL应用程序在所有Android手机上都能工作几乎是不可能的(库的名称不同,并且在不同手机上的位置不同)...请让我知道如果您知道执行此操作的方法:)