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



由于Android 7.0,不再可能链接到非ndk共享库(请参阅ndk应用程序链接到平台库)。

一个可能的解决方法是在apk中包含库(请参阅更新您的应用程序)。

您尝试链接的库可能依赖于其他非ndk库。在这种情况下,您也应该包括这些库。

在我的案例中,我一直在开发一个使用OpenCL的应用程序。在ARM设备上,具有正确符号的库是libGLES_mali.so。该应用程序在安卓<7.0,但它在安卓>=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),因此,据我所知,私人图书馆可能会自由依赖它。

有什么建议吗?

编辑:2019年1月31日:在Android>=7.0上运行的测试设备均为华为。这可能是与供应商有关的问题吗?

Alex Cohn的评论是对的。为了解决这个问题,我做了以下操作:

1) 已重命名android.hardware.graphics.common@1.0.so在libfoo.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,包含OpenCL调用,针对libfoo.so(当然还有libGLES_mali.so)

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

该应用程序不再崩溃,并按预期工作。非常感谢!

我在libOpenCL.so库中遇到了类似的问题,需要libcutils.so,我用一种稍微不同的方式解决了这个问题:

我没有将libOpenCL.so链接并包含在.apk中,而是选择只将我的c++代码链接到它,然后使用libOpenCL.sho这个本地安装在手机上的库(它是同一个文件-不需要在两个不同的位置)。

这对我来说要容易得多,因为通过这样做,我不必在应用程序启动后立即重命名和加载libcutils(我有软件设计限制,无法做到这一点)。

以下是详细信息:

  1. 我在打包.apk文件时Android Studio不包括的位置创建了一个lib目录(例如:src/cpp/lib)
  2. 我从我的手机上下载了32位和64位的libOpenCL.so;adb拉"并将它们分别保存到src/cpp/lib/armeabi-v7asrc/cpp/lib/arm64-v8a(我想你也做了类似的事情-请参阅Android是否支持OpenCL?了解更多详细信息)
  3. 我在CMakeKits.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应用程序几乎是不可能的(libs的名称不同,在不同手机上的不同位置)。。。如果你知道这样做的方法,请告诉我:)

相关内容

最新更新