链接共享库libGLES_mali.so导致dlopen失败:在Android> = 7.0中找不到库“ android.hardware ... @ 1.0.so”

时间:2019-01-30 10:36:57

标签: android android-ndk opencl dlopen unsatisfiedlinkerror

自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上运行的经过测试的设备均为华为。可能是与供应商有关的问题吗?

2 个答案:

答案 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(我受到软件设计的限制,无法执行此操作)。

以下是详细信息:

  1. 我在打包.apk文件时(例如: src / cpp / lib )在Android Studio不包含的位置创建了一个lib目录。
  2. 我使用“ adb pull ...”从手机下载了32位和64位libOpenCL.so,并将它们保存到 src / cpp / lib / armeabi-v7a src / cpp / lib / arm64-v8a (我想您做过类似的事情-有关详细信息,请参见Does Android support OpenCL?
  3. 我在CMakeKists.txt中添加了以下两行:
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手机上都能工作几乎是不可能的(库的名称不同,并且在不同手机上的位置不同)...请让我知道如果您知道执行此操作的方法:)