1 package com.test.androidjni;  2   3 import android.app.Activity;  4 import android.os.Bundle;  5 import android.util.Log;  6 import android.widget.TextView;  7   8   9 public class MainActivity extends Activity { 10     private static final String DEBUGTAG = "NATIVE"; 11     private String myString; 12     private static int si=0; 13     private static String helloString = "What's your name"; 14      15     //对基本数据类型的访问 16     private native String GetNativeString(String str);//访问字串 17     private native int SumArray(int [] ar, int length);//传一个数组的长度 18     private native int SumArrayA(int [] ar);//不传长度 19     private native int SumArray2D(int [][]ar2d);//传一个二维数组,返回一个长度     20     private native int [][] ModifyArray2d(int [][]ar2d);//传入一个二维数组,返回一个二维数组 21      22     //这一部分是对成员和方法的访问 23     private native void AccessField();//访问静态成员 24     private native void AccessMethod(); 25      26     private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh); 27      28     /** 29      * 对于加动.so库做一点说明 30      * System.loadLibrary 这个方法默认去system/lib去找这个.so库, 31      * 再到data/data/com.test.androidjin/lib/目录下找。本应数据存放的目录下 32      * 我们可以通过eclipse上的ddms去查看。前提是把调试的机器联上, 33      * 动态库的名称是:lib前缀+库名+.so后缀。此函数不要前缀,也不要后缀,只要包名,否则找不到 34      * 但是我们在这个apk的libs/armeabi/目录下要用libmyjni.so这个全名. 35      * 另外还有一个加载库的函数 36      * System.load 这个函数是传入全路径名.这样就可以到指定的路径加载了 37      * System.load(/system/lib/libXXX.so);注意访问目录的权限问题 ,这个与linux的目录访问权限一样的. 38      * 有时候我们在使用第三访.so库是,找不到库,但明明库已加打包进了。这里我们要看它的本地方法是在 39      * 那个java包下的那个类中声明的,比如这个apk的native方法是在 40      * com.test.androidjni包的MainActivity 这个类中声明的。生成的native函数都有 41      * Java_com_test_androidjni_MainActivity_这个前缀.我们可以根据第三访.so的函数接口的前缀 42      * 建立相应的包和类名,然后就可以正确加载了。这里与前面讲的找库的路径是刚好相互应证了。 43      *  44      */ 45     static{         46         System.loadLibrary("myjni");         47     } 48      49     @Override 50     protected void onCreate(Bundle savedInstanceState) { 51         super.onCreate(savedInstanceState); 52         setContentView(R.layout.activity_main); 53         //字符串操作     54         String retStr = GetNativeString("Please give me A String"); 55         Log.d(DEBUGTAG, retStr); 56         if(null != retStr){ 57             TextView t = (TextView)findViewById(R.id.nativeString); 58             t.setText(retStr); 59         } 60          61         //传入一维数组,累计和,并修改了第0,第1个数组元素的值 62         int arr[] =new int[]{1,2,3,4,5,6,7}; 63         Integer value = SumArrayA(arr);     64         TextView t = (TextView)findViewById(R.id.nativeArray); 65         t.setText(value.toString());         66         Log.d(DEBUGTAG, "arr[0] = "+ arr[0]+" arr[1]"+arr[1]); 67          68         //访问二维数组,累计和, 69         int arr2d[][] = {{1,1,5,5},{2,2,2,2,}};//new int[2][4]; 70         int sum = SumArray2D(arr2d);         71         Log.d(DEBUGTAG, "len = " + sum); 72          73         //访问二维数组,并返回一个二维数组,且修改了传入二维数组的元素 74         int arr2dA[][] = null; 75         int sumV = 0;         76         arr2dA = ModifyArray2d(arr2d); 77         for(int i=0;i<2;i++) 78         { 79             for(int j=0;j<4;j++) 80             { 81                 sumV += arr2dA[i][j];                 82             }             83         }     84         Log.d(DEBUGTAG, "sumV = " + sumV); 85          86          87         //c中访问java域和方法 88         this.myString = "Android Java String"; 89         this.AccessField(); 90         Log.d(DEBUGTAG, "after modify by native myString = " + myString); 91         Log.d(DEBUGTAG, "after modify by native si = " + si); 92         Log.d(DEBUGTAG, "after modify by native helloString = " + helloString); 93         //c中调用java中的方法 94         this.AccessMethod(); 95     } 96     private void callback(String strFromNative,int i,byte b,char c,boolean bl,long l,double d,float f,short sh){ 97         Log.d(DEBUGTAG,"CALL FROM NATIVE:"+strFromNative +i+b+c+bl+l+d+f+sh);         98     } 99     private  static String  callStaticBack(){100         return    "What's your name ";101     }102     103 }
MainActivity.java
  1 #include <string.h>  2 #include <jni.h>  3 #include "com_test_androidjni_MainActivity.h"  4 /*  5  *    @学习使用jni字串函数 JNIEnv 是一个结构体,下面列出的是这个结构体的部分函数指针,还有很多其他的  6  *  7  *     unicode16编码,字串符没有结束符'\0',  8  *     jstring     (*NewString)(JNIEnv*, const jchar*, jsize);//最后一个参数表示jchar* 内存长度  9  *    jsize       (*GetStringLength)(JNIEnv*, jstring); 10  *    const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); 11  *    void        (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); 12  *    void        (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*); 13  * 14  *    utf8编码,得到的字串是有结束符'\0'的 15  *    jstring     (*NewStringUTF)(JNIEnv*, const char*); 16  *    jsize       (*GetStringUTFLength)(JNIEnv*, jstring); 17  *    const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); 18  *    void        (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); 19  *    void        (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*); 20  * 21  *    获取直接指向jstring的地址,因此没有编码区别。这一对函数中,不能有阻塞操作 22  *    这对函数之间,不能有任何对jni的操作,因此这对函数,一般较少用。 23  *     const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*); 24  *    void        (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*); 25  * 26  */ 27 jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString( 28         JNIEnv *env, jobject obj, jstring str) { 29     const char * pStr; 30     const char* pUTF8Str = "From jni String"; 31     char outbuff[128] = { 0 }; 32  33     //获取传入字串中的所有字串 34     pStr = (*env)->GetStringUTFChars(env, str, NULL); 35     if (pStr == NULL) 36         return NULL; 37     strcat(outbuff, pStr); 38     (*env)->ReleaseStringUTFChars(env, str, pStr); //这里要释放,否则内存泄漏 39     strcat(outbuff, "/"); //加一个分隔符 40     //从传入字串第三个位置开始,获取4个,到字串尾 41     (*env)->GetStringUTFRegion(env, str, 3, 4, outbuff + strlen(outbuff)); 42     strcat(outbuff, "/");    //加一个分隔符 43     strcat(outbuff, pUTF8Str);    //联接一个本地字串 44     //从buff中构建一个jstring返回给java,这个新构建的字串由虚拟机负责回收 45     return (*env)->NewStringUTF(env, outbuff); 46 } 47 /** 48  *     访问基本数组类型 49  jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); 50  jbyteArray    (*NewByteArray)(JNIEnv*, jsize); 51  jcharArray    (*NewCharArray)(JNIEnv*, jsize); 52  jshortArray   (*NewShortArray)(JNIEnv*, jsize); 53  jintArray     (*NewIntArray)(JNIEnv*, jsize); 54  jlongArray    (*NewLongArray)(JNIEnv*, jsize); 55  jfloatArray   (*NewFloatArray)(JNIEnv*, jsize); 56  jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize); 57  58  jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); 59  jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); 60  jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); 61  jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); 62  jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); 63  jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); 64  jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); 65  jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*); 66  67  void        (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,jboolean*, jint); 68  void        (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray,jbyte*, jint); 69  void        (*ReleaseCharArrayElements)(JNIEnv*, jcharArray,jchar*, jint); 70  void        (*ReleaseShortArrayElements)(JNIEnv*, jshortArray,jshort*, jint); 71  void        (*ReleaseIntArrayElements)(JNIEnv*, jintArray,jint*, jint); 72  void        (*ReleaseLongArrayElements)(JNIEnv*, jlongArray,jlong*, jint); 73  void        (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,jfloat*, jint); 74  void        (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,jdouble*, jint); 75  76  77  void        (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, jboolean*); 78  void        (*GetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, jbyte*); 79  void        (*GetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, jchar*); 80  void        (*GetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, jshort*); 81  void        (*GetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, jint*); 82  void        (*GetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, jlong*); 83  void        (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, jfloat*); 84  void        (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, jdouble*); 85  86  spec shows these without const; some jni.h do, some don't 87  void        (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, const jboolean*); 88  void        (*SetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, const jbyte*); 89  void        (*SetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, const jchar*); 90  void        (*SetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, const jshort*); 91  void        (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*); 92  void        (*SetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, const jlong*); 93  void        (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, const jfloat*); 94  void        (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, const jdouble*); 95  * 96  * 97  *这里可以求得任意数组大小的,累计合 98  */ 99 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray(100         JNIEnv *env, jobject obj, jintArray arr, jint length) {101     int i, sum = 0;102     jint* pOutbuf = NULL;103     if (length > 0)104         pOutbuf = (jint*) malloc(length * sizeof(jint));105     else106         return 0;107     (*env)->GetIntArrayRegion(env, arr, 0, length, pOutbuf);108     for (i = 0; i < 10; i++)109         sum += pOutbuf[i];110     free(pOutbuf);111     pOutbuf = NULL;112 113     return sum;114 }115 /*116  *117  *    ReleaseIntArrayElements118  *        第三个参数就是决定更新与否的。119  *             取值 零(0) 时,更新数组并释放所有元素;120  *             取值 JNI_COMMIT 时,更新但不释放所有元素;121  *             取值 JNI_ABORT 时,不作更新但释放所有元素;122  *      #define JNI_COMMIT 1 // copy content, do not free buffer123  *      #define JNI_ABORT  2 // free buffer w/o copying back ^/124  *         //获取数组长度,注意jarray是指所有类型j<类型>array125  *         typedef jarray jintArray //其他的jbyteArray或jfloatArray都是jarray.126  *       jsize       (*GetArrayLength)(JNIEnv*, jarray);127  */128 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA(129         JNIEnv *env, jobject obj, jintArray arr) {130     int i,j, sum = 0;131     jint* buf;132     j = (*env)->GetArrayLength(env,arr);133     //另外,这里返回的值,是jint*,不是const jint*,也就是说可以对其中的值进行修改134     buf = (*env)->GetIntArrayElements(env, arr, NULL);//这一句其实也告java内存回收器,不要回收arr数组的内存,或者不要整理内存135                                                       //如果回收器,回收和整理内存,那么我们在c中,访问的地址就可能错了136     for (i = 0; i < j; i++)//这里是求合137             sum += buf[i];138     //现在我们来修改一下buf中的元素,看看返回后,会不会把buf中的值,更新到java中的arr里去139     buf[0] = 100;140     buf[1] = 200;141 142     (*env)->ReleaseIntArrayElements(env, arr, buf, 0);//调用这个方法,告诉java内存回收器,我忆用完了arr,,现在可以回收arr的内存了143     return sum;144 }145 /**146  *     要点:演示对传入二维数组的访问147  *  功能:计算二维数组的和148  *    NewObjectArray( env,len,jcIntArray,NULL );149  *    参数2:是要创建的元数个数150  *    参数3:是要创建的元素的类型151  *    参数4:是创建时的初值,可以传空152  */153 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D154   (JNIEnv *env, jobject obj, jobjectArray arr2D)155 {156     int len = 0,length = 0;157     int i,j,sum=0;158     jarray jaIntArray;159     jintArray jiaTmpIntArray;160     jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用161     jclass jcIntArray;162     jboolean jbIsCopy = JNI_FALSE;163 164     len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度165     jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址166     length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度167 168     jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用169     joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray.170 171     for(i=0;i<len;i++)172     {173         jint *piSrc,*piDes;174 175         jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针176         jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length177 178         piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了179         piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了180 181         for(j=0;j<length;j++)182         {183             piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组184             sum +=piDes[j];//通过新创建数的值。累计185         }186 187         (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数188         (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数189 190         (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素191         (*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.192     }193 194     (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组195 196     return sum;197 }198 /*199  * 要点:200  *    1:访问传入的二维数组201  *    2:创建一个新的二维数组202  *    3:修改传入的二维数组的值203  *    4:返回一个二维数组对象给java调用端204  */205 JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d206     (JNIEnv *env, jobject obj, jobjectArray arr2D)207 {208     int len = 0,length = 0;209         int i,j,sum=0;210         jarray jaIntArray;211         jintArray jiaTmpIntArray;212         jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用213         jclass jcIntArray;214         jboolean jbIsCopy = JNI_FALSE;215 216         len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度217         jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址218         length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度219 220         jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用221         joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray.222 223         for(i=0;i<len;i++)224         {225             jint *piSrc,*piDes;226 227             jaIntArray =  (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针228             jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length229 230             piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了231             piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了232 233             for(j=0;j<length;j++)234             {235                 piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组236                 sum +=piDes[j];//通过新创建数的值。累计237                 piDes[j] = 5;//修改传入数组的值238             }239 240             (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数241             (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数242 243             (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素244             (*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.245         }246 247 //        (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组248 249         return joaReturnInt2DArray;250 }251 /**252  *    访问java中的成员[通用的逻辑]253  *    注意:访问的是java中非静态成员,非静态成员是属于对象的.另外还要访问静态成员,静态成员属于类254  *    步骤:255  *    1:先找到对象的类256  *    2:根据成员的名称和类型,获取该成员的id引用257  *    3:根据id引用,获取该成员的域引用258  *    4:根据域引用再得到具体的内容259  *260  */261 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField262   (JNIEnv *env, jobject obj)263 {264     jclass cls;//void*指针265     jfieldID fid;//抽象的结构体指针266     jstring jstr;//void*指针267     jint value;268     const char* str;269 270     cls = (*env)->GetObjectClass(env,obj);//得到类的引用271     fid = (*env)->GetFieldID(env, cls, "myString", "Ljava/lang/String;");//得到成员id的引用272     if( fid == NULL ){//检测根据给定的信息是否找到了id,273         return ;274     }275     jstr = (*env)->GetObjectField(env, obj, fid);//得到对象的引用276     str = (*env)->GetStringUTFChars(env, jstr, NULL);//从对象引用中得到内容277     if( str == NULL ){278         return ;279     }280     //printf(" c.s = "%s"\n", str ) ;281     (*env)->ReleaseStringUTFChars(env, jstr, str);//更新或释放,不过最好用SetObjectField来操作。282     jstr = (*env)->NewStringUTF(env, "accedfild");//创建一个新的字串,这个是用java的方法创建的283     if( jstr == NULL ){284         return ;285     }286     //用jstr,更新obj对象的fid域.287     (*env)->SetObjectField(env, obj, fid, jstr);//设置域对象288 289     //===============访问int静态成员=======================290     fid = (*env)->GetStaticFieldID(env,cls,"si","I");291     if(NULL == fid)292         return;293     value = (*env)->GetStaticIntField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员294     value = 100;295     (*env)->SetStaticIntField(env, cls, fid, 100);296     //===============访问String静态成员=======================297     fid = (*env)->GetStaticFieldID(env, cls, "helloString", "Ljava/lang/String;");298     jstr = (*env)->GetStaticObjectField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员299     str = (*env)->GetStringUTFChars(env, jstr, NULL);300     //可以对str做一些处理301     (*env)->ReleaseStringUTFChars(env, jstr, str);302     jstr = (*env)->NewStringUTF(env, "static string");303     (*env)->SetStaticObjectField(env, cls, fid, jstr);//注意第二个参数是类,不是对象,因为是静态成员304 305     return;306 }307 /*308  * 访问java中的方法309  * 并传递了所有java中的数据类型,对象类型除外310  *311  *312  */313 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod314   (JNIEnv *env, jobject obj)315 {316     jclass cls;317     jmethodID mid;318     const char  *str = "hello call back";319     jstring jstr;320 321     jboolean    z = 1;322     jbyte       b = 0xff;323     jchar       c = 'c';324     jshort      s = 60;325     jint        i = 100;326     jlong       j = 568978523;327     jfloat      f = 125643.22222;328     jdouble     d = 123456789.12654789;329     //jobject     l = ;330 331     cls = (*env)->GetObjectClass(env,obj);//得到类的引用332 333     //从静态方法中得到str,再传回给callback方法334     mid = (*env)->GetStaticMethodID(env, cls,"callStaticBack","()Ljava/lang/String;");335     jstr = (*env)->CallStaticObjectMethod(env,cls,mid);336 337     mid = (*env)->GetMethodID(env, cls, "callback", "(Ljava/lang/String;IBCZJDFS)V");338 339     if (mid == NULL) {340         return; /* method not found */341     }342     //printf("In C\n");343 344     //jstr = (*env)->NewStringUTF(env, str);345     (*env)->CallVoidMethod(env, obj, mid,jstr,i,b,c,z,j,d,f,s);346 347 }
myjni.c
 1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class com_test_androidjni_MainActivity */ 4  5 #ifndef _Included_com_test_androidjni_MainActivity 6 #define _Included_com_test_androidjni_MainActivity 7 #ifdef __cplusplus 8 extern "C" { 9 #endif10 /*11  * Class:     com_test_androidjni_MainActivity12  * Method:    GetNativeString13  * Signature: (Ljava/lang/String;)Ljava/lang/String;14  */15 JNIEXPORT jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString16   (JNIEnv *, jobject, jstring);17 18 /*19  * Class:     com_test_androidjni_MainActivity20  * Method:    SumArray21  * Signature: ([II)I22  */23 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray24   (JNIEnv *, jobject, jintArray, jint);25 26 /*27  * Class:     com_test_androidjni_MainActivity28  * Method:    SumArrayA29  * Signature: ([I)I30  */31 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA32   (JNIEnv *, jobject, jintArray);33 34 /*35  * Class:     com_test_androidjni_MainActivity36  * Method:    SumArray2D37  * Signature: ([[I)I38  */39 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D40   (JNIEnv *, jobject, jobjectArray);41 42 /*43  * Class:     com_test_androidjni_MainActivity44  * Method:    ModifyArray2d45  * Signature: ([[I)[[I46  */47 JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d48   (JNIEnv *, jobject, jobjectArray);49 50 /*51  * Class:     com_test_androidjni_MainActivity52  * Method:    AccessField53  * Signature: ()V54  */55 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField56   (JNIEnv *, jobject);57 58 /*59  * Class:     com_test_androidjni_MainActivity60  * Method:    AccessMethod61  * Signature: ()V62  */63 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod64   (JNIEnv *, jobject);65 66 /*67  * Class:     com_test_androidjni_MainActivity68  * Method:    signature69  * Signature: (Ljava/lang/String;IBCZJDFS)V70  */71 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_signature72   (JNIEnv *, jobject, jstring, jint, jbyte, jchar, jboolean, jlong, jdouble, jfloat, jshort);73 74 #ifdef __cplusplus75 }76 #endif77 #endif
com_test_androidjni_MainActivity.h

jni.h 这个头文件在android-ndk包中的platroms/具体的api包的inlcude中。

关于android jni编程,java与c,c++之间数据的传递都在jni.h这个头文件中.根据类型结构,可知为什么不可以在c中,直接访问java传入的jstring或一些其他类型

它们的类若是void*的,那么就无法访问了。因为我们不知道它在内存的布局,占几个字节,也就无法访问。这就是所谓不透明类型。另外对于c++里面访问java,实

际是对c的封装.

我们注意一下jni.h中

#if defined(__cplusplus)//这里表示是c++用的typedef _JNIEnv JNIEnv;//这是native方法的第一个参数typedef _JavaVM JavaVM;//这个是虚拟机#elsetypedef const struct JNINativeInterface* JNIEnv;typedef const struct JNIInvokeInterface* JavaVM;#endifstruct JNINativeInterface{//具体内容省略,//它们都是一些函数指针,这个结构体,每个native方法的第一个参数JNIEnv env 就是它自己};另外注意一下//这两个方法,是由java虚拟机调用的,它传入一个vm,通过vm我们可以得到JNIEnv,通过JNIEnv我们可以得到//java与c,c++之间的交互接口。JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);

上面这些代码,是对<JNI编程指南> 前4章方法的汇总.也总结了许多网友的代码,并对其做了一些修改,加入了自己的理解。

private static final String DEBUGTAG = "NATIVE";    private String myString;    private static int si=0;    private static String helloString = "What's your name";        //对基本数据类型的访问    private native String GetNativeString(String str);//访问字串    private native int SumArray(int [] ar, int length);//传一个数组的长度    private native int SumArrayA(int [] ar);//不传长度    private native int SumArray2D(int [][]ar2d);//传一个二维数组,返回一个长度        private native int [][] ModifyArray2d(int [][]ar2d);//传入一个二维数组,返回一个二维数组        //这一部分是对成员和方法的访问    private native void AccessField();//访问静态成员    private native void AccessMethod();    //这个方法是为了生成一个包括所有基本类型的方法签名,请查看头文件    private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh);

更多相关文章

  1. android JB2连拍降速原理介绍
  2. Android多媒体开发【11】-- android中OpenMax的实现【2】Awesome
  3. android绘制过程
  4. android从byte[]字节数组中播放mp3音乐
  5. Android 开机动画源码分析
  6. Android System Server大纲之LightsService
  7. Android startActivityForResult unfortunately 程序名 has stop
  8. Android Binder AIDL解析

随机推荐

  1. Android入门篇五:使用全局变量在Activity
  2. Android(安卓)8.0 SystemUI下拉状态栏快
  3. Android 之 zygote 与进程创建
  4. 收藏老罗的----------Android应用程序组
  5. Android(二) 基于 eclipse 的 Android配置
  6. Android应用如何支持屏幕多尺寸多分辨率
  7. Android(安卓)5.1 彩蛋游戏分析
  8. android 屏幕分辨率问题
  9. Android(安卓)音频开发之 MediaPlayer
  10. 关于 Chrome for Android(安卓)你必须知