I am trying to import native libraries(.so files) into the android studio.
I created a jniLibs folder and directory with ABI name and respective .so files in it.
made changes in build.gradle and tried to load them.
Then, the error occurs of java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "pthread_cond_clockwait"
can someone give idea how to solve this issue?
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.
Related
I do some native Android development which involves OpenSSL.
I cross compile it for armeabi (32b) using the Android NDK stand-alone toolchains. I cross-compile the native C libraries, copy the OpenSSL/native library .so files inside of my libs/ folder, which is referenced by my gradle this way:
sourceSets {
main {
jniLibs.srcDir(file("libs/"))
}
}
Anyway, the end result is that my .apk looks like this:
- > classes.dex
- > lib/
-> armeabi/
-> libcrypto.so
-> libssl.so
-> libmynativelibrary.so
- > res/ (...)
- > resources.arsc
- > META-INF/ (...)
- > kotlin/ (...)
- > AndroidManifest.xml
The shared libraries are correct 32-bit ARM ELF files. I've been using this exact APK on an API level 24 device with great success (Android 7.0+).
The issue: When I switch to an API level 21 device (Android 5.1-, I suspect that I would have the same issue with Android 6.0), the program instantly crashes when loading libmynativelibrary.so.
Since libcrypto.so is a dependency of libmynativelibrary.so, the program attempts to load it. It actually works fine on API level 24+, but crashes on API level 23-. It's because the loaded library is not the one in my .apk, but the one in the system. And such libraries seem to not be available below API level 24.
My question: How do I explicitly tell Android to look for the library in the .apk file first instead of the regular system libraries directories?
Thanks in advance.
Before Nogut, the system libraries were not protected from user apps. The name collisions are problematic, they caused Google to invent a separate namespace for the C++ shared runtime library, which is part of Android NDK.
The OpenSSL libraries are also widely used beyond your control. They may get loaded into your process even before you have a chance to load your own libssl.
Therefore, the best choice would be to build OpenSSL as static libs, and have libmynativelibrary.so linked to it statically. This way you have a monolithic binary that does not depend on others.
If you cannot follow this course, you should build OpenSSL libraries with mangled names, e.g. libmyssl.so and libmycrypto.so. This may help to avoid the simple name clash with system libraries.
Even better, follow the example of NDK and provide a unique namespace to you SSL API.
Don't expect that loading the libraries explicitly from their unpacked location at ApplicationInfo.nativeLibraryDir will be a robust solution: as I hunted before, the system libraries may happen to get loaded into your address space before.
Note that before Lollipop, you have too manually load all non-system dependencies, and in the proper order.
Also, the new NDK has dropped armeabi , so consider switching to armeabi-v7a.
I have an Android Studio project to which I've added an ndk module. My ndk module builds and creates lots of different .so files in various build/intermediates directories. However, when I run the app it is unable to load the library .so from my System.loadLibrary call.
Java files that I include in the same module are found just fine so I was expecting Android Studio to 'find' the ndk files as well.
In looking at the google hello-libs demo I see that they have added a step in the CMakeLists.txt file to set the LIBRARY_OUTPUT_DIRECTORY:
set(distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../distribution)
set_target_properties(gperf
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY
"${distribution_DIR}/gperf/lib/${ANDROID_ABI}")
and then added an associated reference in app:build.gradle
jniLibs.srcDirs = ['../distribution/gperf/lib']
Adding similar entries to my project allowed it to run properly.
Is there a simpler way to cause an ndk compiled module to be included in the main application? If not, is there a way to do it without having to figure out all the relative ../../ path elements. I guess I was hoping the module CMakeLists.txt would be
the same configuration regardless of what other projects it might be included in but having to know where it's including project is located seems to break this.
How can I create and Android project that links to complete android source code, including classes in "android.annotation" ?
More precisely:
Create a new android project in Android Studio 1.5.1, Minimum SDK = API 23. Template: Add no activity.
Add this fix to resolve junit dependency: https://stackoverflow.com/a/32566057/4182868
gradle sync, make project
open class android.app.Activity
Result: a number of import statements are not resolved:
That's because those classes are actually marked as #hide, and are stripped out of the Android SDK at build time. The SDK android.jar that your project is linked with simply doesn't contain those methods and classes, which is why the IDE gets confused when it looks up the source code for the SDK classes.
(Note: We include the same annotations in the support library, but with a different package prefix: android.support.annotation.*. Those are the annotations applications should be using. But the framework itself doesn't depend on the support library, the dependency is in the other direction.)
I need to extend the functionality of the android.hardware.Camera class and so I have written my own class and companion JNI library to meet my needs. If I place my JNI code and Android.mk file in the Android source tree and build the OS, my library builds and I can use it and the Java class in an application without any problems (on an evaluation module at least).
The problem is that I would prefer to build my JNI library with the NDK but I need several libraries that are not in the NDK (e.g. libandroid_runtime and libcamera_client).
Is it possible to use the NDK to access hardware such as the camera? If so, what is the proper way to get access to OS libraries?
You can access non-standard shared libraries from NDK, but that is undocumented and is not guaranteed to work on different devices. Vendors like HTC, Samsung and other can simply implement them differently.
Only proper way how to use functionality not available in NDK is to wrap it with Java classe/functions, and then use them from native code.
I have a problem when compiling JNI. It returns the error message like
that "arm-eabi/bin/ld: cannot find -landroid_runtime".
I think libandroid_runtime.so is the android's own lib. Why ld can't find the
lib. Can somebody help me.
My develop environment as follow:
OS: Ubuntu 9.10
SDK: Android2.2
NDK: r4b
libandroid_runtime.so is in fact one of the Android system libraries, and as such is not available for NDK apps.
Check the file docs/STABLE-APIS.txt for a list of supported libraries, or even better, check the folder build/platforms/android-#/arch-arm/usr/lib where # is the Android platform level, for the definitive list of libraries you can link against.
As they say on the NDK lists, even if you manage to link against one of the other Android libraries, it likely won't work on some (or possibly even most) phones, even if it works on the one you're testing.
To solve your problem build a emulation of every android possible and recompile a version for each android and put it on the market with specific compatibility.
EDIT: Try using: adb pull /system/lib
EDIT 2: There also should be a egl folder in /lib so you know to look for it.