JNI is the abbreviation of Java Native Interface. It allows Java code to interact with code written in other languages. JNI is provided in Android to allow Java programs to call C language programs. Many Java classes in Android have native interfaces, which are implemented locally and then registered to the system.
The main JNI code is stored in the following path: Frameworks/base/CORE/JNI/. The content in this path is compiled into the library libandroid_runtime.so, which is a common dynamic library, stored in the/system/lib directory of the target system. In addition, Android has other JNI libraries. Each file in JNI is actually a common C ++ source file. The JNI library implemented in Android needs to be connected to the dynamic library libnativehelper. So.
1. Implementation of JNI
To implement JNI, you must declare in the Java source code, implement various JNI methods in the C ++ code, and register these methods into the system. The core of JNI implementation is the jninativemethod struct.
Typedef struct {
Const char * Name;
Const char * signature;
Void * fnptr;
} Jninativemethod;
The first variable name is the name of the JNI function in Java, the second variable signature describes the function parameters and return values using strings, and the third variable fnptr is the c pointer of the JNI function.
In Java code, when the defined function is implemented by JNI, you must specify the function as native.
2. Use JNI in the application, which can be analyzed by/development/samples/simplejni in the Code:
A. Analyze the top-level Android. mk File
Local_package_name: = simplejni // generate the package name, in the out/target/product/smdk6410/obj/apps
Local_jni_shared_libraries: = libsimplejni // generate the name of the JNI shared library, in... smdk6410/obj/shared_libraries
Include $ (build_package) // compile by generating an APK
Include $ (call all-makefiles-under, $ (local_path) // call the lower-layer makefile
B. Analyze the Android. mk file in the JNI directory
Local_src_files: = // C ++ source file of JNI
Native. cpp
Include $ (build_shared_library) // compile as a shared library
3. JNI code implementation and calling
A, native. cpp content
Static jint add (jnienv * ENV, jobject thiz, jint A, jint B) {}// define the Java method add
Static const char * classpathname = "com/example/Android/simplejni/native"; // target Java class path
Static jninativemethod methods [] = {// list of local implementation methods
{"Add", "(ii) I", (void *) add },
};
Static int registernativemethods (jnienv * ENV, const char * classname,
Jninativemethod * gmethods, int nummethods) {}// register a local JNI function for a called Java class
Static int registernatives (jnienv * env) {}// register all classes and JNI functions for the current platform
Jint jni_onload (JavaVM * Vm, void * Reserved) // register a local JNI for the current Virtual Machine Platform
The preceding three commands are called from bottom to top.
B. simplejni. Java content
Package com. example. Android. simplejni; // Java package, which corresponds to the file path
Import Android. App. activity;
Import Android. OS. Bundle;
Import Android. widget. textview; // the class to be included to call the Function
Public class simplejni extends activity {
/** Called when the activity is first created .*/
@ Override
Public void oncreate (bundle savedinstancestate ){
Super. oncreate (savedinstancestate );
Textview TV = new textview (this );
Int sum = native. Add (2, 3); // call the native class function add, which is the JNI function, implemented by CPP
TV. settext ("2 + 3 =" + integer. tostring (SUM ));
Setcontentview (TV); // displayed on the screen
}
}
Class native {
Static {
// The runtime will add "lib" on the front and ". O" on the end
// The name supplied to loadlibrary.
System. loadlibrary ("simplejni"); // load the dynamic library generated by native. cpp. The full name is lib + simplejni +. o
}
Static native int add (int A, int B); // declare the JNI function add implemented in the dynamic library for Java to call
}
Compile and generate a package, install it on the mid, and run the package 2 + 3 = 5.
JNI is a Java Native Interface.
The Java Native Interface (JNI) standard has become part of the Java platform,
It allows Java code to interact with code written in other languages.
JNI is a local programming interface. It enables Java code running inside the Java Virtual Machine (VM)
It can interoperate with applications and libraries written in other programming languages (such as C, C ++, and assembly languages.
The following is a test JNI code in the android environment.
1.
// Testnativeapi. Java
// Native program, which is compiled into a jar package and called by upper-layer Java applications.
// Call Android system. loadlibrary () in the static function to call the. So library,
// Loadlibrary () determines the type of the. So library. If it is a JNI library, the jni_onload () function in the. So library is called to register JNI interface.
Package com. Me. test;
Import Android. util. log;
Public final class testnativeapi {
Static {
Try {
System. loadlibrary ("itest_jni ");
} Catch (unsatisfiedlinkerror e ){
Log. D ("itest_jni", "itest JNI library not found! ");
}
}
/**
* This class is uninstantiable.
*/
Private testnativeapi (){
// This space intentionally left blank.
}
Public native static int apifunction ();
}
// Android. mk for testnativeapi. Java
// Use the build_java_library function to compile it into a jar.
# Build com. Me. Test. Jar
#===================================================== ==================================
Test_dirs: =/
./Test/Java/COM/ME/test
Test_src_files: = $ (call all-Java-files-under, $ (cm_dirs ))
#===== The library ============================================== ==========
Include $ (clear_vars)
Local_src_files: = $ (test_src_files)
Local_no_standard_libraries: = true
Local_java_libraries: = core framework
Local_module: = com. Me. Test
Include $ (build_java_library)
2.
// Testinternalapi. cpp
// JNI interface class, jni_onload () function called when. So is loaded
// The JNI interface function can call the underlying C ++/C function control hardware.
# Define log_tag "itest_jni"
# Include <utils/Misc. h>
# Include <utils/log. h>
# Include "JNI. H"
# Include "jnihelp. H"
# Include "android_runtime/androidruntime. H"
# Include "scm_dbus_utils.h"
# Define internalapi_pkg_name "com/ME/test/testnativeapi"
Using namespace android;
Static jint test_testinterapi_func (jnienv * ENV, jobject clazz)
{
Jint ret = (jint) 0;
Logd ("Call/" % S/"", _ function __);
Return ret;
}
/*
* JNI registration.
*/
Static jninativemethod gtestinterapimethods [] = {
{"Apifunction", "() I", (void *) test_testinterapi_func}
};
Int register_com_me_test_testinternalapinative (jnienv * env)
{
Return androidruntime: registernativemethods (ENV, internalapi_pkg_name, gtestinterapimethods, nelem (gtestinterapimethods ));
}
Jint jni_onload (JavaVM * Vm, void * Reserved)
{
Jnienv * Env = NULL;
Jint result =-1;
Logd ("testinteralapi JNI loaded ");
If (Vm-> getenv (void **) & ENV, jni_version_1_4 )! = Jni_ OK ){
LogE ("getenv failed ");
Goto bail;
}
Assert (ENV! = NULL );
If (register_com_me_test_testinternalapinative (ENV) <0 ){
LogE ("testinternalapi native registration failed ");
Goto bail;
}
Result = jni_version_1_4;
Bail:
Return result;
}
// Android. mk for testinternalapi. cpp
// Use the build_shared_library function to compile it into. So.
Include $ (clear_vars)
Ifeq ($ (target_arch), arm)
Local_cflags + =-dpacked = "_ attribute _ (packed ))"
Else
Local_cflags + =-dpacked = ""
Endif
Local_src_files: =/
Testinternalapi. cpp
Local_c_includes + =/
$ (Jni_h_include)
Local_shared_libraries: =/
Libandroid_runtime/
Libnativehelper/
Libcutils/
Libutils/
Libdvm
Local_module: = libitest_jni
Include $ (build_shared_library)
Endif
Detailed description of the data structure jninativemethod used by Android JNI
Andoird uses a different traditional Java JNI method to define its native function. An important difference is that andorid uses a ing table array of Java and C functions, and describes the parameters and return values of the functions. The type of this array is jninativemethod, which is defined as follows:
Typedef struct {
Const char * Name;
Const char * signature;
Void * fnptr;
} Jninativemethod;
The first variable name is the name of the function in Java.
The second variable signature describes the parameters and return values of the function using a string.
The third variable fnptr is the function pointer pointing to the C function.
The second parameter is hard to understand, for example
"() V"
"(Ii) V"
"(Ljava/lang/string;) V"
In fact, these characters correspond to the function parameter types one by one.
The character in "()" represents a parameter, and the subsequent character represents the return value. For example, "() V" indicates void func ();
"(Ii) V" indicates void func (INT, INT );
The relationship between each character is as follows:
Character Java type C type
V void
Z jboolean Boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
The array starts with "[" and is represented by two characters.
[I jintarray int []
[F jfloatarray float []
[B jbytearray byte []
[C jchararray char []
[S jshortarray short []
[D jdoublearray double []
[J jlongarray long []
[Z jbooleanarray Boolean []
The above are all basic types. If the Java function parameter is a class, it starts with "L" and ends with ";" and ends with a package and class name separated. The parameter of the corresponding C function name is jobject. An exception is the string class, and its corresponding class is jstring.
Ljava/lang/string; string jstring
Ljava/NET/socket; socket jobject
If a Java function is located in an embedded class, $ is used as the delimiter between class names.
For example, "(ljava/lang/string; landroid/OS/fileutils $ filestatus;) z"
This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/zmg1005/archive/2010/01/18/5205961.aspx