转: http://blog.renren.com/GetEntry.do?id=718959269&owner=228440950
上个星期,导师看我们闲的慌,让我们实现Android平台下的socket通信,实现两端通信。采用NDK方法,java编写界面,c编写socket实体。从此开始了我们一个多星期的磨难。本来以为是一个很简单的程序,编写的时候才发现很麻烦,遇到的问题不断,正常问题有,诡异的问题也不少。不过的确增长了不少知识,现在将一些学习到的东西记录下来。
NDK的安装过程就不说了,网上都有。只是在一个文件中增加一句话就可以搞定,很简单。接下来的才是重点。
1.javah 命令
这个命令是用于生成*.c文件的头文件,同时最重要的是,生成java中的本地方法在*.c文件中的函数名。若是你对这个函数写法不清楚的话,可以试试这个命令。使用过程如下:
1.将用javac命令将定义本地方法的java文件编译,生成*.class文件。
2.退后到工程目录下的src文件中。
3.终端输入如下命令: javah -jni com.studentmanager.mars.JNI。其中com.studentmanager.mars是完整的包名,JNI是我定义本地方法的文件。注:可不要将继承Activity的那个文件用javac,这是不能编译通过的,可以将本地方法定义到另一个类中。
4.将在src文件中生成的头文件移到jni文件中,然后在*.c文件中包含这个头文件就可以了。
截图如下:
2.javap
这个命令是用于GetMethodID方法中,显示此java文件中函数的签名。具体意义在后名说明,它的用法如下:
1.进入工程目录下面的bin目录。之所以进入这个目录是由于,javap这个命令对*.class文件起作用,而继承于Activity的java类的*.class文件就在bin目录中。
2.在终端输入:javap -s -p com.studentmanager.mars.Client 其中-s是指获得签名,-p是指显示private函数, com.studentmanager.mars是完整包名,Client是你需要访问的文件名。运行截图如下:
3.c访问java中的类成员和方法
这个在程序开发中非常重要,网上也有很多关于这个的帖子,一般代码如下:
第一行代码的目的是获得一个jclass的对象,有两种获得方式。一种是如图所示的GetObjectClass方法,还有一种是FindClass方法。当使用GetObjectClass方法时,需要具有你所要访问java类的一个实例对象。在系统自动生成的两个函数中的jobject thiz也是一个java类的对象,它是你本地方法定义的那个类的对象。使用FindClass方法的格式如下:
jclass objectClass = (*env)->FindClass(env,"com/studentmanager/mars/MyThread");
其中com/studentmanager/mars是完整包名,MyThread是类的名字。
第二行代码的意思是获得类对象中name成员函数的ID号,"Ljava/lang/String;"表示它的类型为String。
第三行代码的意思是通过这个ID号获取name成员的值。
第四行代码的意思是将jstring类型转换为char * 类型。
注:使用FindClass方法时,由于com/studentmanager/mars/MyThread替代了类对象,故我们需要重新生成一个类的对象。生成代码如下:
第一行中的GetMethodID方法和GetFieldID方法的含义类似,就是获得类中方法的ID号。"<init>"是一个特殊的方法,即构造方法。它的写法就是这样,不需要进行改变。若想调用其他的方法,可以在那个位置写入方法的名字即可。
第二行中的NewObject方法即生成一个新的实例对象。
若想调用类中的方法的话,在获得了方法的ID号之后,调用Call<type>Method方法,即可。整个代码如下: