http://blog.csdn.net/xyz_lmn/article/details/6955031

android支持使用NDK开发C程序,关于配置NDK环境问题应该不用再赘述了,这个网上有很多,这里通过一篇实例来讲述简单的JNI开发,大家可以参考这篇文章(Get Your Eclipse-Integrated NDK On!)搭建Eclipse编译C语言为so文件的开发环境。

native方法实现步骤如下:

1、在Java中声明native()方法,然后编译(javac);

2、用javah产生一个.h文件;

3、编写包含.h文件的c文件

4、编译c文件

5、使用编译成功的so文件。

第一步:

1、声明native方法

[java] view plain copy
  1. publicclassPrintf_Jni{
  2. static{
  3. System.loadLibrary("com_nedu_jni_helloword_printf-jni");
  4. }
  5. publicnativevoidprintHello();
  6. }

2、javac编译

进入java文件所在路径,调用javac命令,如图:

第二步:使用javah命令生成.h头文件,如图:

这个要回到src目录下,不知道什么原因,如果在上面的javac路径下会报错,如图:

使用javah命令生成的头文件如下:

[cpp] view plain copy
  1. /*DONOTEDITTHISFILE-itismachinegenerated*/
  2. #include<jni.h>
  3. /*Headerforclasscom_nedu_jni_helloword_Printf_Jni*/
  4. #ifndef_Included_com_nedu_jni_helloword_Printf_Jni
  5. #define_Included_com_nedu_jni_helloword_Printf_Jni
  6. #ifdef__cplusplus
  7. extern"C"{
  8. #endif
  9. /*
  10. *Class:com_nedu_jni_helloword_Printf_Jni
  11. *Method:printHello
  12. *Signature:()V
  13. */
  14. JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_Printf_1Jni_printHello
  15. (JNIEnv*,jobject);
  16. #ifdef__cplusplus
  17. }
  18. #endif
  19. #endif

第三步:编写c文件,代码如下:

[cpp] view plain copy
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include"com_nedu_jni_helloword_Printf_Jni.h"
  4. JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_Printf_1Jni_printHello
  5. (JNIEnv*e,jobjectj)
  6. {
  7. printf("Helloworld!");
  8. }

第四步,书写Android.mk文件,编译c文件
Android.mk文件如下:

[plain] view plain copy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_MODULE:=com_nedu_jni_helloword_printf-jni
  4. LOCAL_SRC_FILES:=Printf_Jni.c
  5. include$(BUILD_SHARED_LIBRARY)


LOCAL_MODULE := com_nedu_jni_helloword_printf-jniLOCAL_MODULE := com_nedu_jni_helloword_printf-jniLOCAL_MODULE表示so文件名

LOCAL_SRC_FILES 需要编译的文件

按照这篇文章(Get Your Eclipse-Integrated NDK On!)的介绍就可以在Eclipse编译了。

第五步:使用so文件:

通过下面的代码加载so文件

[html] view plain copy
  1. System.loadLibrary("com_nedu_jni_helloword_printf-jni");


通过下面的代码加载so文件通过下面的代码加载so文件

调用如下:

[java] view plain copy
  1. Printf_Jniprint=newPrintf_Jni();
[java] view plain copy
  1. print.printHello();

http://blog.csdn.net/xyz_lmn/article/details/6956003

前面一篇通过简单的例子介绍了android中JNI的使用。这一篇从基础上了解一些Java参数类型与本地参数类型区别。

1)java中的返回值voidJNI中的void是完全对应的哦!(仅仅一个而已)。

2)java中的基本数据类型(byte ,short ,int,long,float,double ,boolean,char8种)在JNI中对应的数据类型只要在前面加上j就对应了(jbyte ,jshort ,jint,jlong,jfloat,jdouble ,jboolean,jchar)。

3)java中的对象,包括类库中定义的类、接口以及自定义的类接口,都对应于JNI中的jobject

4)java中基本数据类型的数组对应与JNI中的j<type>array类型。(type就是上面说的8种基本数据类型)

5)java中对象的数组对应于JNI中的jobjectArray类型。(在java中一切对象、接口以及数组都是对象)

下图是JNI规范中java数据类型和JNI数据类型的映射图。

第一幅为基本数据类型的映射图:

第二幅为引用数据类型的映射图:

http://blog.csdn.net/xyz_lmn/article/details/6959545

一、 首先写了java文件:

