昨天Cygwin在线安装安到一半突然就停处了,这网太无耐了
上面搜“cygwin 离线”,注意:下载下来的东西解压后的文件夹是ftp%...,包含%,&之类的特殊字符,把文件夹
名改成123什么的,不然会很莫名其妙的。害哥搞这个离线包搞了个把小时。
为了清楚,上个图:
敲个LS,什么东西都没有,这个目录是cygwin的安装目录下面的home文件夹下的用户名文件夹。
接下来是配置与Android相关的。在home/用户名,这个文件夹下有一个文件为.bash_profile,打开它,到最后添
加两行NDK的环境变量:
NDK_ROOT=/cygdrive/d/android-ndk-r6
export NDK_ROOT
上面的意思是,ndk的目录是,d:/android-ndk-r6
添加完之后,关闭Cygwin重新启动一下,然后敲入cd $NDK_ROOT,是否进入到ndk的目录了?否则就看看哪个字
母错了。
在ndk的目录下samples下有很多例子,随便弄个就可编译了。下面是新建一个项目,以对C语言在项目中的位置
更清楚。
打开Eclipse新建一个Android项目,取名hellojni,为了清晰,便于维护,及各种各样的好处,JNI的JAVA代码单独
一个类,单独一个包。其实最好能不用JNI就别用JNI,这东西负作用巨大,特别是在用到JNI复杂的地方,什么
内存啊,类型啊,哪里调用的方法,异常啊,可靠性都非常麻烦。非要用JNI的复杂功能,做好两件事,做之前充
分设计,设计之前充分学习一下JNI文档。当然对于一些简单的应用,那只需要充分仔细。作好参数,返回值的检
查,记得释放内存就行了。
新建了一个JNI的类JNIClass,里面申明一个将在C语言中实现的方法。如下:
package com.jjie.jni;
public class JNIClass {
public native int GetSumFromCFunc(int a, int b);
}
C语言就是取两个数的和。
接下来在项目中新建一个文件夹jni,参考NDK目录下的sample中的hello-jni,把hello-jni中的jni目录下的
Android.mk拷贝到我们的项目中的jni文件夹,这个文件中的内容是告诉编译器要编译哪些文件,依赖哪些库,现
在里面很简单,照如下改动一下。
LOCAL_MODULE := hellojni
LOCAL_SRC_FILES := hellojni.c
就是把那个'-'去掉了,山寨一下。hellojni.c是需要实现JAVA中方法的文件,但是怎么把JAVA中的函数名与C中的对
应起来就是下一步,C语言中的函数名不是随便取的,是通过java生成的。
在Windows的cmd中,进入项目的bin目录,用javah对JNIClass.class进行生成C语言方法的头文件,注意是.class文
件,不是.java文件。
javah -jni com.jjie.jni.JNIClass
成功后,在bin文件夹下生成了一个.h的头文件。把这个文件放到项目的jni这个目录中,在这个目录中再新建一个
hellojni.c的文件用来实现java的方法,c函数的原型已经在刚刚的头文件中了:
JNIEXPORT jint JNICALL Java_com_jjie_jni_JNIClass_GetSumFromCFunc
(JNIEnv *, jobject, jint, jint);
我们只有两个整型的参数就是最后两个,至于前面两个是什么意思,阅读JNI文档。这个头文件中还引用到jni.h,
#include <jni.h>,注意把<>改成"",在ndk的目录中搜索一个jni.h,把搜到的这个文件同样放到jni的目录中。
hellojni.c实现函数:
#include "com_jjie_jni_JNIClass.h"
JNIEXPORT jint JNICALL Java_com_jjie_jni_JNIClass_GetSumFromCFunc
(JNIEnv *env, jobject this, jint a, jint b)
{
return a + b;
}
接下来是编译,用到Cygwin了,编译是用到NDK目录下的ndk-build,进入到我们项目的目录,如下命令编译:
$NDK_ROOT/ndk-build
结果:
conan@conan-PC /cygdrive/d/workspace36/hellojni
$ $NDK_ROOT/ndk-build
Compile thumb : hellojni <= hellojni.c
SharedLibrary :
Install : => libs/armeabi/conan@conan-PC /cygdrive/d/workspace36/hellojni
在项目中刷新一下,发现多一个文件夹libs/armeabi/。这个就是生成的库了,相当于Windows中的DLL
接下来就是去调用,在MainActivity中加载这个包,加载的时候注意去掉前缀lib。
在layout中的main.xml中的TextView加个id: android:id="@+id/tvResult"
package com.jjie;
import com.jjie.jni.JNIClass;
import .Activity;
import android.os.Bundle;
import android.widget.TextView;public class MainActivity extends Activity {
private TextView textView = null;
//加载库
static {
System.loadLibrary("hellojni");
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); JNIClass jniClass = new JNIClass();
//调用JNI中的方法
int result = jniClass.GetSumFromCFunc(1, 6);
textView = (TextView)this.findViewById(.tvResult);
textView.setText(String.valueOf(result));
}
}
运行吧。