Which (if any) NDK libraries/headers are compatible with other toolchains - android-ndk

I'm working on a project that is compiled using the arm-linux-musleabi toolchain which builds against musl libc. What are my options to use NDK features such as Android jni.h? Am I wrong when assuming that jni.h on Android NDK is not the same as standard jni.h that targets actual Java? I know porting the project to NDK could be the best approach, but let's assume that its not possible for my case. In other words, 'build using NDK' is not an option even though it would be the wiser path. Also note that JNI features are just used as an example, this question applies to any Android NDK c/c++ libraries that may be used as a drop in with non-ndk toolchains.

Related

Possible to use a static library built from a different Android NDK?

The Android app I am working on is completely written in C++. I need to integrate it with a static library that also is written in C++. There is no dependency on STL in any of the projects.
The static library uses cmake to build. Unfortunately, the app is based on an old AOSP version of Android NDK and has no support for cmake.
I also have a newer version of Android NDK in a different directory. This version does support cmake toolchains.
I am thinking I will build the static library against the new NDK and use it in my main project. The ABI is the same for both the projects - armv7a.
I have tested this logic with a sample code. It seems to work. I am able to invoke methods in the static library from my main app.
Also, there are no name-mangling issues.
The question I have is if there is any issue I am overlooking.
I am thinking it should not matter that the compilers used to build the sources are different. As long as they are producing arm-compatible code, I should be able to able to integrate them.
As a matter of fact, another library that I am using, gstreamer, is available for download as pre-built binaries at https://gstreamer.freedesktop.org/data/pkg/android.
Please advice.
For those interested, mixing NDKs doesn't seem to be an issue as long as you follow certain guidelines. Some of them are listed at https://developer.android.com/ndk/guides/cpp-support.
Essentially, there is no problem if your project is 'C' based. However, if you are using C++, you must not use STL.
I have managed to build part of my code with two NDKs and I am not seeing any link time or runtime errors.

Shared library bundled in the apk is not found at runtime

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.

Feature compliance across different OS versions for the Android NDK

Are NDK features OS dependent? For example, if I have Gingerbread 2.3, can I only use NDK features for 2.3 and below, or can I take advantage of the latest fixes and features the NDK provides?
The main reason I'm asking is because it seems like the NDK is a completely different beast than the SDK, and due to the nature of C/C++ and the underlying internals of the OS should be cross version compatible.
Unfortunately it is as version-dependent as SDK. Each release of NDK bundles an ever-growing list of platforms. Typically, ndk-build chooses the platform according to android:targetSdkVersion as defined in AndroidManifest.XML.

Accessing hardware with Android NDK

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.

android ndk: cannot find android_runtime

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.

Resources