In some cases, java programming cannot meet our needs. For example, a complicated algorithm processing requires jni technology;
- Jni: java native interface
- Jni is actually an interface specification for communication between java and c/cpp. java can call functions in c/cpp. Similarly, c/cpp can also call java class methods;
Install jni development tool ndk:
In the latest ndk version, it is easy to install ndk. You only need to install the ndk path and configure it to the system environment variable;
During compilation, enter the project root directory and execute the commandNdk-buildCompilation can be completed;
1. cpp and java
> 1. java file: TextOutput. java
package com.jnitest;import android.util.Log;public class TextOutput { private native String init(); static { System.loadLibrary("text"); } public String getString() { return init(); } public void sayHello() { Log.e("tag", "void sayHello"); } public String sayHello_() { Log.e("tag", "string sayHello_"); return "return string sayHello_"; } public static void sayHello__() { Log.e("tag", "static sayHello__"); }}
In this class, a local method init [native init] is defined. The method implementation is implemented by the next cpp function. Other methods are defined and called by the cpp file;
> 2. cpp file: test. cpp
# Include <jni. h> # include <android/log. h> # include <string. h> # ifndef _ Included_com_jnitest_TextOutput # define _ Included_com_jnitest_TextOutput # ifdef _ cplusplusextern "C" {# endifJNIEXPORT jstring JNICALLJava_com_jnitest_TextOutput_init(JNIEnv *, jobject); # ifdef _ cplusplus} JNIEXPORT jstring JNICALL Java_com_jnitest_TextOutput_init (JNIEnv * env, jobject obj) {jmethodID mid; // method id jclass cls = env-> GetObjectClass (obj); // class object instance mid = env-> GetMethodID (cls, "sayHello ","() V "); env-> CallVoidMethod (obj, mid); jmethodID mid1; mid1 = env-> GetMethodID (cls," sayHello _ "," () Ljava/lang/String; "); // @ 1 jstring s1 = (jstring) env-> CallObjectMethod (obj, mid1); // @ 2 jmethodID mid2; mid2 = env-> GetStaticMethodID (cls, "sayHello _", "() V"); env-> CallStaticVoidMethod (cls, mid2); return s1 ;}# endif # endif
The name of the function defined in cpp is Java_com_jnitest_TextOutput_init.
As a matter of fact, it is not difficult to see that the matching and definition methods between the java file and the cpp file are Java + package name + java class name + method/function name, separated; the two parameters are:
- Env: the content of the current thread, including all content in the thread;
- Obj: the instance of the current class, which refers to the content of the. java file (in this example, it is the TextOutput class );
@ 1: Obtain MethodId. This method requires three parameters: object instances of the jclass class, function names, and function signatures. The function signature consists of two parts (parameters + function return values );
To view the signature, first go to the class file directory generated by the java file and run the following command:Javap-s-p ClassName
Generate the function signature as shown in;
@ 2: execute this method. In the preceding example, the sayHello _ method is executed.
Run the program:
TextOutput to = new TextOutput();Log.e("tag", "" + to.getString());
II. c and java
There is an int field in the Activity, which is assigned a value through callback.
package com.example.hellojni;import android.app.Activity;import android.util.Log;import android.widget.TextView;import android.os.Bundle;public class HelloJni extends Activity { private static int si; private static void callback() { si = 123; } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText(stringFromJNI()); setContentView(tv); Log.e("tag", "si=" + si); } public native String stringFromJNI(); static { System.loadLibrary("hello-jni"); }}
Hello-jni.c
# Include <string. h> # include <jni. h>/***/jstring Merge (JNIEnv * env, jobject thiz) // env: the content of the current thread, including all things of the thread; thiz: the instance of the current class,. java file content {jint si; jfieldID fid; // a field that actually corresponds to a field or attribute in the java class; jclass cls = (* env)-> GetObjectClass (env, thiz); // class object instance jmethodID mid = (* env)-> GetStaticMethodID (env, cls, "callback", "() V "); // id of a method // (I) V (I) I if (mid = NULL) {return (* env)-> NewStringUTF (env, "mid = null") ;}( * env)-> CallStaticVoidMethod (env, cls, mid); // call the callback method fid = (* env)-> GetStaticFieldID (env, cls, "si", "I"); // retrieve the si field if (fid = NULL) {return (* env)-> NewStringUTF (env, "fid = null");} si = (* env)-> GetStaticIntField (env, cls, fid); // retrieve the value corresponding to the field (value corresponding to the fid field) return (* env)-> NewStringUTF (env, "init success ");}
Run the preceding Activity to assign values to si.
3. Join the Linked Library
Debugging is frequently used in the process of program development. There are many debugging methods. The following describes how to print the status values of a program running through log printing;
Modify the Android. mk file and add a code
Include $ (CLEAR_VARS) LOCAL_LDLIBS + =-llog // LDLIBS: connect to libs. The following parameters are the libs to be linked.-llog indicates the Log library in Android; include $ (BUILD_SHARED_LIBRARY)
After the logstore is added
You can call log in the c file to print the output information:
__android_log_print(ANDROID_LOG_ERROR, "hello", "livingstone"); __android_log_print(ANDROID_LOG_DEBUG, "hello", "livingstone %d" ,23);