Hi, can anyone suggest me some good resources to learn JNI for Android and some good JNI Tutorials?
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++). JNI is vendor-neutral, has support for loading code from dynamic shared libraries, and while cumbersome at times is reasonably efficient.
JNIEXPORT ensures function is visible in the symbols table. JNICALL ensures function uses the correct calling convention. On Android JNICALL has a different value based on architecture. ARM is empty which might trick you to not include it. But you must use JNICALL.
jobject NewGlobalRef(JNIEnv *env, jobject obj); Creates a new global reference to the object referred to by the obj argument. The obj argument may be a global or local reference.
Tutorial for ECLIPSE
Here is first and second small tutorials, but if you want to write a simple program that uses JNI , you may continue reading :)
Create Android application project , Once your project has been created, you’ll need to create a new folder inside the top level of the project. To do this right click on your project name → New → Folder. Name this folder jni. Than add class with name SquaredWrapper
. add these code in it
package org.edwards_research.demo.jni; public class SquaredWrapper { // Declare native method (and make it public to expose it directly) public static native int squared(int base); // Provide additional functionality, that "extends" the native method public static int to4(int base) { int sq = squared(base); return squared(sq); } // Load library static { System.loadLibrary("square"); } }
Open terminal. You must compile these code for getting header file. At first call this command.
cd src # change into the source directory javac -d /tmp/ org/edwards_research/demo/jni/SquaredWrapper.java
Than
cd /tmp javah -jni org.edwards_research.demo.jni.SquaredWrapper
SO you'll have header file named org.edwards_research.demo.jni.SquaredWrapper
in your tmp
directory.
it must be something like this
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class org_edwards_research_demo_jni_SquaredWrapper */ #ifndef _Included_org_edwards_research_demo_jni_SquaredWrapper #define _Included_org_edwards_research_demo_jni_SquaredWrapper #ifdef __cplusplus extern "C" { #endif /* * Class: org_edwards_research_demo_jni_SquaredWrapper * Method: squared * Signature: (I)I */ JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared (JNIEnv *, jclass, jint); #ifdef __cplusplus } #endif #endif
change these name for some short one for your comfort, for example square.h. Copy this header file in the jni folder of your app. Than create square.c file in same folder, copy this in it.
#include "square.h" JNIEXPORT jint JNICALL Java_com_example_android_1jni_1second_1demo_SquaredWrapper_squared (JNIEnv * je, jclass jc, jint base) { return (base*base); }
Add this in your MainActivity.java
int x = SquaredWrapper.to4(2); x = x*2;
Add Android.mk
file in jni
folder with this body
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := squared LOCAL_SRC_FILES := square.c include $(BUILD_SHARED_LIBRARY)
It must create library from header and cpp files.
So you have only to do some configurations by looking on my first link Now you can compile it , be sure that your library has created and your lib
directory consist it.
Tutorial for Android Studio
Let's consider you have simple android application opened by Android Studio
step 1: open Your application by Android Studio
step 2: Download NDK and set the path to NDK in local properties of your application(below/above of android sdk path) like this ndk.dir=C\:\\Android\\android-ndk-r10e
P.S. for windows double // , for linux one /
step3: Add JNI folder in the app (right click on the app -> new -> folder -> JNI Folder)
step 4 Set up the Gradle
by this way:
Add this code in app/build.gradle
for starting NDK
sourceSets.main { jni.srcDirs = [] jniLibs.srcDir 'src/main/libs' } tasks.withType(NdkCompile) { // disable automatic ndk-build call compileTask -> compileTask.enabled = false } task ndkBuild(type: Exec) { // call ndk-build(.cmd) script if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine 'cmd', '/c', 'ndk-build.cmd', '-C', file('src/main').absolutePath } else { commandLine 'ndk-build', '-C', file('src/main').absolutePath } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild }
step 4:
Create files Android.mk and Application.mk in JNI folder of the app with this bodies:
Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := main LOCAL_SRC_FILES := main.cpp include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all include $(BUILD_SHARED_LIBRARY)
In APP_ABI you choose which compilers to use. It
step 5:
We have to manually run NDK as we disable it from build.config
. For creating com_example_nativedemo_app_MainActivit.h
file in src\main\jn folder we have to run this command in terminal
javah -d .\jni -classpath C:\Intel\INDE\IDEintegration\android-sdk-windows\platforms\android-21\android.jar;..\..\build\intermediates\classes\debug com.example.mydemo.nativedemo.MainActivity
for windows cmd you have to give the full path of files. For
step 6:
Add file main.cpp in JNI folder with this body:
#include <string.h> #include <jni.h> #include <vchat_cpptest_Hellojnicpp.h> extern "C" { JNIEXPORT jstring JNICALL Java_vchat_cpptest_Hellojnicpp_stringFromJNI (JNIEnv *env, jobject obj) { #ifdef __INTEL_COMPILER_UPDATE return env->NewStringUTF("Hello from Intel C++ over JNI!"); #else return env->NewStringUTF("Hello from default C++ over JNI!"); #endif }
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