[java] view plain copy
  1. publicclassHeaderFile{
  2. privatenativevoiddoVoid();
  3. nativeintdoShort();
  4. nativevoiddoArray(Object[]o);
  5. nativeintdoInt(inti);//byte,short,int,long,float,double,boolean,char
  6. nativeintdoInt(doubled);//byte,short,int,long,float,double,boolean,char
  7. nativeintdoInt(Objecto);
  8. nativeintdoInt(doubled1,doubled2);
  9. staticnativeintdoInt(doubled1,doubled2,doubled3);
  10. staticnativeintdoInt(doubled1,floatf,booleanb,char[]c);
  11. nativeintdoInt(int[]i);
  12. nativeintdoInt(int[]i1,double[]i2);
  13. staticnativeintdoInt(int[]i1,double[]i2,Object[]o);
  14. publicnativeStringdoString(Strings);
  15. publicnativeObjectdoObject(Objecto);
  16. publicnativeEnumerationdoInterface(Iteratorit);
  17. publicnativeStudentdoStudent(Students);
  18. //nativeint[]doInt(int[]i);//byte,short,int,long,float,double,boolean,char
  19. publicnativeString[]doString(String[]s);
  20. publicnativeObject[]doObjects(Object[]o);
  21. publicnativeEnumeration[]doInterface(Iterator[]it);
  22. publicnativeStudent[]doStudent(Student[]s);
  23. publicnativestaticObjectdoAll(int[]i,String[]s,Student[]student);
  24. }

java文件中包含了private、public、protect等类型的方法,static 方法和非static 方法,返回类型有基础类型、对象等。

二、下面看一下生成的头文件:

