Learn about JNI in Android (four) Simple example, warm and understanding new

Source: Internet
Author: User

In the 0th article simply introduced the JNI programming pattern, in the next two or three articles, we have made some simple introduction to some of the concepts of JNI, do not know what I said clearly no, but I believe a lot of children heel me, in the beginning to learn a thing, The best way to get started is to use a ready-made example for reference, study slowly, then learn the concepts, and then come back to study the code, deepen the impression, and begin to grasp it slowly.

Today we will do a little demo, this example will be slightly more complicated than before, but if you read the previous articles, it is still very simple to understand. Many things are like this, unknown time is very scary, understanding is very simple.

1) We first define a Java class that contains several native methods, as follows:

public class Paramtransfertest {public static int testval = 1;public native void Changetestval ();p ublic native int add (int x, int y);p ublic native string AddTail (string tail);p ublic native int[] Changearray (int[] arr);}

2) Use the Javah tool to generate the corresponding header file as follows:

/* Don't EDIT this file-it are machine generated */#include <jni.h>/* Header for class Com_lms_jni_paramtransferte St */#ifndef _included_com_lms_jni_paramtransfertest#define _included_com_lms_jni_paramtransfertest#ifdef __ Cplusplusextern "C" {#endif/* * class:com_lms_jni_paramtransfertest * method:changetestval * Signature: () V */jni EXPORT void Jnicall java_com_lms_jni_paramtransfertest_changetestval (jnienv *, jobject); */* Class:com_lms_jni_para  Mtransfertest * Method:add * Signature: (II) I */jniexport jint jnicall java_com_lms_jni_paramtransfertest_add (JNIENV *, Jobject, Jint, jint);/* * class:com_lms_jni_paramtransfertest * method:addtail * Signature: (Ljava/lang/strin g;) ljava/lang/string; */jniexport jstring jnicall java_com_lms_jni_paramtransfertest_addtail (jnienv *, Jobject, jstring);/* * class:com_l Ms_jni_paramtransfertest * Method:changearray * Signature: ([i) [i */jniexport Jintarray jnicall java_com_lms_jni_param Transfertest_chaNgearray (JNIEnv *, Jobject, jintarray); #ifdef __cplusplus} #endif #endif 

The corresponding method is generated above, we can see the previous article described the method name in Java beginning, method signature and so on, right.

3) write the C file as follows:

#include <stdio.h> #include <stdlib.h> #include "com_lms_jni_paramtransfertest.h" #include <android/ log.h> #include <jni.h> #include <malloc.h> #define LOG_TAG "System.out" #define LOGD (...) __android_log_ Print (Android_log_debug, Log_tag, __va_args__) #define Logi (...) __android_log_print (Android_log_info, Log_tag, __VA_ args__) char* jstring2cstr (jnienv * env, jstring str) {char * Rtn = Null;jclass clsstring = (*env)->findclass (env, "java/ Lang/string "),//Findclass method to obtain Java String class jstring Strencode = (*env)->newstringutf (env," UTF-8 ");// Call the Newstringutf method, get the "UTF-8" string, as encoded jmethodid mid = (*env)->getmethodid (env, clsstring, "GetBytes", "(ljava/lang/ string;) [B];//Get the GetBytes method of the String class Jbytearray Barr = (Jbytearray) (*env)->callobjectmethod (env, str, MID, Strencode);//Call the GetBytes method of the String class jsize Alen = (*env)->getarraylength (env, Barr);//Get array length jbyte* BA = (*env) Getbytearrayelements (env, Barr, Jni_false);//Gets the first address of the array, and the first element of the array in C + + is a pointer if (Alen > 0) {RTN = (char*) malloc (alen + 1); memcpy (RTN, BA, Alen); Rtn[alen] = 0;} The above step is to copy the values of the array into an array of char*, which is the char array for C/s + +, because C + + has no string concept and ends with 0. (*env)->releasebytearrayelements (env, Barr, BA, 0);//release memory return RTN;} /* * Class:com_lms_jni_paramtransfertest * method:changetestval * Signature: () V */jniexport void Jnicall Java_co M_lms_jni_paramtransfertest_changetestval (JNIENV * env, Jobject obj) {jclass clazz = (*env)->getobjectclass (env,obj )///obtain the corresponding class of obj, i.e. paramtransfertestjint val = (*env)->getstaticintfield (env, Clazz, (*env)->getstaticfieldid ( Env, Clazz, "TestVal", "I"));//Gets the value of the field TestVal Logi ("before change testval =%d", val);//Add log information val = val + 1; Logi ("After change testval =%d", val);(*env)->setstaticintfield (env, Clazz, (*env)->getstaticfieldid (env, Clazz , "TestVal", "I"), Val);//Set the value of the field testval}/* * class:com_lms_jni_paramtransfertest * method:add * Signature: (II) I */j Niexport jint jnicall java_com_lms_jni_paramtransfertest_add (jnienv * env, Jobject obj, Jint x, JintY) {Logi ("x =%d", x);       Logi ("y =%d", y); return x + y; return parameters x and y and}/* * class:com_lms_jni_paramtransfertest * method:addtail * Signature: (ljava/lang/string;) Ljava/lang /string;  */jniexport jstring jnicall java_com_lms_jni_paramtransfertest_addtail (jnienv * env, jobject obj, jstring str) {char* p = Jstring2cstr (ENV,STR);//Converts a string in Java into a char array logi ("str =%s", p) in C/A + +, char* newstr = "Tail"; return (*ENV) Newstringutf (env, strcat (P, newstr));//Call the STRCAT function to concatenate two char arrays, which will be returned through NEWSTRINGUTF. }/* * class:com_lms_jni_paramtransfertest * Method:changearray * Signature: ([i) [I */jniexport Jintarray JNICALL Java_com_lms_jni_paramtransfertest_changearray (JNIENV * env, jobject obj, Jintarray ja) {int len = (*env)->getarrayle Ngth (env, JA);/gets the array length logi ("Len =%d", Len); Logi ("address =% #x", &ja); jint* arr = (*env)->getintarrayelements (env, JA, 0);//Save all elements in the array to jint* In an array of the first address (array name) int i = 0;for (; i < Len; i++) {Logi ("arr[%d] =%d", I, * (arr + i)); * (arr + i) + =10;} The value of each element in the array plus 10return ja; Since the last parameter of getintarrayelements is 0, that means that the obtained array is not copied, that is, they manipulate the same piece of memory, so the returned array is ok return ja;


