Since Android 7.0 it's not possible anymore to link against a non-ndk shared library (see NDK Apps Linking to Platform Libraries).
One possible workaround consists in including the library in the apk (See Update your app).
The library that you are trying to link against may depend on other non-ndk libraries. In that case you should include those libraries too.
In my case I've been developing an application which makes use of OpenCL. On ARM devices the library with the correct symbols is libGLES_mali.so. The application works fine on devices with Android < 7.0 but it crashes on devices with Android >= 7.0. The error that I can read in logcat is:
java.lang.UnsatisfiedLinkError: dlopen failed: library "android.hardware.graphics.common@1.0.so" not found
Using the command
readelf -d libGLES_mali.so | grep NEEDED
I can read the name of the libraries libGLES_mali.so depend on and predictably android.hardware.graphics.common@1.0.so is among them:
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]
I've tried including the aforementioned library in the apk but I get the same error. The weird thing is that the library is part of the VNDK-SP (see SP-HAL) and as such it is my understanding that private libraries may depend on it freely.
Any suggestion?
EDIT 31/01/2019: Tested devices running on Android >= 7.0 were all Huawei. Could it possibly be a vendor related problem?
Alex Cohn comment was right. In order to solve the problem I did the following:
1) Renamed android.hardware.graphics.common@1.0.so in libfoo.so
2) Added libfoo.so in CMakeLists.txt like this:
add_library( foo
SHARED
IMPORTED )
set_target_properties( foo
PROPERTIES IMPORTED_LOCATION
${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libfoo.so )
3) Target-linked MyLibrary, which contains the OpenCL calls, against libfoo.so (and, of course, libGLES_mali.so)
target_link_libraries (MyLibrary GLES_mali foo)
4) Loaded libfoo.so as soon as possible. To do so I created a static method in my MainActivity which I call as soon as the application enters onCreate().
private static void loadLibrary() {
System.loadLibrary("foo");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
loadLibrary();
...
}
At this point the application crashes complaining that it couldn't find some libraries. Using the readelf command:
./readelf -d /Users/rodolforocco/AndroidProjects/OvermindClient/app/libs/arm64-v8a/android-27/libfoo.so | grep NEEDED
I was able to see that these were indeed the libraries that libfoo.so depended on. These libraries also depended on other libraries that could not be located. I copied them all from the folder /system/lib64/ in my device to the folder ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/, where libfoo.so was.
5) Finally, as before, I loaded MyLibrary when I needed it.
The application doesn't crash anymore and works as intended. Thanks a lot!