[cpp] view plain copy
  1. /*DONOTEDITTHISFILE-itismachinegenerated*/
  2. #include<jni.h>
  3. /*Headerforclasscom_nedu_jni_helloword_HeaderFile*/
  4. #ifndef_Included_com_nedu_jni_helloword_HeaderFile
  5. #define_Included_com_nedu_jni_helloword_HeaderFile
  6. #ifdef__cplusplus
  7. extern"C"{
  8. #endif
  9. /*
  10. *Class:com_nedu_jni_helloword_HeaderFile
  11. *Method:doVoid
  12. *Signature:()V
  13. */
  14. JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_HeaderFile_doVoid
  15. (JNIEnv*,jobject);
  16. /*
  17. *Class:com_nedu_jni_helloword_HeaderFile
  18. *Method:doShort
  19. *Signature:()I
  20. */
  21. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doShort
  22. (JNIEnv*,jobject);
  23. /*
  24. *Class:com_nedu_jni_helloword_HeaderFile
  25. *Method:doArray
  26. *Signature:([Ljava/lang/Object;)V
  27. */
  28. JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_HeaderFile_doArray
  29. (JNIEnv*,jobject,jobjectArray);
  30. /*
  31. *Class:com_nedu_jni_helloword_HeaderFile
  32. *Method:doInt
  33. *Signature:(I)I
  34. */
  35. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__I
  36. (JNIEnv*,jobject,jint);
  37. /*
  38. *Class:com_nedu_jni_helloword_HeaderFile
  39. *Method:doInt
  40. *Signature:(D)I
  41. */
  42. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__D
  43. (JNIEnv*,jobject,jdouble);
  44. /*
  45. *Class:com_nedu_jni_helloword_HeaderFile
  46. *Method:doInt
  47. *Signature:(Ljava/lang/Object;)I
  48. */
  49. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__Ljava_lang_Object_2
  50. (JNIEnv*,jobject,jobject);
  51. /*
  52. *Class:com_nedu_jni_helloword_HeaderFile
  53. *Method:doInt
  54. *Signature:(DD)I
  55. */
  56. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DD
  57. (JNIEnv*,jobject,jdouble,jdouble);
  58. /*
  59. *Class:com_nedu_jni_helloword_HeaderFile
  60. *Method:doInt
  61. *Signature:(DDD)I
  62. */
  63. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DDD
  64. (JNIEnv*,jclass,jdouble,jdouble,jdouble);
  65. /*
  66. *Class:com_nedu_jni_helloword_HeaderFile
  67. *Method:doInt
  68. *Signature:(DFZ[C)I
  69. */
  70. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DFZ_3C
  71. (JNIEnv*,jclass,jdouble,jfloat,jboolean,jcharArray);
  72. /*
  73. *Class:com_nedu_jni_helloword_HeaderFile
  74. *Method:doInt
  75. *Signature:([I)I
  76. */
  77. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt___3I
  78. (JNIEnv*,jobject,jintArray);
  79. /*
  80. *Class:com_nedu_jni_helloword_HeaderFile
  81. *Method:doInt
  82. *Signature:([I[D)I
  83. */
  84. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt___3I_3D
  85. (JNIEnv*,jobject,jintArray,jdoubleArray);
  86. /*
  87. *Class:com_nedu_jni_helloword_HeaderFile
  88. *Method:doInt
  89. *Signature:([I[D[Ljava/lang/Object;)I
  90. */
  91. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt___3I_3D_3Ljava_lang_Object_2
  92. (JNIEnv*,jclass,jintArray,jdoubleArray,jobjectArray);
  93. /*
  94. *Class:com_nedu_jni_helloword_HeaderFile
  95. *Method:doString
  96. *Signature:(Ljava/lang/String;)Ljava/lang/String;
  97. */
  98. JNIEXPORTjstringJNICALLJava_com_nedu_jni_helloword_HeaderFile_doString__Ljava_lang_String_2
  99. (JNIEnv*,jobject,jstring);
  100. /*
  101. *Class:com_nedu_jni_helloword_HeaderFile
  102. *Method:doObject
  103. *Signature:(Ljava/lang/Object;)Ljava/lang/Object;
  104. */
  105. JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doObject
  106. (JNIEnv*,jobject,jobject);
  107. /*
  108. *Class:com_nedu_jni_helloword_HeaderFile
  109. *Method:doInterface
  110. *Signature:(Ljava/util/Iterator;)Ljava/util/Enumeration;
  111. */
  112. JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInterface__Ljava_util_Iterator_2
  113. (JNIEnv*,jobject,jobject);
  114. /*
  115. *Class:com_nedu_jni_helloword_HeaderFile
  116. *Method:doStudent
  117. *Signature:(Lcom/nedu/jni/helloword/Student;)Lcom/nedu/jni/helloword/Student;
  118. */
  119. JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doStudent__Lcom_nedu_jni_helloword_Student_2
  120. (JNIEnv*,jobject,jobject);
  121. /*
  122. *Class:com_nedu_jni_helloword_HeaderFile
  123. *Method:doString
  124. *Signature:([Ljava/lang/String;)[Ljava/lang/String;
  125. */
  126. JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doString___3Ljava_lang_String_2
  127. (JNIEnv*,jobject,jobjectArray);
  128. /*
  129. *Class:com_nedu_jni_helloword_HeaderFile
  130. *Method:doObjects
  131. *Signature:([Ljava/lang/Object;)[Ljava/lang/Object;
  132. */
  133. JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doObjects
  134. (JNIEnv*,jobject,jobjectArray);
  135. /*
  136. *Class:com_nedu_jni_helloword_HeaderFile
  137. *Method:doInterface
  138. *Signature:([Ljava/util/Iterator;)[Ljava/util/Enumeration;
  139. */
  140. JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInterface___3Ljava_util_Iterator_2
  141. (JNIEnv*,jobject,jobjectArray);
  142. /*
  143. *Class:com_nedu_jni_helloword_HeaderFile
  144. *Method:doStudent
  145. *Signature:([Lcom/nedu/jni/helloword/Student;)[Lcom/nedu/jni/helloword/Student;
  146. */
  147. JNIEXPORTjobjectArrayJNICALLJava_com_nedu_jni_helloword_HeaderFile_doStudent___3Lcom_nedu_jni_helloword_Student_2
  148. (JNIEnv*,jobject,jobjectArray);
  149. /*
  150. *Class:com_nedu_jni_helloword_HeaderFile
  151. *Method:doAll
  152. *Signature:([I[Ljava/lang/String;[Lcom/nedu/jni/helloword/Student;)Ljava/lang/Object;
  153. */
  154. JNIEXPORTjobjectJNICALLJava_com_nedu_jni_helloword_HeaderFile_doAll
  155. (JNIEnv*,jclass,jintArray,jobjectArray,jobjectArray);
  156. #ifdef__cplusplus
  157. }
  158. #endif
  159. #endif


三、头文件分析如下:

1、文件的前九行就不用说了,他们是CC++的头,应该很好理解。

2、方法的注释部分,每个方法都有它的注释部分,这些都是相似的,对其中一个分析:

[plain] view plain copy
  1. /*
  2. *Class:com_nedu_jni_helloword_HeaderFile
  3. *Method:doVoid
  4. *Signature:()V
  5. */

