How are: Java, NDK, JNI, JVM, C/C++ code etc. related to each other in an android project?
I want to know what happens e.g. Java code runs NDK method, NDK uses JNI library or whatever happens. Also what is the difference between NDK and JNI
Sorry if this question is poorly worded i'm just having difficulties how NDK is implemented in an Android project
JNI is just the way that Java handles calling into native/C++ code, and calling back into Java from there. It has nothing to say about Android - it is a Java language feature. The Android NDK is a way to write Android applications using code called by JNI.
The Native Development Kit (NDK) is a set of tools that allows you to use C and C++ code with Android, and provides platform libraries you can use to manage native activities and access physical device components, such as sensors and touch input.
JNI is the Java Native Interface. It defines a way for the bytecode that Android compiles from managed code (written in the Java or Kotlin programming languages) to interact with native code (written in C/C++).
The NDK is used to compile C/C++/asm code into binaries. You can do a lot of things with the NDK, like compiling executables, static prebuilts... but in the end, in the context of an Android application, you obtain one or more .so files (shared object libraries).
From Java, you can load such .so files and map functions that are implemented inside them. There is a specific case where an Android application project contains only C/C++ code (see native-activity sample from the NDK), but this is still the same principle: .so files are loaded inside ART or Dalvik context.
Anything in an Android application is executed in the context of the Dalvik Virtual Machine or ART. And in order to integrate your C/C++ code with this environment, you use the JNI (Java Native Interface).
You use the JNI first from the JNI mechanism: when you load a .so file, its JNI_OnLoad() function is called if it exists and functions starting with Java_ are mapped to the corresponding Java methods. These methods are to be declared in Java classes and have the keyword native to specify that their implementation comes from a .so file. A .so file is loaded using System.loadLibrary(), usually from the static block of the Java class that have the methods declared as native.
At runtime, when the Java execution reaches a method with its implementation being native, ie. inside a .so file, and that .so file has been loaded, this native implementation is directly executed. When it returns, the Java code execution continues.
The JNI also gives you jni.h header, that gives you the methods to access the Java environment (JavaVM*, JNIEnv*) so you can manipulate, create and access Java primitives (jint, jlong...), objects (jobject, jclass..), exceptions (jthrowable), etc.
To be properly packaged, installed and loaded using System.loadLibrary, your .so files have to be put at specific places:
libs/CPU_ABI inside an eclipse project
jniLibs/CPU_ABI inside an Android Studio project
jni/CPU_ABI inside an AAR
When an application is packaged as an APK, libs are inside its lib/CPU_ABI folders.
During its installation, the libs for the target platform are installed into nativeLibraryPath on a <5.0 device, and inside the app's legacyNativeLibraryDir/CPU_ARCH on a >=5.0 device.
Where CPU_ABI is any of: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips, mips64. Depending on which architectures you're targeting and your libs have been compiled for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With