Corresponding to these four methods, in the above are added some comments, we look at the comments, their own study of logic, it is clear how these several methods to achieve the function is very simple.

4) write the Android.mk file as follows:

Local_path: = $ (call My-dir) include $ (clear_vars) Local_module: = com_lms_jni_hwdemolocal_src_files: = hwdemo.c jnitest.c Paramtransfertest.clocal_ldlibs + =-lloginclude $ (build_shared_library)

One thing to note here is that when compiling multiple files, the backslash "\" is used to break lines and differentiate between C/s + + files.

And here Local_ldlibs is the dynamic package that the JNI uses log to add, the next article will say.

5) After writing the android.mk file, compile with the Ndk-build file, the file structure is as follows:



Run Ndk-build under the JNI directory, as follows:


Here, the implementation of the JNI layer is a matter, the following is the Java side of things.

6) Call in activity, as follows:

public class Hwdemo extends Activity {static {system.loadlibrary ("Com_lms_jni_hwdemo");//Load Dynamic package, The name is the module name in Android.mk. }public native String Printhello (), @Overridepublic void OnCreate (Bundle savedinstancestate) {super.oncreate ( Savedinstancestate); Setcontentview (R.layout.main); TextView Tvadd = (TextView) Findviewbyid (R.id.tvadd); TextView tvstring = (TextView) Findviewbyid (r.id.tvstring); TextView Tvarray = (TextView) Findviewbyid (R.id.tvarray); TextView tvchangetestval = (TextView) Findviewbyid (r.id.tvchangetestval); Paramtransfertest PTT = new Paramtransfertest ();//Call Changetestva () method Ptt.changetestval (); Tvchangetestval.settext ("" + ptt.testval);//Call the Add method int sum = Ptt.add (1, 2); Tvadd.settext (string.valueof (sum));//Call AddTail method Tvstring.settext ( Ptt.addtail ("LMS"));//Call Changearray method int[] NewArr = Ptt.changearray (New int[]{1,2}); StringBuilder sb = new StringBuilder (); Sb.append ("["); Sb.append (Newarr[0]). Append (","). Append (Newarr[1]); sb.append ("]"); Tvarray.settext (sb.tostring ());}}

7) The results show:

If you call the Jni method at the Java layer, there is a method that calls Java in the JNI layer, and manipulate the Java object, I believe that after this example, combined with the previous articles, we should be able to have a relatively basic understanding of the role and application of JNI.

The implementation of the underlying framework in Android, especially when booting, native layer to load a system core service, or start zygote virtual machine, use a large number of JNI level framework, if you are familiar with the JNI understanding, and then to understand these framework things, It's going to be a big help.

End.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.