注释部分分为三部分Class、Method、Signature。

Class:表示Native方法的类名称

Method:表示方法名称

Signature:是方法的标识,它是一个标识符,主要供我们在JNI操作java对象的方法使用的。

Signature一般是两部分构成,一个方法的参数,另一个是返回类型。方法参数在括号里面,返回类型在后面,

例如

[plain] view plain copy
  1. ()V返回为void,没有参数。
[plain] view plain copy
  1. (DFZ[C)I返回为int,参数为double、float、char[]
[plain] view plain copy
  1. (Ljava/lang/String;)Ljava/lang/String;返回String,参数为String


如果不清楚其中的字符含义,就不能知道其中的意思,其中字符对应有基本类型、对象类型、数组类型。分析如下

1)基本类型的对应关系如下:

2)方法参数或者返回值为java中的对象时,必须以“L”加上其路径,不过此路径必须以“/”分开,自定义的对象也使用本规则,不在包中时直接“L”加上类名称。比如说java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为"com/nedu/jni/helloword/Student"

3)方法参数或者返回值为数组时类型前加上[,例如[I表示int[],[[[D表示 double[][][],即几维数组就加几个[。

看一下例子:

3、方法的声明

[cpp] view plain copy
  1. JNIEXPORTvoidJNICALLJava_com_nedu_jni_helloword_HeaderFile_doArray(JNIEnv*,jobject,jobjectArray);

从上面的头文件可以看出方法基本有7部分组成。


1、3部分是都是JNI的关键字,表示此函数是要被JNI调用的。

2、表示方法的返回类型

4、JNI中标识此方法来源于java的标识头

5、方法所在类的包名+类名

6、方法名

7、参数,它们有一个共同的特点,包含JNIEnv *――它是一个接口指针,用于定位函数表中的函数!

JNI规范中一般称 为 “Interface Pointer”。看到这儿好像和过程调用很类似了!是的,JNI

的操作过程,就是面向过程的!后面的jobject是 一个指向该类的指针,类似与C语言中的this。这个

第二个参数是变化的,当该方法为类的实例方法时该参数为jobject;当该方法为类方法(即静态方法)

时该参数为jclass,指向该类的class

根据不同方法前缀生成的头文件比较如下:

1、static与非static的比较:

[cpp] view plain copy
  1. /*
  2. *Class:com_nedu_jni_helloword_HeaderFile
  3. *Method:doInt
  4. *Signature:(DD)I
  5. */
  6. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DD
  7. (JNIEnv*,<spanstyle="background-color:rgb(255,0,0);">jobject</span>,jdouble,jdouble);
  8. /*
  9. *Class:com_nedu_jni_helloword_HeaderFile
  10. *Method:doInt
  11. *Signature:(DDD)I
  12. */
  13. JNIEXPORTjintJNICALLJava_com_nedu_jni_helloword_HeaderFile_doInt__DDD
  14. (JNIEnv*,<spanstyle="color:#000000;background-color:rgb(255,0,0);">jclass</span>,jdouble,jdouble,jdouble);

第一个是非static方法,第二个是static方法,不同点如上红色标记。其中的不同将在以后提到。

2、privatefriendlyprotected以及public这些方法限制符不会在JNI的头文件中出现。这些访问修饰符只有在其它类

使用这些方法时有效!JNI中不关心此修饰符!

http://blog.csdn.net/xyz_lmn/article/details/6966259

Android.mk文件是在使用NDK编译C代码时必须的文件,Android.mk文件中描述了哪些C文件将被编译且指明了如何编译。掌握Android.mk文件的编写主要是掌握其里头将要使用的一些关键字,先来看一个简单的例子,这个例子使用的是android NDK带的

HellJni的例子。

[plain] view plain copy
  1. LOCAL_PATH:=$(callmy-dir)
  2. include$(CLEAR_VARS)
  3. LOCAL_MODULE:=hello-jni
  4. LOCAL_SRC_FILES:=hello-jni.c
  5. include$(BUILD_SHARED_LIBRARY)


LOCAL_PATH 是描述所有要编译的C文件所在的根目录,这边的赋值为$(call my-dir),代表根目录即为Android.mk所在的目录。

include $(CLEAR_VARS) 代表在使用NDK编译工具时对编译环境中所用到的全局变量清零,如LOCAL_MODULE,LOCAL_SRC_FILES等,因为在一次NDK编译过程中可能会多次调用Android.mk文件,中间用到的全局变量可能是变化的。关于这个问题看了下面比较复杂的例子可能就明白了。

LOCAL_MODULE 是最后生成库时的名字的一部分,给其加上前缀lib和后缀.so就是生成的共享库的名字libhello-jni.so。

LOCAL_SRC_FILES 指明要被编译的c文件的文件名

include $(BUILD_SHARED_LIBRARY) 指明NDK编译时将生成一些共享库

参考:

android编译系统makefile(Android.mk)写法

android makefile(android.mk)分析(序)

Android.mk的用法和基础


<!-- JiaThis Button BEGIN -->
<div id="ckepop">
<a href="http://www.jiathis.com/share" class="jiathis jiathis_txt" target="_blank"><img src="http://v2.jiathis.com/code_mini/images/btn/v1/jiathis1.gif" border="0" /></a>
<a class="jiathis_counter_style_margin:3px 0 0 2px"></a>
</div>
<script type="text/javascript" src="http://v2.jiathis.com/code_mini/jia.js" charset="utf-8"></script>
<!-- JiaThis Button END --><!-- JiaThis Button BEGIN -->
<div id="ckepop">
<a href="http://www.jiathis.com/share" class="jiathis jiathis_txt" target="_blank"><img src="http://v2.jiathis.com/code_mini/images/btn/v1/jiathis1.gif" border="0" /></a>
<a class="jiathis_counter_style_margin:3px 0 0 2px"></a>
</div>
<script type="text/javascript" src="http://v2.jiathis.com/code_mini/jia.js" charset="utf-8"></script>
<!-- JiaThis Button END -->

参考网址:

http://blog.csdn.net/xyz_lmn/article/details/6959545

Android JNI入门第三篇——jni头文件分析

http://blog.csdn.net/xyz_lmn/article/details/6966259

Android JNI入门第四篇——Android.mk文件分析

http://blog.csdn.net/xyz_lmn/article/details/7017420

Android JNI开发提高篇

http://blog.csdn.net/xyz_lmn/article/details/6956003

Android JNI入门第二篇——Java参数类型与本地参数类型对照

http://wenku.baidu.com/view/e9e28ca1b0717fd5360cdc18.html

JNI入门

http://www.ibm.com/developerworks/cn/java/j-jni/

使用 Java Native Interface 的最佳实践

http://helloxuweifu.iteye.com/blog/1168647

http://blog.csdn.net/kangyaping/article/details/6584027

JNI函数调用大全

http://newfaction.net/2010/11/30/java-jni-getfieldid-and-getmethodid-and-parameter-description.html

java jni GetFieldID 和 GetMethodID 以及参数的说明

http://hi.baidu.com/spmno/blog/item/7d4d764ea78a6809b3de0588.html

jni中使用数组的几个方法

http://xxw8393.blog.163.com/blog/static/3725683420107109411366/

JNI 返回结构体参数

http://www.cnblogs.com/nicholas_f/archive/2010/11/30/1892124.html

JNI中java类型与C/C++类型对应关系

http://blog.csdn.net/sunny09290/article/details/6884994

JNI数据类型

http://www.cnblogs.com/liangwind/archive/2009/08/18/1925515.html

jni --c/c++ 数据类型、数组、对象

http://www.cnblogs.com/diyunpeng/archive/2009/09/24/1573296.html

Java有符号数与无符号数

http://www.stuhack.com/biancheng/java/35169.html

Java的基本数据类型是无符号的


更多相关文章

  1. Android(安卓)Activity生命周期以及Fragment生命周期的区别与分
  2. android 设置为壁纸代码
  3. Android(安卓)error--No implementation found for native Lcomd
  4. pAdTy_-5 保存数据
  5. 设置布局默认为LinearLayout,却成了RelativeLayout
  6. Android(安卓)RecyclerView 实现快速滑动
  7. FAQ_10_EditText与parseInt方法
  8. Android基础控件(EditView、SeekBar等)的使用方法
  9. Android(安卓)倒计时工具类

随机推荐

  1. 转:LinearLayout布局
  2. Android studio :Please configure Andro
  3. Android优秀实例源码
  4. [Android] 基于 Linux 命令行构建 Androi
  5. android点滴2
  6. Android(安卓)【真机】与【模拟器】触摸
  7. Android安全机制解析与应用实践
  8. android media库中external的读取
  9. Python+Android开发
  10. Android开发优秀博文收录