Accessing hardware with Android NDK - 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.

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.

How does Java JNI interact with Kotlin/Native to find object values?

From JetBrains site :
Kotlin/Native is a technology for compiling Kotlin to native binaries that run without any VM.
But how does Kotlin interact with JNI , in my knowledge if a C/C++ program using JNI wants to access a java field it has to use the GetFieldID function, but the C program needs information from the JVM describing the object and its value.
How does kotlin/Native resolve the value of fields, if Kotlin makes programs that doesn't depend on the VM how can it get the value of Java fields?
What is Kotlin native
Kotlin/Native does not do the same thing as JNI, the site describes Kotlin/Native like this...
Kotlin/Native is a technology for compiling Kotlin to native binaries that run without any VM. It comprises a LLVM-based backend for the Kotlin compiler and a native implementation of the Kotlin runtime library. Kotlin/Native is primarily designed to allow compilation for platforms where virtual machines are not desirable or possible (such as iOS, embedded targets), or where a developer needs to produce a reasonably-sized self-contained program that does not require an additional runtime.
[Source]
JNI lets Java code talk to native code, whereas Kotlin/Native allows you to compile Kotlin code into a native executable that does not require a JVM to run.

C++ Cross Platform Library (iOS and Android) using math.h

I am using VS2015 RC and the cross platform C++ Shared Library Template. Under the .Shared code I added a simple point class. When it created the class, in the .cpp it included pch.h or a pre-compiled header that is only available in .android and not .ios. That threw an error, so I just removed that so I didn't get errors and figured I could include my STL items as needed. Hopefully that is the correct route for that.
Anyway my main issue is
In the Point.cpp file I need to use sqrt so I need to include math.h:
#include <math.h>
I have tried including it several different ways (cmath...), but no matter what I get the error myprojectname.iOS: Error: cannot open source file "math.h".
According to the setting sin the project properties for .iOS Use STL is LLVM C== standard library with C++11 support (libc++).
I am not sure how to add the correct include directory for iOS this is the first time I've written a cross platform library and done any iOS development.
From what I've read all the STL classes are available on both platforms. Any help with any of it would be great. Too bad there isn't a full tutorial on making a simple math library that you then use in an Android and ios app.

JNI code in linux shared lib

I have a c++ library ported to linux.
Now I'm adding a JNI code so I can add a java wrapper.
The question is:
Is adding JNI to the same lib will effect the c++ application of the users --> So might it become not working if java not installed ... etc (Because it links to some code in jni.h and other stuff)?
It won't affect the current library if you add JNI to your library. JNI are a collection of interfaces and callback that make your library can be used by JVM. Without JNI, your library can't be used from JVM.
Your library will grow up in size and more symbols be exported when you add JNI.
By adding JNI to your current library, it means your library can be used as a normal library meanwhile can be loaded from JVM.
You may wish to consider creating a JNI wrapper in C/C++ and statically link to your current library. That way your currently library will still work for C/C++ apps and your code will be easier to debug and maintain. If you choose this route, you may also want to look into enabling link-time optimization for your JNI wrapper. Alternatively you could also dynamically link the JNI wrapper and just put both libraries in /lib (or where ever is appropriate), but you will have a runtime dependency on that base library.

Resources