Android Ndk: Dlopen Failed

Android NDK: dlopen failed

libsharedlibrary.so is missing its SONAME entry. You probably currently see something like the following:

$ readelf -dW libnative.so | grep NEEDED | grep libsharedlibrary
0x0000000000000001 (NEEDED) Shared library: [./obj/local/armeabi-v7a/libsharedlibrary.so]

Note that if you don't have readelf on your system it is provided in the NDK as $NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-readelf (adjust the path as necessary for your OS). Note that the architecture here doesn't actually matter. readelf is a multi-arch tool. Any toolchain's readelf will work fine.

What you should see if libsharedlibrary.so was built with SONAME is:

$ readelf -dW libnative.so | grep NEEDED | grep libsharedlibrary
0x0000000000000001 (NEEDED) Shared library: [libsharedlibrary.so]

You should see the following on libsharedlibrary.so:

$ readelf -dW libsharedlibrary.so | grep SONAME
0x000000000000000e (SONAME) Library soname: [libsharedlibrary.so]

The problem is that libsharedlibrary.so was not built with the -Wl,-soname,libsharedlibrary.so ldflag. ndk-build and CMake will do that for you, but if you're using a standalone toolchain or a custom build system then you need to provide it yourself.

Android cash : UnsatisfiedLinkError: dlopen failed: cannot locate symbol pthread_cond_clockwait

That API is only available on API 30+ devices (note the __INTRODUCED_IN(30)):

int pthread_cond_clockwait(pthread_cond_t* __cond,
pthread_mutex_t* __mutex,
clockid_t __clock,
const struct timespec* __timeout) __INTRODUCED_IN(30);

You're probably seeing the problem on an older device.

As per the Android documentation, it is important to realize that the NDK API level is your app's minimum supported API level:

The API level you build against with the NDK has a very different meaning than compileSdkVersion does for Java. The NDK API level is your app's minimum supported API level. In ndk-build, this is your APP_PLATFORM setting. With CMake, this is -DANDROID_PLATFORM.

So you need to compile the library with the correct NDK API level:

Problem: Your NDK API level is higher than the API supported by your device.

Solution: Set your NDK API level (APP_PLATFORM) to the minimum version of Android your app supports.

dlopen fails on older Android versions

Prior to Lollipop, you must supply the full path to dlopen(). This path can be obtained in Java with getApplicationInfo().nativeLibraryDir.

At any rate, you can check the contents of the /data/data/your.package/lib directory (sometimes it has -1 suffix, or starts with /data/app-lib). This directory is world-readable, so you you should see the file libmylib.so there from Android Studio or adb shell.

Another reason for the observed behavior could be that the older device does not support armeabi-v7a ABI. That's easy to check with adb shell getprop.

Also, make sure that the library is built with the correct APP_PLATFORM, which should match the minSdkVersion.

Your library luckily does not have 'private' dependencies. But for those that do, you need to take this into account, too. Prior to Lollipop, these dependencies would not be loaded automatically (because the nativeLibraryDir was not scanned for dlopen). You had to load all libraries in reverse dependency order.

Link external shared library android ndk

I found the answer there:
Using a prebuilt shared Library in Android Studio (cmake) thanks to @Michael

I changed the INSTSONAME while compiling python to discard the versioned part of the library (libpython3.8.so.1.0 -> libpython3.8.so). Doing so also discarded the SONAME.
Using patchelf I was able to add SONAME and the library is found.

java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol _ZNSt6__ndk17codecvtIcc9mbstate_tE2idE

The symbol _ZNSt6__ndk17codecvtIcc9mbstate_tE2idE (which means std::__ndk1::codecvt::id) is available in libc++_shared.so.

If your runtime environment (emulator) is lower than API 21, you must explicitly load this library from Java, before you load libtest.so.

libc++_shared.so should also be packed into the APK together with libtest.so. Make sure that it is present in libs/x86 and also for other relevant ABIs.

In Android Studio, you can let gradle build the NDK libraries for you, and it will take care of the necessary dependencies.



Related Topics



Leave a reply



Submit