本文全文转载自:http://www.cnblogs.com/shuqingstudy/p/4909089.html,非常感谢

  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. public class MainActivity extends Activity {
  9. private static final String DEBUGTAG = "NATIVE";
  10. private String myString;
  11. private static int si=0;
  12. private static String helloString = "What's your name";
  13.  
  14. //对基本数据类型的访问
  15. private native String GetNativeString(String str);//访问字串
  16. private native int SumArray(int [] ar, int length);//传一个数组的长度
  17. private native int SumArrayA(int [] ar);//不传长度
  18. private native int SumArray2D(int [][]ar2d);//传一个二维数组,返回一个长度
  19. private native int [][] ModifyArray2d(int [][]ar2d);//传入一个二维数组,返回一个二维数组
  20.  
  21. //这一部分是对成员和方法的访问
  22. private native void AccessField();//访问静态成员
  23. private native void AccessMethod();
  24.  
  25. private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh);
  26.  
  27. /**
  28. * 对于加动.so库做一点说明
  29. * System.loadLibrary 这个方法默认去system/lib去找这个.so库,
  30. * 再到data/data/com.test.androidjin/lib/目录下找。本应数据存放的目录下
  31. * 我们可以通过eclipse上的ddms去查看。前提是把调试的机器联上,
  32. * 动态库的名称是:lib前缀+库名+.so后缀。此函数不要前缀,也不要后缀,只要包名,否则找不到
  33. * 但是我们在这个apk的libs/armeabi/目录下要用libmyjni.so这个全名.
  34. * 另外还有一个加载库的函数
  35. * System.load 这个函数是传入全路径名.这样就可以到指定的路径加载了
  36. * System.load(/system/lib/libXXX.so);注意访问目录的权限问题 ,这个与linux的目录访问权限一样的.
  37. * 有时候我们在使用第三访.so库是,找不到库,但明明库已加打包进了。这里我们要看它的本地方法是在
  38. * 那个java包下的那个类中声明的,比如这个apk的native方法是在
  39. * com.test.androidjni包的MainActivity 这个类中声明的。生成的native函数都有
  40. * Java_com_test_androidjni_MainActivity_这个前缀.我们可以根据第三访.so的函数接口的前缀
  41. * 建立相应的包和类名,然后就可以正确加载了。这里与前面讲的找库的路径是刚好相互应证了。
  42. *
  43. */
  44. static{
  45. System.loadLibrary("myjni");
  46. }
  47.  
  48. @Override
  49. protected void onCreate(Bundle savedInstanceState) {
  50. super.onCreate(savedInstanceState);
  51. setContentView(R.layout.activity_main);
  52. //字符串操作
  53. String retStr = GetNativeString("Please give me A String");
  54. Log.d(DEBUGTAG, retStr);
  55. if(null != retStr){
  56. TextView t = (TextView)findViewById(R.id.nativeString);
  57. t.setText(retStr);
  58. }
  59.  
  60. //传入一维数组,累计和,并修改了第0,第1个数组元素的值
  61. int arr[] =new int[]{1,2,3,4,5,6,7};
  62. Integer value = SumArrayA(arr);
  63. TextView t = (TextView)findViewById(R.id.nativeArray);
  64. t.setText(value.toString());
  65. Log.d(DEBUGTAG, "arr[0] = "+ arr[0]+" arr[1]"+arr[1]);
  66.  
  67. //访问二维数组,累计和,
  68. int arr2d[][] = {{1,1,5,5},{2,2,2,2,}};//new int[2][4];
  69. int sum = SumArray2D(arr2d);
  70. Log.d(DEBUGTAG, "len = " + sum);
  71.  
  72. //访问二维数组,并返回一个二维数组,且修改了传入二维数组的元素
  73. int arr2dA[][] = null;
  74. int sumV = 0;
  75. arr2dA = ModifyArray2d(arr2d);
  76. for(int i=0;i<2;i++)
  77. {
  78. for(int j=0;j<4;j++)
  79. {
  80. sumV += arr2dA[i][j];
  81. }
  82. }
  83. Log.d(DEBUGTAG, "sumV = " + sumV);
  84.  
  85. //c中访问java域和方法
  86. this.myString = "Android Java String";
  87. this.AccessField();
  88. Log.d(DEBUGTAG, "after modify by native myString = " + myString);
  89. Log.d(DEBUGTAG, "after modify by native si = " + si);
  90. Log.d(DEBUGTAG, "after modify by native helloString = " + helloString);
  91. //c中调用java中的方法
  92. this.AccessMethod();
  93. }
  94. private void callback(String strFromNative,int i,byte b,char c,boolean bl,long l,double d,float f,short sh){
  95. Log.d(DEBUGTAG,"CALL FROM NATIVE:"+strFromNative +i+b+c+bl+l+d+f+sh);
  96. }
  97. private static String callStaticBack(){
  98. return "What's your name ";
  99. }
  100.  
  101. }
  102.  
  103. MainActivity.java

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. void (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, jboolean*);
  77. void (*GetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, jbyte*);
  78. void (*GetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, jchar*);
  79. void (*GetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, jshort*);
  80. void (*GetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, jint*);
  81. void (*GetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, jlong*);
  82. void (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, jfloat*);
  83. void (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, jdouble*);
  84.  
  85. spec shows these without const; some jni.h do, some don't
  86. void (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, const jboolean*);
  87. void (*SetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, const jbyte*);
  88. void (*SetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, const jchar*);
  89. void (*SetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, const jshort*);
  90. void (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*);
  91. void (*SetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, const jlong*);
  92. void (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, const jfloat*);
  93. void (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, const jdouble*);
  94. *
  95. *
  96. *这里可以求得任意数组大小的,累计合
  97. */
  98. JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray(
  99. JNIEnv *env, jobject obj, jintArray arr, jint length) {
  100. int i, sum = 0;
  101. jint* pOutbuf = NULL;
  102. if (length > 0)
  103. pOutbuf = (jint*) malloc(length * sizeof(jint));
  104. else
  105. return 0;
  106. (*env)->GetIntArrayRegion(env, arr, 0, length, pOutbuf);
  107. for (i = 0; i < 10; i++)
  108. sum += pOutbuf[i];
  109. free(pOutbuf);
  110. pOutbuf = NULL;
  111.  
  112. return sum;
  113. }
  114. /*
  115. *
  116. * ReleaseIntArrayElements
  117. * 第三个参数就是决定更新与否的。
  118. * 取值 零(0) 时,更新数组并释放所有元素;
  119. * 取值 JNI_COMMIT 时,更新但不释放所有元素;
  120. * 取值 JNI_ABORT 时,不作更新但释放所有元素;
  121. * #define JNI_COMMIT 1 // copy content, do not free buffer
  122. * #define JNI_ABORT 2 // free buffer w/o copying back ^/
  123. * //获取数组长度,注意jarray是指所有类型j<类型>array
  124. * typedef jarray jintArray //其他的jbyteArray或jfloatArray都是jarray.
  125. * jsize (*GetArrayLength)(JNIEnv*, jarray);
  126. */
  127. JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA(
  128. JNIEnv *env, jobject obj, jintArray arr) {
  129. int i,j, sum = 0;
  130. jint* buf;
  131. j = (*env)->GetArrayLength(env,arr);
  132. //另外,这里返回的值,是jint*,不是const jint*,也就是说可以对其中的值进行修改
  133. buf = (*env)->GetIntArrayElements(env, arr, NULL);//这一句其实也告java内存回收器,不要回收arr数组的内存,或者不要整理内存
  134. //如果回收器,回收和整理内存,那么我们在c中,访问的地址就可能错了
  135. for (i = 0; i < j; i++)//这里是求合
  136. sum += buf[i];
  137. //现在我们来修改一下buf中的元素,看看返回后,会不会把buf中的值,更新到java中的arr里去
  138. buf[0] = 100;
  139. buf[1] = 200;
  140.  
  141. (*env)->ReleaseIntArrayElements(env, arr, buf, 0);//调用这个方法,告诉java内存回收器,我忆用完了arr,,现在可以回收arr的内存了
  142. return sum;
  143. }
  144. /**
  145. * 要点:演示对传入二维数组的访问
  146. * 功能:计算二维数组的和
  147. * NewObjectArray( env,len,jcIntArray,NULL );
  148. * 参数2:是要创建的元数个数
  149. * 参数3:是要创建的元素的类型
  150. * 参数4:是创建时的初值,可以传空
  151. */
  152. JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D
  153. (JNIEnv *env, jobject obj, jobjectArray arr2D)
  154. {
  155. int len = 0,length = 0;
  156. int i,j,sum=0;
  157. jarray jaIntArray;
  158. jintArray jiaTmpIntArray;
  159. jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用
  160. jclass jcIntArray;
  161. jboolean jbIsCopy = JNI_FALSE;
  162.  
  163. len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度
  164. jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址
  165. length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度
  166.  
  167. jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用
  168. joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray.
  169.  
  170. for(i=0;i<len;i++)
  171. {
  172. jint *piSrc,*piDes;
  173.  
  174. jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针
  175. jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length
  176.  
  177. piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
  178. piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
  179.  
  180. for(j=0;j<length;j++)
  181. {
  182. piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组
  183. sum +=piDes[j];//通过新创建数的值。累计
  184. }
  185.  
  186. (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数
  187. (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数
  188.  
  189. (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素
  190. (*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.
  191. }
  192.  
  193. (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组
  194.  
  195. return sum;
  196. }
  197. /*
  198. * 要点:
  199. * 1:访问传入的二维数组
  200. * 2:创建一个新的二维数组
  201. * 3:修改传入的二维数组的值
  202. * 4:返回一个二维数组对象给java调用端
  203. */
  204. JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d
  205. (JNIEnv *env, jobject obj, jobjectArray arr2D)
  206. {
  207. int len = 0,length = 0;
  208. int i,j,sum=0;
  209. jarray jaIntArray;
  210. jintArray jiaTmpIntArray;
  211. jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用
  212. jclass jcIntArray;
  213. jboolean jbIsCopy = JNI_FALSE;
  214.  
  215. len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度
  216. jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址
  217. length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度
  218.  
  219. jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用
  220. joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray.
  221.  
  222. for(i=0;i<len;i++)
  223. {
  224. jint *piSrc,*piDes;
  225.  
  226. jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针
  227. jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length
  228.  
  229. piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
  230. piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
  231.  
  232. for(j=0;j<length;j++)
  233. {
  234. piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组
  235. sum +=piDes[j];//通过新创建数的值。累计
  236. piDes[j] = 5;//修改传入数组的值
  237. }
  238.  
  239. (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数
  240. (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数
  241.  
  242. (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素
  243. (*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.
  244. }
  245.  
  246. // (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组
  247.  
  248. return joaReturnInt2DArray;
  249. }
  250. /**
  251. * 访问java中的成员[通用的逻辑]
  252. * 注意:访问的是java中非静态成员,非静态成员是属于对象的.另外还要访问静态成员,静态成员属于类
  253. * 步骤:
  254. * 1:先找到对象的类
  255. * 2:根据成员的名称和类型,获取该成员的id引用
  256. * 3:根据id引用,获取该成员的域引用
  257. * 4:根据域引用再得到具体的内容
  258. *
  259. */
  260. JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField
  261. (JNIEnv *env, jobject obj)
  262. {
  263. jclass cls;//void*指针
  264. jfieldID fid;//抽象的结构体指针
  265. jstring jstr;//void*指针
  266. jint value;
  267. const char* str;
  268.  
  269. cls = (*env)->GetObjectClass(env,obj);//得到类的引用
  270. fid = (*env)->GetFieldID(env, cls, "myString", "Ljava/lang/String;");//得到成员id的引用
  271. if( fid == NULL ){//检测根据给定的信息是否找到了id,
  272. return ;
  273. }
  274. jstr = (*env)->GetObjectField(env, obj, fid);//得到对象的引用
  275. str = (*env)->GetStringUTFChars(env, jstr, NULL);//从对象引用中得到内容
  276. if( str == NULL ){
  277. return ;
  278. }
  279. //printf(" c.s = "%s"\n", str ) ;
  280. (*env)->ReleaseStringUTFChars(env, jstr, str);//更新或释放,不过最好用SetObjectField来操作。
  281. jstr = (*env)->NewStringUTF(env, "accedfild");//创建一个新的字串,这个是用java的方法创建的
  282. if( jstr == NULL ){
  283. return ;
  284. }
  285. //用jstr,更新obj对象的fid域.
  286. (*env)->SetObjectField(env, obj, fid, jstr);//设置域对象
  287.  
  288. //===============访问int静态成员=======================
  289. fid = (*env)->GetStaticFieldID(env,cls,"si","I");
  290. if(NULL == fid)
  291. return;
  292. value = (*env)->GetStaticIntField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员
  293. value = 100;
  294. (*env)->SetStaticIntField(env, cls, fid, 100);
  295. //===============访问String静态成员=======================
  296. fid = (*env)->GetStaticFieldID(env, cls, "helloString", "Ljava/lang/String;");
  297. jstr = (*env)->GetStaticObjectField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员
  298. str = (*env)->GetStringUTFChars(env, jstr, NULL);
  299. //可以对str做一些处理
  300. (*env)->ReleaseStringUTFChars(env, jstr, str);
  301. jstr = (*env)->NewStringUTF(env, "static string");
  302. (*env)->SetStaticObjectField(env, cls, fid, jstr);//注意第二个参数是类,不是对象,因为是静态成员
  303.  
  304. return;
  305. }
  306. /*
  307. * 访问java中的方法
  308. * 并传递了所有java中的数据类型,对象类型除外
  309. *
  310. *
  311. */
  312. JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod
  313. (JNIEnv *env, jobject obj)
  314. {
  315. jclass cls;
  316. jmethodID mid;
  317. const char *str = "hello call back";
  318. jstring jstr;
  319.  
  320. jboolean z = 1;
  321. jbyte b = 0xff;
  322. jchar c = 'c';
  323. jshort s = 60;
  324. jint i = 100;
  325. jlong j = 568978523;
  326. jfloat f = 125643.22222;
  327. jdouble d = 123456789.12654789;
  328. //jobject l = ;
  329.  
  330. cls = (*env)->GetObjectClass(env,obj);//得到类的引用
  331.  
  332. //从静态方法中得到str,再传回给callback方法
  333. mid = (*env)->GetStaticMethodID(env, cls,"callStaticBack","()Ljava/lang/String;");
  334. jstr = (*env)->CallStaticObjectMethod(env,cls,mid);
  335.  
  336. mid = (*env)->GetMethodID(env, cls, "callback", "(Ljava/lang/String;IBCZJDFS)V");
  337.  
  338. if (mid == NULL) {
  339. return; /* method not found */
  340. }
  341. //printf("In C\n");
  342.  
  343. //jstr = (*env)->NewStringUTF(env, str);
  344. (*env)->CallVoidMethod(env, obj, mid,jstr,i,b,c,z,j,d,f,s);
  345.  
  346. }
  347.  
  348. myjni.c

jni.h

  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. #endif
  10. /*
  11. * Class: com_test_androidjni_MainActivity
  12. * Method: GetNativeString
  13. * Signature: (Ljava/lang/String;)Ljava/lang/String;
  14. */
  15. JNIEXPORT jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString
  16. (JNIEnv *, jobject, jstring);
  17.  
  18. /*
  19. * Class: com_test_androidjni_MainActivity
  20. * Method: SumArray
  21. * Signature: ([II)I
  22. */
  23. JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray
  24. (JNIEnv *, jobject, jintArray, jint);
  25.  
  26. /*
  27. * Class: com_test_androidjni_MainActivity
  28. * Method: SumArrayA
  29. * Signature: ([I)I
  30. */
  31. JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA
  32. (JNIEnv *, jobject, jintArray);
  33.  
  34. /*
  35. * Class: com_test_androidjni_MainActivity
  36. * Method: SumArray2D
  37. * Signature: ([[I)I
  38. */
  39. JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D
  40. (JNIEnv *, jobject, jobjectArray);
  41.  
  42. /*
  43. * Class: com_test_androidjni_MainActivity
  44. * Method: ModifyArray2d
  45. * Signature: ([[I)[[I
  46. */
  47. JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d
  48. (JNIEnv *, jobject, jobjectArray);
  49.  
  50. /*
  51. * Class: com_test_androidjni_MainActivity
  52. * Method: AccessField
  53. * Signature: ()V
  54. */
  55. JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField
  56. (JNIEnv *, jobject);
  57.  
  58. /*
  59. * Class: com_test_androidjni_MainActivity
  60. * Method: AccessMethod
  61. * Signature: ()V
  62. */
  63. JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod
  64. (JNIEnv *, jobject);
  65.  
  66. /*
  67. * Class: com_test_androidjni_MainActivity
  68. * Method: signature
  69. * Signature: (Ljava/lang/String;IBCZJDFS)V
  70. */
  71. JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_signature
  72. (JNIEnv *, jobject, jstring, jint, jbyte, jchar, jboolean, jlong, jdouble, jfloat, jshort);
  73.  
  74. #ifdef __cplusplus
  75. }
  76. #endif
  77. #endif
  78.  
  79. com_test_androidjni_MainActivity.h

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中

  1. #if defined(__cplusplus)//这里表示是c++用的
  2. typedef _JNIEnv JNIEnv;//这是native方法的第一个参数
  3. typedef _JavaVM JavaVM;//这个是虚拟机
  4. #else
  5. typedef const struct JNINativeInterface* JNIEnv;
  6. typedef const struct JNIInvokeInterface* JavaVM;
  7. #endif
  8.  
  9. struct JNINativeInterface
  10.  
  11. //具体内容省略,
  12.  
  13. //它们都是一些函数指针,这个结构体,每个native方法的第一个参数JNIEnv env 就是它自己
  14.  
  15. };
  16.  
  17. 另外注意一下
  18.  
  19. //这两个方法,是由java虚拟机调用的,它传入一个vm,通过vm我们可以得到JNIEnv,通过JNIEnv我们可以得到
  20. //java与c,c++之间的交互接口。
  21.  
  22. JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
  23. JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);

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

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

自己体会:

学习了这么多天的jni终于要结束了,不知道怎么总结,这5篇博客和这位NB的博主的文章算是对其做一个总结吧,当需要

改变C语言的算法时,直接在操作区修改即可,配置NDK,导入include可以问Java/android调用C,当然是JNI借口了,提供更快速的平台工具

加油,下一个内容!

android jni 总复习(转载)的更多相关文章

  1. [转载]—— Android JNI知识点

    Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 ...

  2. [ 转载 ] Android JNI(一)——NDK与JNI基础

    Android JNI(一)——NDK与JNI基础 隔壁老李头 关注  4.4 2018.05.09 17:15* 字数 5481 阅读 11468评论 8喜欢 140 本系列文章如下: Androi ...

  3. Android JNI学习(四)——JNI的常用方法的中文API

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

  4. android JNI调用(转)

    Android jni开发资料--NDK环境搭建 android开发人员注意了 谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwi ...

  5. Android JNI之JAVA与C++对象建立对称关联(JNI优化设计,确保JNI调用的稳定性)

    转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5930503.html Android JNI之JAVA与C++对象建立对称关联 1.JAVA对象持有C++对象 ...

  6. Android JNI 获取应用程序签名

    使用Android JNI 获取应用程序签名. 获取基础上生成自己的签名password,这可以防止别人反编译找到自己的源代码password. jstring Java_com_masonsdk_j ...

  7. android JNI 简单demo(2)它JNI demo 写

    android JNI 简单demo(2)它JNI demo 写 一.搭建Cygwin 环境:http://blog.csdn.net/androidolblog/article/details/25 ...

  8. 基于NDK的Android防破解& Android防破解 【转载】

    两篇防破解文章转载 基于NDK的Android防破解:http://blog.csdn.net/bugrunner/article/details/8634585 Android防破解:http:// ...

  9. Android JNI学习(五)——Demo演示

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

随机推荐

  1. linux 文件类型识别

    使用 ls -aldrwxr-xr-x. 4 root root 100 Apr 26 15:05 cpulrwxrwxrwx. 1 root root 13 Apr 26 15:05 fd -> ...

  2. linux命令学习-1-less

    less 工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大.less 的用法比起 more 更加的有弹性.在 more 的时候,我们并没有办法向前面翻 ...

  3. 学习c++语言应该牢记的50条准则,同样学习其他语言也一样

    1.把C++当成一门新的语言学习(和C没啥关系!真的.): 2.看<Thinking In C++>,不要看<C++变成死相>: 3.看<The C++ Programm ...

  4. pcommlite串口通讯库使用

    MFC下串口编程使用最多的两种方法是读取注册表和使用mscomm组件,都有着或多或少的缺陷,调用系统SDK比较麻烦,而MSCOMm组件最多支持16个串口,串口号大于16的时候无法打开,遇到这种情况,可 ...

  5. LPC2478内存布局以及启动方式

    LPC2478 是NXP公司推出的一款基于APR7TDMI-S的工控型MCU,内置RAM与flash,同时提供外部扩展flash和ram接口,拥有LCD控制器,其内存布局如下所示 其中Flash高达5 ...

  6. Mybatis3.2.1整合Spring3.1

    Mybatis3.2.1整合Spring3.1 根 据官方的说法,在ibatis3,也就是Mybatis3问世之前,Spring3的开发工作就已经完成了,所以Spring3中还是没有对 Mybatis ...

  7. 【转】进程间通信方式总结(windows 和linux)

    平时看的书很多,了解的也很多,但不喜欢总结,这不昨天面试的时候被问到了进程间通信的方式,因为没有认真总结过,所以昨天答得不是特别好.现在将linux和windows的进程间通信方式好好总结一下.    ...

  8. js extend的实现

    var obj = { a: "aaaaaa" }; var obj1 = { b: "bbbbbb" }; Object.extend = function ...

  9. AndroidManifest.xml文件

    AndroidManifest.xml常用标签解读 1.全局篇(包名,版本信息) 2.组件篇(四大组件) Activity Service Content Provider Broadcast Rec ...

  10. 微信和QQ网页授权登录

    一:微信授权 //用户授权 public function is_weixin(){ $url = "https://open.weixin.qq.com/connect/oauth2/au ...